Делал эксперимент с перезаписью функции в райтайме. Допустим, вы хотите сделать защиту от дампа, что бы важные функции или данные в них не засветились, тогда можно заменить все инструкции в этой функции nop'ами. Сразу скажу, что в дополнении к этому коду, следует использовать обфускаторы. Вот пример кода который получился у меня: Я сделал для примера функцию которая выделяет 320 байт в памяти приложения используя WinApi функцию VirtualAlloc. 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; } 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 функции я написал такой код (оставил комментарии для вас). #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); //Выводим сообщение, что всё прошло успешно. } 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); //Выводим сообщение, что всё прошло успешно. } Результат дампа такой: В теории, если заморочиться, то можно переписать функцию, и записать туда небольшой малварь, и если невнимательный реверсер решит открыть его, вы сами понимаете что может быть...)
а если функция вызывается определенное количество раз, а ты ее перепишешь после 1 вызова, это как то исправляется и будешь ли ты сам знать сколько она будет вызываться? и второй вопрос, можно ли сделать так что пока функция не будет вызвана, то все инструкции в ней будут нопами, а когда к ней будет обращение, то нопы будут приводиться к инструкциям, и после завершения функции обратно к нопу и так по кругу??