299错误解决记录
ReadProcessMemory一直报错。发晕了一整天。
GetLastError() Error:0299 = 仅完成部分 ReadProcessMemory 或 WriteProcessMemory 请求。
以为是OpenProcess的参数问题,不断的修改参数,程序成了这样子:
hProcess = OpenProcess( //PROCESS_VM_OPERATION|PROCESS_VM_READ,
PROCESS_ALL_ACCESS,
//PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ,
//PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE,
//PROCESS_QUERY_INFORMATION,
FALSE,
dwProcessId);
很惨那,都试遍了,还是依然不断的报299错误,也就是说:操作不了内存。
找不到头绪,就整理GetLastError(),作了一个函数,根据ErrorCode返回错误内容。这花费了2个多小时吧,因为顺便将一些最近新写的独立函数也做到模块中。
晚上吃了饭继续整理,体力吃不消啊,从早上6点已经干了12个小时了。其中ReadProcessMemory已经可以读自己的Process内容,但读其他Process依然返回0.
9点了,突然找到了一丝灵感,也许可以修改内存属性?
使用VirtualProtectEx修改内存,如下这样作:
DWORD dwOldProt, dwNewProt = 0;
VirtualProtectEx(hProcess, (void*) pAddress, dwRead, PAGE_READWRITE, &dwOldProt);
if(!ReadProcessMemory( hProcess,
(LPCVOID)pAddress,
pRead,
dwRead,
&dwReaded))
{
char sState[260];
DWORD dwError = GetLastError();
sprintf(sState, "ReadProcessMemory failure! Error Code:%d\n\n%s \n\nSize:%d Readed:%d\n",
dwError,
getLastErrorString(dwError),
dwRead,
dwReaded);
MessageBox(sState, "Query", MB_OK|MB_ICONWARNING);
free(pRead);
CloseHandle(hProcess);
return FALSE;
}
VirtualProtectEx(hProcess, (void*) pAddress, dwRead, dwOldProt, &dwNewProt);
如此这般折腾后,居然可以读了,哇塞,我太开心了。
今晚可以好好休息一下,明天深入下去,将WriteProcessMemory也做好。形成一个完整的Read/Write工作过程。
-------------------------------------------------------------------------------------------------------
今天一直在分析读取结果,前面已经将数据读入到BYTE数组中,将数组内容和整数比较我考虑过多了,本来认为数据应该是由高到低依次排列,就写了下面的处理函数:
static long g_lSearchPosition = 0;
static long g_lTargetLength = 0;
static bool g_bSearchLock = false;
BOOL CQueryDlg::SearchIntBegin(BYTE* pTarget, long lTargetSize, int nVal)
{
if(g_bSearchLock) return FALSE;
g_lSearchPosition = 0;
g_lTargetLength = lTargetSize;
g_bSearchLock = true;
return TRUE;
}
long CQueryDlg::SearchIntNext(BYTE* pTarget, int nVal)
{
for(int i=g_lSearchPosition; i<g_lTargetLength-3; i++, g_lSearchPosition++)
{
int iRead = pTarget[i]<<24 | pTarget[i+1]<<16 | pTarget[i+2]<<8 | pTarget[i+3];
if(iRead == nVal)
{
g_lSearchPosition = i+1;
if(i>=(g_lTargetLength-3)) g_bSearchLock = false;
return i;
}
}
g_bSearchLock = false;
return -1;
}
但是比较结果一直找不到所需要的结果。找到的大量结果都不是正确的地址。
难道是内存中数据存储格式的问题?于是修改iRead组合方式:
int iVal = ((pRead[i]<<24) | (pRead[i+1]<<16) | (pRead[i+2]<<8) | (pRead[i+3]));
int iVal = ((pRead[i]<<0) | (pRead[i+1]<<8) | (pRead[i+2]<<16) | (pRead[i+3]<<24));
int iVal = MAKELONG( MAKEWORD(pRead[i], pRead[i+1]),MAKEWORD(pRead[i+2], pRead[i+3]));
... ...
依然没有找到正确的地址。
今天早上起来,问题现在已经集中在ReadProcessMemory上。一定是调用这个函数的时候出现了问题。
重新修改这个函数的处理过程,以整数为基础,作出如下程序:
#define HOS_READLEN 4096
DWORD dwReaded = 0;
long lPtr = PtrToLong(mbi.BaseAddress);
long lEnd = PtrToLong(mbi.BaseAddress) + (long)mbi.RegionSize;
int iVal[HOS_READLEN];
while( lPtr<lEnd )
{
memset(iVal, 0, sizeof(int)*HOS_READLEN);
ReadProcessMemory(hProcess, LongToPtr(lPtr), iVal, sizeof(int)*HOS_READLEN, &dwReaded);
for(int i=0; i<HOS_READLEN; i++)
{
if(iVal[i] == nVal)
{
char sState[260];
sprintf(sState, "Find Result %d at:0x%8.8X %d\n", nVal, lPtr, dwReaded);
TRACE0(sState);
}
}
lPtr+=sizeof(int)*HOS_READLEN;
}
终于找到了想要的结果,看起来以整数Read不仅快速而且判读很容易。
以后要是再读什么的话,直接将读取的内容做成块,以块的方式操作。那么ReadProcessMemory会在执行操作的时候按照数据块的大小运行,难怪有些人会设计一个CProcessRead类,这么小的功能做成类,以后就不灵会了,空洞而且无聊哟。
经过GetTickCount()测试我发现HOS_READLEN定义成不同的长度,运行速度差别很大。
HOS_READLEN TickCount
4096 109
1024 125
256 296
128 516
64 687
32 1219
16 2297
8 4468
4 9032
2 17968
1 35485
WriteProcessMemory没遇到问题,一次试验就有了结果。
下来我想看看Heap处理过程,对Heap数据进行过滤。