📄 spyengine.cpp
字号:
/********************************************************************
Module : SpyEngine.cpp - part of CeApiSpyDll implementation
Written 2003 by Dmitri Leman
for an article about CE Api Spy.
Purpose: Contains the Spy engine - the main part of CeApiSpyDll
This file was compiled using eMbedded Visual C++ 3.0
with Pocket PC 2002 SDK and 4.0 with Standard SDK.
********************************************************************/
#include <windows.h>
#include <Tlhelp32.h>
//Redefinitions for some CE internal structures and undocumented API:
#include "SysDecls.h"
#include "SpyEngine.h"
#include "SpyControl.h"
#include "HTrace.h"
#define NUM_OUR_API_METHODS 32
HINSTANCE g_hInst = NULL;//this is our DLL instance
#define TRACE_SIZE 0x100000
#define countof(array) (sizeof(array)/sizeof(array[0]))
#pragma data_seg("SH_DATA")
SpyEngine g_SpyEngine = {0};//The only static instance of SpyEngine.
BOOL g_bStarted = FALSE;
#pragma data_seg()
#pragma comment( linker, "/SECTION:SH_DATA,SRW" )
/***************** Beginning of Toolhelp replacement *************/
//Beginning of Toolhelp replacement. PocketPC emulation and retail
//devices do have toolhelp support, but CE.NET emulation version
//does not include toolhelp.dll. Therefore, I have to reimplement
//some toolhelp methods myself using public declarations of necessary
//structures in PUBLIC\COMMON\OAK\INC\TOOLHELP.H.
typedef HANDLE WINAPI T_CreateToolhelp32Snapshot
(DWORD dwFlags, DWORD th32ProcessID);
typedef BOOL WINAPI T_CloseToolhelp32Snapshot(HANDLE hSnapshot);
typedef BOOL WINAPI T_Module32First
(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
typedef BOOL WINAPI T_Module32Next
(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
typedef BOOL WINAPI T_Process32First
(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
typedef BOOL WINAPI T_Process32Next
(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
T_CreateToolhelp32Snapshot * g_pCreateToolhelp32Snapshot = NULL;
T_CloseToolhelp32Snapshot * g_pCloseToolhelp32Snapshot = NULL;
T_Module32First * g_pModule32First = NULL;
T_Module32Next * g_pModule32Next = NULL;
T_Process32First* g_pProcess32First = NULL;
T_Process32Next * g_pProcess32Next = NULL;
//From PUBLIC\COMMON\OAK\INC\TOOLHELP.H:
typedef struct TH32PROC {
PROCESSENTRY32 procentry;
void *pMainHeapEntry;
struct TH32PROC *pNext;
} TH32PROC;
typedef struct TH32MOD {
MODULEENTRY32 modentry;
struct TH32MOD *pNext;
} TH32MOD;
typedef struct THSNAP {
LPBYTE pNextFree;
LPBYTE pHighCommit;
LPBYTE pHighReserve;
TH32PROC *pProc;
TH32MOD *pMod;
void *pThread;
void *pHeap;
} THSNAP;
/*-------------------------------------------------------------------
FUNCTION: MyCreateToolhelp32Snapshot
PURPOSE: Replacement to ToolHelp CreateToolhelp32Snapshot.
Parameters and return value are identical to
documented CreateToolhelp32Snapshot.
-------------------------------------------------------------------*/
HANDLE MyCreateToolhelp32Snapshot
(
DWORD p_dwFlags,
DWORD p_th32ProcessID
)
{
THSNAP * l_pSnapshot = (THSNAP *)
THCreateSnapshot(p_dwFlags, p_th32ProcessID);
HTRACE(TG_DebugSpyBrief, _T("THCreateSnapshot ret %x"),
l_pSnapshot);
return (HANDLE)l_pSnapshot;
}
/*-------------------------------------------------------------------
FUNCTION: MyCloseToolhelp32Snapshot
PURPOSE: Replacement to ToolHelp CloseToolhelp32Snapshot.
Parameters and return value are identical to
documented CloseToolhelp32Snapshot.
-------------------------------------------------------------------*/
BOOL MyCloseToolhelp32Snapshot(HANDLE p_hSnapshot)
{
MEMORY_BASIC_INFORMATION l_MemInfo;
if(!VirtualQuery((void*)p_hSnapshot,
&l_MemInfo, sizeof(l_MemInfo)))
return FALSE;
VirtualFree((void*)p_hSnapshot,
l_MemInfo.RegionSize, MEM_DECOMMIT);
VirtualFree((void*)p_hSnapshot, 0, MEM_RELEASE);
return TRUE;
}
/*-------------------------------------------------------------------
FUNCTION: MyModule32First
PURPOSE: Replacement to ToolHelp Module32First.
Parameters and return value are identical to
documented Module32First.
-------------------------------------------------------------------*/
BOOL MyModule32First(HANDLE p_hSnapshot, LPMODULEENTRY32 p_lpme)
{
THSNAP * l_pSnapshot = (THSNAP*)p_hSnapshot;
if(!l_pSnapshot || !l_pSnapshot->pMod || !p_lpme ||
p_lpme->dwSize < sizeof(MODULEENTRY32))
return FALSE;
memcpy(p_lpme, &l_pSnapshot->pMod->modentry,
sizeof(MODULEENTRY32));
p_lpme->dwFlags = (DWORD)l_pSnapshot->pMod->pNext;
//Kludge. dwFlags is reserved, so reuse it.
return TRUE;
}
/*-------------------------------------------------------------------
FUNCTION: MyModule32Next
PURPOSE: Replacement to ToolHelp Module32Next.
Parameters and return value are identical to
documented Module32Next.
-------------------------------------------------------------------*/
BOOL MyModule32Next(HANDLE p_hSnapshot, LPMODULEENTRY32 p_lpme)
{
THSNAP * l_pSnapshot = (THSNAP*)p_hSnapshot;
if(!l_pSnapshot || !l_pSnapshot->pMod || !p_lpme)
return FALSE;
if(p_lpme->dwFlags < (DWORD)l_pSnapshot ||
p_lpme->dwFlags >= (DWORD)l_pSnapshot->pHighCommit)
return FALSE;
TH32MOD * l_pNextMod = (TH32MOD*)p_lpme->dwFlags;
//Kludge. dwFlags is reserved, so reuse it.
memcpy(p_lpme, &l_pNextMod->modentry, sizeof(MODULEENTRY32));
p_lpme->dwFlags = (DWORD)l_pNextMod->pNext;
//Kludge. dwFlags is reserved, so reuse it.
return TRUE;
}
/*-------------------------------------------------------------------
FUNCTION: MyProcess32First
PURPOSE: Replacement to ToolHelp Process32First.
Parameters and return value are identical to
documented Process32First.
-------------------------------------------------------------------*/
BOOL MyProcess32First(HANDLE p_hSnapshot, LPPROCESSENTRY32 p_lppe)
{
THSNAP * l_pSnapshot = (THSNAP*)p_hSnapshot;
if(!l_pSnapshot || !l_pSnapshot->pProc || !p_lppe ||
p_lppe->dwSize < sizeof(PROCESSENTRY32))
return FALSE;
memcpy(p_lppe, &l_pSnapshot->pProc->procentry,
sizeof(PROCESSENTRY32));
p_lppe->dwFlags = (DWORD)l_pSnapshot->pProc->pNext;
//Kludge. dwFlags is reserved, so reuse it.
return TRUE;
}
/*-------------------------------------------------------------------
FUNCTION: MyProcess32Next
PURPOSE: Replacement to ToolHelp Process32Next.
Parameters and return value are identical to
documented Process32Next.
-------------------------------------------------------------------*/
BOOL MyProcess32Next(HANDLE p_hSnapshot, LPPROCESSENTRY32 p_lppe)
{
THSNAP * l_pSnapshot = (THSNAP*)p_hSnapshot;
if(!l_pSnapshot || !l_pSnapshot->pProc || !p_lppe)
return FALSE;
if(p_lppe->dwFlags < (DWORD)l_pSnapshot ||
p_lppe->dwFlags >= (DWORD) l_pSnapshot->pHighCommit)
return FALSE;
TH32PROC * l_pNextProc = (TH32PROC*)p_lppe->dwFlags;
//Kludge. dwFlags is reserved, so reuse it.
memcpy(p_lppe, &l_pNextProc->procentry,
sizeof(PROCESSENTRY32));
p_lppe->dwFlags = (DWORD)l_pNextProc->pNext;
//Kludge. dwFlags is reserved, so reuse it.
return TRUE;
}
/*-------------------------------------------------------------------
FUNCTION: LoadToolHelp
PURPOSE: Loads ToolHelp API or, if it is missing, initialize
pointers to our replacement routines.
RETURNS: TRUE on success, FALSE on failure
-------------------------------------------------------------------*/
BOOL LoadToolHelp()
{
if(g_pCreateToolhelp32Snapshot)
return TRUE;
HINSTANCE l_hInst = LoadLibrary(_T("TOOLHELP"));
if(!l_hInst)
{
HTRACE(TG_DebugSpyBrief,
_T("Cannot find ToolHelp library. %d"), GetLastError());
}
else
{
g_pCreateToolhelp32Snapshot = (T_CreateToolhelp32Snapshot *)
GetProcAddress(l_hInst, _T("CreateToolhelp32Snapshot"));
g_pCloseToolhelp32Snapshot = (T_CloseToolhelp32Snapshot *)
GetProcAddress(l_hInst, _T("CloseToolhelp32Snapshot"));
g_pModule32First = (T_Module32First * )
GetProcAddress(l_hInst, _T("Module32First"));
g_pModule32Next = (T_Module32Next * )
GetProcAddress(l_hInst, _T("Module32Next"));
g_pProcess32First = (T_Process32First* )
GetProcAddress(l_hInst, _T("Process32First"));
g_pProcess32Next = (T_Process32Next * )
GetProcAddress(l_hInst, _T("Process32Next"));
if(g_pCreateToolhelp32Snapshot && g_pCloseToolhelp32Snapshot
&& g_pModule32First && g_pModule32Next &&
g_pProcess32First && g_pProcess32Next)
return TRUE;
HTRACE(TG_Error,
_T("Cannot find methods in ToolHelp library"));
}
if(l_hInst != NULL)
{
FreeLibrary(l_hInst);
}
g_pCreateToolhelp32Snapshot = MyCreateToolhelp32Snapshot;
g_pCloseToolhelp32Snapshot = MyCloseToolhelp32Snapshot;
g_pModule32First = MyModule32First;
g_pModule32Next = MyModule32Next;
g_pProcess32First = MyProcess32First;
g_pProcess32Next = MyProcess32Next;
HTRACE(TG_DebugSpyBrief, _T("Use our own toolhelp replacement"));
return TRUE;
}
/***************** End of Toolhelp replacement *******************/
/*-------------------------------------------------------------------
FUNCTION: InitProcessList
PURPOSE: InitProcessList uses Toolhelp API to enumerate running
processes and store process information to our
g_SpyEngine.m_Processes array. This will allow accessing this
process information from our interceptor routines.
RETURNS: TRUE on success, FALSE on failure
-------------------------------------------------------------------*/
BOOL InitProcessList()
{
memset(g_SpyEngine.m_Processes, 0,
sizeof(g_SpyEngine.m_Processes));
HANDLE l_hSnapShotProc =
g_pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(l_hSnapShotProc == (HANDLE)-1)
return FALSE;
PROCESSENTRY32 l_ProcEntry;
l_ProcEntry.dwSize = sizeof(l_ProcEntry);
if(g_pProcess32First(l_hSnapShotProc, &l_ProcEntry))
{
HTRACE(TG_DebugSpyDetailed,
_T("Proc %x %s"), l_ProcEntry.th32AccessKey,
l_ProcEntry.szExeFile);
do
{
int l_iKey = l_ProcEntry.th32AccessKey;
int l_iIndex = 0;
l_iKey >>= 1;
while(l_iKey)
{
l_iKey >>= 1;
l_iIndex++;
}
memcpy(g_SpyEngine.m_Processes + l_iIndex,
&l_ProcEntry, l_ProcEntry.dwSize);
} while(g_pProcess32Next(l_hSnapShotProc, &l_ProcEntry));
}
g_pCloseToolhelp32Snapshot(l_hSnapShotProc);
return TRUE;
}//BOOL InitProcessList()
/*-------------------------------------------------------------------
FUNCTION: HookCoredll
PURPOSE: HookCoredll replaces pointers to Win32 method table,
which coredll caches in it's data section when each process loads.
Later most of coredll exported methods will use this cached table
to call the kernel directly (bypassing the regular API dispatcher)
Therefore, Spy has to replace this cached pointer in each process.
RETURNS: TRUE on success, FALSE on failure
-------------------------------------------------------------------*/
BOOL HookCoredll(LPVOID p_pOldWin32Methods,LPVOID p_pNewWin32Methods)
{
HTRACE(TG_DebugSpyBrief,
_T("HookCoredll(old methods=%x, new=%x)\r\n"),
p_pOldWin32Methods, p_pNewWin32Methods);
//Get address of any exported routine in coredll, which is known
//to use the cached table. EventModify happened to be one.
HINSTANCE l_hInst = LoadLibrary(_T("COREDLL"));
LPCTSTR l_pszMethodName = _T("EventModify");
LPBYTE l_pCoreDllFunc = (LPBYTE)GetProcAddress
(l_hInst, l_pszMethodName);
if(!l_pCoreDllFunc)
{
HTRACE(TG_Error,
_T("ERROR: failed to get address of %s in coredll. Err %d"),
l_pszMethodName, GetLastError());
FreeLibrary(l_hInst);
return FALSE;
}
//Now scan the body of the method and look for a pointer to the
//table. There is no way to know exactly where the method ends,
//so use 256 as an upper limit.
//This technique is fragile an may need adjustments for different
//CPUs and newer versions of the OS.
DWORD l_dwAddressInCoredll = 0;
for(int i = 0; i < 256; i++)
{
__try
{
#if defined(ARM) || defined(SH3)
//ARM don't like misaligned addresses
if((DWORD)(l_pCoreDllFunc+i) & 3)
continue;
#endif
HTRACE(TG_DebugSpyDetailed,
_T("Before reading from %x\r\n"),
l_pCoreDllFunc+i);
DWORD * l_pdwAddress = *((DWORD**)(l_pCoreDllFunc+i));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -