debug - 打补丁 - 浮点数加法

文章目录

    • debug - 打补丁 - 浮点数加法
    • 概述
    • 笔记
    • demo
    • 用CE查看汇编(x64debug)
    • main()
    • update_info()
    • 快捷键 - CE中查看代码时的导航
    • 打补丁的时机 - 浮点数加法
    • 补丁代码
    • 补丁效果
    • 浮点数寄存器组的保存
    • END

debug - 打补丁 - 浮点数加法

概述

在cm中, UI上显示的数值仅仅用来显示, 改这个显示值没用.
显示时, 是从一个结构体中取出值(浮点数), 然后转成整数显示.
写了一个demo(vs2019 + console + debug/x64), 模拟结构体信息中的浮点数赋值和浮点数的显示.
用CE来看, 和cm中取值显示的汇编实现很像.
拿自己写的demo, 来打个补丁, 让显示之前, 先对结构体中的浮点值加上一些额外的值, 然后再去显示
这样的话, 显示值和结构体中的值就一致了.

笔记

demo

/*!
* \file fDataOpt.cpp
* \brief 测试在汇编中的浮点数操作的打补丁(浮点加法)
*/#include <windows.h>#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cstdint>typedef struct _tag_info
{int id;float money;
} TAG_INFO;void init();
int rand_ranged(int range_min, int range_max);
void update_info(TAG_INFO& info);int main()
{TAG_INFO info;memset(&info, 0, sizeof(info));init();do {Sleep(1000);update_info(info);printf("money = %d\n", (int)info.money);if (info.money >= 9999) {break;}} while (true);system("pause");return 0;
}void update_info(TAG_INFO& info)
{info.id = 0x1000;info.money += (float)rand_ranged(1, 10);
}void init()
{srand(0215);
}int rand_ranged(int range_min, int range_max)
{// Generate random numbers in the interval [range_min, range_max], inclusive.// Note: This method of generating random numbers in a range isn't suitable for// applications that require high quality random numbers.// rand() has a small output range [0,32767], making it unsuitable for// generating random numbers across a large range using the method below.// The approach below also may result in a non-uniform distribution.// More robust random number functionality is available in the C++ <random> header.// See https://learn.microsoft.com/cpp/standard-library/randomreturn (int)(((double)rand() / RAND_MAX) * (range_max - range_min) + range_min);
}

用CE查看汇编(x64debug)

main()


fDataOpt.main - 40 55                 - push rbp
fDataOpt.main+2- 57                    - push rdi
fDataOpt.main+3- 48 81 EC 08010000     - sub rsp,00000108 { 264 }
fDataOpt.main+A- 48 8D 6C 24 20        - lea rbp,[rsp+20]
fDataOpt.main+F- 48 8D 7C 24 20        - lea rdi,[rsp+20]
fDataOpt.main+14- B9 0A000000           - mov ecx,0000000A { 10 }
fDataOpt.main+19- B8 CCCCCCCC           - mov eax,CCCCCCCC { -858993460 }
fDataOpt.main+1E- F3 AB                 - repe stosd 
fDataOpt.main+20- 48 8B 05 F1B50000     - mov rax,[fDataOpt.__security_cookie] { (192) }
fDataOpt.main+27- 48 33 C5              - xor rax,rbp
fDataOpt.main+2A- 48 89 85 D8000000     - mov [rbp+000000D8],rax
fDataOpt.main+31- 48 8D 0D ED050100     - lea rcx,[fDataOpt.exe+22015] { (1) }
fDataOpt.main+38- E8 52F9FFFF           - call fDataOpt.exe+1137F
fDataOpt.main+3D- 41 B8 08000000        - mov r8d,00000008 { 8 }
fDataOpt.main+43- 33 D2                 - xor edx,edx
fDataOpt.main+45- 48 8D 4D 08           - lea rcx,[rbp+08]
fDataOpt.main+49- E8 92F8FFFF           - call fDataOpt.exe+112D0 { memset()}
fDataOpt.main+4E- E8 66F7FFFF           - call fDataOpt.exe+111A9 { init()}
fDataOpt.main+53- B9 E8030000           - mov ecx,000003E8 { 1000 }
fDataOpt.main+58- FF 15 B2F50000        - call qword ptr [fDataOpt._imp_Sleep] { ->KERNEL32.Sleep }
fDataOpt.main+5E- 48 8D 4D 08           - lea rcx,[rbp+08]
fDataOpt.main+62- E8 9DF7FFFF           - call fDataOpt.exe+111F4 { update_info()}
fDataOpt.main+67- F3 0F2C 45 0C         - cvttss2si eax,[rbp+0C] { 浮点数强转整数}
fDataOpt.main+6C- 8B D0                 - mov edx,eax
fDataOpt.main+6E- 48 8D 0D 43920000     - lea rcx,[fDataOpt.exe+1ACA8] { ("money = %d
") }
fDataOpt.main+75- E8 30F7FFFF           - call fDataOpt.exe+1119A { printf()}
fDataOpt.main+7A- F3 0F10 45 0C         - movss xmm0,[rbp+0C] { 载入浮点数}
fDataOpt.main+7F- 0F2F 05 56920000      - comiss xmm0,[fDataOpt.exe+1ACCC] { (9999.00) }
fDataOpt.main+86- 72 02                 - jb fDataOpt.main+8A
fDataOpt.main+88- EB 07                 - jmp fDataOpt.main+91
fDataOpt.main+8A- 33 C0                 - xor eax,eax
fDataOpt.main+8C- 83 F8 01              - cmp eax,01 { 1 }
fDataOpt.main+8F- 75 C2                 - jne fDataOpt.main+53
fDataOpt.main+91- 48 8D 0D 30920000     - lea rcx,[fDataOpt.exe+1ACB8] { ("pause") }
fDataOpt.main+98- FF 15 3AF80000        - call qword ptr [fDataOpt._imp_system] { ->ucrtbased.system }
fDataOpt.main+9E- 33 C0                 - xor eax,eax
fDataOpt.main+A0- 8B F8                 - mov edi,eax
fDataOpt.main+A2- 48 8D 4D E0           - lea rcx,[rbp-20]
fDataOpt.main+A6- 48 8D 15 E3910000     - lea rdx,[fDataOpt.exe+1AC80] { (1) }
fDataOpt.main+AD- E8 79F8FFFF           - call fDataOpt.exe+1131B
fDataOpt.main+B2- 8B C7                 - mov eax,edi
fDataOpt.main+B4- 48 8B 8D D8000000     - mov rcx,[rbp+000000D8]
fDataOpt.main+BB- 48 33 CD              - xor rcx,rbp
fDataOpt.main+BE- E8 05F7FFFF           - call fDataOpt.exe+111B8
fDataOpt.main+C3- 48 8D A5 E8000000     - lea rsp,[rbp+000000E8]
fDataOpt.main+CA- 5F                    - pop rdi
fDataOpt.main+CB- 5D                    - pop rbp
fDataOpt.main+CC- C3                    - ret 
fDataOpt.exe+11ABD- CC                    - int 3 

update_info()

fDataOpt.update_info - 48 89 4C 24 08        - mov [rsp+08],rcx { rcx是结构体指针}
fDataOpt.update_info+5- 55                    - push rbp
fDataOpt.update_info+6- 57                    - push rdi
fDataOpt.update_info+7- 48 81 EC E8000000     - sub rsp,000000E8 { 232 }
fDataOpt.update_info+E- 48 8D 6C 24 20        - lea rbp,[rsp+20]
fDataOpt.update_info+13- 48 8D 0D 6B070100     - lea rcx,[fDataOpt.exe+22015] { (1) }
fDataOpt.update_info+1A- E8 D0FAFFFF           - call fDataOpt.exe+1137F
fDataOpt.update_info+1F- 48 8B 85 E0000000     - mov rax,[rbp+000000E0] { rbp + 0xE0 也是结构体指针}
fDataOpt.update_info+26- C7 00 00100000        - mov [rax],00001000 { 4096 }
fDataOpt.update_info+2C- BA 0A000000           - mov edx,0000000A { 10 }
fDataOpt.update_info+31- B9 01000000           - mov ecx,00000001 { 1 }
fDataOpt.update_info+36- E8 80F7FFFF           - call fDataOpt.exe+1104B { 产生随机数(1~10)}
fDataOpt.update_info+3B- F3 0F2A C0            - cvtsi2ss xmm0,eax { eax是返回的随机数
cvtsi2ss 是将4字节内容整型内容, 强转为浮点数(e.g. 1 => 1.0f)}
fDataOpt.update_info+3F- 48 8B 85 E0000000     - mov rax,[rbp+000000E0] { rbp + 0xE0是结构体指针}
fDataOpt.update_info+46- F3 0F10 48 04         - movss xmm1,[rax+04] { 将info.money给xmm1}
fDataOpt.update_info+4B- F3 0F58 C8            - addss xmm1,xmm0 { 2个浮点数相加}
fDataOpt.update_info+4F- 0F28 C1               - movaps xmm0,xmm1 { 浮点数拷贝}
fDataOpt.update_info+52- 48 8B 85 E0000000     - mov rax,[rbp+000000E0]
fDataOpt.update_info+59- F3 0F11 40 04         - movss [rax+04],xmm0 { 浮点数转为2进制存储, 更新money}
fDataOpt.update_info+5E- 48 8D A5 C8000000     - lea rsp,[rbp+000000C8]
fDataOpt.update_info+65- 5F                    - pop rdi
fDataOpt.update_info+66- 5D                    - pop rbp
fDataOpt.update_info+67- C3                    - ret 
fDataOpt.update_info+68- CC                    - int 3 

看了汇编实现, 就大概知道怎么给显示前的值打补丁(浮点加法)

快捷键 - CE中查看代码时的导航

在这里插入图片描述
如果不知道导航键, 在查看代码时, 无法回到查看的原始点. 只能按F8执行一步, 那样太麻烦了, 耽误事.

打补丁的时机 - 浮点数加法

在这里插入图片描述
在浮点数更新完, 即将要显示的时候, 打补丁.
打完补丁后, 浮点数增加了, 再执行原始的取浮点数的汇编代码.

补丁代码

[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048,"fDataOpt.exe"+11A57) 
label(returnhere)
label(originalcode)
label(exit)newmem: //this is allocated memory, you have read,write,execute access
//place your code here// save env
push rax// do task
movss xmm1, [rbp+0x0C] // 将info.money给xmm1// 在原始值上加100(CE的汇编写法中, 数字默认都是16进制)
mov eax, 0x64
cvtsi2ss xmm0,eax // eaxcvtsi2ss 是将4字节内容整型内容, 强转为浮点数(e.g. 1 => 1.0f)addss xmm1,xmm0 // 2个浮点数相加movss [rbp+0x0C], xmm1 // 更新改过的info.money到info结构体// restore env
pop raxoriginalcode:
cvttss2si eax,[rbp+0C]exit:
jmp returnhere"fDataOpt.exe"+11A57:
jmp newmem
returnhere:[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"fDataOpt.exe"+11A57:
db F3 0F 2C 45 0C
//cvttss2si eax,[rbp+0C]

补丁效果

money = 96
money = 99
money = 108
money = 112
money = 118 // 这里是原始的实现, 每次money增加1~10
money = 224 // < 从这开始, 加了补丁, 每次money额外增加了100
money = 333
money = 436
money = 543
money = 652

浮点数寄存器组的保存

模拟了一下, 只看到浮点数寄存器组的保存, 没看到浮点数寄存器组的恢复.
等后续再看看哪里能看到浮点数寄存器的恢复, 或者用CE写个补丁试试. 估计就是用movss就行了.

		// 模拟一下函数外边有浮点数, 函数参数也传浮点数, 函数内部也进行浮点数操作// 看看汇编代码如何保存和恢复浮点寄存器组?f3 = f1 + f2;f4 = f1 - f2;f5 = test_xmmx(f1, f2, f3, f4);printf("f5 = %.2f\n", f5);} while (true);system("pause");return 0;
}float test_xmmx(float& f1, float& f2, float f3, float f4)
{float f_rc = (f1 + f2) * f3 / f4;return f_rc;
}
		// 模拟一下函数外边有浮点数, 函数参数也传浮点数, 函数内部也进行浮点数操作// 看看汇编代码如何保存和恢复浮点寄存器组?f3 = f1 + f2;
00007FF629391B48  movss       xmm0,dword ptr [f1]  
00007FF629391B4D  addss       xmm0,dword ptr [f2]  
00007FF629391B52  movss       dword ptr [f3],xmm0  f4 = f1 - f2;
00007FF629391B57  movss       xmm0,dword ptr [f1]  
00007FF629391B5C  subss       xmm0,dword ptr [f2]  
00007FF629391B61  movss       dword ptr [f4],xmm0  f5 = test_xmmx(f1, f2, f3, f4);
00007FF629391B69  movss       xmm3,dword ptr [f4]  
00007FF629391B71  movss       xmm2,dword ptr [f3]  
00007FF629391B76  lea         rdx,[f2]  
00007FF629391B7A  lea         rcx,[f1]  
00007FF629391B7E  call        test_xmmx (07FF6293913B1h)  
00007FF629391B83  movss       dword ptr [f5],xmm0  printf("f5 = %.2f\n", f5);
00007FF629391B8B  cvtss2sd    xmm0,dword ptr [f5]  
00007FF629391B93  movaps      xmm1,xmm0  
00007FF629391B96  movq        rdx,xmm1  
00007FF629391B9B  lea         rcx,[string "f5 = %.2f\n" (07FF62939AD50h)]  
00007FF629391BA2  call        printf (07FF62939119Ah)  } while (true);
--- D:\my_dev\my_local_git_prj\study\asm\case\fxmmxOpt\fDataOpt.cpp ------------float test_xmmx(float& f1, float& f2, float f3, float f4)
{
00007FF6293918A0  movss       dword ptr [rsp+20h],xmm3  // 保存浮点数寄存器
00007FF6293918A6  movss       dword ptr [rsp+18h],xmm2  
00007FF6293918AC  mov         qword ptr [rsp+10h],rdx  
00007FF6293918B1  mov         qword ptr [rsp+8],rcx  
00007FF6293918B6  push        rbp  
00007FF6293918B7  push        rdi  
00007FF6293918B8  sub         rsp,118h  
00007FF6293918BF  lea         rbp,[rsp+30h]  
00007FF6293918C4  lea         rcx,[__E9A00158_fDataOpt@cpp (07FF6293A2015h)]  
00007FF6293918CB  call        __CheckForDebuggerJustMyCode (07FF62939137Fh)  float f_rc = (f1 + f2) * f3 / f4;
00007FF6293918D0  mov         rax,qword ptr [f1]  
00007FF6293918D7  mov         rcx,qword ptr [f2]  
00007FF6293918DE  movss       xmm0,dword ptr [rax]  
00007FF6293918E2  addss       xmm0,dword ptr [rcx]  // 浮点数加法
00007FF6293918E6  mulss       xmm0,dword ptr [f3]  // 浮点数乘法
00007FF6293918EE  divss       xmm0,dword ptr [f4]  // 浮点数除法
00007FF6293918F6  movss       dword ptr [f_rc],xmm0  return f_rc;
00007FF6293918FB  movss       xmm0,dword ptr [f_rc]  
}
00007FF629391900  lea         rsp,[rbp+0E8h]  
00007FF629391907  pop         rdi  
00007FF629391908  pop         rbp  
00007FF629391909  ret  

END

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

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

相关文章

力扣---通配符匹配

题目描述&#xff1a; 给你一个输入字符串 (s) 和一个字符模式 (p) &#xff0c;请你实现一个支持 ? 和 * 匹配规则的通配符匹配&#xff1a; ? 可以匹配任何单个字符。 * 可以匹配任意字符序列&#xff08;包括空字符序列&#xff09;。 判定匹配成功的充要条件是&#xff…

华为23年9月笔试原题,巨详细题解,附有LeetCode测试链接

文章目录 前言思路主要思路关于f函数的剖析Code就到这&#xff0c;铁子们下期见&#xff01;&#xff01;&#xff01;&#xff01; 前言 铁子们好啊&#xff01;今天阿辉又给大家来更新新一道好题&#xff0c;下面链接是23年9月27的华为笔试原题&#xff0c;LeetCode上面的ha…

开源≠不赚钱,开源软件盈利的7大模式。

开源不是目的&#xff0c;目的是圈用户&#xff0c;留住用户&#xff0c;盈利自然不成问题。 开源系统可以通过多种方式赚钱&#xff0c;以下是其中几种常见的方式&#xff1a; 提供付费支持&#xff1a; 开源系统可以提供付费的技术支持服务&#xff0c;包括安装、配置、维…

mysql5.6安装---windows版本

安装包下载 链接&#xff1a;https://pan.baidu.com/s/1L4ONMw-40HhAeWrE6kluXQ 提取码&#xff1a;977q 安装视频 1.解压完成之后将其放到你喜欢的地址当中去&#xff0c;这里我默认放在了D盘&#xff0c;这是我的根目录 2.配置环境变量 我的电脑->属性->高级->环境…

阿里云增加数据库访问白名单

阿里云增加数据库访问白名单 概况 我们希望在外网访问数据库时&#xff0c;可能会遇到无法连接的问题&#xff0c;这有可能是被拦截了。这时就需要去查看自己的ip有没有在白名单里面&#xff0c;没有的话就把ip加入到白名单。 路径 阿里云控制台-搜索RDS-进入RDS管理控制台…

宋小黑的生财知识资料库第1011期

大家好&#xff0c;我是小黑&#xff0c;在当前经济和职场环境中&#xff0c;拥有一份副业已经成为很多人增加财务安全感和提升个人能力的重要手段。通过投身于副业&#xff0c;你不仅可以为自己创造一个额外的收入来源&#xff0c;减少对主职工作的经济依赖&#xff0c;还可以…

【C++】类和对象(四)

前言&#xff1a;在类和对象中&#xff0c;我们走过了十分漫长的道路&#xff0c;今天我们将进一步学习类和对象&#xff0c;类和对象这块荆棘地很长&#xff0c;各位一起加油呀。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:高质量&a…

【Spring】定义过滤器Filter和拦截器Interceptor

# 定义过滤器 package com.holen.filter;import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import java.io.IOException;pub…

【Web】NSSCTF Round#18 Basic个人wp(部分)

目录 ①门酱想玩什么呢&#xff1f; ②Becomeroot ①门酱想玩什么呢&#xff1f; 先试一下随便给个链接 不能访问远程链接&#xff0c;结合评论区功能&#xff0c;不难联想到xss&#xff0c;只要给个评论区链接让门酱访问就可 我们研究下评论区 从评论区知道&#xff0c;要…

jmeter-问题三:如何在给接口命名,使得察看结果树更清晰

问题三&#xff1a;如何在给接口命名&#xff0c;使得察看结果树更清晰 jmeter中声明的变量在任意地方都可以引用&#xff0c;我们可以利用这一点来实现 解决方法&#xff1a; 场景&#xff1a;测试登录接口&#xff08;包含登录成功&#xff0c;密码错误&#xff0c;用户名…

Android---Jetpack Compose学习004

CompositionLocal 通常情况下&#xff0c;在 Compose 中&#xff0c;数据以参数形式向下流经整个界面树传递给每个可组合函数。但是&#xff0c;对于广泛使用的常用数据&#xff08;如颜色或类型样式&#xff09;&#xff0c;这可能会很麻烦。 为了支持无需将颜色作为显式参数…

- 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》

本文属于专栏《构建工业级QPS百万级服务》​​​​​ 1、前置知识 c的内存管理&#xff0c;主要说的是堆内存管理。现代计算机系统中&#xff0c;用户进程的堆内存&#xff0c;由内核映射。 堆内存的来源 主要是通过mmap()函数&#xff0c;在进程的虚拟地址空…

VueCLI核心知识综合案例TodoList

目录 1 拿到一个功能模块首先需要拆分组件&#xff1a; 2 使用组件实现静态页面的效果 3 分析数据保存在哪个组件 4 实现添加数据 5 实现复选框勾选 6 实现数据的删除 7 实现底部组件中数据的统计 8 实现勾选全部的小复选框来实现大复选框的勾选 9 实现勾选大复选框来…

OpenCV Mat 实例详解 二

构造函数 OpenCV Mat实例详解一中已介绍了部分OpenCV Mat构造函数&#xff0c;下面继续介绍剩余部分构造函数。 Mat (const std::vector< _Tp > &vec, bool copyDatafalse)&#xff1b; vec 包含数据的vec对象 copyData 是否拷贝数据&#xff0c;true— 拷贝数据&…

数据分析案例-基于亚马逊智能产品评论的探索性数据分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

亿级推送,得物是怎么架构的?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、滴滴的面试资格。 最近&#xff0c;尼恩指导一个小伙伴简历&#xff0c;需要织入亮点项目、黄金项目。 前段时间&#xff0c;指导小伙写了一个《高…

AI在工业物联网(IIoT)中的安全管理与应用

在开放的工业互联网环境中&#xff0c;数百万个基于物联网的终端和中间设备&#xff0c;需要全天候地持续通信并保持在线状态。不过&#xff0c;这些设备往往由于最初设计上的限制&#xff0c;在机密性、完整性、可用性、扩展性、以及互操作性上&#xff0c;存在着各种安全漏洞…

Unity实现文字转语音并且与人物模型口型同步

文章目录 前言一、插件介绍二、导入RTVoice1.插件传送门2.组件配置 三、导入OVRLipSync1.插件传送门2.组件配置 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 今天我们用Unity实现文字转语音并且与人物模型口型同步&#xff0c;要实现这个功能&a…

Java安全 CC链6分析

CC链6分析 前言CC链分析核心transform链Lazymap类TiedMapEntry类HashMap方法 最终exp 前言 CC链6不受jdk版本与cs版本的影响&#xff0c;在Java安全中最为通用&#xff0c;并且非常简洁&#xff0c;非常有学习的必要&#xff0c;建议在学习CC链6之前先学习一下 URLDNS链 和 CC…

创建良好班风的重要性和意义

为什么有的班级总是充满活力&#xff0c;学生们团结友爱、学习热情高涨&#xff0c;而有的班级却显得沉闷&#xff0c;学生们缺乏动力&#xff0c;对学习毫无兴趣&#xff1f;其实&#xff0c;这背后的关键就在于班风的建设。 班风&#xff0c;简单说&#xff0c;就是一个班级…