user1112347
user1112347

Reputation: 13

C - Inline asm patching at runtime

I am writing a program in C and i use inline asm. In the inline assembler code is have some addresses where i want to patch them at runtime.

A quick sample of the code is this:

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

An say i want to modify the 0xAABBCCDD value from the main C program. What i tried to do is to Call VirtualProtect an is the pointer of the function in order to make it Writeable, and then call memcpy to add the appropriate values to the code.

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

However VirtualProtect fails and GetLastError() returns 487 which means accessing invalid address. Anyone have a clue about this problem?? Thanks

Upvotes: 1

Views: 984

Answers (2)

Peter
Peter

Reputation: 1275

How to do it to another process at runtime,

  1. Create a variable that holds the program base address
  2. Get the target RVA (Relative Virtual Address)
  3. Then calculate the real address like this PA=RVA + BASE
  4. then call it from your inline assembly

You can get the base address like this

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;
}

Assuming you have a local variable and your base address

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

You have to restore the value of your Register after the call returns, since this value may be used somewhere down the code execution, assuming you're trying to patch an existing application that may depend on the eax register after your call. Although this method has it disadvantages, but at least it will give anyone idea on what to do.

Upvotes: 1

Mike Nakis
Mike Nakis

Reputation: 61986

Doesn't this work?

int X = 0xAABBCCDD;

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

Upvotes: 1

Related Questions