Executing Function in Other Process Through Dll Injection

Executing Function in Other Process Through Dll Injection

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?

13

1 Answer

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.

Your Answer

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

Chloe Bennett
Author

Chloe Bennett

Chloe Bennett explores the intersection of pop culture, streaming entertainment, digital trends, and contemporary lifestyle. Her weekly commentary reaches thousands of culture enthusiasts.