CSAPP 3e: Bomb lab (phase_5)

调出phase_5函数:

0000000000401062 <phase_5>:
  401062:    53                       push   %rbx
  401063:    48 83 ec 20              sub    $0x20,%rsp
  401067:    48 89 fb                 mov    %rdi,%rbx
  40106a:    64 48 8b 04 25 28 00     mov    %fs:0x28,%rax    ;此处搞不懂
  401071:    00 00 
  401073:    48 89 44 24 18           mov    %rax,0x18(%rsp)
  401078:    31 c0                    xor    %eax,%eax
  40107a:    e8 9c 02 00 00           callq  40131b <string_length>    ;检测字符串长度
  40107f:    83 f8 06                 cmp    $0x6,%eax
  401082:    74 4e                    je     4010d2 <phase_5+0x70>    ;如果字符串长度不为6,bomb。
  401084:    e8 b1 03 00 00           callq  40143a <explode_bomb>
  401089:    eb 47                    jmp    4010d2 <phase_5+0x70>
  40108b:    0f b6 0c 03              movzbl (%rbx,%rax,1),%ecx    ;%ecx=%eax+%ebx。
  40108f:    88 0c 24                 mov    %cl,(%rsp)        ;取%ecx得低8位,相当于%ecx & 0xff,并将值放入内存地址(%rsp)中
  401092:    48 8b 14 24              mov    (%rsp),%rdx
  401096:    83 e2 0f                 and    $0xf,%edx        ;联系上几行,相当于 %ecx & 0xf,并将运算值放入寄存器%edx。
  401099:    0f b6 92 b0 24 40 00     movzbl 0x4024b0(%rdx),%edx    ;根据%edx的值,从内存地址0x4024b0中将数据读入%edx中
  4010a0:    88 54 04 10              mov    %dl,0x10(%rsp,%rax,1);再将读入的数据转移转移到内存地址(%rsp+0x10+%rax)中
  4010a4:    48 83 c0 01              add    $0x1,%rax    ;%rax+=1
  4010a8:    48 83 f8 06              cmp    $0x6,%rax    ;当rax=6跳出循环,这里注意到6等于所需输入的字符串长度
  4010ac:    75 dd                    jne    40108b <phase_5+0x29>
  4010ae:    c6 44 24 16 00           movb   $0x0,0x16(%rsp)    ;由之前关卡可知strings_not_equal函数的运行机制
  4010b3:    be 5e 24 40 00           mov    $0x40245e,%esi    ;%esi存储答案字符串首地址
  4010b8:    48 8d 7c 24 10           lea    0x10(%rsp),%rdi    ;%rdi存储被检测字符串首地址。
  4010bd:    e8 76 02 00 00           callq  401338 <strings_not_equal>
  4010c2:    85 c0                    test   %eax,%eax    ;字符串一一符合则完成破解。
  4010c4:    74 13                    je     4010d9 <phase_5+0x77>    ;这一关重点是在0x4024b0与0x40245e两个字符串之间的关系。
  4010c6:    e8 6f 03 00 00           callq  40143a <explode_bomb>
  4010cb:    0f 1f 44 00 00           nopl   0x0(%rax,%rax,1)
  4010d0:    eb 07                    jmp    4010d9 <phase_5+0x77>
  4010d2:    b8 00 00 00 00           mov    $0x0,%eax
  4010d7:    eb b2                    jmp    40108b <phase_5+0x29>
  4010d9:    48 8b 44 24 18           mov    0x18(%rsp),%rax
  4010de:    64 48 33 04 25 28 00     xor    %fs:0x28,%rax
  4010e5:    00 00 
  4010e7:    74 05                    je     4010ee <phase_5+0x8c>
  4010e9:    e8 42 fa ff ff           callq  400b30 <__stack_chk_fail@plt>
  4010ee:    48 83 c4 20              add    $0x20,%rsp
  4010f2:    5b                       pop    %rbx
  4010f3:    c3                       retq   

  主要内容在注释中贴出来了,解读如下:

  这一关要求输入一个长度为6的字符串,但是字符串的内容与strings_not_equal函数中%esi存储的地址的字符串不一样,可以看到在这个函数之前有一个转换过程,而且%edi存储的地址是%rsp数据段的地址,这是要点。

  转换过程是取得字符的最低4位,值在0-15之间,通过这个值来调取地址0x4024b0 中的字符,并存入%rsp数据段中,需要%rsp数据段中的字符串与%rsi总的字符串相同,才可以通过这一关。

  地址0x4024b0中的字符串:m a d u i e r s n f o t v b y l  (空格分开只是为了便于查看)

  地址%esi=0x40245e中的字符串:"flyers"

  观察这两个字符串的两两对应关系,要从混乱字符串中选出字符组成"flyers",需要选出的字符序号(从0开始)为 “9,15,4,5,6,7”,十六进制则是"9,f,e,5,6,7"

所以只要输入字符串中对应位的字符的最低4位的数值等于"9,f,e,5,6,7",即可通过这一关。

  比如:通过查看ASCII值,可以得到

  字符最低位值:9  f  e  5  6  7

  对应可选字符:i  o  n  e  f  g

         y       u  v  w

  所以字符串"ionefg"是正确答案。(也可以是"yonefg"或者"yonuvw"都可以,只要字符串满足最低位序号的要求均可以。)

原文地址:https://www.cnblogs.com/xihuyouyu/p/7543634.html