Bomb Lab

626 阅读14分钟

任务目标

通过反汇编可执行程序,来反推出程序执行内容

找到六个正确的字符串来解除自己的炸弹

操作指南

LAB 官网

wget <http://csapp.cs.cmu.edu/3e/bomb.tar>

截屏2023-02-26 21.57.48.png

共有6个 phase,难度逐级提升

objdump-用于反汇编二进制对象文件

gdb-用于运行时单步调试与查看运行时内存与寄存器信息

前置知识

寄存器:存储最常用的数据

截屏2023-02-26 21.58.53.png

常用汇编指令

b w l q 字节1 2 4 8
//传送语句
leaq S,D //加载有效地址D←&S
mov S,D //S传向D(源-目的)
movq (%rdi),%rax //从内存中读值到寄存器
movq %rsi,(%rdi) //从寄存器写到内存  括号括起来表示--寻内存的地址

//控制语句
cmp a,b //比较 计算b-a  cmpb,cmpw,cmpl,cmpq 
test b,a //测试 a&b
test a,a //检查a是正数 负数 还是0
jmp  //跳转
je //相等时跳
jne //不等时跳
jg  //大于时
jl  //小于时
jbe //<=时

//过程语句
call //调用
ret  //从调用返回

//栈相关
pushq S //入栈
popq D //出栈

//算数 逻辑
//二元操作
add S,D //D←D+S
sub S,D //D←D-S
imul S,D //D←D*S 乘
xor S,D //D←D^S 异或
and S,D //D←D&S 与

//移位操作
sar k,D //算数右移 D>>k
sal D    //D默认左移一位
shr k,D //逻辑右移
shr $0x1f,%ecx //ecx >> 31

//核心
//phase_4 递归
//phase_5 for循环
and    $0xf,%edx; //得到当前字符的后四位
movzbl 0x4024b0(%rdx),%edx; //edx = *(rdx + 0x4024b0); 0x4024b0处存了个字符串,每次获取第%rdx个字符,%rdx从输入所获得的字符的后四位
(gdb) x/s 0x4024b0 //数组选择前16位,"maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"
//输入rdx--每个字符&0xf--将其作为maduiersnfotvbyl的下标选择字符

//phase_6 链表 结构体
struct {
    int value;
    int order;
    node* next;
} node;
//输入正确的order--使node的value从大到小排列
//6个node由大到小排序 对node排序(345612)✅ VS ❌将6个值从大到小排序 对值排序
node1: 0x14c 5
node2: 0x0a8 6
node3: 0x39c 1
node4: 0x2b3 2
node5: 0x1dd 3
node6: 0x1bb 4
node3 > node4 > node5 > node6 > node1 > node2

常用操作符含义

gdb命令

截屏2023-02-26 21.58.53.png

截屏2023-02-26 21.59.53.png

截屏2023-02-26 22.00.07.png

截屏2023-02-26 22.00.14.png

内存如何存储数据?

截屏2023-02-26 22.00.23.png

内存模型——-堆+栈

截屏2023-02-26 22.01.56.png

实例

int add_a_and_b(int a, int b) {
   return a + b;
}

int main() {
   return add_a_and_b(2, 3);
}

截屏2023-02-26 22.03.29.png

tmux常用命令+vim语法高亮

参考www.ruanyifeng.com/blog/2019/1…

//tmux常用命令
tmux //启动tmux
ctrl + dexit //退出tmux
ctrl + b % //划分左右两窗口
ctrl + b " //划分上下两窗口
ctrl + b <箭头> //移动光标到上下左右窗格
ctrl + b x //关闭当前窗格

//vim语法高亮
:syntax on
vimrc配置 ... //配置完可以一直使用

//用到的gdb命令
gdb bomb //开始调试
x/s 0x4025cf //查看这个地址的字符串
0x4025cf:       "%d %d"
print (char *) 0x4025cf//同上
jmpq *0x402470(,%rax,8) //间接跳转 是switch特征  dst=0x402470 + 8 * rax
x/8g 0x402470 //检查以0x402470为起始地址的8个内存地址里的内容
x/8a 0x402470

b explode_bomb //打断点
b phase_1
set args ./solution.txt  //设置参数
run //运行
continue // 继续运行
info registers //查看寄存器内容

题目解法

bomb.c — 找到main 函数 — 看注释

objdump命令将炸弹文件反汇编出来:

objdump -d bomb > bomb.s

截屏2023-02-26 22.03.38.png

main 函数

【1】phase 1

考察 字符串

0000000000400ee0 <phase_1>:
  400ee0: 48 83 ec 08                  	subq	$8, %rsp             #栈指针减8
  400ee4: be 00 24 40 00               	movl	$4203520, %esi   # imm = 0x402400    #第二个参数传0x402400
  400ee9: e8 4a 04 00 00               	callq	0x401338 <strings_not_equal>   #调用函数 <strings_not_equal>
  400eee: 85 c0                        	testl	%eax, %eax            #验证函数 <strings_not_equal>返回值
  400ef0: 74 05                        	je	0x400ef7 <phase_1+0x17>    # 如果返回值为0,跳转0x400ef7
  400ef2: e8 43 05 00 00               	callq	0x40143a <explode_bomb>   # 如果返回值不为0,爆炸
  
	400ef7: 48 83 c4 08                  	addq	$8, %rsp
  400efb: c3                           	retq
phase_1(rdi){
	esi = 0x402400;
	strings_not_equal(rdi,rsi);
	if(eax === 0) {
		retq
	}
		callq explode_bomb;
}
gdb -q bomb # -q 安静模式
layout split
b phase_1
b explode_bomb

截屏2023-02-26 22.03.44.png “Border relations with Canada have never been better.”

【1】phase 2

考察 数组和循环

0000000000400efc <phase_2>:
	400efc: 55                           	pushq	%rbp  #栈帧相关:被调用者保存 
  400efd: 53                           	pushq	%rbx  #栈帧相关:被调用者保存 
  400efe: 48 83 ec 28                  	subq	$40, %rsp # 栈指针减40
  400f02: 48 89 e6                     	movq	%rsp, %rsi # 将栈指针作为第二个参数
  400f05: e8 52 05 00 00               	callq	0x40145c <read_six_numbers> # 调用函数

  400f0a: 83 3c 24 01                  	cmpl	$1, (%rsp) #比较rsp内存地址是否是1
  400f0e: 74 20                        	je	0x400f30 <phase_2+0x34> #是1则跳转0x400f30
  400f10: e8 25 05 00 00               	callq	0x40143a <explode_bomb> #否则爆炸
  400f15: eb 19                        	jmp	0x400f30 <phase_2+0x34> 跳转0x400f30

  400f17: 8b 43 fc                     	movl	-4(%rbx), %eax  #%rax = rbx内存地址减去4
  400f1a: 01 c0                        	addl	%eax, %eax  # rax+=rax
  400f1c: 39 03                        	cmpl	%eax, (%rbx) #比较rbx内存地址是否是 rax
  400f1e: 74 05                        	je	0x400f25 <phase_2+0x29> #是 跳转0x400f25
  400f20: e8 15 05 00 00               	callq	0x40143a <explode_bomb> #否 爆炸

  400f25: 48 83 c3 04                  	addq	$4, %rbx  #rbx+= 4
  400f29: 48 39 eb                     	cmpq	%rbp, %rbx #比较rbx是否等于rbp
  400f2c: 75 e9                        	jne	0x400f17 <phase_2+0x1b> #不等于 跳转0x400f17
  400f2e: eb 0c                        	jmp	0x400f3c <phase_2+0x40> #跳转0x400f3c

  400f30: 48 8d 5c 24 04               	leaq	4(%rsp), %rbx  #栈指针+4后赋值给 rbx
  400f35: 48 8d 6c 24 18               	leaq	24(%rsp), %rbp  #栈指针+24后赋值给 rbp
  400f3a: eb db                        	jmp	0x400f17 <phase_2+0x1b>  # 跳转0x400f17

  400f3c: 48 83 c4 28                  	addq	$40, %rsp 
  400f40: 5b                           	popq	%rbx
  400f41: 5d                           	popq	%rbp
  400f42: c3                           	retq

<read_six_numbers>

000000000040145c <read_six_numbers>:
  40145c: 48 83 ec 18                  	**subq	$24, %rsp  #设置6个数字**
  401460: 48 89 f2                     	movq	%rsi, %rdx
  401463: 48 8d 4e 04                  	leaq	4(%rsi), %rcx
  401467: 48 8d 46 14                  	leaq	20(%rsi), %rax
  40146b: 48 89 44 24 08               	movq	%rax, 8(%rsp)
  401470: 48 8d 46 10                  	leaq	16(%rsi), %rax
  401474: 48 89 04 24                  	movq	%rax, (%rsp)
  401478: 4c 8d 4e 0c                  	leaq	12(%rsi), %r9
  40147c: 4c 8d 46 08                  	leaq	8(%rsi), %r8
  401480: be c3 25 40 00               	movl	$4203971, %esi          # imm = 0x4025C3
  401485: b8 00 00 00 00               	movl	$0, %eax
  40148a: e8 61 f7 ff ff               	callq	0x400bf0 **<__isoc99_sscanf@plt>**
  40148f: 83 f8 05                     	cmpl	$5, %eax
  401492: 7f 05                        	jg	0x401499 <read_six_numbers+0x3d>
  401494: e8 a1 ff ff ff               	callq	0x40143a <explode_bomb>

  401499: 48 83 c4 18                  	**addq	$24, %rsp** 
  40149d: c3                           	retq
  • 可读性调整
phase_2(rdi) {
	rsi = rsp - 40;
	callq <read_six_numbers>;

	if(*rsp == 1){  #注意是*rsp
	  go to 0x400f30; 
	}
	callq <explode_bomb>;
  
400f17: 
	rax = *(rbx - 4);
	rax += rax;
	if(*rbx == rax){
	  goto 0x400f25;
  }
	callq <explode_bomb>;

400f25:
	rbx += 4;
	if(rbx != rbp){ 
		goto 0x400f17; #循环
	} else {
		goto 0x400f3c; #循环结束
	}

400f30:
	rbx = rsp + 4;
	rbp = rsp + 24;
	goto 0x400f17;

400f3c:
	popq
	retq
}
  • C 风格
