Last updated on February 8, 2024
gdb 基本使用 参考书 p194
disassemble …
break …
nexti stepi
continue
x /FMT ADDRESS print EXP
run ARGS
1 字符串比较 layout asm
disas phase_1
调用 strings_not_equal 要求返回 0 - equal
x /s 0x4024c0 “I am not part of the problem. I am a Republican.” 将其写入 ans.txt
break phase_1 run ans.txt nexti print $eax
2 循环 disas phase_2
调用 read_six_numbers:
x /s 0x4027b5 “%d %d %d %d %d %d”
调用 sscanf:
%rdi
%rsi
%rdx
%rcx
%r8
%r9
(%rsp)
(%rsp+8)
str
fmt
%rsp
%rsp + 4
%rsp + 8
%rsp + 12
%rsp + 16
%rsp + 20
循环:第一个数为 1,后面依次翻倍 1 2 4 8 16 32
3 条件/分支 disas phase_3
调用 sscanf:
%rdi
%rsi
%rdx
%rcx
str
fmt
%rsp + 12
%rsp + 8
x /s 0x4027c1 “%d %d”
第一个数 <= 7
不妨令第一个数 = 1 x /x 0x402528 0x00400fc9
第二个数 0x52
4 递归调用和栈 disas phase_4
同 3,调用 sscanf:
%rdi
%rsi
%rdx
%rcx
str
fmt
%rsp + 12
%rsp + 8
x /s 0x4027c1 “%d %d”
第一个数 <= 14
调用 func4:
disas func4
递归调用
要求返回值为 f 第一个数 = 5
第二个数 = f
5 指针 disas phase_5
调用 string_length
要求字符串长度为 6
进入循环: 循环 6 次,结果 %edx=0x37
1 2 3 movzbl (%rbx,%rax,1 ),%ecx and $0xf ,%ecx add 0x402560 (,%rcx,4 ),%edx
x /6x 0x402560 2 a 6 1 c 10
16+12+10+10+6+1=55 ASCII 码末四位作为索引 5 4 1 1 2 3 edaabc
6 链表/指针/结构 disas phase_6
调用 read_six_numbers 放到从 %rsp+0x30 开始处
大循环 1: 六个数都不同,并且均 <= 6
循环 2: x /24 0x6042f0
1 2 3 4 5 6 7 8 9 10 11 12 13 0x6042f0 <node1>: 0 x00000271 0 x00000001 0 x00604300 0 x000000000x604300 <node2>: 0 x000002f2 0 x00000002 0 x00604310 0 x000000000x604310 <node3>: 0 x00000111 0 x00000003 0 x00604320 0 x000000000x604320 <node4>: 0 x00000231 0 x00000004 0 x00604330 0 x000000000x604330 <node5>: 0 x0000016e 0 x00000005 0 x00604340 0 x000000000x604340 <node6>: 0 x0000022f 0 x00000006 0 x00000000 0 x000000000x6042f0 <node1>: 625 1 6308608 0 0x604300 <node2>: 754 2 6308624 0 0x604310 <node3>: 273 3 6308640 0 0x604320 <node4>: 561 4 6308656 0 0x604330 <node5>: 366 5 6308672 0 0x604340 <node6>: 559 6 0 0
struct 链表:
1 2 3 4 5 struct Node { int val; int ordinal; struct Node * next ; }
struct 链表中 6 个 struct 的地址,按照输入数字的顺序,顺着放到 %rsp +
循环 3: x /12 0x7fffffffe660 0x7fffffffe660: 6308608 0 6308592 0 0x7fffffffe670: 6308640 0 6308672 0 0x7fffffffe680: 6308656 0 6308624 0
重排链表
循环 4: x /24x 0x6042f0
1 2 3 4 5 6 0x6042f0 <node1>: 0x00000271 0x00000001 0x00604320 0x00000000 0x604300 <node2>: 0 x000002f2 0x00000002 0 x006042f0 0x00000000 0x604310 <node3>: 0x00000111 0x00000003 0x00000000 0x00000000 0x604320 <node4>: 0x00000231 0x00000004 0x00604340 0x00000000 0x604330 <node5>: 0 x0000016e 0x00000005 0x00604310 0x00000000 0x604340 <node6>: 0 x0000022f 0x00000006 0x00604330 0x00000000
验证每个 struct 的 val >= 链表中下一项的 val val 从大到小:2 1 4 6 5 3
secret phase 在 phase_defused 中调了 secret_phase: b *0x401772
(gdb) x /s 0x402660 0x402660: “Curses, you’ve found the secret phase!” (gdb) x /s 0x402688 0x402688: “But finding it and solving it are quite different…” 找对了位置 🤗
先调用 sscanf: (gdb) x /s 0x40280b 0x40280b: “%d %d %s” 三个输入
phase_3 or phase_4? 与 phase_4 读取的 %rdi 地址相同 (gdb) x /s 0x6048b0 0x6048b0 <input_strings+240>: “5 15 DrEvil”
(gdb) x /s 0x402814 0x402814: “DrEvil” 取第三个输入判等
综上,在 phase_4 的输入之后再补一个 DrEvil
secret_phase:
调用 read_line,读入一个字符串 调用 strtol,解析为十进制 num num - 1 <= 1000
调用 fun7:
要求返回值为 5
fun7: 递归调用,比较 num 与 (%rdi)+
x /100xg 0x604110
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 0x604110 <n1>: 0 x0000000000000024 0 x0000000000604130 0x604120 <n1+16 >: 0 x0000000000604150 0 x0000000000000000 0x604130 <n21>: 0 x0000000000000008 0 x00000000006041b0 0x604140 <n21+16 >: 0 x0000000000604170 0 x0000000000000000 0x604150 <n22>: 0 x0000000000000032 0 x0000000000604190 0x604160 <n22+16 >: 0 x00000000006041d0 0 x0000000000000000 0x604170 <n32>: 0 x0000000000000016 0 x0000000000604290 0x604180 <n32+16 >: 0 x0000000000604250 0 x0000000000000000 0x604190 <n33>: 0 x000000000000002d 0 x00000000006041f0 0x6041a0 <n33+16 >: 0 x00000000006042b0 0 x0000000000000000 0x6041b0 <n31>: 0 x0000000000000006 0 x0000000000604210 0x6041c0 <n31+16 >: 0 x0000000000604270 0 x0000000000000000 0x6041d0 <n34>: 0 x000000000000006b 0 x0000000000604230 0x6041e0 <n34+16 >: 0 x00000000006042d0 0 x0000000000000000 0x6041f0 <n45>: 0 x0000000000000028 0 x0000000000000000 0x604200 <n45+16 >: 0 x0000000000000000 0 x0000000000000000 0x604210 <n41>: 0 x0000000000000001 0 x0000000000000000 0x604220 <n41+16 >: 0 x0000000000000000 0 x0000000000000000 0x604230 <n47>: 0 x0000000000000063 0 x0000000000000000 0x604240 <n47+16 >: 0 x0000000000000000 0 x0000000000000000 0x604250 <n44>: 0 x0000000000000023 0 x0000000000000000 0x604260 <n44+16 >: 0 x0000000000000000 0 x0000000000000000 0x604270 <n42>: 0 x0000000000000007 0 x0000000000000000 0x604280 <n42+16 >: 0 x0000000000000000 0 x0000000000000000 0x604290 <n43>: 0 x0000000000000014 0 x0000000000000000 0x6042a0 <n43+16 >: 0 x0000000000000000 0 x0000000000000000 0x6042b0 <n46>: 0 x000000000000002f 0 x0000000000000000 0x6042c0 <n46+16 >: 0 x0000000000000000 0 x0000000000000000 0x6042d0 <n48>: 0 x00000000000003e9 0 x0000000000000000
二叉搜索树
1 2 3 4 5 struct Tree { int val; struct Tree * left ; struct Tree * right ; }
返回值为 5:右 左 右 0 47