计算机系统导论 Bomb Lab Phase 1~6 全解
ICS Bomb Lab——The Ultimate Companion
经验教训:
- 不要尝试通过眼睛瞪来把结果瞪出来——不打草稿的话,难度太大了。
- 不要瞎改内存地址来试图通过——不然会结算成爆炸。
提示:break
、run
、disassemble
、stepi
与nexti
。
- https://stackoverflow.com/questions/3305164/how-to-modify-memory-contents-using-gdb
(gdb) set {int}0x83040 = 4
- https://github.com/Marus/cortex-debug/issues/173
set $r7=4
参考表:
-
b
,w
,l
,q
-
jmp
(页码+表格) -
mov
movz
movs
-
寄存器
解释:
callq
retq
push
main()
Dump of assembler code for function main:
0x00000000000014c9 <+0>: endbr64
0x00000000000014cd <+4>: push %rbx
0x00000000000014ce <+5>: cmp $0x1,%edi
0x00000000000014d1 <+8>: je 0x1524 <main+91>
0x00000000000014d3 <+10>: mov %rsi,%rbx
0x00000000000014d6 <+13>: cmp $0x2,%edi
0x00000000000014d9 <+16>: jne 0x1556 <main+141>
0x00000000000014db <+18>: mov 0x8(%rsi),%rdi
0x00000000000014df <+22>: lea 0x3250(%rip),%rsi # 0x4736
0x00000000000014e6 <+29>: callq 0x1350 <fopen@plt>
0x00000000000014eb <+34>: mov %rax,0x6f9e(%rip) # 0x8490 <infile>
0x00000000000014f2 <+41>: test %rax,%rax
0x00000000000014f5 <+44>: je 0x1534 <main+107>
0x00000000000014f7 <+46>: callq 0x1d3a <initialize_bomb>
0x00000000000014fc <+51>: mov %rax,%rbx
0x00000000000014ff <+54>: cmpl $0x2022fa11,(%rax)
0x0000000000001505 <+60>: je 0x1579 <main+176>
0x0000000000001507 <+62>: lea 0x2b7a(%rip),%rsi # 0x4088
0x000000000000150e <+69>: mov $0x1,%edi
0x0000000000001513 <+74>: mov $0x0,%eax
0x0000000000001518 <+79>: callq 0x1340 <__printf_chk@plt>
0x000000000000151d <+84>: mov $0x0,%eax
0x0000000000001522 <+89>: pop %rbx
0x0000000000001523 <+90>: retq
0x0000000000001524 <+91>: mov 0x6f45(%rip),%rax # 0x8470 <stdin@@GLIBC_2.2.5>
0x000000000000152b <+98>: mov %rax,0x6f5e(%rip) # 0x8490 <infile>
0x0000000000001532 <+105>: jmp 0x14f7 <main+46>
0x0000000000001534 <+107>: mov 0x8(%rbx),%rcx
0x0000000000001538 <+111>: mov (%rbx),%rdx
0x000000000000153b <+114>: lea 0x2ac2(%rip),%rsi # 0x4004
0x0000000000001542 <+121>: mov $0x1,%edi
0x0000000000001547 <+126>: callq 0x1340 <__printf_chk@plt>
0x000000000000154c <+131>: mov $0x8,%edi
0x0000000000001551 <+136>: callq 0x1370 <exit@plt>
0x0000000000001556 <+141>: mov (%rsi),%rdx
0x0000000000001559 <+144>: lea 0x2ac1(%rip),%rsi # 0x4021
0x0000000000001560 <+151>: mov $0x1,%edi
0x0000000000001565 <+156>: mov $0x0,%eax
0x000000000000156a <+161>: callq 0x1340 <__printf_chk@plt>
0x000000000000156f <+166>: mov $0x8,%edi
0x0000000000001574 <+171>: callq 0x1370 <exit@plt>
0x0000000000001579 <+176>: lea 0x2b48(%rip),%rdi # 0x40c8
0x0000000000001580 <+183>: callq 0x1260 <puts@plt>
0x0000000000001585 <+188>: lea 0x2b7c(%rip),%rdi # 0x4108
0x000000000000158c <+195>: callq 0x1260 <puts@plt>
0x0000000000001591 <+200>: callq 0x21f3 <read_line>
0x0000000000001596 <+205>: mov %rax,%rdi
0x0000000000001599 <+208>: callq 0x1778 <phase_1>
0x000000000000159e <+213>: mov %rbx,%rdi
0x00000000000015a1 <+216>: callq 0x233e <phase_defused>
0x00000000000015a6 <+221>: lea 0x2b9b(%rip),%rdi # 0x4148
0x00000000000015ad <+228>: callq 0x1260 <puts@plt>
0x00000000000015b2 <+233>: callq 0x21f3 <read_line>
0x00000000000015b7 <+238>: mov %rax,%rdi
0x00000000000015ba <+241>: callq 0x179c <phase_2>
0x00000000000015bf <+246>: mov %rbx,%rdi
0x00000000000015c2 <+249>: callq 0x233e <phase_defused>
0x00000000000015c7 <+254>: lea 0x2a6d(%rip),%rdi # 0x403b
0x00000000000015ce <+261>: callq 0x1260 <puts@plt>
0x00000000000015d3 <+266>: callq 0x21f3 <read_line>
0x00000000000015d8 <+271>: mov %rax,%rdi
0x00000000000015db <+274>: callq 0x180d <phase_3>
0x00000000000015e0 <+279>: mov %rbx,%rdi
0x00000000000015e3 <+282>: callq 0x233e <phase_defused>
0x00000000000015e8 <+287>: lea 0x2a69(%rip),%rdi # 0x4058
0x00000000000015ef <+294>: callq 0x1260 <puts@plt>
0x00000000000015f4 <+299>: callq 0x21f3 <read_line>
0x00000000000015f9 <+304>: mov %rax,%rdi
0x00000000000015fc <+307>: callq 0x190a <phase_4>
0x0000000000001601 <+312>: mov %rbx,%rdi
0x0000000000001604 <+315>: callq 0x233e <phase_defused>
0x0000000000001609 <+320>: lea 0x2b68(%rip),%rdi # 0x4178
0x0000000000001610 <+327>: callq 0x1260 <puts@plt>
0x0000000000001615 <+332>: callq 0x21f3 <read_line>
0x000000000000161a <+337>: mov %rax,%rdi
0x000000000000161d <+340>: callq 0x1988 <phase_5>
0x0000000000001622 <+345>: mov %rbx,%rdi
0x0000000000001625 <+348>: callq 0x233e <phase_defused>
0x000000000000162a <+353>: lea 0x2a36(%rip),%rdi # 0x4067
0x0000000000001631 <+360>: callq 0x1260 <puts@plt>
0x0000000000001636 <+365>: callq 0x21f3 <read_line>
0x000000000000163b <+370>: mov %rax,%rdi
0x000000000000163e <+373>: callq 0x19d7 <phase_6>
0x0000000000001643 <+378>: mov %rbx,%rdi
0x0000000000001646 <+381>: callq 0x233e <phase_defused>
0x000000000000164b <+386>: mov %rbx,%rdi
0x000000000000164e <+389>: callq 0x1220 <free@plt>
0x0000000000001653 <+394>: jmpq 0x151d <main+84>
End of assembler dump.
Phase 1
void phase_1(char *s) {
}
Phase 2
void phase_2(char *s) {
int a[6];
read_six_numbers(s, a);
if (a[0] != 1) explode_bomb();
for (int i = 1; i <= 5; i++) {
if (a[i] != 2*a[i-1]) explode_bomb();
}
}
+4 +5 +9 +18 处理栈,放金丝雀值。
+23 %eax = 0
+25 +28 read_six_numbers(%rdi, %rsp)
+33 +37 若%rsp != 1,则跳到+46(炸)
+39 %ebx = 1
+44 跳到+61
+46 炸。
+51 跳到+39
+53 炸。
+58 %ebx++;
+61 若%ebx > 5,则跳到86
+64 jg
+66 %rdx = %ebx;
+69 %eax = %rbx - 1;
+72 符号扩展 %rax
+74 %eax = *(%rsp + 4 * %rax);
+77 %eax *= 2;
+79 +82 if ( *(%rsp + 4 * %rdx) == %eax ) 跳到+58
+84 跳到+53(炸)。
+86 +91 +100 +102 验证金丝雀值,处理栈,返回。
+106 返回。
+4 +5 +9 +18 处理栈,放金丝雀值。
+23 %eax = 0
+25 +28 read_six_numbers(%rdi, a) // 把 %rsp 理解成 (int *)a。
+33 +37 若 *a != 1,则炸
for (int i = 1; i <= 5; i++) {
if (a[i] != 2*a[i-1]) 炸;
}
for (int i = 1; i <= 5; i++) {
if (a[i] != 2*a[i-1]) 炸;
}
0 1 3 6 10 15
i = 1
if (i > 5) break;
%rax = i
%rdx = i - 1
c = i
c += a[i-1]
if (c == a[i])
Phase 3
void phase_3(char *s) {
int x, y, z;
if (sscanf(s, "%d %d", &x, &y) <= 1) explode_bomb();
switch (x) {
case 0:
z = 0xbc;
break;
case 1:
z = 0x233;
break;
case 2:
z = 0x159;
break;
case 3:
z = 0x1b2;
break;
case 4:
z = 0x282;
break;
case 5:
z = 0x158;
break;
case 6:
z = 0x17f;
break;
case 7:
z = 0x222;
break;
default:
explode_bomb();
}
if (z != y) explode_bomb();
}
Dump of assembler code for function phase_3:
0x000000000000180d <+0>: endbr64
0x0000000000001811 <+4>: sub $0x18,%rsp
0x0000000000001815 <+8>: mov %fs:0x28,%rax
0x000000000000181e <+17>: mov %rax,0x8(%rsp)
0x0000000000001823 <+22>: xor %eax,%eax
%eax(返回值) = 0
0x0000000000001825 <+24>: lea 0x4(%rsp),%rcx
%rcx(第四个参数) = %rsp(栈底地址) + 4
0x000000000000182a <+29>: mov %rsp,%rdx
%rdx(第三个参数) = %rsp(栈底地址)
0x000000000000182d <+32>: lea 0x2e64(%rip),%rsi # 0x4698
%rsi(第二个参数) = "%d %d"
0x0000000000001834 <+39>: callq 0x1330 <__isoc99_sscanf@plt>
sscanf(%rdi, "%d %d", %rsp, %rsp + 4);
0x0000000000001839 <+44>: cmp $0x1,%eax
0x000000000000183c <+47>: jle 0x1859 <phase_3+76>
if (%rax <= 1) goto +76(炸);
0x000000000000183e <+49>: mov (%rsp),%eax
eax = *rsp;
0x0000000000001841 <+52>: cmp $0x7,%eax
0x0000000000001844 <+55>: ja 0x18aa <phase_3+157>
if ((unsigned)%eax > 7) goto +157(炸);
这一步保证了 0 <= a <= 7
0x0000000000001846 <+57>: mov %eax,%eax
0x0000000000001848 <+59>: lea 0x2ab1(%rip),%rdx # 0x4300
rdx = rip + 0x2ab1;
0x000000000000184f <+66>: movslq (%rdx,%rax,4),%rax
// -10912 -10826 -10880 -10873 -10866 -10859 -10852 -10845
rax = *(%rdx + 4*%rax) // a = d[a];
0x0000000000001853 <+70>: add %rdx,%rax
%rax += %rdx // a += d
上面两条的意思是 a = d + d[a]
// 0x1860<+83> 0x18b6<+169> 0x1880<+115> 0x1887<+122> 0x188e<+129> 0x1895<+136> 0x189c<+153> 0x18a3<+150>
0x0000000000001856 <+73>: notrack jmpq *%rax
0x0000000000001859 <+76>: callq 0x20c0 <explode_bomb>
0x000000000000185e <+81>: jmp 0x183e <phase_3+49>
case 0:
0x0000000000001860 <+83>: mov $0xbc,%eax
eax = 0xbc = 188;
LABEL:
0x0000000000001865 <+88>: cmp %eax,0x4(%rsp)
if (eax != *(rsp + 4))
0x0000000000001869 <+92>: jne 0x18bd <phase_3+176>
goto +176(爆炸);
0x000000000000186b <+94>: mov 0x8(%rsp),%rax
rax = *(rsp + 8)
0x0000000000001870 <+99>: xor %fs:0x28,%rax
0x0000000000001879 <+108>: jne 0x18c4 <phase_3+183>
0x000000000000187b <+110>: add $0x18,%rsp
0x000000000000187f <+114>: retq
case 2:
0x0000000000001880 <+115>: mov $0x159,%eax
0x0000000000001885 <+120>: jmp 0x1865 <phase_3+88>
case 3:
0x0000000000001887 <+122>: mov $0x1b2,%eax
0x000000000000188c <+127>: jmp 0x1865 <phase_3+88>
case 4:
0x000000000000188e <+129>: mov $0x282,%eax
0x0000000000001893 <+134>: jmp 0x1865 <phase_3+88>
case 5:
0x0000000000001895 <+136>: mov $0x158,%eax
0x000000000000189a <+141>: jmp 0x1865 <phase_3+88>
case 6:
0x000000000000189c <+143>: mov $0x17f,%eax
0x00000000000018a1 <+148>: jmp 0x1865 <phase_3+88>
case 7:
0x00000000000018a3 <+150>: mov $0x222,%eax
0x00000000000018a8 <+155>: jmp 0x1865 <phase_3+88>
0x00000000000018aa <+157>: callq 0x20c0 <explode_bomb>
0x00000000000018af <+162>: mov $0x0,%eax
0x00000000000018b4 <+167>: jmp 0x1865 <phase_3+88>
case 1:
0x00000000000018b6 <+169>: mov $0x233,%eax
0x00000000000018bb <+174>: jmp 0x1865 <phase_3+88>
0x00000000000018bd <+176>: callq 0x20c0 <explode_bomb>
0x00000000000018c2 <+181>: jmp 0x186b <phase_3+94>
0x00000000000018c4 <+183>: callq 0x1280 <__stack_chk_fail@plt>
Phase 4
func4
由phase_4
,知一定有esi == 0
,edx == 14
。
返回值为
|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|
|0|0|4|0|2|2|6|0|1|1| 5| 1| 3| 3| 7|
int func4(int i, int l, int r) {
int m = (r - l) / 2 + l;
if (i == m) return 0;
if (i < m) return func4(i, l, m-1) * 2;
if (i > m) return func4(i, m+1, r) * 2 + 1;
}
edx = 14; // r
esi = 0; // l
edi = *rsp;
func(i, l, r)
Dump of assembler code for function func4:
0x00000000000018c9 <+0>: endbr64
0x00000000000018cd <+4>: sub $0x8,%rsp
0x00000000000018d1 <+8>: mov %edx,%ecx
ecx = edx(第三个参数); // l
0x00000000000018d3 <+10>: sub %esi,%ecx
ecx -= esi(第二个参数); // l - r
0x00000000000018d5 <+12>: mov %ecx,%eax
eax = ecx;
0x00000000000018d7 <+14>: shr $0x1f,%eax
eax >>= 31;
0x00000000000018da <+17>: add %ecx,%eax
eax += ecx;
0x00000000000018dc <+19>: sar %eax
eax >>= 1;
以上语句相当于 eax = ecx / 2;(向零取整) // (l - r) / 2
0x00000000000018de <+21>: add %esi,%eax
eax += esi; // ()
0x00000000000018e0 <+23>: cmp %edi,%eax
0x00000000000018e2 <+25>: jg 0x18f0 <func4+39>
if (edi < eax) goto +39;
0x00000000000018e4 <+27>: jl 0x18fc <func4+51>
if (edi > eax) goto +51;
0x00000000000018e6 <+29>: mov $0x0,%eax
0x00000000000018eb <+34>: add $0x8,%rsp
0x00000000000018ef <+38>: retq
return 0;
0x00000000000018f0 <+39>: lea -0x1(%rax),%edx
edx = rax - 1;
0x00000000000018f3 <+42>: callq 0x18c9 <func4>
func4()
0x00000000000018f8 <+47>: add %eax,%eax
eax += eax
0x00000000000018fa <+49>: jmp 0x18eb <func4+34>
0x00000000000018fc <+51>: lea 0x1(%rax),%esi
esi = rax+1;
0x00000000000018ff <+54>: callq 0x18c9 <func4>
0x0000000000001904 <+59>: lea 0x1(%rax,%rax,1),%eax
0x0000000000001908 <+63>: jmp 0x18eb <func4+34>
End of assembler dump.
phase_4
void phase_4(char *s) {
int x, y;
if ((sscanf(s, "%d %d", &x, &y) != 2) || (x < 0) || (x > 14)) explode_bomb();
if (func4(x, 0, 14) != 0 || y != 0) explode_bomb();
}
Dump of assembler code for function phase_4:
0x000000000000190a <+0>: endbr64
0x000000000000190e <+4>: sub $0x18,%rsp
0x0000000000001912 <+8>: mov %fs:0x28,%rax
0x000000000000191b <+17>: mov %rax,0x8(%rsp)
0x0000000000001920 <+22>: xor %eax,%eax
eax = 0;
0x0000000000001922 <+24>: lea 0x4(%rsp),%rcx
rcx = rsp+4;
0x0000000000001927 <+29>: mov %rsp,%rdx
rdx = rsp
0x000000000000192a <+32>: lea 0x2d67(%rip),%rsi # 0x4698
rsi = "%d %d"
0x0000000000001931 <+39>: callq 0x1330 <__isoc99_sscanf@plt>
0x0000000000001936 <+44>: cmp $0x2,%eax
0x0000000000001939 <+47>: jne 0x1947 <phase_4+61>
if (sscanf(rdi, "%d %d", rsp, rsp+4) != 2) explode_bomb();
0x000000000000193b <+49>: mov (%rsp),%eax
eax = *rsp; // b
0x000000000000193e <+52>: test %eax,%eax
0x0000000000001940 <+54>: js 0x1947 <phase_4+61>
if (eax < 0) explode_bomb();
0x0000000000001942 <+56>: cmp $0xe,%eax
0x0000000000001945 <+59>: jle 0x194c <phase_4+66>
0x0000000000001947 <+61>: callq 0x20c0 <explode_bomb>
if (eax > 14) explode_bomb();
0x000000000000194c <+66>: mov $0xe,%edx
edx = 14;
0x0000000000001951 <+71>: mov $0x0,%esi
esi = 0;
0x0000000000001956 <+76>: mov (%rsp),%edi
edi = *rsp; // b
0x0000000000001959 <+79>: callq 0x18c9 <func4>
0x000000000000195e <+84>: test %eax,%eax
0x0000000000001960 <+86>: jne 0x1969 <phase_4+95>
if (eax != 0) explode_bomb();
0x0000000000001962 <+88>: cmpl $0x0,0x4(%rsp)
0x0000000000001967 <+93>: je 0x196e <phase_4+100>
0x0000000000001969 <+95>: callq 0x20c0 <explode_bomb>
if (*(rsp + 4) != 0) explode_bomb();
0x000000000000196e <+100>: mov 0x8(%rsp),%rax
0x0000000000001973 <+105>: xor %fs:0x28,%rax
0x000000000000197c <+114>: jne 0x1983 <phase_4+121>
0x000000000000197e <+116>: add $0x18,%rsp
0x0000000000001982 <+120>: retq
0x0000000000001983 <+121>: callq 0x1280 <__stack_chk_fail@plt>
End of assembler dump.
Phase 4'
int func4(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return 2*f(n-1) + f(n-2);
}
0 1 2 5 12 29
\[f_n = 2f_{n-1} + f_{n-2} \\
\]
+4 +5 +6 处理栈,略。
+10 %rax = 金丝雀值
+19 *(%rsp + 8) = %rax
+24 %eax = 0
+26 +31 +34 +41 sscanf(%rdi , "%d %d", %rsp, %rsp + 4); // n1 n2
+46 +49 +57 如果sscanf的返回值不为2就跳到+57,否则继续。
+51 (n1 == 5)就跳到+62,否则继续。
+57 炸了。
+62 %ebp = 0
+67 %ebx = 0
+72 +75 如果n1 == %ebx跳转到+91,否则继续。
+77 +79 +84 %ebp += func4(%ebx);
+86 %ebx ++;
+89 goto +72;
+91 +95 如果n2 != %ebp跳转到+120,否则继续。
+97 +102 +111 检测金丝雀值,略。
+113 +117 +118 处理栈。
+119 返回零。
+120 炸了。
5 20
Phase 5
const int a[16] = {2, 10, 6, 1, 12, 16, 9, 3, 4, 7, 14, 5, 11, 8, 15, 13};
void phase_5(char *s) {
if (string_length(s) != 6) explode_bomb();
int tmp = 0;
for (int i = 0; i <= 5; ++i) {
tmp += z[s[i]&15];
}
if (tmp != 0x38/*56*/) explode_bomb();
// 56 = 10 + 10 + 10 + 10 + 10 + 6 "111112"
}
phase_5(char *s)
Dump of assembler code for function phase_5:
0x0000000000001988 <+0>: endbr64
0x000000000000198c <+4>: push %rbx
0x000000000000198d <+5>: mov %rdi,%rbx
0x0000000000001990 <+8>: callq 0x1cd1 <string_length>
0x0000000000001995 <+13>: cmp $0x6,%eax
0x0000000000001998 <+16>: jne 0x19c2 <phase_5+58>
if (string_length(s) != 6) explode_bomb();
0x000000000000199a <+18>: mov $0x0,%ecx
ecx = 0;
0x000000000000199f <+23>: mov $0x0,%eax
eax = 0;
0x00000000000019a4 <+28>: cmp $0x5,%eax
0x00000000000019a7 <+31>: jg 0x19c9 <phase_5+65>
if (eax > 5) goto +65;
0x00000000000019a9 <+33>: movslq %eax,%rdx
0x00000000000019ac <+36>: movzbl (%rbx,%rdx,1),%edx
0x00000000000019b0 <+40>: and $0xf,%edx
edx &= (*(eax+rbx))&15;
0x00000000000019b3 <+43>: lea 0x2966(%rip),%rsi # 0x4320 <array.3497>
// x/16dw 0x4320
// 0x4320 <array.3497>: (int *){2, 10, 6, 1, 12, 16, 9, 3, 4, 7, 14, 5, 11, 8, 15, 13}
0x00000000000019ba <+50>: add (%rsi,%rdx,4),%ecx
ecx += <array.3497>[rdx]
0x00000000000019bd <+53>: add $0x1,%eax
eax += 1;
0x00000000000019c0 <+56>: jmp 0x19a4 <phase_5+28>
goto +28;
0x00000000000019c2 <+58>: callq 0x20c0 <explode_bomb>
0x00000000000019c7 <+63>: jmp 0x199a <phase_5+18>
0x00000000000019c9 <+65>: cmp $0x38,%ecx
0x00000000000019cc <+68>: jne 0x19d0 <phase_5+72>
if (ecx != 0x38) explode_bomb();
0x00000000000019ce <+70>: pop %rbx
0x00000000000019cf <+71>: retq
0x00000000000019d0 <+72>: callq 0x20c0 <explode_bomb>
0x00000000000019d5 <+77>: jmp 0x19ce <phase_5+70>
End of assembler dump.
Phase 6
void phase_6(char *s) {
int a[6];
read_six_numbers(s, a);
}
Dump of assembler code for function phase_6:
0x00000000000019d7 <+0>: endbr64
0x00000000000019db <+4>: push %r12
0x00000000000019dd <+6>: push %rbp
0x00000000000019de <+7>: push %rbx
0x00000000000019df <+8>: sub $0x60,%rsp
0x00000000000019e3 <+12>: mov %fs:0x28,%rax
0x00000000000019ec <+21>: mov %rax,0x58(%rsp)
0x00000000000019f1 <+26>: xor %eax,%eax
rax = 0;
0x00000000000019f3 <+28>: mov %rsp,%rsi
rsi = rsp;
0x00000000000019f6 <+31>: callq 0x21ae <read_six_numbers>
read_six_numbers(s, rsi);
0x00000000000019fb <+36>: mov $0x0,%ebp
ebp = 0;
0x0000000000001a00 <+41>: jmp 0x1a29 <phase_6+82>
0x0000000000001a02 <+43>: callq 0x20c0 <explode_bomb>
0x0000000000001a07 <+48>: jmp 0x1a3c <phase_6+101>
0x0000000000001a09 <+50>: callq 0x20c0 <explode_bomb>
0x0000000000001a0e <+55>: add $0x1,%ebx
ebx += 1; // i
0x0000000000001a11 <+58>: cmp $0x5,%ebx
0x0000000000001a14 <+61>: jg 0x1a26 <phase_6+79>
if ((signed)ebx > 5) goto +79;
0x0000000000001a16 <+63>: movslq %ebp,%rax
rax = ebp; // j
0x0000000000001a19 <+66>: movslq %ebx,%rdx
rdx = ebx; // i
0x0000000000001a1c <+69>: mov (%rsp,%rdx,4),%edi
edi = ((int *)rsp)[rdx]; // a[i]
0x0000000000001a1f <+72>: cmp %edi,(%rsp,%rax,4)
0x0000000000001a22 <+75>: jne 0x1a0e <phase_6+55>
if (edi != ((int *)rsp)[rax]/*a[j]*/) goto +55;
0x0000000000001a24 <+77>: jmp 0x1a09 <phase_6+50>
else explode_bomb();
0x0000000000001a26 <+79>: mov %r12d,%ebp
ebp = r12d;
0x0000000000001a29 <+82>: cmp $0x5,%ebp
0x0000000000001a2c <+85>: jg 0x1a45 <phase_6+110>
if (ebp > 5) goto +110;
0x0000000000001a2e <+87>: movslq %ebp,%rax
eax = ebp;
0x0000000000001a31 <+90>: mov (%rsp,%rax,4),%eax
eax = ((int *)rsp)[rax];
0x0000000000001a34 <+93>: sub $0x1,%eax
eax -= 1;
0x0000000000001a37 <+96>: cmp $0x5,%eax
0x0000000000001a3a <+99>: ja 0x1a02 <phase_6+43>
if ((unsigned)eax > 5) explode_bomb();
0x0000000000001a3c <+101>: lea 0x1(%rbp),%r12d
r12d = rbp + 1;
0x0000000000001a40 <+105>: mov %r12d,%ebx
ebx = r12d;
0x0000000000001a43 <+108>: jmp 0x1a11 <phase_6+58>
goto +58;
0x0000000000001a45 <+110>: mov $0x0,%eax
eax = 0;
0x0000000000001a4a <+115>: jmp 0x1a5d <phase_6+134>
0x0000000000001a4c <+117>: movslq %eax,%rcx
0x0000000000001a4f <+120>: mov $0x7,%edx
0x0000000000001a54 <+125>: sub (%rsp,%rcx,4),%edx
0x0000000000001a57 <+128>: mov %edx,(%rsp,%rcx,4)
0x0000000000001a5a <+131>: add $0x1,%eax
0x0000000000001a5d <+134>: cmp $0x5,%eax
0x0000000000001a60 <+137>: jle 0x1a4c <phase_6+117>
0x0000000000001a62 <+139>: mov $0x0,%esi
0x0000000000001a67 <+144>: jmp 0x1a80 <phase_6+169>
0x0000000000001a69 <+146>: mov 0x8(%rdx),%rdx
0x0000000000001a6d <+150>: add $0x1,%eax
0x0000000000001a70 <+153>: movslq %esi,%rcx
0x0000000000001a73 <+156>: cmp %eax,(%rsp,%rcx,4)
0x0000000000001a76 <+159>: jg 0x1a69 <phase_6+146>
0x0000000000001a78 <+161>: mov %rdx,0x20(%rsp,%rcx,8)
0x0000000000001a7d <+166>: add $0x1,%esi
0x0000000000001a80 <+169>: cmp $0x5,%esi
0x0000000000001a83 <+172>: jg 0x1a93 <phase_6+188>
0x0000000000001a85 <+174>: mov $0x1,%eax
0x0000000000001a8a <+179>: lea 0x65bf(%rip),%rdx # 0x8050 <node1>
0x0000000000001a91 <+186>: jmp 0x1a70 <phase_6+153>
0x0000000000001a93 <+188>: mov 0x20(%rsp),%rbx
0x0000000000001a98 <+193>: mov %rbx,%rcx
0x0000000000001a9b <+196>: mov $0x1,%eax
0x0000000000001aa0 <+201>: jmp 0x1ab4 <phase_6+221>
0x0000000000001aa2 <+203>: movslq %eax,%rdx
0x0000000000001aa5 <+206>: mov 0x20(%rsp,%rdx,8),%rdx
0x0000000000001aaa <+211>: mov %rdx,0x8(%rcx)
0x0000000000001aae <+215>: add $0x1,%eax
0x0000000000001ab1 <+218>: mov %rdx,%rcx
0x0000000000001ab4 <+221>: cmp $0x5,%eax
0x0000000000001ab7 <+224>: jle 0x1aa2 <phase_6+203>
0x0000000000001ab9 <+226>: movq $0x0,0x8(%rcx)
0x0000000000001ac1 <+234>: mov $0x0,%ebp
0x0000000000001ac6 <+239>: jmp 0x1acf <phase_6+248>
0x0000000000001ac8 <+241>: mov 0x8(%rbx),%rbx
0x0000000000001acc <+245>: add $0x1,%ebp
0x0000000000001acf <+248>: cmp $0x4,%ebp
0x0000000000001ad2 <+251>: jg 0x1ae5 <phase_6+270>
0x0000000000001ad4 <+253>: mov 0x8(%rbx),%rax
0x0000000000001ad8 <+257>: mov (%rax),%eax
0x0000000000001ada <+259>: cmp %eax,(%rbx)
0x0000000000001adc <+261>: jle 0x1ac8 <phase_6+241>
0x0000000000001ade <+263>: callq 0x20c0 <explode_bomb>
0x0000000000001ae3 <+268>: jmp 0x1ac8 <phase_6+241>
0x0000000000001ae5 <+270>: mov 0x58(%rsp),%rax
0x0000000000001aea <+275>: xor %fs:0x28,%rax
0x0000000000001af3 <+284>: jne 0x1afe <phase_6+295>
0x0000000000001af5 <+286>: add $0x60,%rsp
0x0000000000001af9 <+290>: pop %rbx
0x0000000000001afa <+291>: pop %rbp
0x0000000000001afb <+292>: pop %r12
0x0000000000001afd <+294>: retq
0x0000000000001afe <+295>: callq 0x1280 <__stack_chk_fail@plt>
End of assembler dump.
void phase_6(char *s) {
int a[6]; // a := rsp
read_six_numbers(s, a);
j = 0;
goto L82;
L43:
explode_bomb();
goto L101;
L50:
explode_bomb();
L55:
i++; // i := ebx
L58:
if (i > 5) goto L79;
if (a[i] != a[j]) goto L55; // j := ebp
else explode_bomb();
L79:
j = k; // k := %r12d
L82:
if (j > 5) goto L110;
if (a[j]-1 > 5) goto L43; // explode_bomb();
i = k = j+1;
goto L58;
L110:
eax = 0;
goto L134;
L117:
rcx = eax;
edx = 7;
edx -= a[rcx];
a[rcx] = edx;
eax++;
L134:
if (eax <= 5) goto L117;
esi = 0;
goto L169;
L146:
rdx = *(rdx+8);
eax++;
L153:
rcx = esi;
if (a[rcx] > eax) goto L146;
*(rsp + 8*rcx + 20) = rdx;
esi++;
L169:
if (esi > 5) goto L188;
eax = 1;
rdx = 0x8050;
goto L153;
L188:
rbx = *(rsp + 20);
rcx = rbx;
eax = 1;
goto L221;
L203:
rdx = eax;
rdx = *(rsp + 8*rdx + 20);
*(rcx + 8) = rdx;
eax++;
rcx = rdx;
L221:
if (eax <= 5) goto L203;
*(rcx + 8) = 0;
ebp = 0;
goto L248;
L241:
rbx = *(rbx + 8);
ebp++;
L248:
if (ebp > 4) goto L270;
rax = *(rbx + 8);
if ((*rbx) <= eax) goto L241;
L263:
explode_bomb();
goto L241;
L270:
return;
}
struct node{
int val, id;
node * nxt;
}
int a[6]; // rsp
node *c[6]; // 0x20(%rsp)
for (int j/*ebp*/ = 0; j <= 5/*+82,+85*/; j++) {
if (a[j] > 6 || a[j] <= 0) explode_bomb();
// a[j] <- {1, 2, 3, 4, 5, 6}
for (int i/*ebx*/ = j+1; i <= 5; ++i) {
if (a[i] != a[j]) continue;
else explode_bomb();
}
}
for (int i/*eax*/ = 0/*+110*/; i <= 5/*+134*/; ++i/*+131*/) {
int j/*rcx*/ = i, k/*edx*/ = 7;
a[j] = 7 - a[j]; // +120~+128
}
for (int i/*esi,+139*/ = 0; i <= 5/*+169*/; ++i) {
for (int j/*eax*/ = 1, node *b/*rdx*/ = 0x8050/*+179*/; j < a[i]; j++) b = b->nxt;
c[i] = b; // 换句话说,有c[i] = b + (a[i]-1);
}
node *i/*rbx*/ = c[0]; // +188
node *j/*rcx*/ = i; // +193
for (int k/*eax*/ = 1/*+196*/; k <= 5/*+221*/; ++k, j = l) { // 忽略第0个,也即第一个数此时应该是6,即原先为1。
node *l = c[k];
j->nxt = l; // +203~+218
++k;
}
j->nxt = 0; // +226
for (int k/*ebp*/ = 0/*+234*/; k <= 4/*+248*/; i = *(i + 8), ++k/*245*/) {
if (i->val > i->nxt->val) explode_bomb(); // +263
// 要求最后已经从小到大排好序了,顺序是node3, node2, node1, node4, node5
// 也即此时的值是3, 6, 2, 1, 4, 5,也即原来是4, 1, 5, 6, 3, 2
}
// 答案应当是4, 1, 5, 6, 3, 2
// break *0x1a37