phase_2(a) {
	rsi = rsp - 40;
	read_six_numbers;
	if(*rsp !== 1) bomb;  # 说明 *rsp = 1
	
	rbx = rsp + 4;  # 初始值
	rbp = rsp + 24; # 6个

	do {
	rax += *(rbx - 4);
	if(*rbx != rax) bomb; # 说明 *rbx = 2 *(rbx-4);
	
	rbx += 4;
	} 
	while(rbx != rbp)
	ret
}
  • C 伪代码
phase_2(char *a) {
	int b;
	read_six_numbers(a, b);
	if(b[0] !== 1) bomb();  # 说明 第一个元素 = 1
	
	for(i = 1; i < 6; i++){
		b[i-1] += b[i-1];  # 说明 数组中后一个元素是前一个元素的2倍
		if(b[i] != b[i-1]) bomb();
	}
	return
}
  • 答案

1 2 4 8 16 32

【1】phase 3

考察 switch-case

0000000000400f43 <phase_3>:
  400f43: 48 83 ec 18                  	subq	$24, %rsp # 6个变量
  400f47: 48 8d 4c 24 0c               	leaq	12(%rsp), %rcx #栈指针+12后赋值给 rcx
  400f4c: 48 8d 54 24 08               	leaq	8(%rsp), %rdx #栈指针+8后赋值给 rdx
  400f51: be cf 25 40 00               	movl	0x4025CF, %esi   #gdb: x/s 0x4025CF => rsi = '%d %d' 
  400f56: b8 00 00 00 00               	movl	$0, %eax  #rax = 0
  400f5b: e8 90 fc ff ff               	callq	0x400bf0 <__isoc99_sscanf@plt>
  400f60: 83 f8 01                     	cmpl	$1, %eax 
  400f63: 7f 05                        	jg	0x400f6a <phase_3+0x27>
  400f65: e8 d0 04 00 00               	callq	0x40143a <explode_bomb>

  400f6a: 83 7c 24 08 07               	cmpl	$7, 8(%rsp)
  400f6f: 77 3c                        	ja	0x400fad <phase_3+0x6a>
  400f71: 8b 44 24 08                  	movl	8(%rsp), %eax
  **400f75: ff 24 c5 70 24 40 00         	jmpq	*4203632(,%rax,8)**    #跳转表 *(0x402470+rax*8)

  400f7c: b8 cf 00 00 00               	movl	$207, %eax
  400f81: eb 3b                        	jmp	0x400fbe <phase_3+0x7b>
  400f83: b8 c3 02 00 00               	movl	$707, %eax              # imm = 0x2C3
  400f88: eb 34                        	jmp	0x400fbe <phase_3+0x7b>
  400f8a: b8 00 01 00 00               	movl	$256, %eax              # imm = 0x100
  400f8f: eb 2d                        	jmp	0x400fbe <phase_3+0x7b>
  400f91: b8 85 01 00 00               	movl	$389, %eax              # imm = 0x185
  400f96: eb 26                        	jmp	0x400fbe <phase_3+0x7b>
  400f98: b8 ce 00 00 00               	movl	$206, %eax
  400f9d: eb 1f                        	jmp	0x400fbe <phase_3+0x7b>
  400f9f: b8 aa 02 00 00               	movl	$682, %eax              # imm = 0x2AA
  400fa4: eb 18                        	jmp	0x400fbe <phase_3+0x7b>
  400fa6: b8 47 01 00 00               	movl	$327, %eax              # imm = 0x147
  400fab: eb 11                        	jmp	0x400fbe <phase_3+0x7b>

  400fad: e8 88 04 00 00               	callq	0x40143a <explode_bomb>
  400fb2: b8 00 00 00 00               	movl	$0, %eax
  400fb7: eb 05                        	jmp	0x400fbe <phase_3+0x7b>
  400fb9: b8 37 01 00 00               	movl	$311, %eax              # imm = 0x137

  400fbe: 3b 44 24 0c                  	cmpl	12(%rsp), %eax
  400fc2: 74 05                        	je	0x400fc9 <phase_3+0x86>
  400fc4: e8 71 04 00 00               	callq	0x40143a <explode_bomb>
  400fc9: 48 83 c4 18                  	addq	$24, %rsp
  400fcd: c3                           	retq
  • 可读性调整
