C++ 转储函数的内存

C++ 转储函数的内存,c++,hex,bytearray,function-pointers,dump,C++,Hex,Bytearray,Function Pointers,Dump,我想将函数内存(void)转储到字节数组(unsingedchar[])。之后,虚拟函数应指向字节数组,并应执行虚拟函数 我要转储的函数: void CallMessageBoxExA() { message = "ManualMessageBoxExA"; caption = "Caption"; pAddr = GetProcAddress(GetModuleHandle(L"User32.dll"), "MessageBoxExA"); __asm //

我想将函数内存(void)转储到字节数组(
unsingedchar[]
)。之后,虚拟函数应指向字节数组,并应执行虚拟函数

我要转储的函数:

void CallMessageBoxExA()
{
    message = "ManualMessageBoxExA";
    caption = "Caption";
    pAddr = GetProcAddress(GetModuleHandle(L"User32.dll"), "MessageBoxExA");

    __asm // Call MessageBoxA
    {
        push dword ptr 0 //--- push languageID: 0
        push dword ptr 0 //--- push style: 0
        push dword ptr caption //--- push DWORD parameter (caption)
        push dword ptr message //--- push DWORD parameter (message)
        push dword ptr 0 //--- push hOwner: 0
        mov eax, pAddr
        call eax //-- call address of the function, which is currently in EAX
    }
}
正在转储内存:

string DumpMemory(void *pAddress, int maxLength)
{
    string result = "";
    const unsigned char * p = reinterpret_cast< const unsigned char *>(pAddress);
    cout << "Memory location: 0x" << hex << (unsigned int)p << endl;
    for (unsigned int i = 0; i < maxLength; i++) {
        string code = "";
        stringstream ss;
        ss << hex << int(p[i]);
        ss >> code;
        result += code;
    }
    return result;
}
这是正确的内存位置,还是我必须遵循JMP

内存位置跳转导致:

CPU Disasm
Address   Hex dump          Command                                  Comments
00286230  /$  55            PUSH EBP                                 ; ASM.CallMessageBoxExA(void)
00286231  |.  8BEC          MOV EBP,ESP
00286233  |.  81EC C0000000 SUB ESP,0C0
00286239  |.  53            PUSH EBX
0028623A  |.  56            PUSH ESI
0028623B  |.  57            PUSH EDI
0028623C  |.  8DBD 40FFFFFF LEA EDI,[EBP-0C0]
00286242  |.  B9 30000000   MOV ECX,30
00286247  |.  B8 CCCCCCCC   MOV EAX,CCCCCCCC
0028624C  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
0028624E  |.  C705 A8562900 MOV DWORD PTR DS:[message],OFFSET 00291D ; ASCII "ManualMessageBoxExA"
00286258  |.  C705 AC562900 MOV DWORD PTR DS:[caption],OFFSET 00291D ; ASCII "Caption"
00286262  |.  8BF4          MOV ESI,ESP
00286264  |.  68 041E2900   PUSH OFFSET 00291E04                     ; ASCII "MessageBoxExA"
00286269  |.  8BFC          MOV EDI,ESP
0028626B  |.  68 D01D2900   PUSH OFFSET 00291DD0                     ; /ModuleName = "User32.dll"
00286270  |.  FF15 00602900 CALL DWORD PTR DS:[<&KERNEL32.GetModuleH ; \KERNEL32.GetModuleHandleW
00286276  |.  3BFC          CMP EDI,ESP
00286278  |.  E8 5BB2FFFF   CALL 002814D8                            ; [_RTC_CheckEsp
0028627D  |.  50            PUSH EAX                                 ; |hModule
0028627E  |.  FF15 04602900 CALL DWORD PTR DS:[<&KERNEL32.GetProcAdd ; \KERNEL32.GetProcAddress
00286284  |.  3BF4          CMP ESI,ESP
00286286  |.  E8 4DB2FFFF   CALL 002814D8                            ; [_RTC_CheckEsp
0028628B  |.  A3 B0562900   MOV DWORD PTR DS:[pAddr],EAX
00286290  |.  6A 00         PUSH 0
00286292  |.  6A 00         PUSH 0
00286294  |.  FF35 AC562900 PUSH DWORD PTR DS:[caption]
0028629A  |.  FF35 A8562900 PUSH DWORD PTR DS:[message]
002862A0  |.  6A 00         PUSH 0
002862A2  |.  A1 B0562900   MOV EAX,DWORD PTR DS:[pAddr]
002862A7  |.  FFD0          CALL EAX
002862A9  |.  5F            POP EDI
002862AA  |.  5E            POP ESI
002862AB  |.  5B            POP EBX
002862AC  |.  81C4 C0000000 ADD ESP,0C0
002862B2  |.  3BEC          CMP EBP,ESP
002862B4  |.  E8 1FB2FFFF   CALL 002814D8                            ; [_RTC_CheckEsp
002862B9  |.  8BE5          MOV ESP,EBP
002862BB  |.  5D            POP EBP
002862BC  \.  C3            RETN
这是使伪函数指向字节数组的正确方法吗

函数在哪一点结束?我是否应该简单地检查不同的返回操作码(C3->return near to caller,CB->return far to caller,…)

附言: 一个简单的(例如,不是非常复杂的)解决方案是首选的,因为我是新的C++。p> 编辑:我想在Windows环境中实现这一点。

您需要将“复制的”函数存储在使用
VirtualAllocEx
分配的内存块上。在现代OSs上,每个页面上都有一个位声明其内容是否可执行。这用于将缓冲区溢出造成的损害降至最低。默认情况下,内存不可执行。如果将
VirtualAllocEx
PAGE\u EXECUTE\u READWRITE
保护模式一起使用,则可以写入内存块,然后从内存块执行


至于你的问题“你什么时候到达函数的末尾”,那实际上是不可回答的。您可以查找一些常见的模式,但x86缺少任何识别函数“结束”的方法。

看起来您需要遵循跳转。当您跟随跳转时,您看到的代码与上面编译的代码相匹配

此外,DumpMemory正在使用pAddressIn的地址。正在向函数传递一个名为pAddress的变量。这可能是一个输入错误,或者您正在引用在其他地方声明的变量。我猜你是想用围裙


您分配的内存可能需要特殊权限才能运行。按原样,使用原始函数数据分配的内存将标记为“数据”。“数据执行预防”可能会停止此操作,具体取决于您的环境。

如果您需要特定于平台的建议(它看起来像Windows),然后指定平台。我建议用更复杂的东西来开发C++技巧。你要做的是一个非常强大的事情,它被世界上少数开发者所使用(大部分是为语言编写JIT运行时)。作为一个参考点,在我自己的圈子里,作为一个C++开发者10年来,我是唯一一个我个人知道谁曾经尝试过它。我很好奇(我相信其他人也是)关于你正在做什么。你想把东西钩起来吗?如果有很多商业和免费的工具来做这类事情的话,实际上,我并不是在试图完成任何事情。我是在考虑自我修改代码时想到这个的。这个问题比预期的要困难得多,我不能用我当前的C++能力来解决它。我不记得x86在其操作码上是否有任何对齐要求,但如果有,您必须确保它们得到了考虑。然后,由于代码移动,您还必须应用修正。检测跳转表并将其修复。这很快就变成了停顿问题。谢谢,这是个打字错误。
CPU Disasm
Address   Hex dump          Command                                  Comments
00286230  /$  55            PUSH EBP                                 ; ASM.CallMessageBoxExA(void)
00286231  |.  8BEC          MOV EBP,ESP
00286233  |.  81EC C0000000 SUB ESP,0C0
00286239  |.  53            PUSH EBX
0028623A  |.  56            PUSH ESI
0028623B  |.  57            PUSH EDI
0028623C  |.  8DBD 40FFFFFF LEA EDI,[EBP-0C0]
00286242  |.  B9 30000000   MOV ECX,30
00286247  |.  B8 CCCCCCCC   MOV EAX,CCCCCCCC
0028624C  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
0028624E  |.  C705 A8562900 MOV DWORD PTR DS:[message],OFFSET 00291D ; ASCII "ManualMessageBoxExA"
00286258  |.  C705 AC562900 MOV DWORD PTR DS:[caption],OFFSET 00291D ; ASCII "Caption"
00286262  |.  8BF4          MOV ESI,ESP
00286264  |.  68 041E2900   PUSH OFFSET 00291E04                     ; ASCII "MessageBoxExA"
00286269  |.  8BFC          MOV EDI,ESP
0028626B  |.  68 D01D2900   PUSH OFFSET 00291DD0                     ; /ModuleName = "User32.dll"
00286270  |.  FF15 00602900 CALL DWORD PTR DS:[<&KERNEL32.GetModuleH ; \KERNEL32.GetModuleHandleW
00286276  |.  3BFC          CMP EDI,ESP
00286278  |.  E8 5BB2FFFF   CALL 002814D8                            ; [_RTC_CheckEsp
0028627D  |.  50            PUSH EAX                                 ; |hModule
0028627E  |.  FF15 04602900 CALL DWORD PTR DS:[<&KERNEL32.GetProcAdd ; \KERNEL32.GetProcAddress
00286284  |.  3BF4          CMP ESI,ESP
00286286  |.  E8 4DB2FFFF   CALL 002814D8                            ; [_RTC_CheckEsp
0028628B  |.  A3 B0562900   MOV DWORD PTR DS:[pAddr],EAX
00286290  |.  6A 00         PUSH 0
00286292  |.  6A 00         PUSH 0
00286294  |.  FF35 AC562900 PUSH DWORD PTR DS:[caption]
0028629A  |.  FF35 A8562900 PUSH DWORD PTR DS:[message]
002862A0  |.  6A 00         PUSH 0
002862A2  |.  A1 B0562900   MOV EAX,DWORD PTR DS:[pAddr]
002862A7  |.  FFD0          CALL EAX
002862A9  |.  5F            POP EDI
002862AA  |.  5E            POP ESI
002862AB  |.  5B            POP EBX
002862AC  |.  81C4 C0000000 ADD ESP,0C0
002862B2  |.  3BEC          CMP EBP,ESP
002862B4  |.  E8 1FB2FFFF   CALL 002814D8                            ; [_RTC_CheckEsp
002862B9  |.  8BE5          MOV ESP,EBP
002862BB  |.  5D            POP EBP
002862BC  \.  C3            RETN
void(*func_ptr)();
func_ptr = (void(*)()) &foo[0]; // make function point to foo[]
(*func_ptr)(); // Call the function