Написание самоизменяющегося кода на C в Windows, Невозможно написать патч - PullRequest
0 голосов
/ 29 сентября 2019

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

Я пытался использовать разные способы, чтобы гарантировать, что разрешения на область памяти, которую я пытаюсь исправить, правильны (PAGE_EXECUTE_READWRITE) для того, что я хочу сделать.Я думаю, что проблема в том, как я называю WriteProcessMemory, хотя я не уверен, почему это так.

#include <windows.h>
#include <psapi.h>
#include <stdio.h>

#define PATTERN "\x55\x48\x89\xe5\x48\x83\xec\x20\x48\x8d\x0d\x91\x2a\x00\x00\xe8\x3c\x16\x00\x00\x90\x48\x83\xc4\x20\x5d\xc3"
#define REPLACE "\x55\x48\x89\xe5\x90\x5d\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90x\90\x90\x90\x90\x90\x90\x90\x90\x90\x90\xc3"
#define LEN 27

DWORD SearchPattern(unsigned char* mem, unsigned char* signature, DWORD signatureLen) 
{
    ULONG offset = 0;

    for (int i = 0; i < 0x200000; i++) {
        if (*(unsigned char*)(mem + i) == signature[0] && *(unsigned char*)(mem + i + 1) == signature[1]) {
            if (memcmp(mem + i, signature, signatureLen) == 0) {
                // Found the signature
                offset = i;
                break;
            }
        }
    }

    return offset;
}

void patch_mem()
{
    DWORD oldProtect, oldOldProtect;

    unsigned char *exe = (unsigned char *)GetModuleHandle("patching_tests.exe");
    DWORD patternOffset = SearchPattern(exe, PATTERN, LEN);
    if (patternOffset == 0)
    {
        printf("Error finding offset, returning\n");
        return;
    }

    printf("offset: %#010x\n", (exe + patternOffset));

    VirtualProtect((exe + patternOffset), LEN, PAGE_EXECUTE_READWRITE, &oldProtect);
    CopyMemory((exe + patternOffset), REPLACE, LEN);
    VirtualProtect((exe + patternOffset), LEN, oldProtect, &oldOldProtect);

    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
    if (!FlushInstructionCache(handle, (LPCVOID)(exe + patternOffset), LEN))
    {
        printf("FlushInstructionCache, %d\n", GetLastError());
    }

    return;
}

int say_hi()
{
    printf("hi!\n");
}

int main()
{
    printf("calling say_hi...\n");
    say_hi();

    printf("patching memory...\n");
    patch_mem();

    printf("calling say_hi again...\n");
    say_hi();

    return 0;
}

Цель состоит в том, чтобы изменить сборку в функции say_hi, чтобы она просто возвращала, а не печаталаПривет!

Могу ли я также отметить, что я хотел бы сделать это без использования указателя на функцию say_hi и скорее искать его в памяти.Это потому, что я собираюсь реализовать эту технику в проекте, где невозможно получить прямой доступ к указателю на функцию.

ОБНОВЛЕНИЕ: Я удалил вызов WriteProcessMemory и заменил егос CopyMemory.Я также теперь использовал GetModuleHandle, чтобы получить базовый адрес модуля.Теперь он скомпилируется сам по себе ... хотя, похоже, он не перезаписывает код в функции say_hi.

1 Ответ

0 голосов
/ 30 сентября 2019

Во-первых, в макросе REPLACE возникает ошибка "\x90x\90", но вы не уверены, что это ошибка записи при публикации.

Затем int say_hi() должно иметь возвращаемое значение, например * 1006.*

int say_hi()
{
    printf("hi!\n");
    return 0;
}

или просто с использованием void возвращаемого типа.

Память функций, которую вы пытаетесь изменить, может быть неправильной или может быть пропущена.Обратите внимание, что шаблон, который вы ищете, будет содержать одни и те же данные в другой памяти (поскольку в вашей программе определена постоянная #define PATTERN), поэтому то, что вы изменили, скорее всего, будет PATTERN.

.могу проверить это по memcmp(PATTERN, REPLACE, LEN);:

DWORD SearchPattern(unsigned char* mem, unsigned char* signature, DWORD signatureLen)
{
    ULONG offset = 0;

    for (int i = 0; i < 0x20000; i++) {
        if (*(unsigned char*)(mem + i) == signature[0] && *(unsigned char*)(mem + i + 1) == signature[1]) {
            if (memcmp(mem + i, signature, signatureLen) == 0) {

                if (mem + i == signature)
                    continue;  //Found the memory of the PATTERN
                // Found the signature
                offset = i;
                break;
            }
        }
    }

    return offset;
}

Я могу найти инструкцию выполнения say_hi через правильный PATTERN и изменить ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...