phase_3(a){
	rsi = '%d %d';  
	rax = 0;
	sccanf();
	if(rax <= 1) bomb();
	if(*(rsp + 8) > 7) bomb();
	goto *(0x402470+rax*8)
	
400f7c: #0
	eax == $207; goto 400fbe;
400f83: #2
	eax == $707; goto 400fbe;
400f8a: #3
	eax == $256; goto 400fbe;
400f91: #4
	eax == $389; goto 400fbe;
400f98: #5
	eax == $206; goto 400fbe;
400f9f: #6
	eax == $682; goto 400fbe;
400fa6: #7
	eax == $327; goto 400fbe;
	%eax = 0; goto 400fbe;
400fb9: #1
	eax = $311;

400fbe:
	if(rax != *(rsp + 12)) bomb();
	retq;
}

截屏2023-02-26 22.03.55.png

  • C 风格
phase_3(char* a){
	if(sccanf(a, '%d %d', &x, &y) <= 1) bomb(); # 将输入的字符串解析为两个数字x,y
	if(x > 7) bomb(); # x <= 7

	switch(x){ #映射
		case 0: y = 207; break;
		case 1: y = 311; break;
		case 2: y = 707; break;
		case 3: y = 256; break;
		case 4: y = 389; break;
		case 5: y = 206; break;
		case 6: y = 682; break;
		case 7: y = 327; break;
	}
}
  • 答案

    8组 0 207/1 311/…

【0】phase 4

考察 递归

000000000040100c <phase_4>:
  40100c: 48 83 ec 18                  	subq	$24, %rsp 
  401010: 48 8d 4c 24 0c               	leaq	12(%rsp), %rcx
  401015: 48 8d 54 24 08               	leaq	8(%rsp), %rdx
  40101a: be cf 25 40 00               	movl	$4203983, %esi          # imm = 0x4025CF
  40101f: b8 00 00 00 00               	movl	$0, %eax
  401024: e8 c7 fb ff ff               	callq	0x400bf0 <__isoc99_sscanf@plt>
  401029: 83 f8 02                     	cmpl	$2, %eax
  40102c: 75 07                        	jne	0x401035 <phase_4+0x29>

  40102e: 83 7c 24 08 0e               	cmpl	$14, 8(%rsp)
  401033: 76 05                        	jbe	0x40103a <phase_4+0x2e>

  401035: e8 00 04 00 00               	callq	0x40143a <explode_bomb>

  40103a: ba 0e 00 00 00               	movl	$14, %edx
  40103f: be 00 00 00 00               	movl	$0, %esi
  401044: 8b 7c 24 08                  	movl	8(%rsp), %edi
  401048: e8 81 ff ff ff               	**callq	0x400fce <func4>**

  40104d: 85 c0                        	**testl	%eax, %eax**
  40104f: 75 07                        	jne	0x401058 <phase_4+0x4c>
  401051: 83 7c 24 0c 00               	cmpl	$0, 12(%rsp)
  401056: 74 05                        	je	0x40105d <phase_4+0x51>

  401058: e8 dd 03 00 00               	callq	0x40143a <explode_bomb>

  40105d: 48 83 c4 18                  	addq	$24, %rsp
  401061: c3                           	retq
0000000000400fce <func4>:
  400fce: 48 83 ec 08                  	subq	$8, %rsp
  400fd2: 89 d0                        	movl	%edx, %eax
  400fd4: 29 f0                        	subl	%esi, %eax
  400fd6: 89 c1                        	movl	%eax, %ecx
  400fd8: c1 e9 1f                     	shrl	$31, %ecx
  400fdb: 01 c8                        	addl	%ecx, %eax
  400fdd: d1 f8                        	sarl	%eax 
  400fdf: 8d 0c 30                     	leal	(%rax,%rsi), %ecx
  400fe2: 39 f9                        	cmpl	%edi, %ecx
  400fe4: 7e 0c                        	jle	0x400ff2 <func4+0x24>

  400fe6: 8d 51 ff                     	leal	-1(%rcx), %edx
  400fe9: e8 e0 ff ff ff               	**callq	0x400fce <func4> # 递归**
  400fee: 01 c0                        	addl	%eax, %eax 
  400ff0: eb 15                        	jmp	0x401007 <func4+0x39>

  400ff2: b8 00 00 00 00               	movl	$0, %eax
  400ff7: 39 f9                        	cmpl	%edi, %ecx
  400ff9: 7d 0c                        	jge	0x401007 <func4+0x39>

  400ffb: 8d 71 01                     	leal	1(%rcx), %esi
  400ffe: e8 cb ff ff ff               	**callq	0x400fce <func4> # 递归**
  401003: 8d 44 00 01                  	leal	1(%rax,%rax), %eax

  401007: 48 83 c4 08                  	addq	$8, %rsp
  40100b: c3                           	retq
  • 可读性调整
