64位软件逆向技术

(x64通常是指AMD64, Intel64的合称

1 寄存器

RAX, RBX, RCX, RDX, R8 ~ R15, 扩充8个128位寄存器XMM(一般用来优化代码)
寄存器是向下兼容的, 用后缀DWORD, WORD, BYTE, 例如R8(64位), R8D(32位), R8W(16位), R8B

2 函数

  • (1) 栈平衡
  • (2) 启动函数 一般反汇编成start, 可在start中找到main函数的调用
    编译器设定多线程DLL(/MD)时, IDA会显示main符号, 可直接定位
    设置为/MT多线程时, 不会显示main, 需要通过特征定位main, call cs:exit上的第一个call是main

    • (3) 调用约定
      x64程序只有一种调用约定, 快速调用约定. 6个参数保存在寄存器里, 其余参数从右往左入栈, 调用方负责平衡栈空间. RDI, RSI, RDX, RCX, R8, R9, 大于8或不是1,2,4,8字节的参数由引用(地址)传递. XMM用于传递浮点数参数. 如果子函数需要调用RCX, RDX, R8, R9则调用者提前申请32字节栈空间通过栈来传参.(注意这32字节是默认的预留栈空间, 但是需要调用者申请使用)

    • (4) 参数传递
      • 多参数传参
      • 结构体的传参
        • 不超过8字节
          结构体直接存进寄存器, 用高低32位访问成员, 逆向分析时可以借此特征判断结构体数据
        • 超过8字节
          先复制结构体到栈, 再通过结构体地址当成函数参数(通过寄存器比如rcx, 不够的时候是放到栈里)传递给函数(引用传递), 被调用的函数通过结构体地址+偏移取结构体内容
          不过需要注意, 预留栈空间和局部变量在栈中是有差异的, 调用一个函数, 返回地址之前的是预留栈空间, 之后的是开辟出来存局部变量的空间, 并且局部变量中也有隐含的预留空间, 即4个参数的存储空间, 比如
          对应的栈结构大概如下, rsp0是main函数调用fun函数之前的栈顶
    • thiscall传递
      C++成员函数调用约定, 调用时会隐含传递一个this指针
    • 函数返回值
      8字节返回值在RAX, 浮点数在MMX0, 大于8字节, 返回栈空间地址, 作为引用参数返回

3 数据结构

  • 局部变量
    局部变量保存在栈空间中, 注意与预留栈空间的空间关系, 预留栈空间在低地址, 局部变量在高地址
  • 全局变量
    编译时就会被固定, 常用固定地址访问; 另外注意, 全局变量也是先定义的在低地址, 后定义的在高地址, 据此可还原变量定义顺序
  • 数组
    数组中数据是从低到高地址排列(结合写C程序的经验, 是常理之中)
    访问数组通常用数组访问公式, 数组下标已知会被优化成直接计算偏移量, 未知则继续用寻址公式
    特征
    + [数组首地址 + n]
    + [数组首地址 + 寄存器 * n]
    遇到以上特征就可大致判断为数组访问, 优化过后也可能有XMM寄存器的使用

4 控制语句

  • if 语句
    通常编译器会对表达式的结果取反操作, 比如 > 取成 <= 即jle
  • if else 语句
    特征: jxx跳转, 跳转目的有jmp指令
  • if else if else
    特征: jxx跳转目的有jmp指令, else if跳转目的有jmp指令, else 代码结尾没有jmp指令, 并且所有jmp目的地址相同
  • switch-case
    分支数 < 6 时编译器用if else实现, 当分支数 >= 6时, 编译器会优化
    优化后用一维数组表示case表, 用下表寻址代码块, 而且当case的间隔较小时, 会完整的列出1-n表格, 其中缺失的数字会用default地址替代
    当case用if来实现时, 如果判断次数较多, 会优化成判定树形式
  • 转移指令机器码计算
    (1) call / jmp direct (与x86类似, 用位移量寻址)
    位移量 = 目的地址 - 起始地址 - 跳转指令长度
    (2) call /jmp memory direct
    32位系统, 跳转指令机器码 + 绝对地址
    64位系统, 跳转指令机器码 + 相对地址

5 循环语句

  • do while 循环, 有一个向上跳转的jxx
  • while 循环, 有jmp向上跳转, jxx向下跳转 (效率低于do while, 所以通常被优化为do)
  • for 循环, 开始有一个jmp向下, 最后有一个jmp向上, 中间有个jxx取反向下跳出循环(通常被优化为if + do循环)

6 数字运算符

  • 加减法, 同32位用lea加速程序; 另外常量折叠指编译器在编译时就计算了只涉及常量的加减乘法, 执行时直接拿结果计算即可
  • 乘法, 同32位用lea加速计算
  • 除法, 优化成等价的移位运算或乘法运算
    • 无符号除法移位优化公式
      x ≥ 0 , x 2 n = x > > n x < 0 , x 2 n = ( x + ( 2 n − 1 ) ) > > n x \ge 0, \frac{x}{2^n} = x >> n \\ x < 0, \frac{x}{2^n} = (x + (2^n - 1)) >> n x≥0,2nx​=x>>nx<0,2nx​=(x+(2n−1))>>n
      实际实现时, 用到了有符号扩展+and指令的技巧, 同时概括了正负两种情况, 实现以上两个公式, 正的时候+0, 负的时候+ 2 n − 1 2^n - 1 2n−1

  • 有符号除法
    相当于在无符号除法基础上加一个求补操作
    neg eax

  • 有符号除法, 除数正非 2 n 2^n 2n

    • 优化公式1
      x o = x ∗ c > > 64 ( 32 ) > > n , x ≥ 0 x o = ( x ∗ c > > 64 ( 32 ) > > n ) + 1 , x < 0 c > 0 , n 可 以 为 0 \frac{x}{o} = x * c >> 64(32) >> n, x \ge 0\\ \frac{x}{o} = (x * c >> 64(32) >> n) + 1, x < 0\\ c > 0, n可以为0 ox​=x∗c>>64(32)>>n,x≥0ox​=(x∗c>>64(32)>>n)+1,x<0c>0,n可以为0
    • 优化公式2
      x o = ( x ∗ c > > 64 ( 32 ) ) + x > > n , x ≥ 0 x o = ( ( x ∗ c > > 64 ( 32 ) ) + x > > n ) + 1 , x < 0 c < 0 \frac{x}{o} = (x * c >> 64(32)) + x >> n, x \ge 0\\ \frac{x}{o} = ((x * c >> 64(32)) + x >> n) + 1, x < 0\\ c < 0 ox​=(x∗c>>64(32))+x>>n,x≥0ox​=((x∗c>>64(32))+x>>n)+1,x<0c<0
      n为右移总次数, o是除数, o = 2 n c o = \frac{2^n}{c} o=c2n​, c是编译器为优化除法转成乘法计算出来的magic_num, 根据c的正负知道是采用的哪一个优化公式
  • 有符号除法, 除以负非 2 n 2^n 2n, 区别在与c取相反符号, 即优化公式1中的c是负的, 优化公式2中的c是正的, 这样就是除以负的非 2 n 2^n 2n, 此外还有一处细微差别

    • 优化公式1
      x o = x ∗ c > > 64 ( 32 ) > > n , x ≥ 0 x o = ( x ∗ c > > 64 ( 32 ) > > n ) + 1 , x < 0 c < 0 , n 可 以 为 0 \frac{x}{o} = x * c >> 64(32) >> n, x \ge 0\\ \frac{x}{o} = (x * c >> 64(32) >> n) + 1, x < 0\\ c < 0, n可以为0 ox​=x∗c>>64(32)>>n,x≥0ox​=(x∗c>>64(32)>>n)+1,x<0c<0,n可以为0
    • 优化公式2
      x o = ( x ∗ c > > 64 ( 32 ) ) − x > > n , x ≥ 0 x o = ( ( x ∗ c > > 64 ( 32 ) ) − x > > n ) + 1 , x < 0 c > 0 \frac{x}{o} = (x * c >> 64(32)) - x >> n, x \ge 0\\ \frac{x}{o} = ((x * c >> 64(32)) - x >> n) + 1, x < 0\\ c > 0 ox​=(x∗c>>64(32))−x>>n,x≥0ox​=((x∗c>>64(32))−x>>n)+1,x<0c>0
      n为右移总次数, 除数o计算公式
      ∣ o ∣ = 2 n 2 64 ( 32 ) − c |o| = \frac{2^n}{2^{64(32)} - c} ∣o∣=264(32)−c2n​
  • 无符号除法, 除以 2 n 2^n 2n
    无须判断符号, shr替代除法

  • 无符号除法, 除以非 2 n 2^n 2n
    类似有符号除法优化公式1, 不过不用判断符号, 只考虑正数情况
    注意有符号与无符号的重要区别在于, 无符号用mul, 有符号用imul
    另一种优化公式
    x o = ( x − ( x ∗ c > > 32 ( 64 ) ) > > n 1 ) + ( x ∗ c > > 32 ( 64 ) ) > > n 2 o = 2 32 ( 64 ) + n 2 32 ( 64 ) + c \frac{x}{o} = (x - (x *c >> 32(64)) >> n_1) + (x * c >> 32(64)) >> n_2 \\ o = \frac{2^{32(64) + n}}{2^{32(64) + c}} ox​=(x−(x∗c>>32(64))>>n1​)+(x∗c>>32(64))>>n2​o=232(64)+c232(64)+n​

  • 取模
    通常优化为位运算和除法运算, 再经由除法运算优化

    • 除数为 2 n 2^n 2n
      优化公式1
      x % 2 n = x & ( 2 n − 1 ) , x ≥ 0 x % 2 n = ( x & ( 2 n − 1 ) ) − 1 ∣ ( ∼ ( 2 n − 1 ) ) + 1 , x < 0 x \% 2^n = x \& (2^n - 1), x \ge 0\\ x \% 2^n = (x \& (2^n - 1)) - 1 | (\sim(2^n - 1)) + 1, x < 0 x%2n=x&(2n−1),x≥0x%2n=(x&(2n−1))−1∣(∼(2n−1))+1,x<0
      优化公式2
      x % 2 n = x & ( 2 n − 1 ) , x ≥ 0 x % 2 n = ( ( x + ( 2 n − 1 ) ) & ( 2 n − 1 ) ) − ( 2 n − 1 ) , x < 0 x \% 2^n = x \& (2^n - 1), x \ge 0\\ x \% 2^n = ((x + (2^n - 1)) \& (2^n - 1)) - (2^n - 1), x < 0 x%2n=x&(2n−1),x≥0x%2n=((x+(2n−1))&(2n−1))−(2n−1),x<0
    • 除数为非 2 n 2^n 2n
      x % c = x − x / c ∗ c x \% c = x - x / c * c x%c=x−x/c∗c, 余数 = 被除数 - 除数 * 商

7 虚函数

每个类生成一个虚表(假如存在虚函数)
封装, 继承, 多态相关细节放到C++逆向总结文章中

以上
之后要继续撰写关于windows和linux逆向相关的总结文章, 这只是开始, to be continued …

reversing逆向分析技术总结-(2)相关推荐

  1. 《逆向工程核心原理》学习笔记(六):高级逆向分析技术

    目录 前言 一.TLS回调函数 1.TLS简介 (1)IMAGE_DATA_DIRECTORY (2)IMAGE_TLS_DIRECTORY 2.TLS回调函数简介 3.示例1:HelloTls.ex ...

  2. 逆向工程--苹果移动端app逆向分析技术(一)

    0x01 基础准备 关于iphone移动端app逆向程序相关初级基础大家可以自己提前学习.本 文主要给大家分享关于脱壳加密app程序的技术.学习之前大家先搭建系 统环境,准备相应的工具,参考链接教程自 ...

  3. c++反汇编与逆向分析技术揭秘_C++反汇编与逆向分析技术揭秘

    一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然存在.C++语法规定的访问限制仅限于编译层面,在编译过程中进行语法检查,因此访问控制不会 ...

  4. [安全攻防进阶篇] 一.什么是逆向分析、逆向分析应用及经典扫雷游戏逆向

    从2019年7月开始,我来到了一个陌生的专业--网络空间安全.初入安全领域,是非常痛苦和难受的,要学的东西太多.涉及面太广,但好在自己通过分享100篇"网络安全自学"系列文章,艰难 ...

  5. 《软件调试分析技术》学习笔记

    <软件调试分析技术>学习笔记(一) 今天开始写写一些心得体验. <软件调试分析技术>是好友Monster的处女作品.作为一直以的好伙伴,他是我看着长大的,(*^__^*) 嘻嘻 ...

  6. [安全攻防进阶篇] 二.如何学好逆向分析、逆向路线推荐及吕布传游戏逆向案例

    从2019年7月开始,我来到了一个陌生的专业--网络空间安全.初入安全领域,是非常痛苦和难受的,要学的东西太多.涉及面太广,但好在自己通过分享100篇"网络安全自学"系列文章,艰难 ...

  7. 逆向分析入门实战(三)

    本文由作者首发于合天智汇:http://www.heetian.com/info/840 之前两篇文章,针对恶意代码为了确保自身只有一个实例在运行进行了正向开发和逆向分析.逆向入门分析实战(一).逆向 ...

  8. 逆向分析入门实战(一)

    本文由作者首发于合天智汇,http://www.heetian.com/info/742 1.木马分析入门 大家好,我最近从Web安全开始学习二进制安全,分享一下自己学习过程的收获和心得体会.由于是入 ...

  9. 逆向分析入门实战(二)

    上次我们对主函数分析完成了,逆向入门分析实战(一)那么这次我们对子函数IsAlreadyRun进行分析. C语言代码 IsAlreadyRun函数的C语言代码如下图所示: 下面对其汇编代码进行分析: ...

最新文章

  1. java.io.IOException: No FileSystem for scheme: hdfs
  2. 团队编程项目作业5-小组评分
  3. OpenGL着色器创建一个星系由颗粒制成
  4. checkbox checked属性值
  5. 初步认识Volatile-总线锁和缓存锁
  6. 转载给ffmpeg入门级:我的第一个调用FFmpeg库的程序出炉
  7. Django中--使用redis存储历史浏览记录
  8. 【Java】统计字符个数
  9. spring boot 调试 - 热部署
  10. 2d游戏引擎_8年,从2D到3D,我的学习之路
  11. “通用大模型”趋势下,AI未来当如何?
  12. 膜拜 丹尼斯·里奇(纪念 C 语言之父离世 6 周年) 我们欠他的不止是张电影票
  13. 萤石开放平台——摄像头画面怎么完成一键分享?
  14. VScode 光标乱跳
  15. python图像处理(三)波形叠加模拟
  16. 怎么让照片里的人嘴巴动起来_让照片动起来软件下载-让照片动起来制作软件下载-西西软件下载...
  17. shader02-仿星空粒子
  18. 关键信息基础设施确定指南_干货分享 | 关键信息基础设施运营单位如何做好业务安全测试...
  19. Windows环境下安装PyMySQL(已安装Anaconda)
  20. os x怎么新建html文件格式,如何在Mac OS X中为邮件制作HTML签名 | MOS86

热门文章

  1. 国家航天局:中国探月工程四期和深空探测工程全面拉开序幕
  2. GIT开发学习——合并分支的几种方法
  3. 线程池的设计(二):领导者追随者线程池的设计
  4. 关于CSDN会员充值建议
  5. 九、(机器学习)-Tensorflow算法之全连接层
  6. 微软暗示下一代Windows命名为Win11
  7. 图与网络可视化实战(matlab实现)
  8. linux下使用微信小程序开发环境
  9. 听说 DNS 根服务器只有13台,科学吗?
  10. 探究莲花位主内洗髓经时,各情况下开局3怒的概率