Как отличить импортированную функцию от импортированной глобальной переменной в PE-заголовке DLL?
Я пишу небольшой инструмент, который должен иметь возможность проверять произвольный интересующий процесс и проверять, были ли трамплины какие-либо из его статически связанных функций. (Примером батута может быть то, что Microsoft Detours делает с процессом.)
Для этого я анализирую PE-заголовок целевого процесса и извлекаю все импортированные им DLL со всеми импортированными в них функциями. Затем я могу сравнить следующее между DLL на диске и DLL, загруженными в целевую память процесса:
А. Записи в Import Address Table
для каждой импортируемой функции.
B. Первые N байтов машинного кода каждой функции.
И если что-либо из вышеперечисленного не совпадает, это, безусловно, означает, что trampoline
был применен к определенной функции (или WinAPI.)
Это работает хорошо, за исключением одной ситуации, когда целевой процесс может импортировать глобальную переменную вместо функции. Например _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.)
0 ответов
Глобальные переменные будут находиться в разделе.data, а не в разделе.text, кроме того, этот раздел не будет иметь прав на выполнение, если это не функция. Поэтому вы можете использовать обе эти характеристики для фильтрации.