Что и зачем
Существует ряд ситуаций, когда это имеет смысл. От полного контроля памяти, до вынужденной необходимости. К примеру, одна из возможных ситуаций:
1. Мы используем alignment аллокаторы
2. Мы перегружаем какой-то класс и данные от нашей 3rd зависимости
3. 3rd зависимость не использует alignment аллокаторы
Ищем new/delete/malloc/free
Если нам повезёт, то 3rd может иметь свои new/delete операторы, которые были экспортированы. Хотя везением это сложно назвать, т.к. придётся ковыряться в дизассемблированном коде. Если вы решили не заморачиваться с поиском адресов, то этот шаг можно пропустить.
Немного помучавшись, можно прийти к следующему:

Затем, нам нужен RVA адрес функции.
Для начала получаем адрес dll в памяти:

После чего вычисляем адрес нашего символа:
00007FFC9BB7D760 - Symbol 00007FFC9BAF0000 - Base adress // Без адреса входа B7D760 AF0000 D760 // Раз адрес кончается на 0000, то D760 просто запоминаем 0000 // Те самые ноли // Получаем первые два символа адреса b7 - af = 08 // Конечный итог 08D760
Осталось только достать Ordinal. Для этого подойдёт тот же CFF Explorer

Видим заветные 5CD. Они нам и нужны.
Перегружаем символ
Теперь переходим к более интересной части. Итак, для начала нам потребуется библиотека для создание хуков в рантайме. К примеру, minhook.
Далее пишем базовый код:
using OperatorNewFunc = void* (*)(size_t size); struct InitialHook { InitialHook() { MH_STATUS ResultCode = MH_Initialize(); // Загружаем наш символ из модуля HMODULE hMFC = GetModuleHandle("mfc140.dll"); // Загружаем ordinal OperatorNewFunc hOperatorNew = (OperatorNewFunc)GetProcAddress(hMFC, MAKEINTRESOURCE(0x5CD)); ResultCode = MH_CreateHook(hOperatorNew, /* Вставьте свой каллбек */, nullptr); MH_EnableHook(hOperatorNew); } };
Однако, если же вы решили не искать адрес, то просто достаём malloc из ucrtbase.dll
HMODULE hCRT = GetModuleHandle("ucrtbase.dll"); OperatorNewFunc hFreeFunc = (OperatorNewFunc)GetProcAddress(hCRT, "malloc");
Вторым аргументом для MH_CreateHook передаём нашу новую функцию аллокации памяти.
А теперь самое важно. Нужно заставить компилятор выполнять инициализацию нашей структуры раньше остальных глобальных функций.
// Регистрируем секцию #pragma section(".Hook",read) using OperatorNewFunc = void* (*)(size_t size); struct InitialHook { InitialHook() { MH_STATUS ResultCode = MH_Initialize(); // Загружаем наш символ из модуля HMODULE hMFC = GetModuleHandle("mfc140.dll"); OperatorNewFunc hOperatorNew = (OperatorNewFunc)GetProcAddress(hMFC, MAKEINTRESOURCE(0x5CD)); ResultCode = MH_CreateHook(hOperatorNew, /* Вставьте свой каллбек */, nullptr); MH_EnableHook(hOperatorNew); } }; // Определям символ нашей структуры #pragma init_seg(lib) __declspec(allocate(".Hook")) static const InitialHook HookInit;
Более подробно об этом можно почитать тут.
ссылка на оригинал статьи https://habr.com/ru/post/703906/
Добавить комментарий