Я пишу небольшой инструмент, который должен иметь возможность проверять произвольный интересующий процесс и проверять, была ли какая-либо из его статически связанных функций батут. (примером батута может быть то, что Microsoft Detours относится к процессу.)
Для этого я анализирую заголовок PE. целевого процесса и получить все его импортированные библиотеки DLL со всеми импортированными функциями в них. Затем я могу сравнить следующее между библиотеками DLL на диске и библиотеками DLL, загруженными в память целевого процесса:
А. Записи в Import Address Table
для каждой импортированной функции.
B. Первые N байтов машинного кода каждой функции.
И если что-то из вышеперечисленного не совпадает, это наверняка будет означать, что к конкретной функции (или WinAPI) был применен trampoline
.
Это работает хорошо, за исключением одной ситуации, когда целевой процесс может импортировать глобальную переменную вместо функции. Например, такой глобальной переменной является _acmdln
. Вы все еще можете найти его в msvcrt.dll
и использовать как таковой:
//I'm not sure why you'd want to do it this way,
//but it will give you the current command line.
//So just to prove the concept ...
HMODULE hMod = ::GetModuleHandle(L"msvcrt.dll");
char* pVar = (char*)::GetProcAddress(hMod, "_acmdln");
char* pCmdLine = pVar ? *(char**)pVar : NULL;
Итак, для моего инструмента проверки трамплинов это означает, что мне нужно различать импортированную функцию (WinAPI) и глобальную переменную. Есть идеи как?
PS. Если я этого не сделаю, мой алгоритм, который я описал выше, будет сравнивать «байты кода» глобальной переменной, как если бы это была функция, которая является просто указателем на командную строку, которая наверняка будет другой, а затем пометит ее. как батутная функция.
PS2. Не совсем мой код, но аналогичный способ анализа заголовка PE можно найти здесь< /а>. (Найдите функцию DumpImports
для извлечения импорта DLL.)