CMU Bomblab(汇编小笔记)

参考: https://github.com/CurryTang/bomb_lab_solution

以下从x64架构为准

1. 相关指令:

1.1 objdump: 用于给出所有汇编指令

objdump -d

Display assembler contents of executable sections

1
objdump -d xxx > xxx.asm

1.2 gdb

1
2
3
4
5
6
7
gdb <program> # 调试程序
p <var> # 打印变量
b <func> # 给函数设置端点
c # continue
n # next line, stepping over function calls
s # next line, stepping into funciton calls
list # 展开源程序代码
1
2
3
4
5
6
p/c *0x2000@10 # 查看内存字符值
x /25c 0x2000 # x本身就是看内存的, 不需要加*

p/x $eax # 查看寄存器值的8进制形式

x /20a 0x2000

x 按十六进制格式显示变量。

d 按十进制格式显示变量。

u 按十六进制格式显示无符号整型。

o 按八进制格式显示变量。

t 按二进制格式显示变量。

a 按十六进制格式显示变量。

c 按字符格式显示变量。

f 按浮点数格式显示变量。

切换栈帧:

1
2
3
bt

f [N]

显示所有寄存器

1
i registers

看寄存器的值

1
x /16xb $eax+0x14

1.3 strings

如果从汇编中看到某些关键字符, 可以这样获取一整句话:

1
strings bomb | grep keywords

2. Bomblab实验操作

  1. 开启汇编窗口(好查看对应的汇编代码)
1
layout asm
  1. 打断点

在进每个阶段前且在readline前打断点

1
b *0x400e37 # 地址\指针前要有 *
1
2
3
4
5
6
b phase_1
b phase_2
b phase_3
b phase_4
b phase_5
b phase_6
  1. 开始运行,进行调试
1
2
3
4
5
6
7
8
r

# 查看某一个地址/函数的汇编 (如果不在运行没法根据地址看汇编, 只能用函数名名字)
disassem *0x400ee0

disassem phase_1

disassem strings_not_equal

3. 看汇编

x86系统中,栈的地址是从高地址往低地址, push栈帧的时候, rsp(stack pointer)减少四个字节.

寄存器

3.1 通用寄存器(64位寄存器)

0x8(%rsp) 表示上一个变量(一般第一个)

bomb中将string_length的返回值放在EAX中

EAX: accumulator, 加法乘法指令的缺省寄存器
EBX: base基地址寄存器,在内存寻址时存放基地址
ECX: counter计数器, 重复(REP)前缀指令和LOOP指令的内定计数器
EDX: 存放整数除法产生的余数
ESI/EDI: source/destination index, 字符串操作指令里, DS:ESI指向源串, ES:EDI指向目标串
EBP: base pointer, 高级语言函数调用时的frame pointer保存地方
如:

1
2
3
push ebp;  // 保存当前ebp
mov ebp,esp; // ebp设为当前
sub esp,xxx; // 预留xxx字节给函数临时变量

ESP: 专门用作堆栈的顶部指针

3.2 其他寄存器:

R0~R12 是64位工作寄存器, 其中R12有可能被linker修改,所以函数开头经常对R12进行保护

1
push %r12 # 将R12的内容推入堆栈进行保护

当函数参数少于7个时, 从左到右参数依次放入寄存器:

  • rdi
  • rsi
  • rdx
  • rcx
  • r8
  • r9

3.3 条件跳转指令和比较指令:

https://faydoc.tripod.com/cpu/jle.htm

test 指令主要将两个操作数按位与, 并根据结果设置标志寄存器 (结果不会写回到目标操作数), test的两个寄存器只有都是空(全0)时或者不同时, ZF才会被置位

注意: addq src, dst -> dst = dst + src, 会将结果写回到目标寄存器上

test指令位与运算结果为0的话, ZF(Zero Flag)设为0.

je 是jz(jump if zero)的别称.
jne就是反过来的条件跳转指令

1
2
3
4
5
6
7
cmp eax, edx
ja somewhere ; will go "somewhere" if eax >u edx
; where >u is "unsigned greater than"

cmp eax, edx
jg somewhere ; will go "somewhere" if eax >s edx
; where >s is "signed greater than"

cmpb: 判断是否相等, 然后置ZF为1:

cmpl:
For >, there is ja for unsigned and jg for signed (jump if above and jump if greater).

For <, there is jb for unsigned and jl for signed (jump if below and jump if less).
1
cmpb $0x0, (%edx)

(%edx) 表示 %edx中所保存的地址指向单元的内容(即取指针所指内容)

3.4 寄存器操作:

https://stackoverflow.com/questions/19748074/meaning-of-0x8rsp

0x8(%rsp) means "get the location on the stack that is 8 bytes away from the stack pointer %rsp

lea: 和mov很像, 不过有其他作用

其他:

因为不同同学的bomb内容不同, 我帮的一位同学比网上的版本要稍微复杂一些,共计19小时,bingo~

这篇笔记只是零星随笔, 帮助自己回忆汇编, 日后有机会会综合整理


CMU Bomblab(汇编小笔记)
https://www.torch-fan.site/2022/09/22/CMU-Bomblab-汇编小笔记/
作者
Torch-Fan
发布于
2022年9月22日
更新于
2022年11月15日
许可协议