开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1160|回复: 4
收起左侧

[图文资料] 极其方便的多级指针读取封装

[复制链接]
发表于 2020-7-23 10:46:05 | 显示全部楼层 |阅读模式   广西壮族自治区桂林市

极其方便的多极指针读取封装

我想你或许写过这样的代码:


  1. DWORD a = *(DWORD*)0x12345678;
  2. a = *(DWORD*)(a+0xXX);
  3. a = *(DWORD*)(a+0xXX);
  4. a = *(DWORD*)(a+0xXX);
复制代码


图片1.png

或者这样的:


  1. DWORD a = NULL;
  2. ReadProcessMemory(hProcess, (DWORD*)(a), &a, sizeof(DWORD), 0);
  3. ReadProcessMemory(hProcess, (DWORD*)(a+0xXX), &a, sizeof(DWORD), 0);
  4. ReadProcessMemory(hProcess, (DWORD*)(a+0xXX), &a, sizeof(DWORD), 0);
  5. ReadProcessMemory(hProcess, (DWORD*)(a+0xXX), &a, sizeof(DWORD), 0);
  6. ReadProcessMemory(hProcess, (DWORD*)(a+0xXX), &a, sizeof(DWORD), 0);
复制代码


图片2.png

如果你为这玩意烦恼过,下面的代码或者思路或许可以帮到你。


后面写出的代码可以如这样般简洁:
xyGet(0x12345678,0x403,0xC,0x8);



图片3.png

让我们来看看代码:


XyGet.h


  1. #include <Windows.h>

  2. void F输出调试信息(char * pszFormat, ...);

  3. DWORD xyGet(char* szpCHAR, int index, DWORD nd基质, DWORD nd中间值);

  4. template<typename... Types>
  5. DWORD xyGet(char* szpCHAR, int index, DWORD nd基质, DWORD nd中间值, int ndIndex, const Types&... args)
  6. {
  7.         __try
  8.         {
  9.                 return xyGet(szpCHAR, index, nd基质, *(DWORD*)(nd中间值 + ndIndex), args...);
  10.         }
  11.         __except (1)
  12.         {
  13.                 F输出调试信息("%s xyGet,基址:%4X 第%d层偏移:%X 读取异常\r\n", szpCHAR, nd基质,index - sizeof...(args) + 1, ndIndex);
  14.                 return 0;
  15.         }
  16. }
  17. template<typename... Types>
  18. DWORD xyGet(char* szpCHAR, DWORD nd基质, const Types&... args)
  19. {
  20.         __try
  21.         {
  22.                 //int ndIndex =
  23.                 return xyGet(szpCHAR, (int)sizeof...(args), nd基质, *(DWORD*)nd基质, args...);
  24.         }
  25.         __except (1)
  26.         {
  27.                 F输出调试信息("%s xyGet,基址:%4X 异常!请传入有效基地址\r\n", szpCHAR, nd基质);
  28.                 return 0;
  29.         }
  30. }
  31. template<typename... Types>
  32. DWORD xyGet(DWORD nd基质, const Types&... args)
  33. {
  34.         return xyGet("调试头", nd基质, args...);
  35. }
复制代码

xyGet.cpp


  1. #include "xyGet.h"

  2. void F输出调试信息(char * pszFormat, ...)
  3. {
  4. #ifdef _DEBUG
  5.         char szbufFormat[0x1000];
  6.         char szbufFormat_Game[0x1100] = "";
  7.         va_list argList;
  8.         va_start(argList, pszFormat);
  9.         vsprintf_s(szbufFormat, pszFormat, argList);
  10.         strcat_s(szbufFormat_Game, szbufFormat);
  11.         OutputDebugStringA(szbufFormat_Game);
  12.         va_end(argList);
  13. #endif
  14. }

  15. DWORD xyGet(char* szpCHAR, int index, DWORD nd基质, DWORD nd中间值)
  16. {
  17.         return nd中间值;
  18. }
复制代码


图片4.png

例子:xyGet(0x12345678,0x403,0xC,0x8);

使用方法第一个参数传入基地址,后面跟任意多个偏移
使用了C++ 11的新特性,任意类型任意个数的函数模板,如果你的编译器无法通过编译,或许需要手动开启C++ 11,如下。



图片5.png

现在我们一起来看看 例子:xyGet(0x12345678,0x403,0xC,0x8); 是怎么执行的。
PS:需要一些C++ 理论知识。


首先4个重载函数和我们的例子匹配度最高的肯定是:


第一步:


  1. template<typename... Types>
  2. DWORD xyGet(DWORD nd基质, const Types&... args)
  3. {
  4.         return xyGet("调试头", nd基质, args...);
  5. }
复制代码

我们看它接受什么参数,一个DWORD  和 const Types&... args(一包东西)

