Страницы

Поиск по вопросам

вторник, 7 апреля 2020 г.

Как определить размер функции в программе?

#cpp #c

                    
В коде имеется функция. Хочу инжектировать эту функцию в чужой процесс, но чтобы
выделить под нее память в процессе нужно знать ее размер в байтах. Как это можно сделать?
    


Ответы

Ответ 1



Универсального решения не существует. Особенно если вы пишите на C++. А вообще, вот занимательное чтиво прямо на тему твоего вопроса: https://rsdn.ru/forum/cpp/2333802.hot Если коротко, то можно попытаться так: static int test_proc() { return 1; } static void size_proc() {} static size_t test_proc_size() { return (uintptr_t)((uintptr_t)(void*)size_proc - (uintptr_t)(void*)test_proc); } но вообще никаких гарантий, особенно в том, что size_proc так и останется сразу за test_proc. Ну и в развитие данной темы: можно попробовать получить адреса всех символов, отсортировать по возрастанию, размер между твоей функцией и следующим символом вполне может оказаться искомой величиной.

Ответ 2



Функция в С/С++ не обязана быть непрерывной последовательностью инструкций машинного кода с четко выраженным началом и концом. Если несколько функций содержат одинаковый завершающий блок кода ("эпилог"), оптимизирующий компилятор может включить его в бинарник только в одной функции, а в других заменить его на инструкцию перехода в первую. В таком случае понятие "размер функции" становится неоднозначным. Кроме того, попытка перенести машинный код из одного процесса в другой "как есть" скорее всего закончится неудачей, ведь инструкции часто оперируют относительными адресами. Более правильным решением было бы реализовать инжектируемый блок кода полностью в виде ассемблерной вставки, как например здесь. Тем не менее, API для получения размера функции (как справочной информации) существуют. Например, так это можно сделать в Windows с помощью dbghelp: #include #include #include #include "DbgHelp.h" #pragma comment(lib, "Dbghelp.lib") struct Function { const char* name; unsigned int size; bool success; }; BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID context) { Function* pfstruct = (Function*)context; if (strcmp(pSymInfo->Name, pfstruct->name) == 0) { pfstruct->size = SymbolSize; pfstruct->success = true; return FALSE; //закончить поиск } return TRUE; //продолжить поиск } // Находит размер функции fname и помещает в переменную resultvar // Требует наличия отладочных символов (PDB-файла) в каталоге с программой bool GetFunctionSize(const char* fname, unsigned int& resultvar) { bool ret; Function fstruct; fstruct.name = fname; fstruct.size = 0; fstruct.success = false; HANDLE hProcess = GetCurrentProcess(); //текущий процесс char Mask[] = "*!"; //искать среди всех модулей BOOL status; status = SymInitialize(hProcess, NULL, TRUE); //загрузка символов if (status == FALSE) { printf("SymInitialize failed. Error code: %d\n", GetLastError()); return false; } //поиск символов if (SymEnumSymbols(hProcess, 0, Mask, &EnumSymProc, (void*)&fstruct)) { if (fstruct.success != false) { resultvar = fstruct.size; //возвращаем размер ret = true; } else { printf("Symbol [%s] not found\n", fname); ret = false; } } else { printf("SymEnumSymbols failed. Error code: %d\n", GetLastError()); ret = false; } SymCleanup(hProcess); return ret; } //********************************** void Func() { printf("Hello, World!\n"); } int main(int argc, char **argv) { uintptr_t p = (uintptr_t)&Func; printf("Func address: 0x%x\n", (UINT)p); unsigned int size = 0; if (GetFunctionSize("Func", size) != false) { printf("Func size: %u bytes", size); } getchar(); return 0; } При использовании Visual Studio 2017+ для корректной работы данного кода необходимо собирать проект с параметром /DEBUG:FULL (см. /DEBUG).

Комментариев нет:

Отправить комментарий