Так уж случилось, что время от времени я развлекаюсь анализом клиентов ММО-игр на тему различного рода полезностей или получения информации о действии тех или иных игровых аспектов. Основное количество информации приносит разбор клиента в IDA Pro или OllyDbg.
Так как опыта у меня не так уж и много в данном действе, обычно я банально беру какую-либо функцию, пишу dll-перехватчик и анализирую аргументы функции, полученные при перехвате.
К сожалению, даже IDA не идеальна — получить аргументы функции, соответствующие истине, зачастую проблематично(самый простой пример — lua-функции, lua_state определяется Идой как int). Да и, по мере анализа клиента, dll обрастает порой просто неприличным количеством функций, их объявлений и описаний, а также прочего добра. В результате получаем километры кода.
Но стремление к прекрасному живет в большинстве из нас — потому возникает желание как-то этот код «утрамбовать», сделать более читаемым. К примеру, я при написании dll люблю использовать макросы, регионы, по возможности уменьшать количество однотипных функций и т.д.
И вот не так давно я загорелся идеей еще сильнее сжать код путем сжатия объявления и описания функции, переменных и прочего добра в 1 макрос. В идеале — скидывать список аргументов перехваченной функции в файл. На данный момент я написал относительно универсальный перехватчик для __cdecl функций(т.к. уровень знаний в данной области у меня не слишком высок, могу предположить, что адекватно работать будет только для Windows x86, возможно, есть еще какие-то ограничения). Для перехвата использую обычно Detours x86, иногда — простенький аналог.
Собственно, код:
Ну и, собственно, пример объявления всего этого добра:
Вот так 1 строкой мы объявляем функцию-перехватчик, указываем, какую функцию и по какому адресу мы хотим перехватить, а также при перехвате получаем список аргументов(в данном примере все аргументы будут записаны в файл как int, можно добавить формат в макрос).
Далее все просто — если используем Detours, то аттач будет выглядеть как-то так:
Остальное, в принципе, не нуждается в пояснениях.
Пример вывода аргументов:
Итого, при помощи пары небольших макросов, мы получили возможность неплохо ужать код.
Недостатки:
1) На данный момент не работает с __stdcall'ом, __thiscall'ом и другими соглашениями о вызовах. Не откажусь от помощи или совета по данному поводу.
2) Как я уже упоминал, опыта в данном вопросе достаточно мало, так что вполне могут быть косяки, которых я не учел, так что просьба сильно не тролить.
3) Не нашел аналогов, однако это не значит, что нету более адекватных способов / нельзя оптимизировать текущий. Замечания по данному поводу также были бы кстати.
Благодарю за внимание!
Так как опыта у меня не так уж и много в данном действе, обычно я банально беру какую-либо функцию, пишу dll-перехватчик и анализирую аргументы функции, полученные при перехвате.
К сожалению, даже IDA не идеальна — получить аргументы функции, соответствующие истине, зачастую проблематично(самый простой пример — lua-функции, lua_state определяется Идой как int). Да и, по мере анализа клиента, dll обрастает порой просто неприличным количеством функций, их объявлений и описаний, а также прочего добра. В результате получаем километры кода.
Но стремление к прекрасному живет в большинстве из нас — потому возникает желание как-то этот код «утрамбовать», сделать более читаемым. К примеру, я при написании dll люблю использовать макросы, регионы, по возможности уменьшать количество однотипных функций и т.д.
И вот не так давно я загорелся идеей еще сильнее сжать код путем сжатия объявления и описания функции, переменных и прочего добра в 1 макрос. В идеале — скидывать список аргументов перехваченной функции в файл. На данный момент я написал относительно универсальный перехватчик для __cdecl функций(т.к. уровень знаний в данной области у меня не слишком высок, могу предположить, что адекватно работать будет только для Windows x86, возможно, есть еще какие-то ограничения). Для перехвата использую обычно Detours x86, иногда — простенький аналог.
Собственно, код:
#define cdecl_hook(name1)\ /*Macro definition*/ void name1##_hook(int a1, ...)\ /*Declare hooker*/ {\ int check_s = 0;\ __asm{mov check_s, esp}\ /*Save esp state*/ int *ptr = &a1;\ /*Get pointer to 1st arg, equialent of va_list*/ debug_msg("Advanced",true,"--%s arg list started--", __FUNCTION__);\ /*debug_msg() - vfprintf wrapper*/ for(int i=0; i*4<name1##_arg_amount; i++)\ {\ debug_msg("Advanced",true," |---Element %d: %d", i, ptr[i]);\ }\ /*Arg list -> file(Advanced.txt)*/ debug_msg("Advanced",true,"--arg list finished--\n");\ __asm{lea ecx, a1}\ /*Move addr of a1 to ecx*/ __asm{mov eax, name1##_arg_amount}\ /*move size of args in stack(can get from IDA, for ex.) to eax*/ __asm{label_loop: }\ /*Start loop*/ __asm{mov ebx, dword ptr[ecx+eax-4]}\ /*Move args from stack to ebx in loop and push ebx*/ __asm{push ebx}\ __asm{sub eax,4}\ __asm{cmp eax,0}\ __asm{jg label_loop}\ __asm{call dword ptr[name1##_Detour]}\ /*Call original function*/ __asm{mov esp, check_s}\ /*Restore stack, same as __asm{add esp, name1##_arg_amount}*/ }\
#define RF_O_UP_FUNC(name1, address, args)\ /*Define needed functions and variables*/ typedef void (* t##name1 ) ();\ /*__declspec(dllexport) */t##name1 name1##_Detour = ( t##name1 ) ( address );\ /*Define original function and bind to addr*/ void name1##_hook(int a1, ...);\ /*Define hooker*/ int name1##_arg_amount = args;\ /*Summary size of args in stack, can get from IDA*/ cdecl_hook(name1); /*Call hooker definition*/
Ну и, собственно, пример объявления всего этого добра:
RF_O_UP_FUNC(resources, 0x687054, 0x4C); RF_O_UP_FUNC(hooker, 0x17E4D18, 7); RF_O_UP_FUNC(begin, 0x689BA0, 5);
Вот так 1 строкой мы объявляем функцию-перехватчик, указываем, какую функцию и по какому адресу мы хотим перехватить, а также при перехвате получаем список аргументов(в данном примере все аргументы будут записаны в файл как int, можно добавить формат в макрос).
Далее все просто — если используем Detours, то аттач будет выглядеть как-то так:
DetourAttach(&(PVOID&)resources_Detour, resources_hook).Остальное, в принципе, не нуждается в пояснениях.
Пример вывода аргументов:
--resources_hook arg list started-- |---Element 0: 204181 |---Element 1: 204181 |---Element 2: 1277574 |---Element 3: 1363294854 |---Element 4: 1 |---Element 5: 0 |---Element 6: 0 |---Element 7: 0 |---Element 8: 0 |---Element 9: 0 |---Element 10: 0 |---Element 11: 0 |---Element 12: 0 |---Element 13: 0 |---Element 14: 0 |---Element 15: 0 |---Element 16: 1 |---Element 17: 100 |---Element 18: 1 --arg list finished--
Итого, при помощи пары небольших макросов, мы получили возможность неплохо ужать код.
Недостатки:
1) На данный момент не работает с __stdcall'ом, __thiscall'ом и другими соглашениями о вызовах. Не откажусь от помощи или совета по данному поводу.
2) Как я уже упоминал, опыта в данном вопросе достаточно мало, так что вполне могут быть косяки, которых я не учел, так что просьба сильно не тролить.
3) Не нашел аналогов, однако это не значит, что нету более адекватных способов / нельзя оптимизировать текущий. Замечания по данному поводу также были бы кстати.
Благодарю за внимание!
