zoukankan      html  css  js  c++  java
  • CSAPP 3e: Bomb lab (secret_phase)

      这是秘密关卡,需要通过主动调用secret_phase函数才能触发,可以通过call secret 或者jump *0x地址来调用。

      贴出函数:(fun7函数部分没有注释,后边续上了手写的图来解析这个函数了)

    0000000000401204 <fun7>:
      401204:    48 83 ec 08              sub    $0x8,%rsp
      401208:    48 85 ff                 test   %rdi,%rdi        
      40120b:    74 2b                    je     401238 <fun7+0x34>;如果%rdi==0,ret。
      40120d:    8b 17                    mov    (%rdi),%edx
      40120f:    39 f2                    cmp    %esi,%edx
      401211:    7e 0d                    jle    401220 <fun7+0x1c>
      401213:    48 8b 7f 08              mov    0x8(%rdi),%rdi
      401217:    e8 e8 ff ff ff           callq  401204 <fun7>
      40121c:    01 c0                    add    %eax,%eax
      40121e:    eb 1d                    jmp    40123d <fun7+0x39>
      401220:    b8 00 00 00 00           mov    $0x0,%eax
      401225:    39 f2                    cmp    %esi,%edx
      401227:    74 14                    je     40123d <fun7+0x39>
      401229:    48 8b 7f 10              mov    0x10(%rdi),%rdi
      40122d:    e8 d2 ff ff ff           callq  401204 <fun7>
      401232:    8d 44 00 01              lea    0x1(%rax,%rax,1),%eax
      401236:    eb 05                    jmp    40123d <fun7+0x39>
      401238:    b8 ff ff ff ff           mov    $0xffffffff,%eax
      40123d:    48 83 c4 08              add    $0x8,%rsp
      401241:    c3                       retq   
    
    0000000000401242 <secret_phase>:
      401242:    53                       push   %rbx
      401243:    e8 56 02 00 00           callq  40149e <read_line>;返回值%rax为所输入字符串的首地址
      401248:    ba 0a 00 00 00           mov    $0xa,%edx    ;strtol函数参数,令函数将字符串读取为10进制
      40124d:    be 00 00 00 00           mov    $0x0,%esi    ;NULL,strtol函数参数
      401252:    48 89 c7                 mov    %rax,%rdi    ;字符串首地址,作为参数
      401255:    e8 76 f9 ff ff           callq  400bd0 <strtol@plt>
      40125a:    48 89 c3                 mov    %rax,%rbx    ;%rax为strtol函数返回值,是一个long int型数字
      40125d:    8d 40 ff                 lea    -0x1(%rax),%eax    ;要求(%rax-1)值小于0x3e8 (1000)。
      401260:    3d e8 03 00 00           cmp    $0x3e8,%eax
      401265:    76 05                    jbe    40126c <secret_phase+0x2a>
      401267:    e8 ce 01 00 00           callq  40143a <explode_bomb>
      40126c:    89 de                    mov    %ebx,%esi        ;%esi等于strtol函数返回的那个long int型数字
      40126e:    bf f0 30 60 00           mov    $0x6030f0,%edi    ;fun7函数用到的一个地址
      401273:    e8 8c ff ff ff           callq  401204 <fun7>
      401278:    83 f8 02                 cmp    $0x2,%eax        ;要求fun7函数返回值为2,否则Bomb.
      40127b:    74 05                    je     401282 <secret_phase+0x40>
      40127d:    e8 b8 01 00 00           callq  40143a <explode_bomb>
      401282:    bf 38 24 40 00           mov    $0x402438,%edi
      401287:    e8 84 f8 ff ff           callq  400b10 <puts@plt>
      40128c:    e8 33 03 00 00           callq  4015c4 <phase_defused>
      401291:    5b                       pop    %rbx
      401292:    c3                       retq   
      401293:    90                       nop
      401294:    90                       nop
      401295:    90                       nop
      401296:    90                       nop
      401297:    90                       nop
      401298:    90                       nop
      401299:    90                       nop
      40129a:    90                       nop
      40129b:    90                       nop
      40129c:    90                       nop
      40129d:    90                       nop
      40129e:    90                       nop
      40129f:    90                       nop

      先研究secret_phase函数,它先调用了read_line函数,通过gdb追踪运行发现,运行read_line函数后,%rax与%rsi的值都是所输入字符串的首地址,%rcx为所输入字符串的长度。

    在call read_line之后的三行都是对调用strtol函数进行参数赋值,mov $0xa,%edx指示strtol函数将字符串转换成十进制值输出。对strtol函数的用法是(具体的百度一下你就知道):

    /**************************************************************/
    表头文件: #include <stdlib.h>
    定义函数: long int strtol(const char *nptr, char **endptr, int base)
    函数说明: strtol()会将参数nptr字符串根据参数base来转换成长整型数。参数base范围从2至36,或0。参数base代表采用的进制方式,如base值为10则采用10进制(字符串以10进制表示),若base值为16则采用16进制(字符串以16进制表示)。当base值为0时则是采用10进制做转换,但遇到如''0x''前置字符则会使用16进制做转换。一开始strtol()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时('''')结束转换,并将结果返回。若参数endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr返回。

    返回值:   返回转换后的长整型数,否则返回ERANGE并将错误代码存入errno中

    比如:

         char a[] = "100";
         char b[] = "100";
         char c[] = "ffff";
         printf("a = %d ", strtol(a, NULL, 10)); //100
         printf("b = %d ", strtol(b, NULL, 2));    //4
         printf("c = %d ", strtol(c, NULL, 16)); //65535

    /*****************************************************************/

      这里将输入的字符串转换成了十进制值,然后在func7函数中校验所输入的值是否正确,具体过程则需要研究fun7函数。

    注意:下图里路径C中少些了一个call fun7;

      在func7中,%rsi的值一直都是所输入的被转换之后的值。

     按照图中所示路径b--->c--->d 计算:

      第一次 b:  %edx=(%rdi); %rdi的值为0x6030f0; 所以%edx的值为0x24

    说明%rsi小于0x24;(%rsi的值就是输入且被转换之后的值)

      第二次 c:   %rdi=(%rdi+0x8); 得%rdi==0x603110;然后调用了fun7自身,%edx=(%rdi); 此时%edx的值为 0x8;

    说明%rsi虽然小于0x24,却不等于0x8,而大于0x8;

      第三次 d:  注意此时%rdi值为0x603110, 然后%rdi=(%rdi+0x10); 新的%rdi的值为0x603150; 之后调用自身fun7,%edx=(%rdi); %edx值为0x16;

    此时可以逐步返回了,说明%rsi的值就是0x16,即10进制的22;

    这样,read_line函数中输入的字符串被转换为10进制值后应该为22;所以,"22"就是正确答案。

    "22"被转换成十进制后值为22,即0x16,符合在fun7函数中的计算结果。

    验证:(call调用出错,所以用jump 跳转调用,0x401242是secret_phase函数入口)

    Wow!

    I've defused the secret stage! 

    Congraduations!!!

  • 相关阅读:
    Wix Burn:如何将32位和64位的安装包制作成一个安装包
    禁止32位安装包运行在64位操作系统上
    图片校验码
    Oracle建表命令
    npm系列
    git使用
    syslog
    hibernate配置enum枚举属性
    httpClient发送post请求
    修改ubuntu系统语言
  • 原文地址:https://www.cnblogs.com/xihuyouyu/p/7545453.html
Copyright © 2011-2022 走看看