Here is the code:
Code:
#include <windows.h>
// you must include your source sdk header here!
//I used "cdll_int.h"
void ConsoleThread();
typedef void * (*CreateInterfaceDef)( char *, int );
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ConsoleThread, 0, 0, 0);
break;
}
return TRUE;
}
void ConsoleThread()
{
DWORD OP;
HMODULE hEngineDll = 0;
HANDLE hOut, hIn;
char buf[128];
int r;
IVEngineClient *IEngine;
Beep( 440, 70 );
while( !(hEngineDll = GetModuleHandle( "Engine.dll" )) ) Sleep( 1000 );
while( !GetModuleHandle( "Client.dll" ) ) Sleep( 1000 );
if( !AllocConsole() ) return;
hOut = GetStdHandle( STD_OUTPUT_HANDLE );
hIn = GetStdHandle( STD_INPUT_HANDLE );
WriteConsole( hOut, "Your Console!\n", strlen( "Your Console!\n" ), (LPDWORD)&r, 0);
WriteConsole( hOut, "Getting Interface...\n", strlen( "Getting Interface...\n" ), (LPDWORD)&r, 0);
CreateInterfaceDef EngFac = (CreateInterfaceDef) GetProcAddress(hEngineDll, "CreateInterface");
IEngine = (IVEngineClient *) EngFac( "VEngineClient012", 0);
WriteConsole( hOut, "Patching...\n", strlen( "Patching...\n" ), (LPDWORD)&r, 0);
unsigned short *Addr = (unsigned short *) 0x4204b466;
VirtualProtect( (LPVOID) Addr, 4, PAGE_EXECUTE_READWRITE, &OP );
*Addr = 0x9090;
while(1)
{
memset(buf, 0, 128 );
ReadConsole( hIn, buf, 127, (LPDWORD)&r, 0);
IEngine->ClientCmd( buf );
}
}
You might be thinking "there is nothing new in this code, it's like hell_demon's code but when I tried use his code Vindictus Crashes. Why?"
The magic happens here:
unsigned short *Addr = (unsigned short *) 0x4204b466;
VirtualProtect( (LPVOID) Addr, 4, PAGE_EXECUTE_READWRITE, &OP );
*Addr = 0x9090;
But what this code does?
This code just NOPs the "jnz CRASHCODE"
Code inside Engine.dll IVEngineClient::ClientiCmd (before):
mov eax,fs:[18h]
mov eax, ds:[eax+24h]
mov [ebp-4], eax
mov eax, [428616a8]
cmp eax, [ebp-4]
jnz CRASHCODE // our branch to crash code
JMP GOODCODE
Code inside Engine.dll IVEngineClient::ClientiCmd (after):
mov eax,fs:[18h]
mov eax, ds:[eax+24h]
mov [ebp-4], eax
mov eax, [428616a8]
cmp eax, [ebp-4]
nop //do nothing
nop //do nothing
JMP GOODCODE
Then now you can call ClientCmd without crashing Vindictus.
If you don't have source sdk change:
IVEngineClient *IEngine; -> DWORD IEngine;
IEngine = (IVEngineClient *) EngFac( "VEngineClient012", 0); -> IEngine = ( DWORD ) EngFac( "VEngineClient012", 0);
and
IEngine->ClientCmd( buf );
for
_asm
{
push eax
push ecx
mov ecx, IEngine
mov eax, [ecx]
mov eax, [eax + 0x1C]
push buf
call eax
pop ecx
pop eax
}
This code was tested only on NA Version, (I don't have EU Client).
It may work on EU if you search and change the address ( unsigned short *Addr = (unsigned short *) 0x4204b466;) from EU engine.dll or if that address be the same for both Engine.dll.