phase_4(rdi){
	rcx = rsp + 12; #参数4
	rdx = rsp + 8; #参数3
	rsi = 0x4025CF; #参数2
	rax = 0; 
	**sccanf(rdi, '%d %d', rdx, rcx);**
	if(rax != 2) bomb();
	if(*(rsp + 8) <= 14) goto 0x40103a;
	bomb();

0x40103a:
	rdx = 14; #参数3
	rsi = 0; #参数2
	rdi = *(rsp + 8); #参数1
	**func4(rdi, rsi, rdx);**
	if(rax ! = 0) bomb();
	if(*(rsp + 12) != 0) bomb();
	return
}
func4(a, b, c){
	rax = c - b;
	rax = (rax + rax >>31) >> 1;
	rcx = rax + rsi;
	if(rcx <= a) goto 0x400ff2;
	
	c = rcx - 1;
	**func4(); #递归**
	rax += rax;
	goto 0x401007;

0x400ff2:
	rax = 0;
	if(rcx >= a) goto 0x401007;
	
	b = rcx + 1;
	**func4(); #递归
	rax = rax + rax +1;**

0x401007:
	return
}
  • C风格
phase_4(char *input){

	rax = sccanf(input, '%d %d', &x, &y) 
	if(rax != 2 || x > 14) bomb();

	ret = func4(x, 0, 14);
	if(ret != 0 || y != 0) bomb(); => func4(x, 0, 14) = 0, y = 0
}
func4(a, b=0, c=14){
	int x = c - b;  # 14
	x = (x + x >>31) / 2; 
	int y = x + b;  #7
	if(y <= a) {
		if(y >= a) return 0;
		return 2 * func4(a, y+1, c) + 1;
	}
	return 2 * func4(a, b, y-1)
}
  • 答案 7 0/……

【0】phase 5

考察 for循环/数组/字符串

0000000000401062 <phase_5>:
  401062: 53                           	pushq	%rbx
  401063: 48 83 ec 20                  	subq	$32, %rsp
  401067: 48 89 fb                     	movq	%rdi, %rbx
  40106a: 64 48 8b 04 25 28 00 00 00   	**movq	%fs:40, %rax #金丝雀**
  401073: 48 89 44 24 18               	movq	%rax, 24(%rsp)
  401078: 31 c0                        	xorl	%eax, %eax
  40107a: e8 9c 02 00 00               	callq	0x40131b <string_length>

  40107f: 83 f8 06                     	cmpl	$6, %eax
  401082: 74 4e                        	je	0x4010d2 <phase_5+0x70>
  401084: e8 b1 03 00 00               	callq	0x40143a <explode_bomb>
  401089: eb 47                        	jmp	0x4010d2 <phase_5+0x70>

  40108b: 0f b6 0c 03                  	movzbl	(%rbx,%rax), %ecx
  40108f: 88 0c 24                     	movb	%cl, (%rsp)
  401092: 48 8b 14 24                  	movq	(%rsp), %rdx
  401096: 83 e2 0f                     	andl	$15, %edx
  401099: 0f b6 92 b0 24 40 00         	movzbl	4203696(%rdx), %edx
  4010a0: 88 54 04 10                  	**movb	%dl, 16(%rsp,%rax)**
  4010a4: 48 83 c0 01                  	addq	$1, %rax
  4010a8: 48 83 f8 06                  	cmpq	$6, %rax
  4010ac: 75 dd                        	jne	0x40108b <phase_5+0x29>
  4010ae: c6 44 24 16 00               	movb	$0, 22(%rsp)
  4010b3: be 5e 24 40 00               	movl	$4203614, %esi          # imm = 0x40245E
  4010b8: 48 8d 7c 24 10               	leaq	16(%rsp), %rdi
  4010bd: e8 76 02 00 00               	callq	0x401338 <strings_not_equal>
  4010c2: 85 c0                        	testl	%eax, %eax
  4010c4: 74 13                        	je	0x4010d9 <phase_5+0x77>
  4010c6: e8 6f 03 00 00               	callq	0x40143a <explode_bomb>
  4010cb: 0f 1f 44 00 00               	nopl	(%rax,%rax)
  4010d0: eb 07                        	jmp	0x4010d9 <phase_5+0x77>

  4010d2: b8 00 00 00 00               	movl	$0, %eax
  4010d7: eb b2                        	jmp	0x40108b <phase_5+0x29>

  4010d9: 48 8b 44 24 18               	movq	24(%rsp), %rax
  4010de: 64 48 33 04 25 28 00 00 00   	xorq	%fs:40, %rax
  4010e7: 74 05                        	je	0x4010ee <phase_5+0x8c>
  4010e9: e8 42 fa ff ff               	callq	0x400b30 <__stack_chk_fail@plt>

  4010ee: 48 83 c4 20                  	addq	$32, %rsp
  4010f2: 5b                           	popq	%rbx
  4010f3: c3                           	retq
  • 可读性调整
