一、CE的简单使用

1.CE的介绍

  • CE是一款什么软件:

    • CE修改器(Cheat Engine)是一款内存修改编辑工具,CE允许你修改游戏。它包括16进制编辑,反汇编程序,内存查找工具。与同类修改工具相比,它具有强大的反汇编功能,且自身附带了辅助工具制作工具,可以用它直接生成辅助工具

    • 页面如下:

2.CE的简单查找及修改数据

  • 假如现在你的电脑上正在运行一个exe文件,再复杂的exe文件,都是由一堆二进制数组成的

  • 可以用CE搜索任何一款没有加反调试功能的exe程序,打开后可以搜索和修改此时exe文件在内存中的数据

    比如现在我打开一款游戏,但是现在血量不多了,我想将血量加满,那么我们可以在游戏运行时使用CE打开游戏进程,接着可以找到血量对应内存中的数据是哪一块,可以将它修改

  • 现在点击左上角的电脑图标,这里会显示电脑上的应用程序和当前正在运行的进程

    如果有的软件加了反调试,这里就不会显示,打都打不开,后边中级阶段再去研究

  • 如果我现在想知道nag.exe这个程序的在内存中有多少个1字节的1,就是以1字节的内存为单位找数值1。那么在CE中加载它,接着将数值类型改为"字节",十六进制数写为"1",由于搜索的是精确的数值,那么扫描类型选"精确数值",点击首次扫描

  • 接着我们发现扫描出来的内存中,有两个颜色的地址中的数值都是1,绿色就是我们所说的基址,就是全局变量,下一次打开程序这些地址是不会发生变化的;黑色的可能是在堆中分的,也就是局部变量,下一次打开nag程序,黑色的地址可能会发生变化

    **怎么解释为什么显示这些数:看到第一行的0x026A01A1 1表示的是从0x026A01A1这个内存地址开始往后的1字节宽度存的就是1!**现在懂了数值类型是什么意思了叭。再举个例子:如果扫描的值为4字节的100,则最后显示出来的结果就是以显示的地址开始往后4字节宽度内存中存的值是100

  • 如果我们还想继续搜其他的数据,先点击新的扫描,接着设置好要扫描的内容即可

  • 扫描类型:还可以是大于指定值、在指定值之间等等;数值类型:还可以是string,4字节等

  • 找到我们想要的值以后,双击一下,接着会显示到下方栏中,再点击下方的数据修改即可:如果想改数值就双击数值;如果想修改地址就双击地址…

3.修改内存数据说明

  • 如果我们平时打开单机游戏修改内存中的值,改的就会生效
  • 但是现在很多网页端游或者需要连网和服务器交互的游戏,如果你修改此时客户端的游戏数据,只是改的客户端的数据,也就是你自己看的,但是服务器端的数据你是没有修改的,而且目前市面上大多连网游戏的服务端都有数据校验的,改了客户端的内存的值没有任何用

二、模拟CE扫描的功能

1.说明

  • 这一堆数据中存储了角色的血值信息,假设血值的类型为int类型,值为100(10进制),请列出所有可能的值以及该值对应的地址

    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09,
    0x00,0x20,0x10,0x03,0x03,0x0C,0x00,0x00,0x44,0x00,
    0x00,0x33,0x00,0x47,0x0C,0x0E,0x00,0x0D,0x00,0x11,
    0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xAA,0x00,
    0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x02,0x00,0x74,0x0F,0x41,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0A,0x00,
    0x00,0x02,0x74,0x0F,0x41,0x00,0x06,0x08,0x00,0x00,
    0x00,0x00,0x00,0x64,0x00,0x0F,0x00,0x00,0x0D,0x00,
    0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00
    

2.模拟思路

  • 先准备一大段数据(如上图),十六进制或者二进制都可以,这就模拟了任意exe文件的数据,可以使用char型数组来存放这100个十六进制数,因为这100个数都是两位十六进制,即1字节,那么使用char来存储就可以了

  • 现在在一堆数据中,我们需要找到值为100的数,100换成16进制为0x64,即找0x64,但是注意我们应该要给定100的数值类型:比如是1字节的100,还是2字节的200,还是4字节的100等,即给定一个宽度

    • 如果查找1字节的100,则从头到尾依次查找0x64即可

    • 如果查找2字节的100,则从头到尾依次查找0x0064即可(在内存中会显示64 00,因为内存是反着存的,从低位到高位),但是要注意不是2字节2字节跳着查找,而是从第一个地址开始,往后数两字节宽度,如果是0x0064即把这个地址返回;接着再从第二个地址开始查找(而不是直接从第三个地址查)!即从第二个地址开始往后数两字节宽度,如果是0x0064(内存中显式64 00)则把第二个地址返回。所以还是要一个地址一个地址挨着查找,每到一个地址,取后面的2字节宽度来判断是否是0x0064

      因为如果是00,64,00,00,64,00…虽然我们查的是2字节的100,即0x0064,但是不知道起始地址从哪开始。这个例子中,从第一个地址开始往后的2字节是0x6400;但是如果我们直接从第三个地址开始0x0000不满足;接着又从第五个地址开始0x0064,那么此时就会漏一个0x0064,因为第二个地址开始往后数两个字节值也是0x0064(记得反过来从内存中读数)。所以查找2字节的100,不能以两字节为单位跳着查找!那么还是要一个地址一个地址挨着查找,每到一个地址,取后面的2字节宽度来判断是否是0x0064

    • 如果查找4字节的100,同理还是要一个地址一个地址挨着查找,每到一个地址,取后面的4字节宽度来判断是否是0x00000064,不能以4字节跳着查

3.实现步骤

  • C语言代码如下:

    #include "stdafx.h"char blood[100] = {  //全局变量0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09,0x00,0x20,0x10,0x03,0x03,0x0C,0x00,0x00,0x44,0x00,0x00,0x33,0x00,0x47,0x0C,0x0E,0x00,0x0D,0x00,0x11,0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xAA,0x00,0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x74,0x0F,0x41,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0A,0x00,0x00,0x02,0x74,0x0F,0x41,0x00,0x06,0x08,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0x0F,0x00,0x00,0x0D,0x00,0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00
    };void findblood(int size){if(size == 2){   //数值类型为short时,即2字节short* temp = (short*)blood;    //因为每次定位到一个地址,要查的数是从这往后2字节,所以先强转for(int i = 0;i < 100 - size + 1;i++){if(*(temp) == 100){         //因为temp是short*类型,所以取的地址宽度为2字节printf("%x\t%d\n",temp,*temp);}char* temp2 = (char*)temp;  //因为要一个一个地址挨着找,所以先转换成char*类型,如果拿               short*的temp直接++,那么结果就是源temp中地址+2*1,就不是依次逐个地址找了,就是跳了一个temp2++;                   //那么char*变量在++时,结果为:地址 + char宽度,即下一个地址temp = (short*)temp2;//然后再将下一个地址的值赋给temp,下次比较就是从temp往后数2字节是否                                是0x0064}}else if(size == 4){    //数值类型为int时,即4字节int* temp = (int*)blood;for(int i = 0;i < 100 - size + 1;i++){  //因为如果4字节为单位,则查到倒数第4个地址就是最后                                                 一个地址了,就不用继续我往后查了if(*(temp) == 100){printf("%x\t%d\n",temp,*temp);}char* temp2 = (char*)temp;temp2++;temp = (int*)temp2;}}else{       //数值类型为char时,即1字节for(int i = 0;i < 100 - size + 1;i++){if(*(blood + i) == 100){printf("%x\t%d\n",(blood + i),*(blood + i));}}}}int main(int argc,char* argv[]){printf("result:\n");int size = 2;   //当数值类型为short时findblood(size);printf("\n\n");size = 1;       //当数值类型为char时findblood(size);printf("\n\n");size = 4;       //当数值类型为int时findblood(size);printf("\n\n");return 0;
    }
    

    第二遍学时的改进:

    #include "stdafx.h"char data[100] = {  //全局变量0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09,0x00,0x20,0x10,0x03,0x03,0x0C,0x00,0x00,0x44,0x00,0x00,0x33,0x00,0x47,0x0C,0x0E,0x00,0x0D,0x00,0x11,0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xAA,0x00,0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x74,0x0F,0x41,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0A,0x00,0x00,0x02,0x74,0x0F,0x41,0x00,0x06,0x08,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0x0F,0x00,0x00,0x0D,0x00,0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00
    };
    int length = sizeof(data) / sizeof(data[0]);void find_blood(int num,int width){  //输入要查找的数值,查找宽度if(width == 1){for(int i = 0;i < length - width + 1;i++){if(*(data + i) == num)printf("add:%x  num:%d\n",data + i,*(data + i));}}else if(width == 2){for(int i = 0;i < length - width + 1;i++){short* p = (short*)(data + i);  //直接使用char* data++,但是每次判断前把当前地址转型赋给一个新short* p即可,不需要上面那么麻烦if(*p == num){printf("add:%x  num:%d\n",p,*p);}}}else if(width == 4){for(int i = 0;i < length - width + 1;i++){int* p = (int*)(data + i);if(*p == num){printf("add:%x  num:%d\n",p,*p);}}}else{printf("宽度不符合规定");}}int main(int argc, char* argv[])
    {printf("%x\n",data);find_blood(256,2);getchar();return 0;
    }
    
    • 内存图和结果如下:

  • 我们来分析一下short:当选择查询的数据类型为2字节时,从第一个地址开始查

    • 当查到0x424A52时,从这个地址开始往后数2字节在内存中显式为64 00,那么由于VC的堆栈图和内存都是反的:从低地址往高地址显式,那么此时我们应该读作0x0064,换算成十进制就是100,满足要求;

    • 当查到0x424A5A时,虽然此地址是0x64,但是我们选择的数据类型为2字节,所以应该从地址往后数2字节,内存显式为64 10,我们读作0x1064,所以不满足要求,则不要

    • 当查到0x424A83时,从此地址开始往后数2字节,内存显式为64 00,我们读作0x0064,所以满足要求

    • 后面依次类推

  • 再分析一下int类型:也是从第一个地址开始逐个往后查,当查到0x424A52时,往后数4字节内存显式为64 00 00 00,我们读作0x00000064,所以满足要求。其他的4字节为单位都不满足要求

day20.1-CE基本使用与原理相关推荐

  1. 2023-01-20 网工进阶(三十九)MPLS 虚拟专用网络---概述、路由交互、CE接入PE方法、基本组网方案详解、团体属性、防环、MCE组网、伪连接方案、跨域组网详解、各种组网方案配置举例

    概述 VPN(Virtual Private Network,虚拟专用网络)指的是在一个公共网络中实现虚拟的专用网络,从而使得用户能够基于该专用网络实现通信的技术.MPLS VPN也是VPN技术中的一 ...

  2. CE Loss,BCE Loss以及Focal Loss的原理理解

    一.交叉熵损失函数(CE Loss,BCE Loss) 最开始理解交叉熵损失函数被自己搞的晕头转向的,最后发现是对随机变量的理解有偏差,不知道有没有读者和我有着一样的困惑,所以在本文开始之前,先介绍一 ...

  3. DAVINCI开发原理之三----达芬奇编解码引擎Codec Engine(CE)

    DaVinci是DSP和ARM 双核架构的SOC芯片.对芯片与外界的交互通过ARM端的Montavista Linux和相关驱动与应用程序来管理, DSP端只处理编解码相关的算法.DSP和ARM之间的 ...

  4. java signature 性能_Java常见bean mapper的性能及原理分析

    背景 在分层的代码架构中,层与层之间的对象避免不了要做很多转换.赋值等操作,这些操作重复且繁琐,于是乎催生出很多工具来优雅,高效地完成这个操作,有BeanUtils.BeanCopier.Dozer. ...

  5. 目标检测 | 清晰易懂的SSD算法原理综述

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 SSD(Single Shot Detection)是一个流行且强 ...

  6. html5游戏变速,深入游戏变速底层原理以及内核变速的实现

    深入 0x7FFE0000 SharedUserData 我们百度0x7FFE0000这个地址,得到了一个叫做 SharedUserData 的东东,是个内核的映射,Ring3下是只读的,所以如上,我 ...

  7. 天线开路短路检测原理_变频空调通讯电路原理与元件级维修

    通讯故障在变频空调器维修中占有较大比率,虽然品牌型号种类繁多但是其通讯电路工作原理雷同,下面我就以常见的格力直流变频空调器典型通信电路为例加以解说. 一.通讯原理 室内外机的通讯信号由0和1组成的数码 ...

  8. VC++下命名管道编程的原理及实现

    概述 管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机.命名管道(Named Pipes)是在管道服务器和一台或多台管道客户机之间进行 ...

  9. git入门:概念、原理、使用

    git和Github 概念 Git --- 版本控制工具(命令). 工具介绍官方网站:http://git-scm.com 工具下载地址:http://git-scm.com/download/ gi ...

最新文章

  1. 构造类斐波那契数列矩阵(矩阵
  2. 总结一下qsort()函数的使用与注意
  3. ASP.NET Core 实战:基于 Jwt Token 的权限控制全揭露
  4. linux-远程管理-xshell
  5. 随想录(从开源的宝库中学习)
  6. 重访 list comprehension
  7. 《JavaScript高级程序设计》阅读笔记(十五):浏览器中的JavaScript
  8. Java常用集合类详解
  9. 安装金山词霸2007
  10. 计算机硬盘突然只有一个c盘,win10硬盘消失了只剩下c盘怎么恢复_win10硬盘突然消失只有c盘解决方法-win7之家...
  11. 【QT】简单易学的QT安装教程
  12. 华为服务器sn码查询网站,linux 查询服务器sn号
  13. iis设置开启GZIP网页压缩功能
  14. 一个简单的例子来理解监督学习和非监督学习及其区别
  15. 【读书向】阿里云天池大赛赛题解析——可视化
  16. 数字孪生是什么,数字孪生能干什么?一文读懂
  17. 使用 Kali Linux 爆破 WiFi 密码
  18. SCT2650STER、SCT2450STER、SCT2630ASTER 北京冠宇铭通
  19. 关于AML芯片电视,风行刷机包的自定义和去广告的研究
  20. FPGA模拟PS2接口的方法

热门文章

  1. ISP嵌入式平台/成像sensor
  2. 那些改变过世界的代码都是怎么写的?
  3. Grads转成Netcdf
  4. python如何启动前端_Python入门(一)-打开世界之Hello World
  5. ubuntu 安装 acrobat reader
  6. c语言背包问题装字母,C语言动态规划之背包问题详解
  7. Surface 3 重做系统官方步骤
  8. multisim12 仿真运放结果不对问题解决
  9. Java通过selenium+ashot对网页进行长截屏
  10. 【VPR】 Graphics - vpr的图形界面