整数除法(除以2的幂, 除以非2的幂)
来源:互联网 发布:linux proccess port 编辑:程序博客网 时间:2024/04/29 10:37
前言
除法推导过程还不理解, 先用公式吧.
试验总结
找个Demo来逆向.
只有除法(变量/常量)会有魔法数, +-*都不会.
看到魔法数(很怪的很大的16进制数)时, 先套除法公式, 看是不是整数除法. 一共就7种, 判断完, 都不是, 再按照正常的做法翻译成C代码.
如果不能用C语言直接描述, 还是得看看是否看错了. e.g. cdq出现在魔法数的上下文中.
如果做个除法片段判断程序, 将反汇编定式都收录进来, 就不用人工判断是否为除法了, 能提高效率.
在没作出除法定式判断程序前, 可以封装一个函数, 根据m,n算出b, 看像不像除数.
逆向完后, 先比对RE工程生成的反汇编代码和原始工程的反汇编代码的区别, 在release模式下, 因为使用了寄存器变量, 无法保证完全相同.
如果测试数据够全或输入数据够少或输出结果可预测, 可以输入数据跑一下, 看RE工程和原始工程输出是否一样.
试验代码
// RE.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <math.h>// int CalcDiv_B(double fM, int n) {// int iC = 0;// // /*// 变量除以非2的幂 公式:// // 被除数 a// 除数 b// 商q// 余数 r// // a = qb + r// a/b = q + r/b// // a/b = a* (1/b) = a* (2^n) /b * (1/2^n) = a* 2^n /b >> n// 设m = (2^n)/b// b = (2^n)/m// a/b = a * m >> n// // m已知, 出现的除法反汇编实现中// 被除数a已知, 和m做乘积的那个数就是a// n要根据除法反汇编中移位次数算出来, 也是已知的// */// // double fB = pow(2, n);// fB = fB / fM;// // // 一直要向上取整// iC = (int)fB + 1;// return iC;// }int main(int argc, char* argv[]){ // int iC = CalcDiv_B(0x6BCA1AF3, 35); ///< 19 // int iC = CalcDiv_B(0x55555556, 32);// ; =============== S U B R O U T I N E =======================================// // ; .text:00401000// // ; int __cdecl main(int argc, const char **argv, const char **envp)// _main proc near ; CODE XREF: start+AF.p// // argc = dword ptr 4// argv = dword ptr 8// envp = dword ptr 0Ch// // push esi// push edi int eax = 0;// xor eax, eax int ecx = 0;// xor ecx, ecx int esi = 8;// mov esi, 8 int edi = 0;// xor edi, edi// do { if (0 == eax) {// L_BEGIN: ; CODE XREF: _main+1D.j _main+3C.j ...// test eax, eax ; .text:0040100D// jnz short L_NEXT1 ; .text:0040101F edi = 1;// mov edi, 1 eax = 4;// mov eax, 4 ecx = edi;// mov ecx, edi continue;// jmp short L_BEGIN ; .text:0040100D// ; --------------------------------------------------------------------------- }// // L_NEXT1: ; CODE XREF: _main+F.j if (1 == eax) {// cmp eax, 1 ; .text:0040101F// jnz short L_NEXT2 ; .text:0040103E // 变量/常量的除法么? // m = (2^n)/c // c = (2^n)/m // 如果是除法 // n = 32 + 3 = 35 // m = 6BCA1AF3h // c(除数) = (2^35)/6BCA1AF3h = // mov eax, 6BCA1AF3h// imul ecx// sar edx, 3// mov eax, edx// shr eax, 1Fh// add edx, eax ecx = ecx / 19;// mov eax, 3 eax = 3;// mov ecx, edx// jmp short L_BEGIN ; .text:0040100D continue; }// ; ---------------------------------------------------------------------------// // L_NEXT2: ; CODE XREF: _main+22.j// cmp eax, 2 ; .text:0040103E// jnz short L_NEXT3 ; .text:0040105A if (2 == eax) {// mov eax, edi// imul eax, ecx eax = edi * ecx; // cdq不是C语言能直接描述的// cdq// and edx, 3// add eax, edx// sar eax, 2// mov ecx, eax /* 变量除以2的幂 公式: 对零取整[X / 2^n] = 下取整[(x + 2^n - 1)/2^n] */ // 依赖[变量除以2的幂]公式, 看出 n = 2, 被乘数是eax ecx = eax / 4;// mov eax, 1 eax = 1;// jmp short L_BEGIN ; .text:0040100D continue; }// ; ---------------------------------------------------------------------------// // L_NEXT3: ; CODE XREF: _main+41.j// cmp eax, 3 ; .text:0040105A// jz short L_NEXT4 ; .text:00401083 if (eax == 3) { break; }// cmp eax, 4// jnz short L_BEGIN ; .text:0040100D if (eax != 4) { continue; }// mov edx, esi// mov eax, 55555556h// imul edx, esi// imul esi, edx esi = esi * esi *esi; // imul esi 开始操作魔法数eax, 开始算除法(变量/非2的幂), m = 0x55555556 // esi * eax => edx:eax // a/b = am >> n // a*m后, 没有继续向右移位, 直接使用edx调整商, 说明 n = 32 // CalcDiv_B(0x55555556, 32) 算出除数 = 3// imul esi // 用符号位调整商// mov eax, edx// shr eax, 1Fh// add edx, eax edi = esi / 3;// mov eax, 2 eax = 2;// mov edi, edx// jmp short L_BEGIN ; .text:0040100D continue;// ; --------------------------------------------------------------------------- } while (1);// // L_NEXT4: ; CODE XREF: _main+5D.j// lea edx, [ecx+ecx*8] ; .text:00401083 // 9 * ecx// lea eax, [ecx+edx*2] // 变量扩散 // lea eax, [ecx + 9 * ecx * 2] // lea eax, 19*ecx// shl eax, 2 // 19*ecx *4 = 76*ecx eax = 76*ecx;// push eax// push offset Format ; "%d\r\n"// call _printf printf("%d\r\n", eax);// add esp, 8// xor eax, eax// pop edi// pop esi// retn ; .text:0040109E// _main endp// // ; --------------------------------------------------------------------------- return 0;}
0 0
- 整数除法(除以2的幂, 除以非2的幂)
- 无符号数除以非2的幂
- 有符号数除以非2的幂
- 随笔十九:除以 2 的幂
- C语言中除以2的幂
- 无符号数除以2的幂
- 有符号数除以2的幂
- 有符号数除以-2的幂
- 一个整数N除以2余1,除以3余2,除以4余3,...,除以10余9,但除以11余0,计算符合该条件的最小整数
- 无符号数除以非2的幂(MagicNumber有进位)
- 有符号数除以非2的幂(MagicNumber为负)
- 有符号数除以非-2的幂(MagicNumber为负)
- 有符号数除以非-2的幂(MagicNumber为正)
- 负数除以整数的余数怎么算?
- python中整数除以整数的结果是取整数
- 1017A除以B(大整数除法)
- 整数相除以及DateTime.ToString()的小细节
- int整数除以int整数一定得到的是int整数(易忽视)
- 胃 癌 治疗 药方
- Java - static
- nginx切割字符串、泛域名、kong、转发代理
- Leetcode 175. Combine Two Tables
- USB相关知识
- 整数除法(除以2的幂, 除以非2的幂)
- Leetcode 176. Second Highest Salary
- 吴翰清的一封邮件(来自知乎)
- iOS开发:[!] You need to register a session first.
- Struts2运行流程
- Windows系统 为 QT5软件 搭建 OpenCV2 开发环境
- MySQL字符集和乱码问题初探
- C、C++中使用const提高程序的健壮性和效率
- response time(一)