Executing function in other process through dll injection

812 Views Asked by At

I'm trying to execute a function in a VB6 app, I already know the instruction address and the format of the original code but when I execute it the app crashes. It's probably wrong the way I'm executing it or there is something else missing.

This is the "original" function code:

Public Sub WriteLeftClick(ByVal x As Byte, ByVal y As Byte)
    
    On Error GoTo WriteLeftClick_Err
    
    With outgoingData
        Call .WriteByte(ClientPacketID.LeftClick)
        
        Call .WriteByte(x)
        Call .WriteByte(y)

    End With

    
    Exit Sub

WriteLeftClick_Err:
    Call RegistrarError(Err.number, Err.Description, "Protocol.WriteLeftClick", Erl)
    Resume Next
    
End Sub

This is the decompiled version from the exe:

Private Sub Proc_98_29_793220(arg_C) '793220
  loc_00793220: push ebp
  loc_00793221: mov ebp, esp
  loc_00793223: sub esp, 00000018h
  loc_00793226: push 0042B2B6h ; __vbaExceptHandler
  loc_0079322B: mov eax, fs:[00000000h]
  loc_00793231: push eax
  loc_00793232: mov fs:[00000000h], esp
  loc_00793239: sub esp, 00000034h
  loc_0079323C: push ebx
  loc_0079323D: push esi
  loc_0079323E: push edi
  loc_0079323F: mov var_18, esp
  loc_00793242: mov var_14, 00425FD8h
  loc_00793249: xor edi, edi
  loc_0079324B: mov var_10, edi
  loc_0079324E: mov var_C, edi
  loc_00793251: mov var_24, edi
  loc_00793254: mov var_28, edi
  loc_00793257: mov var_2C, edi
  loc_0079325A: mov var_30, edi
  loc_0079325D: mov var_4, 00000001h
  loc_00793264: mov var_4, 00000002h
  loc_0079326B: push 00000001h
  loc_0079326D: call [00401134h] ; __vbaOnError
  loc_00793273: mov var_4, 00000003h
  loc_0079327A: mov eax, [007CE9C4h]
  loc_0079327F: mov esi, [eax]
  loc_00793281: mov ecx, 00000016h
  loc_00793286: call [00401204h] ; __vbaI2I4
  loc_0079328C: push eax
  loc_0079328D: mov ecx, [007CE9C4h]
  loc_00793293: push ecx
  loc_00793294: call [esi+00000030h]
  loc_00793297: fnclex
  loc_00793299: cmp eax, edi
  loc_0079329B: jge 007932B6h
  loc_0079329D: push 00000030h
  loc_0079329F: push 00484EA0h
  loc_007932A4: mov edx, [007CE9C4h]
  loc_007932AA: push edx
  loc_007932AB: push eax
  loc_007932AC: mov esi, [004010E0h] ; __vbaHresultCheckObj
  loc_007932B2: call __vbaHresultCheckObj
  loc_007932B4: jmp 007932BCh
  loc_007932B6: mov esi, [004010E0h] ; __vbaHresultCheckObj
  loc_007932BC: mov var_4, 00000004h
  loc_007932C3: mov eax, [007CE9C4h]
  loc_007932C8: mov ecx, [eax]
  loc_007932CA: mov edx, arg_8
  loc_007932CD: push edx
  loc_007932CE: push eax
  loc_007932CF: call [ecx+0000002Ch]
  loc_007932D2: fnclex
  loc_007932D4: cmp eax, edi
  loc_007932D6: jge 007932E9h
  loc_007932D8: push 0000002Ch
  loc_007932DA: push 00484EA0h
  loc_007932DF: mov ecx, [007CE9C4h]
  loc_007932E5: push ecx
  loc_007932E6: push eax
  loc_007932E7: call __vbaHresultCheckObj
  loc_007932E9: mov var_4, 00000005h
  loc_007932F0: mov eax, [007CE9C4h]
  loc_007932F5: mov edx, [eax]
  loc_007932F7: mov ecx, arg_C
  loc_007932FA: push ecx
  loc_007932FB: push eax
  loc_007932FC: call [edx+0000002Ch]
  loc_007932FF: fnclex
  loc_00793301: cmp eax, edi
  loc_00793303: jge 00793316h
  loc_00793305: push 0000002Ch
  loc_00793307: push 00484EA0h
  loc_0079330C: mov edx, [007CE9C4h]
  loc_00793312: push edx
  loc_00793313: push eax
  loc_00793314: call __vbaHresultCheckObj
  loc_00793316: mov var_4, 00000006h
  loc_0079331D: mov eax, [007CE0ACh]
  loc_00793322: add eax, 00000001h
  loc_00793325: jo 007934A1h
  loc_0079332B: mov [007CE0ACh], eax
  loc_00793330: mov var_4, 00000007h
  loc_00793337: mov ecx, [007CE9C4h]
  loc_0079333D: mov edx, [ecx]
  loc_0079333F: push eax
  loc_00793340: push ecx
  loc_00793341: call [edx+00000034h]
  loc_00793344: fnclex
  loc_00793346: cmp eax, edi
  loc_00793348: jge 0079335Bh
  loc_0079334A: push 00000034h
  loc_0079334C: push 00484EA0h
  loc_00793351: mov ecx, [007CE9C4h]
  loc_00793357: push ecx
  loc_00793358: push eax
  loc_00793359: call __vbaHresultCheckObj
  loc_0079335B: mov var_4, 00000008h
  loc_00793362: mov edx, [007CE9C4h]
  loc_00793368: push edx
  loc_00793369: lea eax, var_28
  loc_0079336C: push eax
  loc_0079336D: call [00401148h] ; __vbaObjSetAddref
  loc_00793373: push eax
  loc_00793374: call 007B8560h
  loc_00793379: lea ecx, var_28
  loc_0079337C: call [00401438h] ; __vbaFreeObj
  loc_00793382: call [00401118h] ; __vbaExitProc
  loc_00793388: push 0079348Eh
  loc_0079338D: jmp 0079348Dh
  loc_00793392: mov var_4, 00000009h
  loc_00793399: mov eax, [007CE9C4h]
  loc_0079339E: mov ecx, [eax]
  loc_007933A0: push eax
  loc_007933A1: call [ecx+0000000Ch]
  loc_007933A4: fnclex
  loc_007933A6: test eax, eax
  loc_007933A8: jge 007933BFh
  loc_007933AA: push 0000000Ch
  loc_007933AC: push 00484EA0h
  loc_007933B1: mov edx, [007CE9C4h]
  loc_007933B7: push edx
  loc_007933B8: push eax
  loc_007933B9: call [004010E0h] ; __vbaHresultCheckObj
  loc_007933BF: mov var_4, 0000000Ah
  loc_007933C6: mov edi, [00401370h] ; rtcErrObj
  loc_007933CC: call edi
  loc_007933CE: push eax
  loc_007933CF: lea eax, var_28
  loc_007933D2: push eax
  loc_007933D3: mov ebx, [00401138h] ; __vbaObjSet
  loc_007933D9: call ebx
  loc_007933DB: mov esi, eax
  loc_007933DD: mov ecx, [esi]
  loc_007933DF: lea edx, var_30
  loc_007933E2: push edx
  loc_007933E3: push esi
  loc_007933E4: call [ecx+0000001Ch]
  loc_007933E7: fnclex
  loc_007933E9: test eax, eax
  loc_007933EB: jge 007933FCh
  loc_007933ED: push 0000001Ch
  loc_007933EF: push 00455DF4h
  loc_007933F4: push esi
  loc_007933F5: push eax
  loc_007933F6: call [004010E0h] ; __vbaHresultCheckObj
  loc_007933FC: call edi
  loc_007933FE: push eax
  loc_007933FF: lea eax, var_2C
  loc_00793402: push eax
  loc_00793403: call ebx
  loc_00793405: mov esi, eax
  loc_00793407: mov ecx, [esi]
  loc_00793409: lea edx, var_24
  loc_0079340C: push edx
  loc_0079340D: push esi
  loc_0079340E: call [ecx+0000002Ch]
  loc_00793411: fnclex
  loc_00793413: test eax, eax
  loc_00793415: jge 00793426h
  loc_00793417: push 0000002Ch
  loc_00793419: push 00455DF4h
  loc_0079341E: push esi
  loc_0079341F: push eax
  loc_00793420: call [004010E0h] ; __vbaHresultCheckObj
  loc_00793426: call [004012A0h] ; rtcGetErl
  loc_0079342C: mov ecx, eax
  loc_0079342E: call [00401204h] ; __vbaI2I4
  loc_00793434: push eax
  loc_00793435: push 00486528h ; "Argentum20.Protocol_Writes.WriteLeftClick"
  loc_0079343A: mov eax, var_24
  loc_0079343D: push eax
  loc_0079343E: mov ecx, var_30
  loc_00793441: push ecx
  loc_00793442: call 0066E230h
  loc_00793447: lea ecx, var_24
  loc_0079344A: call [00401434h] ; __vbaFreeStr
  loc_00793450: lea edx, var_2C
  loc_00793453: push edx
  loc_00793454: lea eax, var_28
  loc_00793457: push eax
  loc_00793458: push 00000002h
  loc_0079345A: call [00401098h] ; __vbaFreeObjList
  loc_00793460: add esp, 0000000Ch
  loc_00793463: call [00401118h] ; __vbaExitProc
  loc_00793469: push 0079348Eh
  loc_0079346E: jmp 0079348Dh
  loc_00793470: lea ecx, var_24
  loc_00793473: call [00401434h] ; __vbaFreeStr
  loc_00793479: lea ecx, var_2C
  loc_0079347C: push ecx
  loc_0079347D: lea edx, var_28
  loc_00793480: push edx
  loc_00793481: push 00000002h
  loc_00793483: call [00401098h] ; __vbaFreeObjList
  loc_00793489: add esp, 0000000Ch
  loc_0079348C: ret
  loc_0079348D: ret
  loc_0079348E: mov ecx, var_20
  loc_00793491: mov fs:[00000000h], ecx
  loc_00793498: pop edi
  loc_00793499: pop esi
  loc_0079349A: pop ebx
  loc_0079349B: mov esp, ebp
  loc_0079349D: pop ebp
  loc_0079349E: retn 0008h
