无法使用 CreateRemoteThread 调用函数

逆向工程 dll注入 字节码 外壳代码 注射
2021-06-27 23:42:00

我正在处理一些 dll 注入/代码注入。因此我制作了一个什么都不做的小程序,但它有一个函数,它永远不会被调用,我编写了另一个程序,将代码注入第一个应该调用该函数的程序。

这是我注入代码的程序(仅显示相关部分):

BYTE codeCave[15] = {
        0xFF, 0x74, 0x24, 0x04, //PUSH DWORD PTR:[ESP+04]
        0x88, 0x00, 0x00, 0x00, 0x00,   //MOV EAX, 0x0  (0x0 is the address of the function)
        0xFF, 0xD0, //CALL EAX
        0x83, 0xC4, 0x04,   //ADD ESP, 0x04
        0xC3    //RETN
    };

    DWORD offset = 0x00014D80;
    DWORD funcAdr = offset + myLib.getBaseAdress();
    memcpy(&codeCave[5], &funcAdr, 4);

    char testString[] = "I called the function.";

    int stringlen = strlen(testString) + 1; //+1 for \0 at the end
    int caveLen = sizeof(codeCave);
    int fullLen = caveLen + stringlen;

    LPVOID remoteString = myLib.allocateMemoryInProcess(fullLen);
    if (remoteString == NULL) {
        printf("FAILED");
        return 1;
    }
    LPVOID remoteCave = (LPVOID)((DWORD)remoteString + stringlen);
    myLib.writeMemory((LPVOID)remoteString, testString);
    myLib.writeMemory((LPVOID)remoteCave, codeCave);
    printf("%x\n", funcAdr);
    printf("%x\n", remoteCave);
    getchar();
    myLib.createThread((LPTHREAD_START_ROUTINE)remoteCave, remoteString);

和:

LPVOID allocateMemoryInProcess(int length) {
    return VirtualAllocEx(gameHandle, 0, length, MEM_COMMIT, PAGE_EXECUTE);
}

和:

void createThread(LPTHREAD_START_ROUTINE startAdr, LPVOID arg) {
    HANDLE thread = CreateRemoteThread(gameHandle, NULL, NULL, startAdr, arg, NULL, NULL);
    WaitForSingleObject(thread, INFINITE);
    CloseHandle(thread);
}

“funcAdr”是我想在另一个程序中调用的地址,当我打印出来并在ollydbg中打开它时是正确的:

CPU Disasm
Address   Hex dump          Command                                  Comments
00034D80  /$  55            PUSH EBP                                 ; ListTest.print(string)
00034D81  |.  8BEC          MOV EBP,ESP
00034D83  |.  81EC C0000000 SUB ESP,0C0
00034D89  |.  53            PUSH EBX
00034D8A  |.  56            PUSH ESI
00034D8B  |.  57            PUSH EDI
00034D8C  |.  8DBD 40FFFFFF LEA EDI,[EBP-0C0]
00034D92  |?  B9 30000000   MOV ECX,30
00034D97  |?  B8 CCCCCCCC   MOV EAX,CCCCCCCC
00034D9C  |?  F3:AB         REP STOS DWORD PTR ES:[EDI]
00034D9E  |?  68 28BC0300   PUSH OFFSET 0003BC28                     ; ASCII "TROLOLOLO"
00034DA3  |.  E8 61C8FFFF   CALL 00031609
00034DA8  |?  83C4 04       ADD ESP,4
00034DAB  |?  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
00034DAE  |?  50            PUSH EAX
00034DAF  |?  E8 55C8FFFF   CALL 00031609
00034DB4  |.  83C4 04       ADD ESP,4
00034DB7  |?  5F            POP EDI
00034DB8  |?  5E            POP ESI
00034DB9  |?  5B            POP EBX
00034DBA  |.  81C4 C0000000 ADD ESP,0C0
00034DC0  |?  3BEC          CMP EBP,ESP
00034DC2  |?  E8 5AC4FFFF   CALL 00031221
00034DC7  |.  8BE5          MOV ESP,EBP                              ; |
00034DC9  |?  5D            POP EBP                                  ; |
00034DCA  |?  C3            RETN                                     ; |
00034DCB  |?  CC            INT3                                     ; |
00034DCC  |?  CC            INT3                                     ; |

我想从我的第二个程序调用的函数只是接收一个 const char* 并打印它。

void print(const char* string) {
    printf("TROLOLOLO");
    printf(string);
}

如果我运行上面的代码,我会收到以下错误: 在此处输入图片说明

但是,如果我在第一个应用程序中更改我的打印函数,使其不接收任何参数,并且我直接通过 .createThread 调用“funcAdr”,但它可以正常工作。

你们能不能帮我一下,告诉我哪里出了问题?

1个回答

由于我无法添加评论,我将在此处发布:

@NirIzr :它实际上并没有指向结尾,是吗?它应该指向实际字节数组开始的内存。请注意,我首先将 testString 写入第二个程序的内存,然后再写入字节码。然后我做 remoteCave = (LPVOID)((DWORD)remoteString + stringlen) 这应该是字节码的开始。

编辑:好吧,我找到了答案……我的字节缓冲区出错了。我需要将第二行的 0x88 更改为 0xB8。