phase_5(rdi){
	rbx = rdi;
	**rax = fs:40;**
	*(rsp + 24) = rax;
	rax = rax ^ rax;
	string_length(rdi);
	if(rax != 6) bomb();
	goto 0x4010d2;

0x40108b:
	rcx = rbx + rax; #将输入的字符串保存至rcx中
	*rsp = cl; # 字符串的某一位保存至栈顶
	rdx = *rsp;
	**rdx &= 0xf;  #与0xf做与运算
	rdx = *(rdx + 0x4024b0);**  **#取0x4024b0数组edx位置的值
	# x/s 0x4024b0
	# "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"**

	*(rsp + rax + 16) = dl;
	rax += 1; #自增
	if(rax != 6) goto 0x40108b; #循环
	*(rsp + 22) = 0;
	**rsi = 0x40245E; 
	# x/s 0x40245e
	# 参数二 "flyers"**

	rdi = *(rsp + 16); # 参数一 上面循环压栈的字符
	strings_not_equal(rdi, rsi);
	if(rax == 0) bomb();
	nopl(%rax,%rax);
	goto 0x4010d9;

0x4010d2:
	rax = 0;
	goto 0x40108b; 

0x4010d9:
	rax = *(rsp + 24);
	rax ^= fs:40;
	**if(rax == 0) return**
	callq __stack_chk_fail@plt;
}
  • C风格
phase_5(char *input){
	char str[7];
	**const char g_str[16] = "maduiersnfotvbyl";
	if(string_length(input) != 6) bomb();**  # 长度必须为6
	for(int i = 0; i < 6; i++){
		**str[i] = g_str[input[i] & 0xf]**
	}
	**if(strings_not_equal(str,"flyers") != 0) bomb()
	# f  l  y  e  r  s
	# 9  15 14  5  6  7  input[i] & 0xf**
}
  • 答案

查ascii表 c.biancheng.net/c/ascii/,可以找到六个&0xf分别为 9 15 14 5 6 7的字符:

【0】phase 6

考察 嵌套循环 / 结构体(异构数组)/ 链表


00000000004010f4 <phase_6>:
  4010f4: 41 56                        	pushq	%r14
  4010f6: 41 55                        	pushq	%r13
  4010f8: 41 54                        	pushq	%r12
  4010fa: 55                           	pushq	%rbp
  4010fb: 53                           	pushq	%rbx
  4010fc: 48 83 ec 50                  	subq	$80, %rsp
  401100: 49 89 e5                     	movq	%rsp, %r13 #
  401103: 48 89 e6                     	movq	%rsp, %rsi
  401106: e8 51 03 00 00               	callq	0x40145c <read_six_numbers>
  40110b: 49 89 e6                     	movq	%rsp, %r14
  40110e: 41 bc 00 00 00 00            	movl	$0, %r12d

  401114: 4c 89 ed                     	movq	%r13, %rbp
  401117: 41 8b 45 00                  	movl	(%r13), %eax

  40111b: 83 e8 01                     	subl	$1, %eax
  40111e: 83 f8 05                     	cmpl	$5, %eax
  401121: 76 05                        	jbe	0x401128 <phase_6+0x34>
  401123: e8 12 03 00 00               	callq	0x40143a <explode_bomb>

  401128: 41 83 c4 01                  	addl	$1, %r12d
  40112c: 41 83 fc 06                  	cmpl	$6, %r12d
  401130: 74 21                        	je	0x401153 <phase_6+0x5f>
  401132: 44 89 e3                     	movl	%r12d, %ebx

  401135: 48 63 c3                     	movslq	%ebx, %rax
  401138: 8b 04 84                     	movl	(%rsp,%rax,4), %eax
  40113b: 39 45 00                     	cmpl	%eax, (%rbp)
  40113e: 75 05                        	jne	0x401145 <phase_6+0x51>
  401140: e8 f5 02 00 00               	callq	0x40143a <explode_bomb>

  401145: 83 c3 01                     	addl	$1, %ebx
  401148: 83 fb 05                     	cmpl	$5, %ebx
  40114b: 7e e8                        	jle	0x401135 <phase_6+0x41>
  40114d: 49 83 c5 04                  	addq	$4, %r13
  401151: eb c1                        	jmp	0x401114 <phase_6+0x20>

  401153: 48 8d 74 24 18               	leaq	24(%rsp), %rsi
  401158: 4c 89 f0                     	movq	%r14, %rax
  40115b: b9 07 00 00 00               	movl	$7, %ecx

  401160: 89 ca                        	movl	%ecx, %edx
  401162: 2b 10                        	subl	(%rax), %edx
  401164: 89 10                        	movl	%edx, (%rax)
  401166: 48 83 c0 04                  	addq	$4, %rax
  40116a: 48 39 f0                     	cmpq	%rsi, %rax
  40116d: 75 f1                        	jne	0x401160 <phase_6+0x6c>
  40116f: be 00 00 00 00               	movl	$0, %esi
  401174: eb 21                        	jmp	0x401197 <phase_6+0xa3>

  401176: 48 8b 52 08                  	movq	8(%rdx), %rdx
  40117a: 83 c0 01                     	addl	$1, %eax
  40117d: 39 c8                        	cmpl	%ecx, %eax
  40117f: 75 f5                        	jne	0x401176 <phase_6+0x82>
  401181: eb 05                        	jmp	0x401188 <phase_6+0x94>
  401183: ba d0 32 60 00               	movl	$6304464, %edx          # imm = 0x6032D0
  
	401188: 48 89 54 74 20               	movq	%rdx, 32(%rsp,%rsi,2)
  40118d: 48 83 c6 04                  	addq	$4, %rsi
  401191: 48 83 fe 18                  	cmpq	$24, %rsi
  401195: 74 14                        	je	0x4011ab <phase_6+0xb7>

  401197: 8b 0c 34                     	movl	(%rsp,%rsi), %ecx
  40119a: 83 f9 01                     	cmpl	$1, %ecx
  40119d: 7e e4                        	jle	0x401183 <phase_6+0x8f>
  40119f: b8 01 00 00 00               	movl	$1, %eax
  4011a4: ba d0 32 60 00               	movl	$6304464, %edx          # imm = 0x6032D0
  4011a9: eb cb                        	jmp	0x401176 <phase_6+0x82>
  
	4011ab: 48 8b 5c 24 20               	movq	32(%rsp), %rbx
  4011b0: 48 8d 44 24 28               	leaq	40(%rsp), %rax
  4011b5: 48 8d 74 24 50               	leaq	80(%rsp), %rsi
  4011ba: 48 89 d9                     	movq	%rbx, %rcx

  4011bd: 48 8b 10                     	movq	(%rax), %rdx
  4011c0: 48 89 51 08                  	movq	%rdx, 8(%rcx)
  4011c4: 48 83 c0 08                  	addq	$8, %rax
  4011c8: 48 39 f0                     	cmpq	%rsi, %rax
  4011cb: 74 05                        	je	0x4011d2 <phase_6+0xde>
  4011cd: 48 89 d1                     	movq	%rdx, %rcx
  4011d0: eb eb                        	jmp	0x4011bd <phase_6+0xc9>

  4011d2: 48 c7 42 08 00 00 00 00      	movq	$0, 8(%rdx)
  4011da: bd 05 00 00 00               	movl	$5, %ebp

  4011df: 48 8b 43 08                  	movq	8(%rbx), %rax
  4011e3: 8b 00                        	movl	(%rax), %eax
  4011e5: 39 03                        	cmpl	%eax, (%rbx)
  4011e7: 7d 05                        	jge	0x4011ee <phase_6+0xfa>

  4011e9: e8 4c 02 00 00               	callq	0x40143a <explode_bomb>

  4011ee: 48 8b 5b 08                  	movq	8(%rbx), %rbx
  4011f2: 83 ed 01                     	**subl	$1, %ebp**
  4011f5: 75 e8                        	**jne	0x4011df <phase_6+0xeb>**
  4011f7: 48 83 c4 50                  	addq	$80, %rsp
  4011fb: 5b                           	popq	%rbx
  4011fc: 5d                           	popq	%rbp
  4011fd: 41 5c                        	popq	%r12
  4011ff: 41 5d                        	popq	%r13
  401201: 41 5e                        	popq	%r14
  401203: c3                           	retq
  • 可读性调整
