I am messing around with some dll injection/code injection. Therefore I made a little program which does nothing, but it has a function in it, which never get called and I wrote another program which injects code into the first which should call that function.

Here is my program which injects the code (only relevant part is shown):

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) {
        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);
    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);

The "funcAdr" is the address I want to call in the other program, it is right as I print it out and opened it up in 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
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                                     ; |

The function which I want to call from my second program simply receives a const char* and prints it.

void print(const char* string) {

If I run the above code I receive following error: enter image description here

If I however change my print function in the first application so that it doesn't receive any argument and I call "funcAdr" directly through .createThread it works without problems though.

Can you guys maybe help me and tell me where I have something wrong?

  • One issue I spotted is that remoteCave points to the end of the allocated buffer, instead of it's begining.
    – NirIzr
    Commented Jan 2, 2017 at 17:46

1 Answer 1


Since I cannot add a comment I will post it here:

@NirIzr : Well it doesn't actually point to the end, does it? It should point to the memory where the actual byte array starts. Note that I first write the testString into the memory of my second program then the bytecode. Then I do remoteCave = (LPVOID)((DWORD)remoteString + stringlen) which should then be the start of the bytecode.

EDIT: Okey I found the answer...I had an error in my byte buffer. I needed to change the 0x88 from my second line to 0xB8.

  • If this is an answer you feel comfortable with you should mark it as Accepted Answer by clicking the V button below the up/down vote buttons.
    – NirIzr
    Commented Jan 3, 2017 at 10:18
  • Yeah I thought about that already, but I cannot seem to find a button to accept the answer? Can maybe a mod or someone mark it? Commented Jan 3, 2017 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.