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?
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.