phase_6(rdi){
	r13 = rsp;
	rsi = rsp;
	callq read_six_numbers(rdi, rsi);
	r14 = rsp;
	r12 = 0;
	
401114:
	rbp = r13;
	rax = *r13;

40111b: 
	rax -= 1;
	if(rax > 5) bomb();

401128:
	r12 += 1;
	if(r12 == 6) goto 0x401153; #外循环
	rbx = r12;

401135:
	rax = rbx;
	rax = *(rsp + 4 * rax);
	if(*rbp != rax) goto 0x401145;
	bomb();

401145:
	rbx += 1;
	if(rbx <= 5) goto 0x401135; #内循环
	r13 += 4;
	goto 0x401114;

---------------------------------------------------

401153:
	rsi = *(rsp + 24);
	rax = r14;
	rcx = 7;

401160:
	rdx = rcx;
	rdx -= *rax;
	*rax = rdx;
	rax += 4;
	if(rax != rsi) goto 0x401160; #循环
	rsi = 0;
	goto 0x401197;
	
------------------------------------------------------

401176:
	rdx = *(rdx + 8);
	rax += 1;
	if(rax != rcx) goto 0x401176; #循环
	goto 0x401188;

401183:
	rdx = 0x6032D0;

401188:
	*(rsp + 2rsi + 32) = rdx;
	rsi += 4;
	if(rsi == 24) goto 0x4011ab;  #外循环
	
401197: 
	rcx = *(rsp + rsi);
	if(rcx <= 1) goto 0x401183;
	rax = 1;
	rdx = 0x6032D0;
	goto 0x401176;

-----------------------------------------------------------------

4011ab:
	rbx = *(rsp + 32);
	rax = *(rsp + 40);
	rsi = *(rsp + 80);
	rcx = rbx;

4011bd:
	rdx = *rax;
	*(rcx + 8) = rdx;
	rax += 8;
	if(rax == rsi) goto 0x4011d2;
	rcx = rdx;
	goto 0x4011bd;

-----------------------------------------------------------------

4011d2: 
	*(rdx + 8) = 0;
	rbp = 5;

4011df:
	rax = *(rbp + 8);
	rax = *(rax);
	if(*(rbx) >= rax) goto 0x4011ee;
	bomb();

4011ee:
	rbx = *(rbx + 8);
	rbp -= 1;
	if(rbp != 0) goto 4011df;
}
  • C风格
