Files
l2-unlegits/L2Detect_2/hooks/hooks.cpp
2012-02-01 05:25:08 +00:00

250 lines
8.6 KiB
C++
Raw Permalink Blame History

#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" );
}