C#内存搜索问题,为什么搜索要一个小时

「已注销」 2009-10-15 11:36:32
各位高人帮下忙!
这几天在写个内存修改的例子,现在有个问题是我搜索出来的地址从0x00400000-0x7FFFFFFF这么大的区间确只能搜索出50多个地址,这些地址的值也取的出来。其中用到了VirtualQueryEx这个API,请问下这个方法是一次跳过一块那样的执行方式吗?也就是说在后面地址累加时是这样的:BaseAddress = (IntPtr)(inf.BaseAddress + inf.RegionSize); 这里的regionsize增加的太快,所以我现在想让自定义个IntStr类型的地址StartAddress然后每查完一个就StartAddress+0x10也就是每次加16.但是这样是有问题的。
上面是累加的问题,用那种方法就会出现问题了,将内存中的每个地址遍历出来那不是要浪费很长时间,请问下各位在做内存搜索时常用的做法是什么,还望各位帮下,答好的加分!
...全文
250 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
fice1989 2009-10-16
  • 打赏
  • 举报
回复
帮顶个。。。
「已注销」 2009-10-16
  • 打赏
  • 举报
回复
怎么没人回答呢
「已注销」 2009-10-16
  • 打赏
  • 举报
回复
比如说现在针对一块头地址查出来的有1000多个字节bytearray[],我现在也有个要查询的C8 00 00 00 2A 01 00 00 FF EE FF EE 02 00 00 00,我要在bytearray中查出是不是存在要查的字符串,并且要得到这个地址(不是块地址,是符合这个值的地址),我该怎么办,谢谢你帮我下!
whg01 2009-10-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 shiyanlaji 的回复:]
楼上答的不错,是不是这样,用readprocessmemory读出从virtualqueryex中取出的baseaddress地址里的regionsize个字节的数据?是这样吗?
[/Quote]
是的。除非你要对比内存是否有变化,否则最好一次读个10M(或者你自己衡量一个值),直到整个regionsize全读完。一次将regionsize,可能会读很大的空间。
「已注销」 2009-10-16
  • 打赏
  • 举报
回复
楼上答的不错,是不是这样,用readprocessmemory读出从virtualqueryex中取出的baseaddress地址里的regionsize个字节的数据?是这样吗?
whg01 2009-10-16
  • 打赏
  • 举报
回复
http://vip.6to23.com/NowCan1/tech/VirtualQ.htm VirtualQueryEx+ReadProcessMemory
VirtualQueryEx和ReadProcessMemory都会触发系统调用,会让操作系统从用户态切换到内核态。这是比较耗时间的。
所以用VirtualQueryEx查询到一个有效的内存区段,然后用ReadProcessMemory去读取这段的内容,然后再解析。
「已注销」 2009-10-16
  • 打赏
  • 举报
回复

//开始循环搜索
while(searchedLength==sizeof(MEMORY_BASIC_INFORMATION)&&(int)BaseAddress < 0x7FFFFFFF) {
System.Console.Write("当前第"+ y +"个 ");
searchedLength = (int)ProcessMemoryWorokApi.VirtualQueryEx(PinballHandle, BaseAddress, out inf,
sizeof(MEMORY_BASIC_INFORMATION));
Console.WriteLine(inf.State+" "+inf.Protect+" "+inf.State+" "+inf.RegionSize);
System.Console.Write(Convert.ToString(inf.BaseAddress, 16));
if (inf.State == MEMMessage.MEM_COMMIT &&
(inf.Protect == PAGEinfo.PAGE_READWRITE || inf.Protect == PAGEinfo.PAGE_WRITECOPY||
inf.Protect == PAGEinfo.PAGE_EXECUTE_READWRITE || inf.Protect == PAGEinfo.PAGE_EXECUTE_WRITECOPY))
{
y++;
ProcessMemoryWorokApi.ReadProcessMemory(PinballHandle,
(IntPtr)inf.BaseAddress, ReadByte, 16, (IntPtr)0);

ReadString = ProcessMemoryWorokApi.ConvertByte(ReadByte);

System.Console.WriteLine(" "+Convert.ToString(inf.BaseAddress,16)+"=" + ReadString);

if (UserInputString.Trim().Equals(ReadString.Trim()))
{
MessageBox(new IntPtr(0), "查到了,恭喜你!", "提示", 0);
//修改游戏分数
ProcessMemoryWorokApi.WriteProcessMemory(PinballHandle,
(IntPtr)inf.BaseAddress, ProcessMemoryWorokApi.ConvertToBytes(inputByteStr), 16, (IntPtr)0);
break;
}
else
{
BaseAddress = (IntPtr)(inf.BaseAddress + inf.RegionSize);
}

}
else if (inf.State == MEMMessage.MEM_FREE && inf.RegionSize > 0x08000000)
{
break;
}
else if (inf.Protect == PAGEinfo.PAGE_NOACCESS)
{
// || inf.Protect == PAGEinfo.PAGE_GUARD
Console.WriteLine("是不能访问的!");

ProcessMemoryWorokApi.VirtualProtectEx(PinballHandle,
(IntPtr)inf.BaseAddress, inf.RegionSize, PAGEinfo.PAGE_READWRITE, PAGEinfo.PAGE_NOACCESS);

ProcessMemoryWorokApi.ReadProcessMemory(PinballHandle,
(IntPtr)inf.BaseAddress, ReadByte, 16, (IntPtr)0);

ReadString = ProcessMemoryWorokApi.ConvertByte(ReadByte);

System.Console.WriteLine(" " + Convert.ToString(inf.BaseAddress, 16) + "=" + ReadString);
y++;
BaseAddress = (IntPtr)(inf.BaseAddress + inf.RegionSize);
}
else if (inf.Protect == PAGEinfo.PAGE_GUARD||inf.Protect == PAGEinfo.PAGE_READONLY ||
inf.Protect == 0 || inf.Protect == PAGEinfo.PAGE_EXECUTE_READ)
{
// || inf.Protect == PAGEinfo.PAGE_GUARD
Console.WriteLine("是不能访问的!");

ProcessMemoryWorokApi.VirtualProtectEx(PinballHandle,
(IntPtr)inf.BaseAddress, inf.RegionSize, PAGEinfo.PAGE_READWRITE, inf.Protect);

ProcessMemoryWorokApi.ReadProcessMemory(PinballHandle,
(IntPtr)inf.BaseAddress, ReadByte, 16, (IntPtr)0);

ReadString = ProcessMemoryWorokApi.ConvertByte(ReadByte);

System.Console.WriteLine(" " + Convert.ToString(inf.BaseAddress, 16) + "=" + ReadString);
y++;
BaseAddress = (IntPtr)(inf.BaseAddress + inf.RegionSize);
}
else
{
System.Console.WriteLine("xxxxxxxxxxxxxxxxxxxxx"+inf.Protect);
BaseAddress = (IntPtr)(inf.BaseAddress + inf.RegionSize);
}

}

