当前位置: 首页 > ai >正文

【Cheat Engine】官方教程步骤8:多级指针 超详解!

目录

1.步骤8的题目

2.指针回顾

复习

四级指针C语言代码

反汇编代码

单步执行分析

画出整个地址图

4.教程解析

5.按CE步骤8教程的设计思路来写模拟多级指针的代码

代码

设计原因

某盘下载链接(压缩包无密码)

代码可视化图片

6.多级指针的应用

7.推荐阅读


1.步骤8的题目

2.指针回顾

复习

19.【C语言】指针(重难点)(A)-CSDN博客

37.【C语言】指针(重难点)(B)-CSDN博客

38.【C语言】指针(重难点)(C)-CSDN博客

39.【C语言】指针(重难点)(D)-CSDN博客

40.【C语言】指针(重难点)(E)-CSDN博客

43.【C语言】指针(重难点)(F)-CSDN博客

44.【C语言】指针(重难点)(G)-CSDN博客

45.【C语言】指针(重难点)(H)-CSDN博客

46.【C语言】指针(重难点)(I)-CSDN博客

47.【C语言】指针(重难点)(J)-CSDN博客

四级指针C语言代码

CE官方教程中用四级指针来训练,那么就以四级指针来分析

int main()
{int val = 1;int* p1 = &val;int** p2 = &p1;int*** p3 = &p2;int**** p4 = &p3;****p4 = 2;//val改成2return 0;
}

VS2022的属性页改两个地方,之后下断点至return 0,转到反汇编

反汇编代码

int main()
{push        ebp  mov         ebp,esp  sub         esp,54h  push        ebx  push        esi  push        edi  mov         ecx,offset _105D5803_FileName@cpp (06C000h)  call        @__CheckForDebuggerJustMyCode@4 (06130Ch)  nop  int val = 1;mov         dword ptr [val],1  int* p1 = &val;lea         eax,[val]  mov         dword ptr [p1],eax  int** p2 = &p1;lea         eax,[p1]  mov         dword ptr [p2],eax  int*** p3 = &p2;lea         eax,[p2]  mov         dword ptr [p3],eax  int**** p4 = &p3;lea         eax,[p3]  mov         dword ptr [p4],eax  ****p4 = 2;//val改成2mov         eax,dword ptr [p4]  mov         ecx,dword ptr [eax]  mov         edx,dword ptr [ecx]  mov         eax,dword ptr [edx]  mov         dword ptr [eax],2  return 0;xor         eax,eax  
}pop         edi  pop         esi  pop         ebx  mov         esp,ebp  pop         ebp  ret  

直接看重点,如何通过p1~p4指针来修改val

 mov         eax,dword ptr [p4]  
 mov         ecx,dword ptr [eax]  
 mov         edx,dword ptr [ecx]  
 mov         eax,dword ptr [edx]  
 mov         dword ptr [eax],2

将上面5条指令按汇编语法压缩成一条指令(虽然实际上不能这样写)

mov dword ptr [dword ptr [dword ptr [dword ptr [dword ptr [p4] ] ] ] ],2

如果不选择代码字节

 mov         eax,dword ptr [ebp-14h]  
 mov         ecx,dword ptr [eax]  
 mov         edx,dword ptr [ecx]  
 mov         eax,dword ptr [edx]  
 mov         dword ptr [eax],2

将上面5条指令按汇编语法压缩成一条指令(虽然实际上不能这样写)

mov dword ptr [dword ptr [dword ptr [dword ptr [dword ptr [ebp-14h] ] ] ] ],2

在逆向破解时可能情况更复杂,会有多个偏移,例如

mov dword ptr [dword ptr [dword ptr [dword ptr [dword ptr [ebp -14h]  +0c ] +3 ] +1f ] +1 ],2

单步执行分析

下断点至****p4 = 2;单步分析

 先跳到ebp-14h地址处

在寄存器窗口中观察eax寄存器的变化

跳到eax指向的地址

单步执行,观察ecx寄存器变化

跳到ecx指向的地址 

单步执行,观察edx寄存器变化  

跳到edx指向的地址  

 单步执行,观察eax寄存器变化 

 跳到eax指向的地址,发现就是val变量存储的地址

单步执行后,val已经被修改为2了

画出整个地址图

而逆向的过程即从一级指针找到四级指针

4.教程解析

打开CE教程:

输入密码:525927,点确定

载入进程:

 按照教程给出的数值搜索:

点击首次扫描:

看到3个有关地址,只有一个是正确的,在教程中单击"改变数值"后再次筛选

只有一个发生变动,

 右击,选择"找出是什么访问了这个地址"

 单击"Yes"

 在教程中单击"改变数值",看看调试器有什么反馈:

 发现有一个指令操作了这个值,右击点"详细信息"

mov [esi+18],eax中将eax的值放入esi+18指向的值,那么指针一定和esi有关

(注意记录此时的偏移+18,之后会用到)

 复制ESI的值后关闭调试器,勾选HEX,搜索ESI的值

发现只有一个结果,右击"找出是什么访问了这个地址"(注意不是改写,因为没有在教程中单击"改变指针",因此指针并没有变,只不过被访问到了)

 再次改变数值,,看看调试器有什么反馈:

选第二个看看:

ESI的值:019A9B10早就在之前搜索过,显然不是正确的地址,排除

 选第一个看看:

 ([esi]等价为[esi+0],注意记录此时的偏移+0,之后会用到)

