PC逆向之代码还原技术,第六讲汇编中除法代码还原以及原理第二讲,被除数是正数 除数非2的幂
一丶简介
上一篇博客说的除2的幂. 如果被除数是有符号的,那么会进行调整,并使用位操作进行优化
本片博客专门讲解除数不是2的幂
二丶代码还原讲解
1.被除数无符号 除数非2的幂
高级代码:
Release汇编
.text:0040101A mov eax, 38E38E39h
.text:00401023 mul [esp+10h+var_8]
.text:00401027 shr edx, 1
除数怎么还原
代码定式:
.text:0040101A mov eax, M
.text:00401023 mul x 此指令等价于 mul x,M
.text:00401027 shr edx, N
还原公式 : (2^(32 +n)) / M = 2^n / M 最后结果向上取整.
代入公式:
2^33 / 38E38E39
= 8589934592 / 954437177
= 8.9999999989522621036795594143123
= 向上取整(8.999...)
= 9
得出被除数是9
原理:
如果不感兴趣可不看,或者你有<<C++ 与反汇编与逆向分析揭秘>>这本书,可以观看第67页.
原理分析:
首先那么大数是怎么来了.
由于除法指令周期比乘法指令周期长.所以编译器会使用较短的乘法指令来代替除法.
数学证明公式:
设被除数为 x 除数为o
则有下面公式:

其实上图所说就是一个除法 转化成分子乘法的转变.
如下:
5/2 == 5 * ½ ==> 5 * (2N/2 * 2N) == 5 * (2n/2) * (1/2n);
其实 2n/2 (2分之2n) 是在编译器的时候进行计算的。也就是说可以的出来的。
设 (2n/2) == m
那么 5 * M * (1/2n)
继续简化既可以得出 (5*m) / 2n == 结果
那么根据反汇编也明白了。
.text:0040101A mov eax, 38E38E39h 编译器计算出的(2n/2)
.text:00401023 mul [esp+10h+var_8] 这句代码的意思 = x * (2n/2)
.text:00401027 shr edx, 1 这句代码的意思是 结果 /2n 2n此时的取值是33 因为 edx,eax 直接操作的edx的一位等价于操作 2^1 + 2^32次方
根据上面的公式
eax = 2N/o (o)为常量。
mul == x * (2n/0)
shr edx,1 == x * (2n/o) / 2n
此时 2n我们可以知道是 2^33次方。
带入公式得到
x * (2^33/o) / 2^33
求o
2n / 2^33/o == 最终的常量就可以求出来了。
带入公式得到 2^33 / 38E38E39h ≈ 8.99999999 结果向上取整就是9
最终的结果就是
x / 9
公式如下

所以还原的时候。 首先确定 38E38E39h 他其实是除法演变成乘法的一个产物。
而后统计n。 n就是 右移的次数。 我们这里看到的是 2^33次方。
带入公式解方程
o = 2^n / M
M = 2N/o
2.被除数无符号 除数为特例7
高级代码:
int main(int argc, char* argv[])
{
unsigned int nValue = 16;
scanf("%d",&nValue);// 防止优化.核心代码不是这个
int nTemp = nValue / 7; //核心代码 一会观看反汇编
scanf("%d",&nTemp); //防止优化
return 0;
}
Debug下的汇编
.text:00401040 mov eax, [ebp+var_4]
.text:00401043 xor edx, edx
.text:00401045 mov ecx, 7
.text:0040104A div ecx
.text:0040104C mov [ebp+var_8], eax
Debug下的汇编很简单. 获取被除数,因为被除数是无符号.所以edx为0.所以会使用指令 xor edx,edx
进行清零. 这条语句也可以是 cdq.因为是无符号.所以使用cdq符号扩展那么edx也是0.可能xor指令周期
比xor周期长.所以没有使用. 虽然Debug不进行有效优化. 注意不进行有效优化是方便我们调试.但是也会
进行优化.当然不会影响你的调试. 比如 xor 也可以是cdq
如下:
.text:00401040 mov eax, [ebp+var_4]
.text:00401043 cdq
.text:00401045 mov ecx, 7
.text:0040104A div ecx eax = eax / ecx 等价于 eax = eax / 7;
.text:0040104C mov [ebp+var_8], eax
Debug下直接进行还原即可.很简单.
Release下的汇编
.text:0040101A mov ecx, [esp+10h+var_8]
.text:0040101E mov eax, 24924925h
.text:00401023 mul ecx
.text:00401025 sub ecx, edx
.text:00401027 shr ecx, 1
.text:00401029 add ecx, edx
.text:0040102B shr ecx, 2
.text:0040102E mov [esp+10h+var_4], ecx
Release下的汇编就比较烦了.为什么指令是这样. 有一个超大的数, 还有各种乘法, 减法. 移位 加法.
其实这都是有数学原理进行支撑了.而且这个还是个特例.如果不想知道数学原理.直接记住汇编顺序
**乘 减 移 加 移. 也算是特征. 正好对应 mul sub shr add shr **
还原方法:
还原的时候我们可以设置未知数.这样直接给一个公式进行还原
如下:
.text:0040101A mov ecx, [esp+10h+var_8]
.text:0040101E mov eax, M 设最大数为M
.text:00401023 mul ecx
.text:00401025 sub ecx, edx
.text:00401027 shr ecx, N 设移位为N
.text:00401029 add ecx, edx
.text:0040102B shr ecx, N 设置移位为N
.text:0040102E mov [esp+10h+var_4], ecx
还原方法: 2N/(232+M)的商向上取整
可以带入公式:
M = 24924925h 十进制 = 613566757
n 有两个,一个是1 一个是2 两个n相加就是3, 因为使用edx.没有使用eax 除法会使用 eax,edx. 所以使用edx变相的相当于以及有了2^32次方了.
代入公式:
2^35 / (2 ^32 + M)
= 34359738368 / (4294967296 + 613566757)
= 34359738368 / 4908534053
= 6.9999999993888195604619552997935
= 商向上取整 (6.9999999993888195604619552997935)
= 7
所以得出了除数为7
代码还原的时候直接还原成 Var_8 / 7 即可.如果想看原理,且向下看.
三丶代码还原总结
学习了新的两种定式:
第一种,被除数为正数, 除数为正数. MUL是无符号,所以不需要进行调整.直接套用公式还原
.text:0040101A mov eax, M
.text:00401023 mul x 此指令等价于 mul x,M
.text:00401027 shr edx, N
还原公式 : (2^(32 +n)) / M = 2^n / M 最后结果向上取整.
第二种 被除数为正数 除数是特例
特征: 汇编中出现 乘 减 移 加 移
.text:0040101A mov ecx, [esp+10h+var_8]
.text:0040101E mov eax, M 设最大数为M
.text:00401023 mul ecx ecx = ecx * M
.text:00401025 sub ecx, edx
.text:00401027 shr ecx, N 设移位为N
.text:00401029 add ecx, edx
.text:0040102B shr ecx, N 设置移位为N
.text:0040102E mov [esp+10h+var_4], ecx
还原方法: 2^(32 + N)/(2^32+M)的商向上取整
简化公式: 2^N / (2^32 + M) 一定注意隐藏的N大于32.
PC逆向之代码还原技术,第六讲汇编中除法代码还原以及原理第二讲,被除数是正数 除数非2的幂的更多相关文章
- PC逆向之代码还原技术,第四讲汇编中减法的代码还原
目录 PC逆向之代码还原技术,第四讲汇编中减法的代码还原 一丶汇编简介 二丶高级代码对应汇编观看. 1.代码还原解析: 三丶根据高级代码IDA反汇编的完整代码 四丶知识总结 PC逆向之代码还原技术,第 ...
- PC逆向之代码还原技术,第三讲汇编中加法的代码还原
目录 PC逆向之代码还原技术,第三讲汇编中加法的代码还原 一丶汇编简介 二丶高级代码对应汇编观看. 1.代码还原解析: 总结 PC逆向之代码还原技术,第三讲汇编中加法的代码还原 一丶汇编简介 在讲解加 ...
- 第16讲——C++中的代码重用
C++的一个主要目标是促进代码重用.除了我们之前学的公有继承,我们在这一讲将介绍另一种代码重用的方法——类模板.
- XGBoost中参数调整的完整指南(包含Python中的代码)
(搬运)XGBoost中参数调整的完整指南(包含Python中的代码) AARSHAY JAIN, 2016年3月1日 介绍 如果事情不适合预测建模,请使用XGboost.XGBoost算法已 ...
- 捕捉WPF应用程序中XAML代码解析异常
原文:捕捉WPF应用程序中XAML代码解析异常 由于WPF应用程序中XAML代码在很多时候是运行时加载处理的.比如DynamicResource,但是在编译或者运行的过程中,编写的XAML代码很可能有 ...
- Spring官网阅读(十六)Spring中的数据绑定
文章目录 DataBinder UML类图 使用示例 源码分析 bind方法 doBind方法 applyPropertyValues方法 获取一个属性访问器 通过属性访问器直接set属性值 1.se ...
- PC逆向之代码还原技术,第五讲汇编中乘法的代码还原
目录 PC逆向之代码还原技术,第五讲汇编中乘法的代码还原 一丶简介乘法指令 1.乘法指令 2.代码还原注意问题 二丶乘法的汇编代码产生的格式 1.高级代码观看 2.乘法的汇编代码还原. 三丶乘法总结 ...
- PC逆向之代码还原技术,第二讲寻找程序入口点
PC逆向之代码还原技术,第二讲寻找程序入口点 一丶简介 程序逆向的时候.我们需要知道程序入口点.动态分析的时候以便于看是什么程序编写的. 比如VC++6.0 我们可以写一个程序测试一下 我们写一段代码 ...
- PC逆向之代码还原技术,第一讲基本数据类型在内存中的表现形式.浮点,指针寻址公式
目录 代码还原技术 一丶简介代码还原 二丶代码还原中的数据类型表现形式 1.整数类型 2.无符号整数 3.有符号整数 4.浮点数数据类型 5.浮点编码 4.Double类型解析. 三丶浮点汇编 1.浮 ...
随机推荐
- BZOJ5412 : circle
若仅保留这$k$个点仍然有环,那么显然无解. 否则设$A$表示这$k$个点的集合,$B$表示剩下的点的集合,因为是竞赛图,每个集合内部的拓扑关系是一条链,方便起见将所有点按照在所在集合的链上的位置进行 ...
- 2018 Multi-University Training Contest 3 - HDU Contest
题解: solution Code: A. Ascending Rating #include<cstdio> const int N=10000010; int T,n,m,k,P,Q, ...
- vue-These relative modules were not found
今天在做vue2.0+webpack的项目的时候,本来一切正常,整理了一下文件夹分类,就是把一些基础的组件新建了一个文件夹移进去,然后就报了以下的错误,其他东西都没改 最后网上找了很多资料,有说配置文 ...
- Php中文件下载功能实现超详细流程分析
浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php),该网页的代码如下 客户端从服务端下载文件的流程分析: 浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php) ...
- spring-cloud-Zuul学习(二)【基础篇】--典型配置【重新定义spring cloud实践】
-- 2019-04-15 20:22:34 引言 上一节是一个最基本的zuul网关实例,它是整个spring-cloud生态里面“路由-服务”的一个缩影,后续也就是锦上添花.这节主要讲述zuul的一 ...
- hibernate框架搭建
hibernate框架的搭建步骤: 1.导包 2.创建数据库准备表 3.书写orm元数据(对象与表的映射配置文件) 4.书写配置文件 5.书写代码测试 一.导包: 创建web-maven工程添加hib ...
- [FPGA] 1、Artix-7 35T Arty FPGA 评估套件学习 + SiFive risc-v 指令集芯片验证
目录 1.简介 2.深入 3.DEMO 4.SiFive基于risc-v指令集的芯片验证 LINKS 时间 作者 版本 备注 2018-10-09 08:38 beautifulzzzz v1.0 到 ...
- Ansible配置免密登陆
0x01: 把远程服务器的公钥来获取到本地 #ssh-keyscan ip1 ip2 ip3 ip4 >> /root/.ssh/known_hosts 完成后,/root/.ssh/k ...
- 如何在微信小程序定义全局变量、全局函数、如何实现 函数复用 模块化开发等问题详解
1.如何定义全局数据 在app.js的App({})中定义的数据或函数都是全局的,在页面中可以通过var app = getApp(); app.function/key的方式调用,不过我们没有必要 ...
- Java面试中笔试题——Java代码真题,这些题会做,笔试完全可拿下!
大家好,我是上海尚学堂Java培训老师,以下这些Java笔试真题是上海尚学堂Java学员在找工作中笔试遇到的真题.现在分享出来,也写了参考答案,供大家学习借鉴.想要更多学习资料和视频请留言联系或者上海 ...