Кастомный аллокатор для закрытого 3rd

от автора

Что и зачем

Существует ряд ситуаций, когда это имеет смысл. От полного контроля памяти, до вынужденной необходимости. К примеру, одна из возможных ситуаций:
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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *