CSAPP: Bomb Lab Phase1- Phase3

Get to know there're 6 phase from bomb.c and get to know the bomb will be trigged via explode_bomb.

Phase 1

  • run debugger : gdb bomb
  • set breakpoints: b explode_bomb
  • disassmble phase_1: disas phase_1
Dump of assembler code for function phase_1:
   0x0000000000400ee0 <+0>: sub    $0x8,%rsp
   0x0000000000400ee4 <+4>: mov    $0x402400,%esi
   0x0000000000400ee9 <+9>: callq  0x401338 <strings_not_equal>
   0x0000000000400eee <+14>:    test   %eax,%eax
   0x0000000000400ef0 <+16>:    je     0x400ef7 <phase_1+23>
   0x0000000000400ef2 <+18>:    callq  0x40143a <explode_bomb>
   0x0000000000400ef7 <+23>:    add    $0x8,%rsp
   0x0000000000400efb <+27>:    retq   
End of assembler dump.
  • we can see something stored in esi: mov $0x402400,%esi, since %rsi/%esi is the second argument.
  • check the value in location 0x402400: x/s 0x402400

0x402400: "Border relations with Canada have never been better."

  • run the program: run
  • type the key: "Border relations with Canada have never been better."

实际上这里的 %rsp - 0x8 是生成 stack grow, 相当于 push. 后面的 %rsp + 0x8 是 pop from stack.

然后常见的register %esi 相当于 %rsi 第二个参数。

这里的 0x0000000000400ee9 <+9>: callq 0x401338 <strings_not_equal> 也就是 procedure 的进行。

Phase 2

The key to solve phase 2 is understand the difference between mov and lea

lea是“load effective address”的缩写,简单的说,lea指令可以用来将一个内存地址直接赋给目的操作数,

例如:lea eax,[ebx+8]就是将ebx+8这个值直接赋给eax,而不是把ebx+8处的内存地址里的数据赋给eax。
而mov指令则恰恰相反,例如:mov eax,[ebx+8]则是把内存地址为ebx+8处的数据赋给eax。

  • run debugger : gdb bomb
  • set breakpoints: b explode_bomb
  • disassmble phase_1: disas phase_2
0000000000400efc <phase_2>:
  400efc:   55                      push   %rbp
  400efd:   53                      push   %rbx
  400efe:   48 83 ec 28             sub    $0x28,%rsp
  400f02:   48 89 e6                mov    %rsp,%rsi
  400f05:   e8 52 05 00 00          callq  40145c <read_six_numbers>
  400f0a:   83 3c 24 01             cmpl   $0x1,(%rsp)
  400f0e:   74 20                   je     400f30 <phase_2+0x34>
  400f10:   e8 25 05 00 00          callq  40143a <explode_bomb>
  400f15:   eb 19                   jmp    400f30 <phase_2+0x34>
  400f17:   8b 43 fc                mov    -0x4(%rbx),%eax
  400f1a:   01 c0                   add    %eax,%eax
  400f1c:   39 03                   cmp    %eax,(%rbx)
  400f1e:   74 05                   je     400f25 <phase_2+0x29>
  400f20:   e8 15 05 00 00          callq  40143a <explode_bomb>
  400f25:   48 83 c3 04             add    $0x4,%rbx
  400f29:   48 39 eb                cmp    %rbp,%rbx
  400f2c:   75 e9                   jne    400f17 <phase_2+0x1b>
  400f2e:   eb 0c                   jmp    400f3c <phase_2+0x40>
  400f30:   48 8d 5c 24 04          lea    0x4(%rsp),%rbx
  400f35:   48 8d 6c 24 18          lea    0x18(%rsp),%rbp
  400f3a:   eb db                   jmp    400f17 <phase_2+0x1b>
  400f3c:   48 83 c4 28             add    $0x28,%rsp
  400f40:   5b                      pop    %rbx
  400f41:   5d                      pop    %rbp
  400f42:   c3                      retq   

we can tell by the name we have a function called read_six_numbers.

000000000040145c <read_six_numbers>:
  40145c:   48 83 ec 18             sub    $0x18,%rsp
  401460:   48 89 f2                mov    %rsi,%rdx
  401463:   48 8d 4e 04             lea    0x4(%rsi),%rcx
  401467:   48 8d 46 14             lea    0x14(%rsi),%rax
  40146b:   48 89 44 24 08          mov    %rax,0x8(%rsp)
  401470:   48 8d 46 10             lea    0x10(%rsi),%rax
  401474:   48 89 04 24             mov    %rax,(%rsp)
  401478:   4c 8d 4e 0c             lea    0xc(%rsi),%r9
  40147c:   4c 8d 46 08             lea    0x8(%rsi),%r8
  401480:   be c3 25 40 00          mov    $0x4025c3,%esi
  401485:   b8 00 00 00 00          mov    $0x0,%eax
  40148a:   e8 61 f7 ff ff          callq  400bf0 <__isoc99_sscanf@plt>
  40148f:   83 f8 05                cmp    $0x5,%eax
  401492:   7f 05                   jg     401499 <read_six_numbers+0x3d>
  401494:   e8 a1 ff ff ff          callq  40143a <explode_bomb>
  401499:   48 83 c4 18             add    $0x18,%rsp
  40149d:   c3                      retq   

we called sscanf inside this function. we do a man sscanf

sscanf(const char *restrict s, const char *restrict format, ...);

Actually we can tell by its name we try to read six numbers in.

Try to decode this line:

401480: be c3 25 40 00 mov $0x4025c3,%esi

x/s 0x4025c3

0x4025c3 :"%d %d %d %d %d %d"

We know first it will try to read the input as string, maybe something like input2.
then we do sscanf from the input2.

Decode these line:

400f0a: 83 3c 24 01 cmpl $0x1,(%rsp)
400f0e: 74 20 je 400f30 <phase_2+0x34>

register value
%rsp some meory address at rsp

and we know the value at some meory address at rsp have to be 1, otherwise it will not je, it'll go to next line and explode_bomb.

memory adress value
memory address at rsp 1

Guess the first number is 1.

Then we jump, decode these lines:

400f30: 48 8d 5c 24 04          lea    0x4(%rsp),%rbx
400f35: 48 8d 6c 24 18          lea    0x18(%rsp),%rbp
400f3a: eb db                   jmp    400f17 <phase_2+0x1b>

register value
%rbx memory address at rsp + 0x4
%rbp memory address at rsp + 0x18

if we have format like this:

int int int int int int

<del>int take 2 byte, blank space take 1 byte:</del> 这里纯粹都是错误的分析啊||||

6 * 4 + 5 + 1 = 18

try to guess rbp = '\0'

rbx is we try to read next number?

Then we jump again, decode these lines:

400f17: 8b 43 fc mov -0x4(%rbx),%eax
400f1a: 01 c0 add %eax,%eax
400f1c: 39 03 cmp %eax,(%rbx)

action register value
mov -0x4(%rbx),%eax %eax memory address at rbx - 0x4 = memory adress at rsp
add %eax,%eax %eax 2

400f1c: 39 03 cmp %eax,(%rbx)

This line requires value at %rbx, that is the value at emory address at rsp + 0x4 equal to 2. double value of %eax.

Guess the second number 2.

Accroding to the format, int takes 2 bytes, char takes 1 byte. Guess the input is:

01 02 04 08 16 32

Type in. phase 2 solved.

然后阅读了这篇文章 : CSAPP: Bomb Lab 实验解析,发现

  • 并不一定需要 type in 01 02 04 08 16 32 , 直接写入 1 2 4 8 16 32 也一样,sscanf 会自动读入int 占4位。0x18 也不是 18啊, 是 1 *16 + 8 = 24
  • 画出数据存储和写出对应的类C代码更帮助解题
  • 这里还有一些推断,比如 %rsp 中存的内存中的值是第一个input number,这里是否也说明了 stack pointer作用?

位置 & 内存

% rsp %rsp + 0x4 %rsp + 0x8 %rsp + 0xc %rsp + 0x10 %rsp + 0x14 %rbp = %rsp + 0x18
num[0] num[1] num[2] num[3] num[4] num[5] edge

对应的类C代码:

void phase_2(){
  if (%rsp) == 0x1 { // 保证第一个数是1,不jump则会 💣
    goto label_400f30;
  }
label_400f17:
  %rax = (%rbx - 0x4);
  %eax = %eax + %rax;
  if %rax != (%rbx){  // 保证后一个数为前一个数的两倍,否则会 💣
    explode_bomb();
  }
  %rbx = %rbx + 0x4;
  if (%rbp != %rbx) {
    goto label_400f17;
  } else {
    return ;  //jump out of phase_2;
  }
label_400f30:
  %rbx = (%rsp + 0x4);
  %rbp = (%rsp + 0x18);
  goto label_400f17;
    
}

Phase 3

disas phase_3

Dump of assembler code for function phase_3:
   0x0000000000400f43 <+0>: sub    $0x18,%rsp
   0x0000000000400f47 <+4>: lea    0xc(%rsp),%rcx
   0x0000000000400f4c <+9>: lea    0x8(%rsp),%rdx
   0x0000000000400f51 <+14>:    mov    $0x4025cf,%esi
   0x0000000000400f56 <+19>:    mov    $0x0,%eax
   0x0000000000400f5b <+24>:    callq  0x400bf0 <__isoc99_sscanf@plt>
   0x0000000000400f60 <+29>:    cmp    $0x1,%eax
   0x0000000000400f63 <+32>:    jg     0x400f6a <phase_3+39>
   0x0000000000400f65 <+34>:    callq  0x40143a <explode_bomb>
   0x0000000000400f6a <+39>:    cmpl   $0x7,0x8(%rsp)
   0x0000000000400f6f <+44>:    ja     0x400fad <phase_3+106>
   0x0000000000400f71 <+46>:    mov    0x8(%rsp),%eax
   0x0000000000400f75 <+50>:    jmpq   *0x402470(,%rax,8)
   0x0000000000400f7c <+57>:    mov    $0xcf,%eax
   0x0000000000400f81 <+62>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f83 <+64>:    mov    $0x2c3,%eax
   0x0000000000400f88 <+69>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f8a <+71>:    mov    $0x100,%eax
   0x0000000000400f8f <+76>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f91 <+78>:    mov    $0x185,%eax
   0x0000000000400f96 <+83>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f98 <+85>:    mov    $0xce,%eax
   0x0000000000400f9d <+90>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400f9f <+92>:    mov    $0x2aa,%eax
   0x0000000000400fa4 <+97>:    jmp    0x400fbe <phase_3+123>
   0x0000000000400fa6 <+99>:    mov    $0x147,%eax
   0x0000000000400fab <+104>:   jmp    0x400fbe <phase_3+123>
   0x0000000000400fad <+106>:   callq  0x40143a <explode_bomb>
   0x0000000000400fb2 <+111>:   mov    $0x0,%eax
   0x0000000000400fb7 <+116>:   jmp    0x400fbe <phase_3+123>
   0x0000000000400fb9 <+118>:   mov    $0x137,%eax
   0x0000000000400fbe <+123>:   cmp    0xc(%rsp),%eax
   0x0000000000400fc2 <+127>:   je     0x400fc9 <phase_3+134>
   0x0000000000400fc4 <+129>:   callq  0x40143a <explode_bomb>
   0x0000000000400fc9 <+134>:   add    $0x18,%rsp
   0x0000000000400fcd <+138>:   retq   
End of assembler dump.

Decode these two lines:

400f47: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
400f4c: 48 8d 54 24 08 lea 0x8(%rsp),%rdx

register value
%rcx memory address at rsp + 0xc
%rdx memory address at rsp + 0x8

400f51: be cf 25 40 00 mov $0x4025cf,%esi

x/w 0x4025cf
0x4025cf: "%d %d"

So we need two ints for this phase.

400f60: 83 f8 01 cmp $0x1,%eax

if return value is greater than 0x1, and it should, since we read two numbers in:

400f63: 7f 05 jg 400f6a <phase_3+0x27>

We jump to 400f6a

400f6a: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp)

compare the value %rsp + 0x8 with $0x7, if above:

400f6f: 77 3c ja 400fad <phase_3+0x6a>

jump to 400fad

400fad: e8 88 04 00 00 callq 40143a <explode_bomb>

So the value %rsp + 0x8 should be smaller than $0x7. also here we use ja, so the value should be >= 0 and <7.

400f71: 8b 44 24 08 mov 0x8(%rsp),%eax
400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)
400f7c: b8 cf 00 00 00 mov $0xcf,%eax

mov the vluae of %rsp + 0x8 to %eax, sth smaller than $0x7。

for this line: 400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)

This operation jmpq *0x402390(,%rax,8) is for jumping directly to the absolute address stored at
8 * %rax + 0x402390

If you do x/16gx 0x402390 in gdb (inspect 16 "giant words" in hexadecimal starting at 0x402390) you will find an address table looks like the following:(i have a different lab so it's not the same as yours)

0x402880: 0x0000000000400fee 0x000000000040102b
0x402890: 0x0000000000400ff5 0x0000000000400ffc
0x4028a0: 0x0000000000401003 0x000000000040100a
0x4028b0: 0x0000000000401011 0x0000000000401018

Where all these addresses all point back to the a single mov operation immediately after jmpq *0x402390(,%rax,8)

https://stackoverflow.com/a/50978155/3608824

We have the instruction jump = 0x402470 + 8 *i (i <= 7)

If I do x/16gx 0x402470:

(gdb) x/16gx 0x402470
0x402470:   0x0000000000400f7c  0x0000000000400fb9
0x402480:   0x0000000000400f83  0x0000000000400f8a
0x402490:   0x0000000000400f91  0x0000000000400f98
0x4024a0:   0x0000000000400f9f  0x0000000000400fa6
0x4024b0 <array.3449>:  0x737265697564616d  0x6c796276746f666e
0x4024c0:   0x7420756f79206f53  0x756f79206b6e6968
0x4024d0:   0x6f7473206e616320  0x6f62206568742070
0x4024e0:   0x206874697720626d  0x202c632d6c727463

For the first 0 - 7 locations, we have all those lines:

   0x0000000000400f7c <+57>:    mov    $0xcf,%eax

   0x0000000000400fb9 <+118>:   mov    $0x137,%eax

   0x0000000000400f83 <+64>:    mov    $0x2c3,%eax

   0x0000000000400f8a <+71>:    mov    $0x100,%eax

   0x0000000000400f91 <+78>:    mov    $0x185,%eax

   0x0000000000400f98 <+85>:    mov    $0xce,%eax

   0x0000000000400f9f <+92>:    mov    $0x2aa,%eax

   0x0000000000400fa6 <+99>:    mov    $0x147,%eax

try i = 0, we jump to 0x0000000000400f7c.

0x0000000000400f7c <+57>: mov $0xcf,%eax
0x0000000000400f81 <+62>: jmp 0x400fbe <phase_3+123>

the %eax number is 0xcf, and we jump to 0x400fbe.

0x0000000000400fbe <+123>: cmp 0xc(%rsp),%eax
0x0000000000400fc2 <+127>: je 0x400fc9 <phase_3+134>
0x0000000000400fc4 <+129>: callq 0x40143a <explode_bomb>
0x0000000000400fc9 <+134>: add $0x18,%rsp

The value at memory address at rsp + 0xc should equal to value in eax. and then we jump out of the function.

And we have rsp + 0x8 and rsp + 0xc, so we should count the 0s, tried type in

0000 0207 solved.

I can also try other values: 0001 0311 can also solve phase_3.

这一关的思路基本上和文章一致,值得注意的是 x 的用法:

x /[Length][Format] [Address expression]
以给定的参数查看内存中的内容。
x commnad

(Note: the format string for the ‘x’ command has the general form
   x/[NUM][SIZE][FORMAT] where
  NUM  = number of objects to display
  SIZE = size of each object (b=byte, h=half-word, w=word,
                              g=giant (quad-word))
  FORMAT = how to display each object (d=decimal, x=hex, o=octal, etc.)
  If you don’t specify SIZE or FORMAT, either a default value, or the last
  value you specified in a previous ‘print’ or ‘x’ command is used.
)

如果我们直接

(gdb) x 0x402470
0x402470:   0x0000000000400f7c

但是我们知道 第一个数 < 7 ,所以尝试 x/8gx 0x402470

x/8gx 0x402470
0x402470:   0x0000000000400f7c  0x0000000000400fb9
0x402480:   0x0000000000400f83  0x0000000000400f8a
0x402490:   0x0000000000400f91  0x0000000000400f98
0x4024a0:   0x0000000000400f9f  0x0000000000400fa6

这一句还是这样理解:

400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)

0x400f75处的跳转指令依据第一个数的值做间接跳转,还是相当于去去存在此处的内存中的地址。这个 * 有点取(地址)内容的意思。

所以phase_3的答案是7组。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容