End Sub

And this is the code I'm using for my DLL:

#include <windows.h>
#include "Memory.h"
#include <sstream>
typedef void(__stdcall* myFunc)(byte, byte);
myFunc func;

DWORD WINAPI MainThread(LPVOID param) {
    //func = (myFunc)(0x793220);

    //typedef int func(byte x, byte y); // Creating an int function alias, replace (void) with your parameters

    uintptr_t modBase = (uintptr_t)GetModuleHandle(NULL);

    //func* f = (func*)reinterpret_cast<void*>(modBase + 0x393220);

    func = (myFunc)(modBase + 0x393220);

    HANDLE hPipe;
    char buffer[1024];
    DWORD dwRead;


    
    /*int value = modBase + 0x393220;
    std::stringstream stream;
    stream << "Value is " << value;

    MessageBoxA(NULL, stream.str().c_str(), "Test Msg", MB_OK | MB_ICONINFORMATION);*/


    hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Pipe"),
        PIPE_ACCESS_DUPLEX,
        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,   // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
        1,
        1024 * 16,
        1024 * 16,
        NMPWAIT_USE_DEFAULT_WAIT,
        NULL);
    while (hPipe != INVALID_HANDLE_VALUE)
    {
        if (ConnectNamedPipe(hPipe, NULL) != FALSE)   // wait for someone to connect to the pipe
        {
            while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE)
            {
                /* add terminating zero */
                buffer[dwRead] = '\0';

                /* do something with data in buffer */
                //printf("%s", buffer);
                func(55,55);

                MessageBoxA(NULL, buffer, "Test Msg", MB_OK | MB_ICONINFORMATION);
            }
        }

        DisconnectNamedPipe(hPipe);
    }

    FreeLibraryAndExitThread((HMODULE)param, 0);
    return 0;
}

BOOL APIENTRY DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        MessageBoxA(NULL, "Hello From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);

        CreateThread(NULL, NULL, MainThread, hInstDLL, NULL, NULL);


        break;

    case DLL_THREAD_ATTACH:
        MessageBoxA(NULL, "Hello From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);
        break;

    case DLL_THREAD_DETACH:
        MessageBoxA(NULL, "Hello Again From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);
        break;

    case DLL_PROCESS_DETACH:
        MessageBoxA(NULL, "Hello Again From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);
        break;
    }

    return TRUE;
}

So basically when it receives a message from the Pipe it should execute that function.

func* f = (func*)reinterpret_cast<void*>(0x793220);
f(55,55);

But when I execute it, the app crashes.

Any ideas?

1

There are 1 best solutions below

0
On

Finally I got it working.

But I had to change completly the perspective.

Instead of injecting a C++ dll into the game, I created an injector that launches the game, creates a VB object using "CreateVBObjectInThread" and with that using a placeholder for the function and the real address of the pointer I could execute the function in the game and avoid the crash due to the "On error". Both DLLs now are developed in VB6 as well.