C - встроенное исправление asm во время выполнения

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

Быстрый пример кода:

void __declspec(naked) inline(void)
{
      mov eax, 0xAABBCCDD
      call 0xAABBCCDD
}

Скажем, я хочу изменить значение 0xAABBCCDD из основной программы C. То, что я пытался сделать, это вызвать VirtualProtect и является указателем на функцию, чтобы сделать ее доступной для записи, а затем вызвать memcpy, чтобы добавить соответствующие значения в код.

DWORD old;
VirtualProtect(inline, len, PAGE_EXECUTE_READWRITE, &old);

Однако VirtualProtect дает сбой, и GetLastError() возвращает 487, что означает доступ к неверному адресу. Кто-нибудь имеет представление об этой проблеме? Спасибо

1 ответ

Решение

Разве это не работает?

int X = 0xAABBCCDD;

void __declspec(naked) inline(void)
{
      mov eax, [X]
      call [X]
}

Как сделать это с другим процессом во время выполнения,

  1. Создайте переменную, содержащую базовый адрес программы
  2. Получить целевой RVA (относительный виртуальный адрес)
  3. Затем вычислите реальный адрес следующим образом: PA=RVA + BASE
  4. затем вызовите его из своей встроенной сборки

Вы можете получить базовый адрес вот так

DWORD dwGetModuleBaseAddress(DWORD dwProcessID)
{
    TCHAR zFileName[MAX_PATH];
    ZeroMemory(zFileName, MAX_PATH);

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, true, dwProcessID);
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
    DWORD dwModuleBaseAddress = 0;

    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 ModuleEntry32 = { 0 };
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
        {
            do
            {
                if (wcscmp(ModuleEntry32.szModule, L"example.exe") == 0)
                {
                    dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnapshot, &ModuleEntry32));
        }
        CloseHandle(hSnapshot);
        CloseHandle(hProcess);
    }
    return dwModuleBaseAddress;
}

Предполагая, что у вас есть локальная переменная и ваш базовый адрес

mov     dword ptr ss : [ebp - 0x14] , eax;
mov     eax, dword ptr BaseAddress;
add     eax, PA;
call    eax;
mov     eax, dword ptr ss : [ebp - 0x14] ;

Вы должны восстановить значение вашего Register после возврата вызова, поскольку это значение может использоваться где-то в процессе выполнения кода, если вы пытаетесь исправить существующее приложение, которое может зависеть от регистра eax после вашего вызова. Хотя у этого метода есть свои недостатки, но он, по крайней мере, подскажет, что делать.

Другие вопросы по тегам