phase_6(rdi, rsi){
	r13 = rsp;
	rsi = rsp;
	callq read_six_numbers(rdi, rsi);
	r14 = rsp;
	
	for(r12 = 0; r12 != 6; r12++) { 
		rbp = r13;
		rax = *r13; #数组
		rax -= 1;
		if(rax > 5) bomb();  # rax-1<=5 rax<=6
	
		for(rbx = r12 + 1; rbx <= 5; rbx++){
				rax = rbx;
				rax = *(rsp + 4 * rax);
				if(*rbp == rax) bomb();  #元素不重复
		}
		r13 += 4;
	}

---------------------------------------------------------------

401153:
	rsi = *(rsp + 24);
	rcx = 7;

	for(rax = 14; rax != rsi; rax += 4){
			rdx = rcx;   # 修改数组
			rdx -= *rax;  # rdx = 7 - *rax
			*rax = rdx;   # *rax = 7 - *rax
	}
	
----------------------------------------------------------------

401176:
for(rsi = 0; rsi != 24; rsi +=4){
		rcx = *(rsp + rsi);
		rdx = 0x6032D0;  // 链表head
		if(rcx > 1) {
			for(rax = 1; rax != rcx; rax++){
				rdx = *(rdx + 8);
			}
		}
		*(rsp + 2rsi + 32) = rdx;
}

-----------------------------------------------------------------

4011ab:
	rbx = *(rsp + 32);
	rcx = rbx;
	for(rax = *(rsp + 40); rax != *(rsp + 80); rax += 8){
		rdx = *rax;
		*(rcx + 8) = rdx;   # *(rax + 8) = *rax;
		rcx = rdx; 
	}

-----------------------------------------------------------------

4011d2: 
	*(rdx + 8) = 0;  # ListNode* ptr = node_array[0];
	
	for(rbp = 5; rbp != 0; rbp -= 1;){
		rax = *(rbp + 8);
		rax = *(rax);
		if(*(rbx) < rax) bomb(); # ptr->val < ptr->next->val
		rbx = *(rbx + 8); # ptr = ptr->next;
	}
}
typedef struct {
    int val;
    ListNode* next;
} ListNode;

phase_6(char* input){
	int array[6]; #r13
	read_six_numbers(input, array[6]);

	# 输入数组的一些限定条件
	for(int i = 0; i != 6; i++){
		int num = array[i];
		num -= 1;
		**if(num > 5) bomb(); #num小于等于 5, i小于等于6**
		for(int j = i+1; j <= 5; j++){
			num = j;
			**if(arr[i] == arr[j]) boumb(); #元素不重复**
		}
	}

	# 修改数组元素的值
	for(int i = 0; i != 6; i++){
		array[i] = 7 - array[i] **#重排**
	}

	# 
	for(int i = 0; i != 6; i++){
		int num = array[i];
		**rdx = 0x6032D0;  
		# ListNode* node = 0x6032d0;
		#(gdb) x/24w 0x6032d0 结构体 应该是链表结构**

		if(num > 1){
			for(int j = 1; j!= num; j++){
				rdx = *(rdx + 8);
			}
		}
		***(rsp + 2rsi + 32) = rdx; # node_array[i] = node;**
	}

	#
	for(int i = 0; i != 5; i++){
		**node_array[i]->next = node_array[i+1]; #链表**
	}

	
	ListNode* ptr = node_array[0];
	for (int i = 5; i > 0; i--) {
      **if (ptr->val < ptr->next->val) # 降序**
          explode_bomb();
      ptr = ptr->next;
  }
}
  • 答案

	// (gdb) x/24w 0x6032d0 结构体 应该是链表结构**
	// node1 node2 node3 node4 node5 node6**
	// 0x6032d0 0x6032e0 0x6032f0 0x603300 0x603310 0x603320
  // 332 168 924 691 477 443
	// 递减node排序 -- 3,4,5,6,1,2
	// 7 - array[i]
	// 递增 -- 4,3,2,1,6,5

截屏2023-02-26 22.04.13.png

截屏2023-02-26 22.04.18.png

参考博客

blog.csdn.net/qq_38537503…解题思路 转换成C 第四五题

zhuanlan.zhihu.com/p/104130161 注释

zhuanlan.zhihu.com/p/458872003

earthaa.github.io/2020/01/12/… 注释写的好

wdxtub.com/csapp/thick… CMU的学生 另一种解题思路

www.viseator.com/2017/06/21/…

blog.csdn.net/zhangjs0322… gdb调试的 layout

www.coonote.com/gdb-note/gd… gdb 命令大全

www.ruanyifeng.com/blog/2018/0… x86-64汇编语言入门

最好的搭配:每一题的栈帧+转换代码

八. 总结

  1. 寄存器的eflags 每个寄存器都有条件码位(ZF SF...)
  2. 数组 循环 结构体的表示
  3. 栈帧结构
  4. gdb调试打断点 + info register很酷
  5. tmux + vim很酷