关闭调试器,搜索ESI的值:

右击,选择"找出是什么访问了这个地址"

再次改变数值,,看看调试器有什么反馈:

选第一个查看详细信息:

选第二个查看详细信息:

 (注意记录此时的偏移+14,之后会用到)  

发现CE猜测指针的数值都是一样的,关闭调试器,搜索这个数值:

 右击,选择"找出是什么访问了这个地址"

再次改变数值,,看看调试器有什么反馈:

选第一个查看详细信息:

选第二个查看详细信息:

 (注意记录此时的偏移+0C,之后会用到)   

发现CE猜测指针的数值都是一样的,关闭调试器,搜索这个数值:

发现地址已经变成绿色的了,说明019A1298是基地址,每次程序启动这个地址的值都不会改变,

之前记录的偏移依次为:+18 +0 +14 +0C

则用指针访问这个值的方法是: [[[[019A1298 +0C ] +14] +0] +18]

右击,选择"将这个地址添加到地址列表"

在地址列表中双击这个地址来打开更改地址窗口

不要勾选"十六进制",勾选"指针",依次填入偏移量,单击"确定"

教程中单击"改变指针",试着将基址中的值更改为5000,并锁定它

发现下一步按钮变成可点击状态,任务完成

5.按CE步骤8教程的设计思路来写模拟多级指针的代码

理解了上述过程,可以写出如下代码来理解CE教程中设计的多级指针:

代码

#include <iostream>
#include <ctime>
using namespace std;
class Myclass4
{
public:int _val;bool b = true;
};class Myclass3
{
public:int _val=3;Myclass4* obj3;
};class Myclass2
{
public:int _val=0xFF;char c = 'x';Myclass3* obj2;
};class Myclass1
{
public:char _val='c';Myclass2* obj1;short s = 123;
};int main()
{cout << "初始化多级指针......" << endl;static Myclass1* g_obj;g_obj = new Myclass1;g_obj->obj1 = new Myclass2;g_obj->obj1->obj2 = new Myclass3;g_obj->obj1->obj2->obj3 = new Myclass4;srand((unsigned int)time(0));
loop:cout << "按1设置随机值,按其他键退出" << endl;char c;cin >> c;if (c == '1'){g_obj->obj1->obj2->obj3->_val  = rand() % 101;cout << "val的值设置为:" << g_obj->obj1->obj2->obj3 ->_val << endl;goto loop;}return 0;
}

设计原因

1. static Myclass1* g_obj;为静态指针,以此来演示基址

2.Myclass1到Myclass2添加了一些成员变量,以此来演示使用指针+偏移的形式访问

3.Myclass1中有Myclass2的指针,Myclass2中有Myclass3的指针,......以此来模拟多级指针

4. g_obj->obj1->obj2->obj3->_val为随机值,可手动变化,这样可使用CE多次搜索

经过尝试,发现如下规律:

保存为CT,下次程序启动时还能找到该值

演示视频:

多级指针详解的演示视频 

多级指针详解的演示视频

某盘下载链接(压缩包无密码)

链接: https://pan.baidu.com/s/1rbwUsgMzSF4-2m5X-C9rDQ?pwd=53g7  提取码: 53g7

代码可视化图片

来自:Python Tutor code visualizer: Visualize code in Python, JavaScript, C, C++, and Java

6.多级指针的应用

例如访问二维数组的元素,链表的遍历等,工程中Nginx源码的四级指针等

7.推荐阅读

34.【C语言之外】聊聊CE扫雷(XP版)作弊

41.【C语言之外】聊聊Cheat Engine官方教程步骤6的思考

http://www.xdnf.cn/news/389.html

相关文章:

  • 玩转Docker | 使用Docker部署tududi任务管理工具
  • 面向对象设计中的类的分类:实体类、控制类和边界类
  • Serving入门
  • B端管理系统:企业运营的智慧大脑,精准指挥
  • STM32的三种启动方式
  • Rsync+sersync2实现目录实时同步
  • 《解锁图像“高清密码”:超分辨率重建之路》
  • llama-factory微调报错:
  • MySQL——触发器
  • 使用C语言的cJSON中给JSON字符串添加转义
  • 7.vtk坐标系
  • 爬取B站视频弹幕的简易教程(下)
  • c++_csp-j算法 (1)
  • Win 11 重装 Ubuntu 双系统方法
  • [Java微服务组件]注册中心P3-Nacos中的设计模式1-观察者模式
  • 机械设计【】一些常用的技术要求
  • 使用 TensorFlow 和 Keras 构建 U-Net
  • STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统
  • Linux编译艺术:源码编译安装指南
  • SICAR 标准 安全门锁操作箱 按钮和指示灯说明
  • Linux线程——锁
  • 四级英语题型分析
  • 全链路灰度实现
  • 从FPGA实现角度介绍DP_Main_link主通道原理
  • 递归下降 ll(1) 型文法 识别二元组文法分析
  • libevent的bufferevent测试用例和使用方法(附带源码)
  • 筛选法(埃氏筛法)C++
  • 聊聊Doris的数据模型,如何用结构化设计解决实时分析难题
  • 【Linux我做主】make和makefile自动化构建
  • Python语法系列博客 · 第3期 数据结构入门(列表、元组、字典、集合)