然后调用了另外一个重载函数,第一个参数传入了一个字符串,然后把剩下2个参数原封不动的传入。 为什么?主要我是担心我的程序出异常,指针读取非常危险的动作,我们必须时刻小心,所以传入一个调试头 ,以便出异常方便使用 Dbgview 捕捉异常所打印的信息,以此知道我们的程序 在读取那一个基地址 那一级偏移 产生了错误,如:



图片6.png

接下来显而易见的程序走到了这,
第二步:


  1. template<typename... Types>
  2. DWORD xyGet(char* szpCHAR, DWORD nd基质, const Types&... args)
  3. {
  4.         __try
  5.         {
  6.                 //int ndIndex =
  7.                 return xyGet(szpCHAR, (int)sizeof...(args), nd基质, *(DWORD*)nd基质, args...);
  8.         }
  9.         __except (1)
  10.         {
  11.                 F输出调试信息("%s xyGet,基址:%4X 异常!请传入有效基地址\r\n", szpCHAR, nd基质);
  12.                 return 0;
  13.         }
  14. }
复制代码

接收一个字符串,一个DWORD ,还有一包东西,嗯100%匹配,看看它做了什么处理。
调用了重载函数,传入一个字符串原封不动,计算一包东西还有多少个,DWORD基地址,把基地址里面的值读取出来传入,还有一包东西。


有什么参数?Char int DWORD DWORD 加 args...(一包东西)
好像现在没有完美匹配的重载函数了,是的。但是编译器非常聪明,它把那一包东西拆解一下,变成 char
int DWORD DWORD int 加 args...(一包东西) 显而易见的:

第三步:


  1. DWORD xyGet(char* szpCHAR, int index, DWORD nd基质, DWORD nd中间值, int ndIndex, const Types&... args)
  2. {
  3.         __try
  4.         {
  5.                 return xyGet(szpCHAR, index, nd基质, *(DWORD*)(nd中间值 + ndIndex), args...);
  6.         }
  7.         __except (1)
  8.         {
  9.                 F输出调试信息("%s xyGet,基址:%4X 第%d层偏移:%4X 读取异常\r\n", szpCHAR, nd基质,index - sizeof...(args) + 1, ndIndex);
  10.                 return 0;
  11.         }
  12. }
复制代码

看它干了什么,再次调用了重载函数。前3个参数原封不动的传入,但是传入的第4个参数是什么?

nd中间值 是什么?没记住的去看第二步,它基地址里面读取出来的值把,ndIndex又是什么?它是那一包东西中的第一个数值,那一包东西是什么?可以去看第一步  一包东西 是那一堆偏移,显然我们读取了一层偏移。

看看我们现在传入调用函数什么东西: char int DWORD DOWRD加 一包东西。很熟悉把,和第三步一样 编译器有会从一包东西里面取一样东西出来 变成char int DWORD DWORD int 加 args...(一包东西)


那么很明显又会调用第三步的那货:


  1. DWORD xyGet(char* szpCHAR, int index, DWORD nd基质, DWORD nd中间值, int ndIndex, const Types&... args)
复制代码

程序陷入了递归循环,什么时候结束呢? 一包东西一个一个的取出来,总有一次递归会取干净。那么传入重载函数的参数会变成:szpCHAR, index, nd基质, (DWORD)(nd中间值 + ndIndex)
也就是 char* int DWORD DWORD , 这一堆参数有完美匹配的重载函数:


  1. DWORD xyGet(char* szpCHAR, int index, DWORD nd基质, DWORD nd中间值)
  2. {
  3.         return nd中间值;
  4. }
复制代码

看看他内部做了什么:

哦,直接返回了nd中间值,如果一包东西被消耗干净了,那么说明所有的偏移都被读取完毕,没错 这里返回了我们要的东西。



图片7.png

总结

本文章所提到的思路以及代码,是我在学习C++ 11新特性时 无意想到的,相对于C++ 98的半成品产品,C++ 11新标准明显更现代更经典更好用。

文章中所提到的代码已经经过测试 可以正常使用,或许会有轻微的效率和内存损失,强迫症们 务必不要在循环中调用。由于本人习惯问题,并未经常使用以上代码。所有我相信它肯定还有很多不足之处 和 提升优化的空间,在这里为大家提供思路,相信大家能有更加优秀的解决方案, 比如 “[[[0x12345678]+0x40C]+0x8]+0xC” 通过解析这类字符串来得到我们想要的,到时候分享出来我们一起交流和进步!



图片8.png

点评

666   广西壮族自治区桂林市  发表于 2020-7-23 11:48

发表于 2021-1-28 19:22:34 | 显示全部楼层   广东省潮州市
。。。。秀儿
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-23 19:04:21 | 显示全部楼层   湖南省长沙市
是这样嘛........  吐血.....
回复 支持 反对

使用道具 举报

结帖率:100% (4/4)

签到天数: 10 天

发表于 2020-7-23 12:03:25 | 显示全部楼层   浙江省金华市
C++的多半看不懂的
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表