Всем привет, делал эксперимент с перезаписью функции в райтайме.
Допустим, вы хотите сделать защиту от дампа, что бы важные функции или данные в них не засветились, тогда можно заменить все инструкции в этой функции nop'ами.
Вот пример кода который получился у меня:
Я сделал для примера функцию которая выделяет 320 байт в памяти приложения используя WinApi функцию VirtualAlloc.
Предположим, что данная функция отработает у нас только 1 раз и в будущем она нам не понадобится.
В main функции я написал такой код (оставил комментарии для вас).
Результат дампа такой:
Теперь реверсер вместо функции получит попу)).
В теории, если заморочиться, то можно переписать функцию, и записать туда небольшой малварь, и если невнимательный реверсер решит открыть его, вы сами понимаете что может быть...)
Как узнать размер нашей функции, можно найти в этой статье: Малварь как искусство - Генерация кода на си. Часть вторая. Исполняем код на лету
Отрывок из статьи пользователя @X-Shar
3. Ну тут думаю понятно, вычисляем длину функции, далее копируем в специальный буфер и этот буфер сохраняем в файл:
Допустим, вы хотите сделать защиту от дампа, что бы важные функции или данные в них не засветились, тогда можно заменить все инструкции в этой функции 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); //Выводим сообщение, что всё прошло успешно.
}
Результат дампа такой:
Теперь реверсер вместо функции получит попу)).
В теории, если заморочиться, то можно переписать функцию, и записать туда небольшой малварь, и если невнимательный реверсер решит открыть его, вы сами понимаете что может быть...)
Как узнать размер нашей функции, можно найти в этой статье: Малварь как искусство - Генерация кода на си. Часть вторая. Исполняем код на лету
Отрывок из статьи пользователя @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);
Последнее редактирование: