87.游戏改造-UI修正全面分析

news2024/9/27 6:49:05

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

内容参考于:易道云信息技术研究院

上一个内容:86.游戏改造-UI修正暴力分析

首先来到下图位置

一个函数上来就 ECX+4 这种不用想直接就看作为成员函数,按CTRL + f9再按f7来到调用它的地方可以看到是 MOV ECX,Sword2-1.0044A928 这样的传参可以看作为是一个类了

 首先它ecx+4 放到了 EAX里,然后又做了 TEST EAX,EAX,所以ecx+4位置是一个布尔类型的值,代码可能就是

class UI{
    unsigned 未知;
    unsigned Show;// BOOL或bool +0x04
}

然后ECX+8放到了eax里面,是把ECX+8地址的值放到了eax里

class UI{
    unsigned 未知;
    unsigned Show;// BOOL或bool +0x4
    unsigned UN; // 0x8
    void ShowUI(){ // 00407A20 - 00407A30位置是一个成员函数假设这个函数叫ShowUI
          if(Show)  
    }
}

然后打断点分析ecx+0x8位置是什么东西,现在ecx的值是447D90也是我们上面写的UI类的地址

然后它把下图红框位置的值(4357D4)读出来放到了EAX里,然后ADD ecx,0x8然后jmp了4357D4+0x8(eax+0x8),4357D4+0x8这样的写法可能是访问成员变量也可能是访问数组,jmp过去之后是一段完完整整可执行代码然后可以看出EAX+0x8的值是一个函数地址,它的值是通过UN指向的数据偏移了8字节得出来的所以这是典型虚函数的表现

跳转到4357D4位置可以看出是一个虚表,每一个值都是一个虚函数的函数地址

随便找一个值跳过去可以看出确实是一段完整的函数代码,所以这一定是虚函数了ECX+0x8就是调用的虚函数

 虚函数是会出现在一个类的头部,所以可以得出UN是一个类,然后eax+0x8位置是虚表中第三个函数,然后调用虚函数一定会传它的指针,然后eax是通过ecx+8得到,然后00407A2A位置的代码进行的add ecx,8紧接着就jmp到虚函数了,然后现在的c++代码如下:

class UIEx{
    
}
class UI{
    unsigned 未知;
    unsigned Show;// BOOL或bool +0x4
    UIEx ui; // 0x8,ecx+0x8
    void ShowUI(){ // 00407A20 - 00407A30位置是一个成员函数假设这个函数叫ShowUI
          if(Show)  {
          
          }
     }
}

然后如果代码是如上的写法又很奇怪,它不是通过对象去调用的函数而是通过指针(0x4357D4这个地址)调用的,然后它有可能是多重继承,如下的写法,

class UIBase{
    unsigned 未知;
    unsigned Show;// BOOL或bool +0x4
}
class UIEx{
    public virtual void _func1(); // 0x0
    public virtual void _func2(); // 0x4
    public virtual void _Show(); // 0x8
}
class UI:public UIBase, public UIEx{ 
    void ShowUI(){ // 00407A20 - 00407A30位置是一个成员函数假设这个函数叫ShowUI
          if(Show)  {
              _Show(); // 0x8
          }
     }
}

首先通过ECX+4访问了 基类(UIBase)的Show变量,然后通过ecx+0x8有访问了基类(UIEx)的_Show函数

00407A20  /$  8B41 04       MOV EAX,DWORD PTR DS:[ECX+4]
00407A23  |.  85C0          TEST EAX,EAX
00407A25  |.  74 09         JE SHORT Sword2-1.00407A30
00407A27  |.  8B41 08       MOV EAX,DWORD PTR DS:[ECX+8]
00407A2A  |.  83C1 08       ADD ECX,8
00407A2D  |.  FF60 08       JMP DWORD PTR DS:[EAX+8]
00407A30  \>  C3            RETN

然后来到eax+0x8位置的函数(_Show函数)

0040BF70   .  56            PUSH ESI                                ; 保存的ESI的值
0040BF71   .  8BF1          MOV ESI,ECX                             ;ECX是UIEx类首地址
0040BF73   .  8B46 50       MOV EAX,DWORD PTR DS:[ESI+50]           ; UIEx+0x50位置是一个变量
0040BF76   .  85C0          TEST EAX,EAX
0040BF78      74 11         JE SHORT Sword2-1.0040BF8B
0040BF7A   .  8B06          MOV EAX,DWORD PTR DS:[ESI]              ;ESI是UIEx首地址这是虚表,所以又把虚表给到了EAX
0040BF7C   .  FF50 0C       CALL DWORD PTR DS:[EAX+C]
               ;然后这里调用了虚表函数UIEx+0xC位置又是一个函数
0040BF7F   .  8B4E 5C       MOV ECX,DWORD PTR DS:[ESI+5C]           ;然后ESI+5C位置又是一个变量,通过下面的代码分析它是一个指针是一个类的指针
0040BF82   .  85C9          TEST ECX,ECX
0040BF84   .  74 05         JE SHORT Sword2-1.0040BF8B
0040BF86   .  8B11          MOV EDX,DWORD PTR DS:[ECX]              
0040BF88   .  FF52 08       CALL DWORD PTR DS:[EDX+8]               ;这里调用了ECX这里是一个指针,又是调用虚表,它调用的又是当前函数(0040BF70),一个递归函数,可以看下面的 图1
0040BF8B   >  8B4E 58       MOV ECX,DWORD PTR DS:[ESI+58]           ;ESI+58位置又是一个指针可以看图2
0040BF8E   .  5E            POP ESI
0040BF8F   .  85C9          TEST ECX,ECX
0040BF91   .  74 05         JE SHORT Sword2-1.0040BF98
0040BF93   .  8B01          MOV EAX,DWORD PTR DS:[ECX]
0040BF95   .  FF60 08       JMP DWORD PTR DS:[EAX+8]               ;又来了一次递归
0040BF98   >  C3            RETN

翻译成c++代码

class UIBase{
    unsigned 未知;
    unsigned Show;// BOOL或bool +0x4
}
class UIEx{
    public virtual void _func1(); // 0x0
    public virtual void _func2(); // 0x4
    public virtual void _Show(){ // 0x8
            if(SHOW_UI){
                  _func3();
            }
            if(uiex)uiex->_Show();
            if(uiex_f){
                   uiex_f->_Show();         
            }
    }
    public virtual void _func3(); // 0xC
    // 前4字节指向虚表
    unsigned UN[12];
    // 0x50除0x4结果是14
    unsigned SHOW_UI; // 0x50
    unsigned UN1; // 0x54
    UIEx* uiex_f; // 0x58
    UIEx* uiex; // 0x5C,上面的汇编代码它是一个递归,可以想想UIEx是一个链表0x5c位置有指向下一个链表
}
class UI:public UIBase, public UIEx{ 
    void ShowUI(){ // 00407A20 - 00407A30位置是一个成员函数假设这个函数叫ShowUI
          if(Show)  {
              _Show(); // 0x8
          }
     }
}

然后把 0x5C(uiex)改成JMP发现那些小图标都没有了

然后把0x58(uiex_f)位置改成JMP,发现也有一部分图标没有了

把0x50(SHOW_UI)位置改为JMP发现全没了

可以总结出它的ui图标是通过链表调用同一个虚函数来展示的

图1:EDX虚表

图2

 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2077410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

羚羊软件:处理sql server 2008 R2 Error 9003

在很多情况下,服务器突然断电或其他原因会造成,数据库附加时出现:错误代码为90003的错误。 解决办法: 1、新建一个同名得数据库(Ly_Men_16_2005)。 2、停止SQL服务。 3、用原来得主数据库文件,覆盖新建得…

使用在AMD GPU上运行的ROCm进行大语言模型的自然语言处理任务

Performing natural language processing tasks with LLMs on ROCm running on AMD GPUs — ROCm Blogs 在这篇博客中,您将学习如何使用在AMD的Instinct GPU上运行的ROCm进行一系列流行且有用的自然语言处理(NLP)任务,使用不同的大…

CSS学习笔记(01)flex布局

1、首先对父元素设置disiplay:felx, 其有6个属性 fex-direction:设置主轴的方向 justify-content:设置主轴上的子元素排列方式 flex-wrap:设置子元素是否换行 align-content:设置侧轴上的子元素的排列方式(多行) align-items:设置侧轴上的子元素排列方式…

Debain 安装 MySql

一 Debian安装MySQL 5.7 1 更新安装列表 sudo apt update 2 添加MySql官方APT仓库到Debian wget https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb sudo dpkg -i mysql-apt-config_0.8.22-1_all.deb先下载再安装源,如下图: 再次执行更新…

从零到一,2024年数据恢复软件新手到专家指南

在数字化的时代,相信你的数据大部分也都是存在一些电子设备里吧。很多时候因为一些意外情况会导致我们数据的丢失,这个时候有什么办法能恢复我们的数据资料呢?这次我们就来一起探讨一些大家都在用的数据恢复工具吧。 1.福昕数据恢复 链接直…

热点 | 爆款游戏的诞生与游戏出海的持续增长

近日,《黑神话:悟空》一经上线就在国内获得了空前的关注。国产大IP3A国际水准带来的超炫视觉体验专业发行与市场营销等,共同引爆了这个现象级的话题。同时,我们也关注到,这款游戏同时在海外多个发行平台进行全球发售。…

Redis 源码安装

目录 1 Redis 的获取 2 Redis 部署 2.1 下载并解压 2.2 Makerfile 文件 2.3 安装所需要编译所需要的包 2.4 开始源码编译 2.5 utils 下的 install_server.sh 脚本文件 2.5 运行脚本进行安装 3 systemd 管理 3.1 编写Redis systemd 服务脚本 3.2 重新加载 systemd 系统 3.3 …

Apache CloudStack Official Document 翻译节选(九)

关于 Apache CloudStack 的 最佳实践 (三) 配置云外的 防火墙与交换机 对Cisco VNMC(Cisco Virtual Network Management Center)设备集成云外的客户机网路防火墙: 思科虚拟网络管理中心为思科网络虚拟服务提供了中心…

考试:计算机网络(01)

网络功能和分类 计算机网络是计算机技术与通信技术相结合的产物,它实现了远程通信、远程信息处理和资源共享。 计算机网络的功能:数据通信、资源共享、管理集中化、实现分布式处理、负载均衡。 网络性能指标:速率、带宽(频带宽度或传送线路…

我的新书《Android系统多媒体进阶实战》正式发售

我的新书要正式发售了,把链接贴在下面,感兴趣的朋友可以支持下。 ❶发售平台:当当,京东,抖音北航社平台,小红书,b站 ❷目前当当和京东已开启预售 ❸当当网 https://u.dangdang.com/KIDHJ ❹…

机器人语音聊天绕坑

为了给机器人添加语音,网上淘了一块离线语音芯片,用过之后就有些后悔了。离线语音定制性比较差,有150句限制,而且与大模型接驳需要一块额外的esp8266或者esp32。如果使用了esp32,事实上可以自己制作离线语音&#xff0…

【多线程】深入剖析线程安全问题

💐个人主页:初晴~ 📚相关专栏:多线程 / javaEE初阶 前言 线程安全问题是在多线程学习中一个十分重要的话题。多个线程并发执行就容易产生许多冲突与问题,如何协调好每个线程的执行,让多线程编程“多而不乱…

图神经网络实战(19)——异构图神经网络

图神经网络实战(19)——异构图神经网络 0. 前言1. 异构图1.1 异构图基本概念1.2 构建异构图数据集 2. 将同构图神经网络转换为异构图神经网络2.1 数据集介绍2.2 同构图注意力网络2.3 异构图神经网络 小结系列链接 0. 前言 我们已经学习了如何生成包含不…

4、Unity【基础】画线功能Linerenderer、物理系统Physics

文章目录 画线功能Linerenderer1、LineRenderer是什么2、LineRender参数相关3、LineRender代码相关思考1 请写一个方法,传入一个中心点,传入一个半径,用LineRender画个圆出来思考2 在Game窗口长按鼠标用LineRender画出鼠标移动的轨迹 核心系统…

Android studio设置国内镜像代理(HTTP Proxy)教程详解

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂,风趣幽默",感觉非常有意思,忍不住分享一下给大家。 👉点击跳转到教程 1、Android Studio是在谷歌的服务器上,初次安装Android Studio时下载SDK可能…

6Valley 14.2 免授权php – 跨境电商在线商城 – 完整的电子商务APP端和web端程序

6Valley 14.2 Nulled – 多供应商电子商务 – 完整的电子商务移动应用程序、Web、卖家和管理面板 后台可自定义收款,和翻译多国语言,中文需要自己对比翻译!一般用不到中文。毕竟是跨境电商平台 带商家即时通讯,全套带文档和APP双…

Spring(2)

目录 一、使用注解开发 1.1 主要注解 1.2 衍生注解 1.3 xml与注解 二、使用Java的方式配置Spring 三、代理模式 3.1 静态代理 3.1.1 角色分析 3.1.2 代码步骤 3.1.3 优点 3.1.4 缺点 3.2 动态代理 3.2.1 代码步骤 四、AOP 4.1 使用Spring的API接口 4.2 使用自定义…

云计算实训36——mysql镜像管理、同步容器和宿主机时间、在容器外执行容器内命令、容器的ip地址不稳定问题、基础镜像的制作、镜像应用

一、线上考试系统的数据虚拟化技术部署 1.部署前段服务器 步骤一:将资源上传到服务器 将dist.zip上传给服务器 下载unzip的包 yum -y install unzip 解压 unzip dist.zip 步骤二:创建基础容器在服务器上 启动服务 systemctl start docker.servic…

LVS部署——DR集群

目录 一、LVS—DR工作原理 二、LVS-DR数据流向 三、LVS-DR模式特点和优缺点 3.1、特点 3.2、优缺点 四、LVS-DR中的ARP问题 4.1、IP地址冲突 4.2、第二次访问请求失败 五、部署LVS-DR集群 5.1、实验准备 5.2、配置负载调度器(192.168.20.15) …

SeaweedFS 分布式存储安装weed

下载Single Binary weed Start 官方推荐 https://github.com/seaweedfs/seaweedfs 下载 https://github.com/seaweedfs/seaweedfs/releases解压 single binary file weed or weed.exe. wget https://github.com/seaweedfs/seaweedfs/releases/download/3.72/darwin_amd64.…