250 lines
8.6 KiB
C++
250 lines
8.6 KiB
C++
#include "pch.h"
|
||
#include "hooks.h"
|
||
|
||
unsigned int hook_addr_ws2_connect = 0;
|
||
unsigned int hook_addr_ws2_send = 0;
|
||
unsigned int hook_addr_ws2_recv = 0;
|
||
unsigned int hook_addr_ws2_WSAconnect = 0;
|
||
unsigned int hook_addr_ws2_WSAsend = 0;
|
||
unsigned int hook_addr_ws2_WSArecv = 0;
|
||
|
||
const unsigned char hook_original_connect_6_bytes[6] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x83 };
|
||
const unsigned char hook_original_send_6_bytes[6] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x83 };
|
||
const unsigned char hook_original_recv_6_bytes[6] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x83 };
|
||
const unsigned char hook_original_WSAconnect_6_bytes[6] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x51 };
|
||
const unsigned char hook_original_WSArecv_6_bytes[6] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x51 };
|
||
const unsigned char hook_original_WSAsend_6_bytes[6] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x51 };
|
||
const unsigned char hook_original_vpex_6_bytes[6] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x56 };
|
||
|
||
unsigned char hook_my_connect_prolog[5] = {0,0,0,0,0};
|
||
|
||
#pragma pack( push, 1 )
|
||
struct hook_jmp_addr
|
||
{
|
||
unsigned char instr_jmp;
|
||
unsigned int jmp_addr;
|
||
};
|
||
#pragma pack( pop )
|
||
|
||
int __stdcall connect_hook( int sock, void *psockaddr, int addrlen );
|
||
int __stdcall call_real_connect( int s, void *a, int l );
|
||
|
||
void Hook_connect( bool write_hook )
|
||
{
|
||
BOOL bRet = FALSE;
|
||
DWORD oldProtect = 0;
|
||
HINSTANCE hws2 = LoadLibraryW( L"ws2_32.dll" );
|
||
if( !hws2 )
|
||
{
|
||
ErrorLogger_LogLastError( "Hook_connect(): cannot load ws2_32.dll!", GetLastError() );
|
||
return;
|
||
}
|
||
|
||
// find ws_32.dll!connect() address
|
||
hook_addr_ws2_connect = (unsigned int)GetProcAddress( hws2, "connect" );
|
||
if( hook_addr_ws2_connect == 0 )
|
||
{
|
||
ErrorLogger_LogLastError( "Hook_connect(): cannot find address of connect()!", GetLastError() );
|
||
return;
|
||
}
|
||
|
||
hook_addr_ws2_send = (unsigned int)GetProcAddress( hws2, "send" );
|
||
hook_addr_ws2_recv = (unsigned int)GetProcAddress( hws2, "recv" );
|
||
hook_addr_ws2_WSAconnect = (unsigned int)GetProcAddress( hws2, "WSAConnect" );
|
||
hook_addr_ws2_WSAsend = (unsigned int)GetProcAddress( hws2, "WSASend" );
|
||
hook_addr_ws2_WSArecv = (unsigned int)GetProcAddress( hws2, "WSARecv" );
|
||
|
||
log_error( LOG_DEBUG, "hooks: ws2_32.dll loaded at 0x%08X, connect() found at 0x%08X\n", hws2, hook_addr_ws2_connect );
|
||
|
||
if( write_hook )
|
||
{
|
||
bRet = VirtualProtectEx( (HANDLE)-1, (LPVOID)hook_addr_ws2_connect, 5, PAGE_EXECUTE_READWRITE, &oldProtect );
|
||
if( !bRet )
|
||
{
|
||
ErrorLogger_LogLastError( "Hook_connect(): VirtualProtectEx() failed!", GetLastError() );
|
||
return;
|
||
}
|
||
}
|
||
|
||
hook_jmp_addr st;
|
||
st.instr_jmp = 0xE9;
|
||
st.jmp_addr = (unsigned int)connect_hook - (unsigned int)hook_addr_ws2_connect - 5;
|
||
// save my prolog bytes
|
||
memcpy( (void *)&hook_my_connect_prolog, (const void *)&st, sizeof(hook_jmp_addr) );
|
||
|
||
if( write_hook )
|
||
{
|
||
unsigned char *src = (unsigned char *)&st;
|
||
unsigned char *dst = (unsigned char *)hook_addr_ws2_connect;
|
||
// write hook code
|
||
dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3]; dst[4] = src[4];
|
||
log_error( LOG_DEBUG, "Hook_connect(): connect hook written\n" );
|
||
}
|
||
|
||
ErrorLogger_FlushLogFile();
|
||
}
|
||
|
||
int __stdcall connect_hook( int sock, void *psockaddr, int addrlen )
|
||
{
|
||
sockaddr_in *psaddr = (sockaddr_in *)psockaddr;
|
||
char ip[16] = {0};
|
||
strcpy( ip, inet_ntoa( psaddr->sin_addr ) );
|
||
int port = psaddr->sin_port;
|
||
int host_port = ntohs( psaddr->sin_port );
|
||
log_error( LOG_DEBUG, "connect_hook( %d, 0x%p (%s:%d), %d );\n", sock, psaddr, ip, host_port, addrlen );
|
||
ErrorLogger_FlushLogFile();
|
||
// check if we should change connect address
|
||
if( host_port == 7777 )
|
||
{
|
||
log_error( LOG_DEBUG, "Intercepting GS connection...\n" );
|
||
int real_ip = psaddr->sin_addr.s_addr;
|
||
//GameListener *gl = GameListener::getInstance();
|
||
//gl->setRealPlayServerInfo( real_ip, port );
|
||
//psaddr->sin_port = htons( (unsigned short)GameListener::LISTEN_PORT );
|
||
psaddr->sin_addr.s_addr = inet_addr( "127.0.0.1" );
|
||
}
|
||
//
|
||
int result = call_real_connect( sock, psockaddr, addrlen );
|
||
log_error( LOG_DEBUG, "connect_hook(): orig. connect returned %d\n", result );
|
||
ErrorLogger_FlushLogFile();
|
||
return result;
|
||
}
|
||
|
||
__declspec(naked) int __stdcall call_real_connect( int s, void *a, int l )
|
||
{
|
||
UNREFERENCED_PARAMETER( s );
|
||
UNREFERENCED_PARAMETER( a );
|
||
UNREFERENCED_PARAMETER( l );
|
||
__asm
|
||
{
|
||
mov edi, edi
|
||
push ebp
|
||
mov ebp, esp
|
||
mov eax, [hook_addr_ws2_connect]
|
||
add eax, 5
|
||
//jmp eax
|
||
//jmp [addr_ws2_connect]
|
||
call eax
|
||
mov esp, ebp
|
||
pop ebp
|
||
ret
|
||
}
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> JMP-<2D><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//
|
||
// old_ptr - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// new_ptr - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// jmp_ptr - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//
|
||
/*void Hook_InterceptCall( DWORD old_ptr, DWORD new_ptr, DWORD *jmp_ptr )
|
||
{
|
||
hook_jmp_addr jump;
|
||
jump.instr_jmp = 0xE9;
|
||
jump.jmp_addr = new_ptr - old_ptr - 5;
|
||
|
||
DWORD oldProtect, prot;
|
||
|
||
GetCurrentProcess();
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
prot = PAGE_EXECUTE_WRITECOPY; // PAGE_READWRITE;
|
||
BOOL vp_res = VirtualProtectEx( (HANDLE)-1, (LPVOID)old_ptr, 5, prot, &oldProtect );
|
||
if( !vp_res )
|
||
{
|
||
DWORD le = GetLastError();
|
||
ErrorLogger_LogLastError( "Hook_InterceptCall(): VirtualProtectEx() failed", le );
|
||
ErrorLogger_FlushLogFile();
|
||
return;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
//WriteProcessMemory(hprocess, (LPVOID)old_ptr, (void*)(&jump), 5, &written);
|
||
unsigned char *po = (unsigned char *)old_ptr;
|
||
unsigned char *pj = (unsigned char *)&jump;
|
||
po[0] = pj[0];
|
||
po[1] = pj[1];
|
||
po[2] = pj[2];
|
||
po[3] = pj[3];
|
||
po[4] = pj[4];
|
||
|
||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
prot = oldProtect;
|
||
VirtualProtectEx( (HANDLE)-1, (LPVOID)old_ptr, 5, prot, &oldProtect );
|
||
|
||
(*jmp_ptr) = old_ptr + 5;
|
||
}*/
|
||
|
||
int hook_compare_bytes( unsigned int addr, const unsigned char *bytes, size_t size )
|
||
{
|
||
unsigned char *pcur = (unsigned char *)addr;
|
||
return memcmp( pcur, bytes, size );
|
||
}
|
||
|
||
void hook_log_bytes_uint( unsigned int addr, size_t sz )
|
||
{
|
||
unsigned char *b = (unsigned char *)addr;
|
||
size_t s = 0;
|
||
while( s < sz )
|
||
{
|
||
log_error_np( LOG_OK, "%02X", (unsigned int)(b[s]) );
|
||
s++;
|
||
if( s < sz ) log_error_np( LOG_OK, " " );
|
||
}
|
||
}
|
||
|
||
bool Hook_validateIntercept_connect()
|
||
{
|
||
int r = hook_compare_bytes( hook_addr_ws2_connect, hook_my_connect_prolog, 5 );
|
||
if( r == 0 )
|
||
{
|
||
log_error( LOG_OK, "Hooks: ws2_32!connect is hooked by us!\n" );
|
||
ErrorLogger_FlushLogFile();
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
log_error( LOG_WARNING, "Hooks: our ws2_32!connect hook is not installed!\n" );
|
||
r = hook_compare_bytes( hook_addr_ws2_connect, hook_original_connect_6_bytes, 6 );
|
||
if( r == 0 ) log_error( LOG_WARNING, "Hooks: ws_32!connect is original\n" );
|
||
else
|
||
{
|
||
log_error( LOG_WARNING, "Hooks: ws_32!connect hook unknown!\n" );
|
||
log_error( LOG_WARNING, "Hooks: bytes: " );
|
||
hook_log_bytes_uint( hook_addr_ws2_connect, 6 );
|
||
log_error_np( LOG_WARNING, "\n" );
|
||
}
|
||
}
|
||
ErrorLogger_FlushLogFile();
|
||
return false;
|
||
}
|
||
|
||
void Hook_dbg_displayInterceptionState()
|
||
{
|
||
int r = 0;
|
||
log_error( LOG_DEBUG, "Hook_dbg_displayInterceptionState(): 0 if original, 1 if hooked\n" );
|
||
// connect
|
||
r = hook_compare_bytes( hook_addr_ws2_connect, hook_original_connect_6_bytes, 6 );
|
||
log_error( LOG_DEBUG, "connect: %d (", r ); hook_log_bytes_uint( hook_addr_ws2_connect, 6 ); log_error_np( LOG_DEBUG, ")\n" );
|
||
// send
|
||
r = hook_compare_bytes( hook_addr_ws2_send, hook_original_send_6_bytes, 6 );
|
||
log_error( LOG_DEBUG, "send: %d (", r ); hook_log_bytes_uint( hook_addr_ws2_send, 6 ); log_error_np( LOG_DEBUG, ")\n" );
|
||
// recv
|
||
r = hook_compare_bytes( hook_addr_ws2_recv, hook_original_recv_6_bytes, 6 );
|
||
log_error( LOG_DEBUG, "recv: %d (", r ); hook_log_bytes_uint( hook_addr_ws2_recv, 6 ); log_error_np( LOG_DEBUG, ")\n" );
|
||
// WSConnect
|
||
r = hook_compare_bytes( hook_addr_ws2_WSAconnect, hook_original_WSAconnect_6_bytes, 6 );
|
||
log_error( LOG_DEBUG, "WSAConnect: %d (", r ); hook_log_bytes_uint( hook_addr_ws2_WSAconnect, 6 ); log_error_np( LOG_DEBUG, ")\n" );
|
||
// WSASend
|
||
r = hook_compare_bytes( hook_addr_ws2_WSAsend, hook_original_WSAsend_6_bytes, 6 );
|
||
log_error( LOG_DEBUG, "WSASend: %d (", r ); hook_log_bytes_uint( hook_addr_ws2_WSAsend, 6 ); log_error_np( LOG_DEBUG, ")\n" );
|
||
// WSARecv
|
||
r = hook_compare_bytes( hook_addr_ws2_WSArecv, hook_original_WSArecv_6_bytes, 6 );
|
||
log_error( LOG_DEBUG, "WSARecv: %d (", r ); hook_log_bytes_uint( hook_addr_ws2_WSArecv, 6 ); log_error_np( LOG_DEBUG, ")\n" );
|
||
//
|
||
log_error_np( LOG_DEBUG, "===================\n" );
|
||
}
|