|

提醒:若下载的软件是收费的"请不要付款",可能是骗子,请立即联系本站举报,执意要付款被骗后本站概不负责。(任何交易请走第三方中介,请勿直接付款交易以免被骗!切记).
本帖最后由 cocop 于 2020-4-17 18:52 编辑
无聊逛论坛时,偶然发现了关于偷 内存检测的帖子,于是思考了下偷内存的实现。 最先想到的方法肯定是内存对比,但因需要对比游戏全部内存,效率差强人意,而且内存对比需要不断的改变需要获取的内存以过滤无关数据,大部分检测又是只写一次,不会重写多次,根本无法从海量数据中挑出自己需要的。
之后查询相关资料了解到内存监视器的原理是Hook kernel32.dll中的WriteProcessMemory实现监视更改内存的作用。对于我这种菜鸡来说,Hook是仅仅了解过但又从未自己去实现过的新奇事物,自然勾动着我的好奇心。于是我去查阅了相关的资料、代码明白了hook监视内存的实现方法。在这里做下笔记加深理解。
下面是hook的实现过程,大牛就别看了 ,这里拿WriteProcessMemory做示范
1.保存系统函数入口处的代码,此步骤的目的是便于恢复。
这里GetModuleHandleA获取了kernel32.dll的模块地址,接着GetProcAddress获取WriteProcessMemory的地址。
改变要hook地址的虚拟内存页保护属性为64
保存原始数据
2.替换掉进程中的系统函数入口指向我们的函数
因为我对机器语言不了解,拼接颇为费劲,故利用的超级模块,转换为字节集后写到hook函数的入口。
Mov_EAX (到整数 (&_WriteProcessMemory)),这里_WriteProcessMemory是我们重写的WriteProcessMemory,意思是将这个地址赋值给EAX寄存器
JMP_EAX () 跳转到我们编写的函数地址。
3.当系统函数被调用,立即跳转到我们的函数
|
_WriteProcessMemory | 逻辑型 | | |
进程句柄 | 整数型 | | | | 内存地址 | 整数型 | | | | 缓冲指针 | 整数型 | √ | | | 内存长度 | 整数型 | | | | 实际长度 | 整数型 | √ | | | R_WriteProcessMemory ()result = WriteProcessMemory (进程句柄, 内存地址, 缓冲指针, 内存长度, 实际长度 ) 如果 (PID > 0 ) R_ReadProcessMemory () Write (“WriteProcessMemory”, “进程句柄:” + 到文本 (进程句柄 ) + tab + “内存地址:” + Get_Base_Address (内存地址 ) + tab + “内存长度:” + 到文本 (内存长度 ) + tab + “写入数据:” + _字节集_到十六进制 (读内存字节集 (PID, 内存地址, 内存长度 )), 到文本 (result )) 写到内存 (ReadProcessMemory_.代码, ReadProcessMemory_.钩子地址, 8 ) Write (“WriteProcessMemory”, “进程句柄:” + 到文本 (进程句柄 ) + tab + “内存地址:” + Get_Base_Address (内存地址 ) + tab + “内存长度:” + 到文本 (内存长度 ) + tab + “写入数据因为未获取到Crossfire进程ID而无法获取”, 到文本 (result )) 写到内存 (WriteProcessMemory_.代码, WriteProcessMemory_.钩子地址, 8)返回 (result ) 如果真 (取字节集长度 (WriteProcessMemory_.原始数据 ) > 0 ) 写到内存 (WriteProcessMemory_.原始数据, WriteProcessMemory_.钩子地址, )
首先调用子程序R_WriteProcessMemory,还原入口,毕竟还是要调用WriteProcessMemory实现功能的,我们只是获取数据,不是破坏功能。
之后调用正经的WriteProcessMemory API,得到结果result,将参数带result输出,若要获取写入了什么,调用读内存获取即可。
这里暂时屏蔽ReadProcessMemory是因为同时hook了ReadProcessMemory会干扰结果。
4.再修改系统函数入口指向我们的函数,便于下次调用
但是只hook一个API怎么可能满足的了我呢?于是便写了GetModuleHandleA,ReadProcessMemory,VirtualAllocEx,VirtualProtect,VirtualProtectEx。
file:///C:\Users\coco\AppData\Roaming\Tencent\Users\794087777\TIM\WinTemp\RichOle\2NSCS%H4I3I35NA}SPWD))M.png
再一次无聊逛论坛时发现,他们的监视器居然能通过内存找到对应的静态地址!那我肯定坐不住了啊,写起来。
目前只有获取一级基址的思路,多级不能调试游戏估计莫得办法,望各位大哥指点。
|
Get_Base_Address | 文本型 | | |
address | 整数型 | | | |
计次循环首 (取数组成员数 (模块信息 ), i ) 如果真 (address ≥ 模块信息 [i ].基地址 且 address < 模块信息 [i ].基地址 + 模块信息 [i ].大小 ) 返回 (模块信息 [i ].文件名 + “+” + 十到十六 (address - 模块信息 [i ].基地址 ))   计次循环尾 ()返回 (到文本 (address ))
用timeSetEvent开启了一个时钟监测是否存在游戏,若有游戏则获取PID并用超级模块提供的取进程模块获取模块信息。
P_ID = XF_PID () 如果 (P_ID > 0 ) PID = P_ID 取进程模块 (PID, 模块信息 ) timeKillEvent (XF_Timer )  PID = -1 
Get_Base_Address的作用便是输入一个内存,循环比较模块信息,若在模块内,返回对应基址,若找不到则返回原地址。
编译为dll,注入 进程测试,这里就不拿XF测试了,自己随便写了个测试程序把名字改成了crossfire.exe测试。
测试还算挺W美的。至于读写之前为什么要VirtualProtectEx应该是得改内存的属性,避免读写不了。若有错误,希望指正!谢谢各位大佬!
使用方法:dll注入相关 即可,怕成品有毒的就自己编译,模块也只是个超级模块,还是不放心就用自己的超级模块。
理论上注入游戏的 dll也能获取数据,把自己的dll也注入游戏就行。但得过了游戏的保护,我菜,就不注入游戏献丑了 。需要的大佬自己拿着源码改一改过一下保护应该就可以。
还需要hook其他api稍稍改一下就行,不费劲~
最后附上源码模块和成品!
联系我时,请说是在 挂海论坛 上看到的,谢谢! |
上一篇: 一个免费的游戏平台分享给大家下一篇: CE功能+检测
免责声明:
1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关。一切关于该内容及资源商业行为与www.52ghai.com无关。
2、本站提供的一切资源内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。
3、本站信息来自第三方用户,非本站自制,版权归原作者享有,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
4、如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵犯你版权的,请邮件与我们联系删除(邮箱:xhzlw@foxmail.com),本站将立即改正。
|