• Уменьшение отступа

    Обратная связь

    (info@ru-sfera.pw)

Уроки Защита приложения C++ от дампа.


MKII

Администратор
Администрация
Регистрация
03.10.2022
Сообщения
256
Репутация
182
Всем привет, делал эксперимент с перезаписью функции в райтайме.
Допустим, вы хотите сделать защиту от дампа, что бы важные функции или данные в них не засветились, тогда можно заменить все инструкции в этой функции nop'ами.

Вот пример кода который получился у меня:
Я сделал для примера функцию которая выделяет 320 байт в памяти приложения используя WinApi функцию VirtualAlloc.
C++:
LPVOID Valloc()
{
    LPVOID lpvResult;

    lpvResult = VirtualAlloc(NULL, 320, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    if (lpvResult == NULL)
    {
        MessageBoxA(NULL, "VirtualAlloc failed!", "SHC", MB_OK);
        return 0;
    }
    VirtualFree(lpvResult, 0, MEM_RELEASE);
    MessageBoxA(NULL, "VirtualAlloc success!", "SHC", MB_OK);
  
    return lpvResult;
}

Предположим, что данная функция отработает у нас только 1 раз и в будущем она нам не понадобится.

В main функции я написал такой код (оставил комментарии для вас).
C++:
#pragma optimize( "", off )

typedef LPVOID(*pAlloc)();
LPVOID Valloc();

VOID WINAPI Entry(VOID)
{
    //MessageBoxA(NULL, "Hello World!", "SHC", MB_OK);
    LPVOID Done = Valloc(); //Выполняем нашу основную функцию
  
    DWORD oldProtect;
    size_t functionSize = 97; //Указываем размер нашей функции Valloc в моём случае, она весит 98 байт, но я указываю 97, так как в конце функции есть ret, который занимает 1 байт (её можно тоже заменить, но в таком случае дебаггер не будет видеть её:().
        VirtualProtect(Valloc, functionSize, PAGE_EXECUTE_READWRITE, &oldProtect);

        //Заменяем нашу функцию на указанный опкод, если хотите заменить nop'ы, то 0x61 замените на 0x90
        //Опкоды можно узнать тут: http://xxeo.com/single-byte-or-small-x86-opcodes
    for (size_t i = 0; i < functionSize; ++i) {
        *((char*)Valloc + i) = 0x61;
    }
    VirtualProtect(Valloc, functionSize, oldProtect, &oldProtect);

    pAlloc functionPointer = Valloc;
    MessageBoxA(NULL, "NOP success!", "SHC", MB_OK); //Выводим сообщение, что всё прошло успешно.
}

Результат дампа такой:
1675170912221.png


Теперь реверсер вместо функции получит попу)).

В теории, если заморочиться, то можно переписать функцию, и записать туда небольшой малварь, и если невнимательный реверсер решит открыть его, вы сами понимаете что может быть...)

Как узнать размер нашей функции, можно найти в этой статье: Малварь как искусство - Генерация кода на си. Часть вторая. Исполняем код на лету
Отрывок из статьи пользователя @X-Shar
3. Ну тут думаю понятно, вычисляем длину функции, далее копируем в специальный буфер и этот буфер сохраняем в файл:
C++:
int func_len = (unsigned int) _Bild
                  - (unsigned int) _Demo;
  char buff[1000];
  memcpy (buff, _Demo, func_len);

  f=fopen("Demo32.bin","wb");
  for (int a=0;a<func_len;a++)
    fputc(((int) buff[a]),f);
  fclose(f);
 
Последнее редактирование:

MKII

Администратор
Администрация
Регистрация
03.10.2022
Сообщения
256
Репутация
182
Кстати, если вы полностью перепишите функцию (в моем случае все 98 байт, то она пропадет из дебаггера).
1675172253647.png


Ещё можно использовать рантайм линковку из моей статьи, и ещё больше запутать реверсеров (на скриншоте я не накладывал шифрование строк, но вам советую, это прибавит защиты и усложнит анализ приложения).
1675172809022.png
 
Последнее редактирование:

MKII

Администратор
Администрация
Регистрация
03.10.2022
Сообщения
256
Репутация
182
Кстати, ещё один способ узнать размер функции:
Открываем оригинальный файл в IDA -> ПКМ на нашу функцию -> Edit Function (CTRL + E).
1675175448046.png

Смотрим адреса:
1675175469320.png

Открываем Calc.exe - режим Программист - Hex.
1675175514904.png

Вводим End Address - Start Address
1675175650271.png

Получаем ответ!
 

Вложения

  • 1675175558516.png
    1675175558516.png
    406 байт · Просмотры: 9
Автор темы Похожие темы Форум Ответы Дата
X-Shar С++ 0
Верх Низ