C-运行时内联asm修补

C-运行时内联asm修补,c,windows,assembly,x86,patch,C,Windows,Assembly,X86,Patch,我正在用C写一个程序,我使用内联asm。在内联汇编代码中,我有一些地址,我想在运行时修补它们 下面是代码的一个快速示例: void __declspec(naked) inline(void) { mov eax, 0xAABBCCDD call 0xAABBCCDD } 假设我想修改主C程序中的0xAABBCCDD值。 我试图做的是调用VirtualProtect an is函数的指针以使其可写,然后调用memcpy向代码中添加适当的值 DWORD old; Virt

我正在用C写一个程序,我使用内联asm。在内联汇编代码中,我有一些地址,我想在运行时修补它们

下面是代码的一个快速示例:

void __declspec(naked) inline(void)
{
      mov eax, 0xAABBCCDD
      call 0xAABBCCDD
}
假设我想修改主C程序中的0xAABBCCDD值。 我试图做的是调用VirtualProtect an is函数的指针以使其可写,然后调用memcpy向代码中添加适当的值

DWORD old;
VirtualProtect(inline, len, PAGE_EXECUTE_READWRITE, &old);
但是VirtualProtect失败,GetLastError()返回487,这意味着访问无效地址。有人对这个问题有线索吗?? 谢谢,这不管用吗

int X = 0xAABBCCDD;

void __declspec(naked) inline(void)
{
      mov eax, [X]
      call [X]
}
如何在运行时对另一个进程执行此操作

  • 创建一个保存程序基址的变量
  • 获取目标RVA(相对虚拟地址)
  • 然后计算实际地址,如PA=RVA+BASE
  • 然后从内联程序集中调用它
  • 你可以像这样得到基址

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

    您必须在调用返回后恢复寄存器的值,因为该值可能会在代码执行过程中的某个地方使用,假设您尝试在调用后修补可能依赖于eax寄存器的现有应用程序。虽然这种方法有它的缺点,但至少它会让任何人知道该怎么做。

    你为什么要这样做?似乎应该有更好的方法来解决让你想这么做的真正问题。另外,您如何确定0xAABBCCDD的实际值?根据地址的来源,可能有一些方法可以“免费”进行替换。(同时,从语法和系统调用猜测这是Win32/MSVC-您可能希望通过标记和/或问题明确指出)。您到底想做什么?您是否试图在目标进程中创建一个钩子,以便它跳转到您的函数?如果是这样,你应该
    VirtualProtect
    覆盖你将要覆盖的内存块来创建钩子,而不是你的函数,你还需要跳出你的codecave(或者
    call
    +
    ret
    或者
    jmp
    到函数末尾的特定地址)。是的,但地址不是静态的。我会在运行时得到它。是的,当然你会在运行时得到它。然后你将执行一行代码,上面写着
    X=在运行时得到的地址