thy38 2009-10-16
  • 打赏
  • 举报
回复
贴点代码
「已注销」 2009-10-16
  • 打赏
  • 举报
回复
大家有没好点的解决办法呢
bobo_2003 2009-10-16
  • 打赏
  • 举报
回复
不会很长的,帮UP
「已注销」 2009-10-16
  • 打赏
  • 举报
回复
谢谢你们的回答 不过 C#语言就不一样了 哪有那么好取地址呢?
现在不是那个问题了
看下面:
数据地址 块头地址 块大小 堆句柄
0x000a0688 0x000a0680 6144 0x000a0000


当我点这个地址时下面显示的是
000A0688 00 00 00 00 00 00 00 00 04 00 00 01 00 00 00 00
000A0698 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000A06A8 00 00 00 00 62 01 00 00 17 00 00 00 00 00 00 00
........

上面是一个软件读出来的
我用BaseAddress加上regionsize取出的地址是 上面的堆句柄的地址,请问各位我怎样取到 数据地址和块头地址,因为我要用数据地址当起始地址,要不我从堆句柄中读出的byte怎么计算它的内存地址呢,你们说呢!
whg01 2009-10-16
  • 打赏
  • 举报
回复
KMP会更快。
先实现简单的,再换KMP吧。
调通KMP也不是件非常容易的事。
M_S_D_N 2009-10-16
  • 打赏
  • 举报
回复
这里用KMP搜索不是会快点?这样似乎很慢啊。
[Quote=引用 13 楼 whg01 的回复:]
大概代码:
cosnt unsigned char toFind[] = {C8, 00, 00, 00, 2A, 01, 00, 00, FF, EE, FF, EE, 02, 00, 00, 00}; //要查找的内容。
//00多个字节bytearray[],设长度为len。
for (i=0;i <len;i++)
{
    if (!memcmp(bytearray+i, toFind, sizeof(toFind)/sizeof(toFind[0]))
        break;
}
if (i <len)
{
    return bytearray+i; //这个就是找到的地址。
}
[/Quote]
whg01 2009-10-16
  • 打赏
  • 举报
回复
for (i=0;i <len-sizeof(toFind)/sizeof(toFind[0]));i++) 改成这样。
yang_e_2009 2009-10-16
  • 打赏
  • 举报
回复
不用那么长时间吧, 全部搜索我的机子上大概20秒左右
whg01 2009-10-16
  • 打赏
  • 举报
回复
大概代码:
cosnt unsigned char toFind[] = {C8, 00, 00, 00, 2A, 01, 00, 00, FF, EE, FF, EE, 02, 00, 00, 00}; //要查找的内容。
//00多个字节bytearray[],设长度为len。
for (i=0;i<len;i++)
{
if (!memcmp(bytearray+i, toFind, sizeof(toFind)/sizeof(toFind[0]))
break;
}
if (i<len)
{
return bytearray+i; //这个就是找到的地址。
}
jackyjkchen 2009-10-16
  • 打赏
  • 举报
回复
怀疑你不是内存地址遍历造成的速度问题,而是控制逻辑,内存的读取速度,是以G/S为单位的,从头到尾遍历内存一遍花不了多少时间的

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