📄 function.cpp
字号:
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : function.cpp //
// Description: KFuncTable class //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define NOCRYPT
#include <windows.h>
#include <string.h>
#include <assert.h>
#include "..\..\include\Decoder.h"
#include "..\..\include\atom.h"
#include "Function.h"
#include "Format.h"
#include "Report.h"
#include "Diver.h"
#include "..\Patcher\Patcher.h"
bool HackCopy(void * pDest, void * pSource, DWORD nSize);
/*
{
#ifdef WRITE_PROCESS
static HANDLE hCurProcess = 0;
DWORD dwWritten;
bool rslt;
if ( hCurProcess==0 )
hCurProcess = GetCurrentProcess();
rslt = WriteProcessMemory(hCurProcess, pDest, pSource, nSize, & dwWritten) != 0;
return rslt && (dwWritten==nSize);
#else
__try
{
memcpy(pDest, pSource, nSize);
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
__try
{
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(pDest, & mbi, sizeof(mbi));
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, & mbi.Protect);
memcpy(pDest, pSource, nSize);
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
return false;
}
}
return true;
#endif
}
*/
FARPROC KFuncTable::GetProcAddr(int funcid)
{
int mod = m_func[funcid].f_module;
switch ( m_func[funcid].f_kind )
{
case FUNC_COMMETHOD:
{
const unsigned * pFunc = (const unsigned *) VTable(mod);
assert(pFunc);
return (FARPROC) pFunc[m_func[funcid].f_methodid];
}
break;
case FUNC_WIN32API:
{
HINSTANCE hModule = ModHandle(m_func[funcid].f_module);
assert(hModule);
FARPROC fp = GetProcAddress(hModule, GetFuncName(funcid));
// assert(fp);
if ( fp==NULL )
{
char temp[128];
wsprintf(temp, "Not found module %d at %x, func %s at %x",
m_func[funcid].f_module, hModule, GetFuncName(funcid), fp);
Send(M_TEXT, 0, 0, temp);
}
return fp;
}
case FUNC_SYSCALL:
return m_func[funcid].f_oldaddress;
default:
assert(false);
}
return NULL;
}
int KFuncTable::DefPara(const char * paratype, const char *name)
{
if ( m_parano > MAX_PARA )
{
assert(0);
return -1;
}
if ( (m_lastmodule<0) || (m_lastfunc<0) )
return -1;
m_func[m_lastfunc].f_parano ++;
int len = strlen(paratype);
const char * pSpace = strchr(paratype, ' ');
if ( pSpace )
len = (int) pSpace - (int) paratype;
char temp[64];
assert(64>len);
memcpy(temp, paratype, len);
temp[len] = 0;
m_para[m_parano].p_type = AddAtom(temp);
m_para[m_parano].p_name = AddAtom(name);
return m_parano ++;
}
void KFunction::InitStub(int index, FARPROC newaddress)
{
f_stub[0] = 0x68; // push
*((int *)(f_stub+1)) = index; // index
f_stub[5] = 0xE9; // jmp relative
*((unsigned *)(f_stub+6)) = (unsigned) newaddress - (unsigned) (f_stub+10);
}
#define field_this 0
int KFuncTable::AddFunc(unsigned ord, const char *name, unsigned opt,
int parano,
const char * paratype,
int kind,
const void * oldaddr)
{
if ( (m_funcno > MAX_FUNC) || (m_lastmodule<0) )
{
assert(0);
m_lastfunc = -1;
return -1;
}
m_lastfunc = m_funcno ++;
m_func[m_lastfunc].f_kind = kind;
m_func[m_lastfunc].f_module = m_lastmodule;
m_func[m_lastfunc].InitStub(m_lastfunc, (FARPROC) ProxyProlog);
m_func[m_lastfunc].f_methodid = ord;
m_func[m_lastfunc].f_name = AddAtom(name);
m_func[m_lastfunc].f_parano = 0;
m_func[m_lastfunc].f_firstpara = m_parano;
m_func[m_lastfunc].f_class = opt;
m_func[m_lastfunc].f_hooked = FALSE;
m_func[m_lastfunc].f_totaltime = 0;
m_func[m_lastfunc].f_callno = 0;
for (int i=0; i<parano; i++)
{
DefPara(paratype);
if ( i < (parano-1) )
{
paratype = strchr(paratype, ' ') + 1;
if ( paratype==(const char *) 1 )
{
assert(false);
paratype = NULL;
}
}
}
if ( oldaddr )
m_func[m_lastfunc].f_oldaddress = (FARPROC) oldaddr;
else
m_func[m_lastfunc].f_oldaddress = GetProcAddr(m_lastfunc);
return m_lastfunc;
}
void KFuncTable::Initialize(void)
{
KModuleTable::Initialize();
m_funcno = 0;
m_parano = 0;
Initialize_API();
}
FARPROC KFuncTable::LookupInterceptedAPI(FARPROC address, int & id)
{
for (int i=0; i<m_funcno; i++)
{
if ( (m_func[i].f_kind==FUNC_WIN32API) && !m_func[i].f_hooked )
if ( m_func[i].f_oldaddress == address )
{
id = i;
return m_func[i].f_newaddress();
}
}
/*
// If it's Chicago, and the app is being debugged (as this app is)
// the loader doesn't fix up the calls to point directly at the
// DLL's entry point. Instead, the address in the .idata section
// points to a PUSH xxxxxxxx / JMP yyyyyyyy stub. The address in
// xxxxxxxx points to another stub: PUSH aaaaaaaa / JMP bbbbbbbb.
// The address in aaaaaaaa is the real address of the function in the
// DLL. This ugly code verifies we're looking at this stub setup,
// and if so, grabs the real DLL entry point, and scans through
// the InterceptedAPIArray list of addresses again.
// ***WARNING*** ***WARNING*** ***WARNING*** ***WARNING***
// This code is subject to change, and is current only as of 9/94.
if ((GetVersion() & 0xC0000000) == 0xC0000000)
{
if ( (unsigned) address < 0x80000000 ) // Only shared, system DLLs
return NULL; // have stubs
if ( IsBadReadPtr(address, 9) || (*(PBYTE)address != 0x68)
|| (*((PBYTE)address+5) != 0xE9) )
return NULL;
FARPROC stubAddress = * (FARPROC *)((PBYTE) address+1);
for (int i=0; i<m_funcno; i++ )
if (!m_func[i].f_isvfunc)
{
FARPROC lunacy = m_func[i].f_oldaddress;
if ( lunacy == stubAddress )
return m_func[i].f_newaddress();
if ( !IsBadReadPtr(lunacy, 9) &&
(*(PBYTE)lunacy == 0x68) &&
(*((PBYTE)lunacy+5) == 0xE9) )
{
lunacy = * (FARPROC *)( ((PBYTE)lunacy)+1);
if ( lunacy == stubAddress )
return m_func[i].f_newaddress();
}
}
}
*/
return NULL;
}
_declspec(naked) void SysCall_00(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret
}
_declspec(naked) void SysCall_04(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 4
}
_declspec(naked) void SysCall_08(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 8
}
_declspec(naked) void SysCall_0C(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x0c
}
_declspec(naked) void SysCall_10(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x10
}
_declspec(naked) void SysCall_14(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x14
}
_declspec(naked) void SysCall_18(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x18
}
_declspec(naked) void SysCall_1C(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x1C
}
_declspec(naked) void SysCall_20(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x20
}
_declspec(naked) void SysCall_24(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x24
}
_declspec(naked) void SysCall_28(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x28
}
_declspec(naked) void SysCall_2C(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x2C
}
_declspec(naked) void SysCall_30(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x30
}
_declspec(naked) void SysCall_34(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x34
}
_declspec(naked) void SysCall_38(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x38
}
_declspec(naked) void SysCall_3C(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x3C
}
_declspec(naked) void SysCall_40(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x40
}
_declspec(naked) void SysCall_44(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x44
}
_declspec(naked) void SysCall_48(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x48
}
_declspec(naked) void SysCall_4C(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x4C
}
_declspec(naked) void SysCall_50(void)
{
__asm lea edx, [esp+4]
__asm int 0x2E
__asm ret 0x50
}
const void * SysCall_Stub [] =
{
SysCall_00,
SysCall_04,
SysCall_08,
SysCall_0C,
SysCall_10,
SysCall_14,
SysCall_18,
SysCall_1C,
SysCall_20,
SysCall_24,
SysCall_28,
SysCall_2C,
SysCall_30,
SysCall_34,
SysCall_38,
SysCall_3C,
SysCall_40,
SysCall_44,
SysCall_48,
SysCall_4C,
SysCall_50
};
int KFuncTable::InterceptSysCall(void)
{
int no = 0;
for (int i=0; i<m_funcno; i++)
if ( (m_func[i].f_kind==FUNC_SYSCALL) && !m_func[i].f_hooked )
{
unsigned char * p = (unsigned char *) m_func[i].f_oldaddress;
// B8 DB 10 00 00 mov eax,10DBh
// 8D 54 24 04 lea edx,[esp+4]
// CD 2E int 2Eh
// C3 ret
// verify that the destination follows a system call pattern
if ( ! IsBadReadPtr(p, 12) )
if ( (p[0]==0xB8) &&
(p[5]==0x8D) && (p[6]==0x54) && (p[7]==0x24) && (p[8]==0x04) &&
(p[9]==0xCD) && (p[10]==0x2E) )
{
// let ProxyProlog return control to our SysCall_xx routines
// f_parano counts return type, so decrease by 1
m_func[i].f_oldaddress = (FARPROC) SysCall_Stub[m_func[i].f_parano-1];
unsigned char Link[6];
Link[0] = 0xE9;
* (unsigned *) (Link+1) = (unsigned) m_func[i].f_newaddress() -
(unsigned) ( p +10);
Link[5] = 0x90;
HackCopy(p+5, Link, 6);
m_func[i].f_hooked = TRUE;
no ++;
}
}
return no;
}
int KFuncTable::InterceptCom(void)
{
int no = 0;
for (int i=0; i<m_funcno; i++)
if ( (m_func[i].f_kind==FUNC_COMMETHOD) && !m_func[i].f_hooked )
{
if ( HackMethod(VTable(m_func[i].f_module),
m_func[i].f_methodid,
m_func[i].f_newaddress()) )
{
m_func[i].f_hooked = TRUE;
no ++;
}
}
return no;
}
int KFuncTable::InterceptWin32(const char *Caller,
const char *Callee,
PIMAGE_THUNK_DATA pName,
PIMAGE_THUNK_DATA pThunk,
const char *baseAddress)
{
int no = 0;
// if module not added to module table, quit
if (LookupModule(Caller, Callee) == -1)
return 0;
while ( pThunk->u1.Function )
{
int id;
PBYTE pFunctionName = (PBYTE) ( baseAddress + (unsigned) pName->u1.ForwarderString + 2);
FARPROC pInterceptedFunction = LookupInterceptedAPI((FARPROC) pThunk->u1.Function, id);
if ( pInterceptedFunction )
if ( HackCopy(& pThunk->u1.Function, & pInterceptedFunction, sizeof(FARPROC)) )
{
m_func[id].f_hooked = TRUE;
no ++;
}
pName ++;
pThunk++;
}
return no;
}
int KFuncTable::InterceptWin32(const char *ModuleName, const char * baseAddress)
{
int no = 0;
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) baseAddress;
if ( IsBadReadPtr(baseAddress, sizeof(PIMAGE_NT_HEADERS)) )
return 0;
if ( pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE )
return 0;
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS) ( baseAddress + pDOSHeader->e_lfanew);
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
return 0;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
(PIMAGE_IMPORT_DESCRIPTOR) ( baseAddress +
pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress );
// Bail out if the RVA of the imports section is 0 (it doesn't exist)
if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR) pNTHeader )
return 0;
while ( pImportDesc->Name )
{
no += InterceptWin32(ModuleName,
(const char *) ( baseAddress + pImportDesc->Name ),
(PIMAGE_THUNK_DATA) ( baseAddress + (unsigned) pImportDesc->OriginalFirstThunk),
(PIMAGE_THUNK_DATA) ( baseAddress + (unsigned) pImportDesc->FirstThunk),
baseAddress);
pImportDesc++;
}
return no;
}
KPatcher directpatcher;
int KFuncTable::InterceptWin32(void)
{
int no = 0;
// DebugBreak();
for (int i=0; i<m_funcno; i++)
if ( (m_func[i].f_kind==FUNC_WIN32API) & !m_func[i].f_hooked )
// if there is an unhooked win32 function
{
int module = m_func[i].f_module;
// if caller and callee are the same module, patch function target
if ( strcmp(CallerName(module), CalleeName(module))==0 )
{
if ( directpatcher.Patch(ModHandle(module), GetFuncName(i),
i, ProxyProlog,
(unsigned long *) & m_func[i].f_oldaddress) )
no ++;
}
else
{
const char *caller = CallerName(module);
const char *address = (const char *) ModHandle(module);
// if caller module is loaded into current process, hack in it.
if (address)
no += InterceptWin32(caller, address);
}
}
return no;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -