x86/x64汇编基础12.汇编基础8:算术运算指令

笔记

学习最新前沿软件逆向安全技术、游戏安全辅助脚本技术,B 站 小迪 xiaodi 老师

微信 i-xiaodi

基本的数学运算指令

操作符

功能

示例

add

加法

add eax, ebx

sub

减法

sub eax, ecx

mul

无符号乘法

mul ecx

imul

有符号乘法

imul eax, ecx

div

无符号除法

div ecx

idiv

有符号除法

idiv ecx

inc(increase +1)

自增

inc eax

dec(decrease – 1)

自减

dec eax

以下是 mulimuldividiv 指令的详细讲解和代码示例。这些指令主要用于整数的乘法和除法操作,分别处理无符号和有符号数据。通过反汇编代码,我们可以更好地理解它们在汇编中的实际作用。


乘除法

1. mul(无符号乘法)

  • 功能:执行无符号整数乘法。
  • 操作数
    • 单操作数:默认为 EAX 寄存器作为被乘数,操作数为乘数。
    • 结果:
      • 如果是 32 位:低 32 位结果存储在 EAX,高 32 位存储在 EDX

示例代码

mov eax, 5        ; 被乘数
mov ecx, 3        ; 乘数
mul ecx           ; 无符号乘法,EAX * ECX
; 结果存储在 EAX(低 32 位),高位结果存储在 EDX

反汇编

00401000  B8 05 00 00 00        mov eax, 5    ; 将 5 加载到 EAX
00401005  B9 03 00 00 00        mov ecx, 3    ; 将 3 加载到 ECX
0040100A  F7 E1                 mul ecx       ; EAX = EAX * ECX

结果

  • EAX = 15
  • EDX = 0(因为乘积小于 2^32,EDX 为 0)
  • 2 ^ 32 - 1= FFFF FFFF

2. imul(有符号乘法)

  • 功能:执行有符号整数乘法。
  • 操作数
    • 支持单操作数、双操作数或三操作数形式:
      • 单操作数:默认被乘数在 EAX
      • 双操作数imul dest, src,目标寄存器存储结果。
      • 三操作数imul dest, src, imm,将 src * imm 的结果存入 dest

示例代码

mov eax, -5       ; 被乘数
mov ecx, 3        ; 乘数
imul eax, ecx     ; 有符号乘法,EAX = EAX * ECX
; 结果存储在 EAX

反汇编

00401000  B8 FB FF FF FF        mov eax, -5   ; 将 -5 加载到 EAX
00401005  B9 03 00 00 00        mov ecx, 3    ; 将 3 加载到 ECX
0040100A  0F AF C1              imul eax, ecx ; EAX = EAX * ECX

结果

  • EAX = -15

3. div(无符号除法)

  • 功能:执行无符号整数除法。
  • 操作数
    • 被除数默认是 EDX:EAX 组成的 64 位整数(高 32 位在 EDX,低 32 位在 EAX)。
    • 操作数为除数,结果:
      • 商存储在 EAX
      • 余数存储在 EDX

注意:需要确保 EDX 被清零(或正确设置),否则结果可能出错。

示例代码

mov edx, 0        ; 高位被除数清零
mov eax, 15       ; 低位被除数
mov ecx, 3        ; 除数
div ecx           ; 无符号除法,EAX = EAX / ECX,EDX = EAX % ECX

反汇编

00401000  BA 00 00 00 00        mov edx, 0    ; EDX = 0
00401005  B8 0F 00 00 00        mov eax, 15   ; EAX = 15
0040100A  B9 03 00 00 00        mov ecx, 3    ; ECX = 3
0040100F  F7 F1                 div ecx       ; EAX = EAX / ECX, EDX = EAX % ECX

结果

  • EAX = 5(商)
  • EDX = 0(余数)

4. idiv(有符号除法)

  • 功能:执行有符号整数除法。
  • 操作数
    • 被除数为 EDX:EAX 组成的 64 位整数(同 div)。
    • 操作数为除数,结果:
      • 商存储在 EAX
      • 余数存储在 EDX

注意:与 div 类似,需正确设置 EDX,且结果符号由操作数符号决定。确保 EDX 符号开启:cdq 指令

 

示例代码

mov eax, -15      ; 低位被除数
cdq               ; 扩展符号位到 EDX(符号扩展指令)
mov ecx, 3        ; 除数
idiv ecx          ; 有符号除法,EAX = EAX / ECX,EDX = EAX % ECX

反汇编

00401000  B8 F1 FF FF FF        mov eax, -15  ; EAX = -15
00401005  99                    cdq           ; 扩展符号到 EDX(EDX = -1)
00401006  B9 03 00 00 00        mov ecx, 3    ; ECX = 3
0040100B  F7 F9                 idiv ecx      ; EAX = EAX / ECX, EDX = EAX % ECX

结果

  • EAX = -5(商)
  • EDX = 0(余数)

总结

指令

类型

被除数 / 被乘数

操作数

商 / 结果存储位置

余数存储位置

mul

无符号乘法

EAX

操作数寄存器

EAX(低位)

EDX(高位)

imul

有符号乘法

EAX(默认)或指定

操作数寄存器

根据目标寄存器

N/A

div

无符号除法

EDX:EAX(64 位)

除数寄存器

EAX(商)

EDX(余数)

idiv

有符号除法

EDX:EAX(64 位)

除数寄存器

EAX(商)

EDX(余数)

 

拓展阅读

在反汇编技术和安全对抗中,mulimuldividiv 指令确实存在一些针对性的使用场景,尤其在逆向工程、代码混淆、漏洞利用和恶意软件分析等领域,这些指令可以被用来达成特定目的。以下是它们的典型使用场景和在安全领域的作用


1. mul(无符号乘法)和 imul(有符号乘法)

典型场景

  1. 加密和哈希算法
    • 乘法指令常用于实现简单的加密或哈希算法。例如,很多哈希函数(如 CRC、FNV-1a)会使用乘法来增加数据的混淆性。
    • 反汇编中分析到大量乘法时,可能意味着代码在处理数据混淆、加密或哈希操作。
  1. 指针计算与数组索引
    • 在复杂数据结构中,特别是二维数组或动态分配的数据结构,编译器可能用乘法来计算内存偏移。
    • 在逆向中看到 imulmul 指令时,可能需要关注操作数,推断是否涉及数组或内存访问。
  1. 混淆和虚拟机(VM)保护
    • 恶意软件或受保护的程序可能会用 imulmul 生成复杂的数值计算路径,增加反汇编后的逻辑复杂性,使其难以理解。
  1. 数据溢出漏洞利用
    • 当有符号和无符号数据混用时,乘法可能导致整数溢出(如超出 32 位范围),引发逻辑漏洞。
    • 攻击者可以利用这一点,在输入数据时精心构造数值,导致计算结果异常。

对抗分析

  • 如果乘法用于混淆,在逆向中需要分析乘法结果的具体意义。
  • 通过数据追踪和解密算法复现,逆向分析人员可以还原加密或混淆逻辑。

2. div(无符号除法)和 idiv(有符号除法)

典型场景

  1. 数据格式化与解析
    • 除法常用于数据格式化(如时间戳计算、文件偏移计算)。例如,从字节流中解析结构化数据时,除法用于拆分字段。
    • 反汇编时,看到 dividiv 时,可能需要检查是否在处理协议数据或文件格式。
  1. 计算模块与循环控制
    • dividiv 常用于模运算。例如,程序可能通过 dividiv 提取数组索引或检查数据对齐性。
    • 攻击者可利用这一点构造特定输入,破坏程序逻辑。
  1. 触发除零漏洞
    • 安全漏洞利用:如果程序没有检查除数是否为零,攻击者可以提供特定输入,触发除零异常,导致程序崩溃或执行异常。
    • 在逆向中,分析除法操作的除数来源是否可控,是定位潜在漏洞的重要方法。
  1. 指令执行时间攻击
    • 除法操作比其他算术操作(如加法、乘法)耗时更多。攻击者可能通过分析程序的执行时间,推断关键数据(如密码或密钥)。
  1. 代码混淆与陷阱
    • 有时恶意软件会用故意复杂的除法操作混淆逻辑。例如,通过嵌套多层除法,将简单的逻辑包装成看似复杂的操作。

对抗分析

  • 动态分析:在调试环境中检查除法操作的输入数据,尤其是除数,确定是否存在溢出或异常。
  • 解混淆:对于混淆代码,可以通过符号执行或数学化简,还原原始逻辑。

3. 在恶意软件与反调试中的作用

反调试检测

  • 恶意软件可能利用 idiv 触发异常的特性来检测调试环境:
    • 在调试器运行时,程序故意用 idiv 执行除零操作。如果调试器没有正确处理异常,程序会进入异常处理流程,进而检测到调试器存在。
    • 示例:
xor eax, eax    ; 设置被除数为 0
idiv ecx        ; 故意执行除零操作
; 如果被调试器捕获,进入异常处理逻辑

混淆代码生成

  • 恶意软件使用 imuldiv 生成复杂的数学路径,例如:
mov eax, key
imul eax, 0x1337
div ecx
    • 这种操作隐藏了关键数据(如 key),让逆向分析更困难。

4. 逆向与安全对抗中的分析重点

  • 操作数追踪
    • 关注乘法和除法指令的操作数,明确数据来源(常量、寄存器、内存地址)。
    • 在工具(如 IDA Pro、Ghidra)中,通过符号追踪明确值的意义。
  • 异常处理逻辑
    • 分析代码是否对除法异常(如除零)有特定处理逻辑,结合反调试场景加以分析。
  • 混淆逻辑解读
    • 尝试用数学化简方法,解读乘法和除法结果。例如,muldiv 的链式调用通常可以还原为简单的代数表达式。
  • 溢出检测
    • 如果存在 mulimul 操作,检查高位结果(EDX)是否被使用或丢弃,判断是否可能导致整数溢出。

5. 案例总结

以一个恶意软件的混淆示例为例:

mov eax, 0x1234
imul eax, 0x5678
div ecx

在代码中,imuldiv 配合实现了数据混淆。在反汇编中,我们可以:

  1. 动态调试,检查寄存器值在每条指令执行后的变化。
  2. 解混淆,通过将 imuldiv 的操作还原为代数公式,简化逻辑。

总结

mulimuldividiv 在反汇编技术和安全对抗中,既可以作为分析目标,也能用作保护手段:

  1. 攻击者可能利用它们的异常特性(如除零)或溢出特性来制造漏洞或反调试逻辑。
  2. 恶意软件可能使用这些指令混淆数据流,隐藏真实逻辑。
  3. 逆向工程师需要通过静态和动态分析工具,还原这些指令的逻辑和用途,从而解读隐藏意图。

对这些指令的深入理解,是掌握反汇编技术和安全对抗的关键环节!

请登录后发表评论