VirtualQueryEx这个函数很有用,可以用于查询目标进程地址空间中内存地址的信息。
但此函数在Win CE 6.0以前是不被支持的(Windows Mobile 6是基于WinCE 5.2的)。
不过也不是没有办法的,WinCE中有一未公开API:PerformCallBack4。函数声明如下:
extern "C" DWORD WINAPI PerformCallBack4(CALLBACKINFO *pcbi, DWORD dw1, DWORD dw2, DWORD dw3);
此函数网上有相关说明,我在此不多说。
接下来是VirtualQueryEx实现代码,参数同MSDN中一样:
typedef
struct
CALLBACKINFO{
HANDLE m_hDestProcess;
FARPROC m_pFunction;
PVOID m_pFirstArgument;
};
extern " C " DWORD WINAPI PerformCallBack4(CALLBACKINFO * pcbi, DWORD dw1, DWORD dw2, DWORD dw3);
DWORD VirtualQueryEx(HANDLE hProcess, LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
{
DWORD dRetn = 0 ;
static FARPROC _VirtualQuery = NULL;
if ( ! _VirtualQuery)
{
// 获取VirtualQuery函数的址址
HINSTANCE h_CoreDll = LoadLibrary(TEXT( " Coredll.dll " ));
if ( ! h_CoreDll) return dRetn;
_VirtualQuery = GetProcAddress(h_CoreDll,TEXT( " VirtualQuery " ));
FreeLibrary(h_CoreDll);
}
CALLBACKINFO cbi = {hProcess};
cbi.m_pFunction = _VirtualQuery;
cbi.m_pFirstArgument = lpAddress;
return PerformCallBack4( & cbi,(DWORD)lpBuffer,(DWORD)dwLength, 0 );
}
HANDLE m_hDestProcess;
FARPROC m_pFunction;
PVOID m_pFirstArgument;
};
extern " C " DWORD WINAPI PerformCallBack4(CALLBACKINFO * pcbi, DWORD dw1, DWORD dw2, DWORD dw3);
DWORD VirtualQueryEx(HANDLE hProcess, LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
{
DWORD dRetn = 0 ;
static FARPROC _VirtualQuery = NULL;
if ( ! _VirtualQuery)
{
// 获取VirtualQuery函数的址址
HINSTANCE h_CoreDll = LoadLibrary(TEXT( " Coredll.dll " ));
if ( ! h_CoreDll) return dRetn;
_VirtualQuery = GetProcAddress(h_CoreDll,TEXT( " VirtualQuery " ));
FreeLibrary(h_CoreDll);
}
CALLBACKINFO cbi = {hProcess};
cbi.m_pFunction = _VirtualQuery;
cbi.m_pFirstArgument = lpAddress;
return PerformCallBack4( & cbi,(DWORD)lpBuffer,(DWORD)dwLength, 0 );
}
==补充============================================================
PerformCallBack4函数的内部分工作原理我不是很清楚,不过从运行结果看它似乎是把代码放到了目标进程的地址空间中去执行的,时间关系也没有深入去研究。
必竟是未公开的API感觉这种方式性能不是很理想,今天换一种“标准”的方式实现:
DWORD VirtualQueryEx(HANDLE hProcess, LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
{
LPVOID _lpAddress;
/* 如果当前线程的AK不是0xFFFFFFFF,并且不加本条语句,也可以正常访问其它进程,不知道为什么?
为保险起见我还是加上了,还请高手指点!! */
if (GetCurrentPermissions() != 0xFFFFFFFF )SetProcPermissions( 0xFFFFFFFF ); // 赋于当前线程所有进程访问权限
if ( ! (_lpAddress = MapPtrToProcess(lpAddress,hProcess))) return 0 ;
return VirtualQuery(_lpAddress,lpBuffer,dwLength);
}
{
LPVOID _lpAddress;
/* 如果当前线程的AK不是0xFFFFFFFF,并且不加本条语句,也可以正常访问其它进程,不知道为什么?
为保险起见我还是加上了,还请高手指点!! */
if (GetCurrentPermissions() != 0xFFFFFFFF )SetProcPermissions( 0xFFFFFFFF ); // 赋于当前线程所有进程访问权限
if ( ! (_lpAddress = MapPtrToProcess(lpAddress,hProcess))) return 0 ;
return VirtualQuery(_lpAddress,lpBuffer,dwLength);
}