深入理解计算机系统 / CSAPP Data Lab2 "扫雷"

拿着锅碗瓢盆造火箭(我更新了!)

反汇编

objdump -d bomb >test.txt

答案
1、Border relations with Canada have never been better.
2、1 2 4 8 16 32
3、0 207 ;1 311 ;2 707 ;3 256 ;4 389 ;5 206 ;6 682 ;7 327(任意一组)
4、0 0 ;1 0 ;3 0 ;7 0(任意一组)
5、ioNu6W(省略其余38880种答案)
6、4 3 2 1 6 5
隐藏关卡见最后

phase_1:字符串

0000000000400ee0 <phase_1>:
  400ee0: 48 83 ec 08           sub    $0x8,%rsp
  #压栈
  400ee4: be 00 24 40 00        mov    $0x402400,%esi
  #将内存 0x402400 中的值移动到%esi
  400ee9: e8 4a 04 00 00        callq  401338 <strings_not_equal>
  #调用函数string_not_equal    #猜测是判断函数,见 401338
  400eee: 85 c0                 test   %eax,%eax
  #测试(%eax)(由string_not_equal返回)是否为 0
  400ef0: 74 05                 je     400ef7 <phase_1+0x17>
  #  相等(%eax==0)时跳转到 400ef7(出栈)
  400ef2: e8 43 05 00 00        callq  40143a <explode_bomb>
  #不相等时调用 explode_bomb(爆炸)
  400ef7: 48 83 c4 08           add    $0x8,%rsp
  #出栈
  400efb: c3                    retq                    retq   

查看内存 0x402400的内容

(gdb) x/ls 0x402400
0x402400: "Border relations with Canada have never been better."

第一个炸弹的答案 Border relations with Canada have never been better.

phase_2:循环

0000000000400efc <phase_2>:
  400efc: 55                    push   %rbp                         
  #压栈
  400efd: 53                    push   %rbx                         
  #压栈
  400efe: 48 83 ec 28           sub    $0x28,%rsp                   
  #压栈 0x28 = 40
  400f02: 48 89 e6              mov    %rsp,%rsi
  400f05: e8 52 05 00 00        callq  40145c <read_six_numbers>    
  #调用函数 read_six_numbers         #猜测输入六个数的函数
  400f0a: 83 3c 24 01           cmpl   $0x1,(%rsp)                  
  #比较 1 和 (%rsp)
  400f0e: 74 20                 je     400f30 <phase_2+0x34>        
  #  相等 跳转到 400f30
  400f10: e8 25 05 00 00        callq  40143a <explode_bomb>        
  #不相等 调用explode_bomb (爆炸)
  400f15: eb 19                 jmp    400f30 <phase_2+0x34>
  400f17: 8b 43 fc              mov    -0x4(%rbx),%eax              
  # %eax = -4 + (%rbx)    (%rbx 为内存地址,-4 则为前一个数)
  400f1a: 01 c0                 add    %eax,%eax                    
  # %eax = 2 * %eax
  400f1c: 39 03                 cmp    %eax,(%rbx)                  
  #比较%eax和(%rbx)  (比较一个数和是否和前一个数的二倍相等)
  400f1e: 74 05                 je     400f25 <phase_2+0x29>       
  #  相等则跳转到 400f25 
  400f20: e8 15 05 00 00        callq  40143a <explode_bomb>        
  #不相等则调用explode_bomb (爆炸)
  400f25: 48 83 c3 04           add    $0x4,%rbx                    
  # %rbx = %rbx + 4 
  400f29: 48 39 eb              cmp    %rbp,%rbx                    
  # %rbp == %rbx 
  400f2c: 75 e9                 jne    400f17 <phase_2+0x1b>        
  #不相等则跳转到 400f17 (循环出现,这里应该是判断)
  400f2e: eb 0c                 jmp    400f3c <phase_2+0x40>        
  #循环结束 则跳转到 400f3c (出栈)
  400f30: 48 8d 5c 24 04        lea    0x4(%rsp),%rbx               
  # %rbx = 4 + (%rsp)      (第二个数的值)
  400f35: 48 8d 6c 24 18        lea    0x18(%rsp),%rbp              
  # %rbp = 24 + (%rsp)     (第六+1个数的值,应该结束后的空间,地址偏移24空间反正是无效的)
  400f3a: eb db                 jmp    400f17 <phase_2+0x1b>        
  #跳转到 400f17
  400f3c: 48 83 c4 28           add    $0x28,%rsp                   
  #出栈  
  400f40: 5b                    pop    %rbx                         
  #出栈        
  400f41: 5d                    pop    %rbp                         
  #出栈
  400f42: c3                    retq   

一个数必须为 1
存在一个循环, 循环结构为 [400f17,400f3a] ,大概整理伪代码,假设六个数为数列(同名变量名表示寄存器)a[5]:

 if a[0]!=1
        explode_bomb();
  int *rbx = a+1; 
  int *rbp = a+6;
  do
  {
    int *eax =rbx-1;
    if((*eax) * 2 != rbx)
      explode_bomb()
    rbx + 1
  }
  while(rbx!=rbp)

不满足条件则不触发
即为长度6,(多也无所谓,read_six_numbers()将多余的数字过滤)为首项为1,公比为2的等比数列为第二题的解
1 2 4 8 16 32

phase_3:分支

0000000000400f43 <phase_3>:
  400f43: 48 83 ec 18           sub    $0x18,%rsp                   
  #压栈 0x18 = 24
  400f47: 48 8d 4c 24 0c        lea    0xc(%rsp),%rcx               
  # %rcx = (%rsp) + 12
  400f4c: 48 8d 54 24 08        lea    0x8(%rsp),%rdx               
  # %rdx = (%rsp) + 8
  400f51: be cf 25 40 00        mov    $0x4025cf,%esi               
  # 0x4025cf:%d %d  暗示输入为两个操作数
  400f56: b8 00 00 00 00        mov    $0x0,%eax                      # 
  400f5b: e8 90 fc ff ff        callq  400bf0 <__isoc99_sscanf@plt> 
  # scanf
  400f60: 83 f8 01              cmp    $0x1,%eax                   
   # 1 == %eax
  400f63: 7f 05                 jg     400f6a <phase_3+0x27>        
  #如果 %eax > 1 则跳转到 400f6a
  400f65: e8 d0 04 00 00        callq  40143a <explode_bomb>        
  # 调用 explode_bomb(爆炸)
  400f6a: 83 7c 24 08 07        cmpl   $0x7,0x8(%rsp)               
  # 7== (%rsp) +8 
  400f6f: 77 3c                 ja     400fad <phase_3+0x6a>        
  #如果(%rsp) + 8 > 7 即,第一个是大于 7 则跳转到 400fad (爆炸)
  400f71: 8b 44 24 08           mov    0x8(%rsp),%eax               
  # %eax = (%rsp) + 8  第一个数
  400f75: ff 24 c5 70 24 40 00  jmpq   *0x402470(,%rax,8)            
  #跳转到 0x402470 + 8 * (%rax)                                                                        
  #这里似乎使用的是switch的判断条件,但是不知道%rax的值
  #可以通过 x/s *(int *)(0X402470 + i * 8)寻址,但是不知道的具体方式
  400f7c: b8 cf 00 00 00        mov    $0xcf,%eax                    
  # %eax = 0xcf = 207
  400f81: eb 3b                 jmp    400fbe <phase_3+0x7b>         
  #直接跳转到 400fbe
  400f83: b8 c3 02 00 00        mov    $0x2c3,%eax                  
  # %eax = 0x2c3 = 707
  400f88: eb 34                 jmp    400fbe <phase_3+0x7b>        
  #直接跳转到 400fbe
  400f8a: b8 00 01 00 00        mov    $0x100,%eax                  
  # %eax = 0x100 = 256
  400f8f: eb 2d                 jmp    400fbe <phase_3+0x7b>        
  #直接跳转到 400fbe
  400f91: b8 85 01 00 00        mov    $0x185,%eax                  
  # %eax = 0x185 = 344
  400f96: eb 26                 jmp    400fbe <phase_3+0x7b>        
  #直接跳转到 400fbe
  400f98: b8 ce 00 00 00        mov    $0xce,%eax                  
  # %eax = 0xce 206
  400f9d: eb 1f                 jmp    400fbe <phase_3+0x7b>        
  #直接跳转到 400fbe
  400f9f: b8 aa 02 00 00        mov    $0x2aa,%eax                  
  # %eax = 0x2aa = 682
  400fa4: eb 18                 jmp    400fbe <phase_3+0x7b>        
  #直接跳转到 400fbe
  400fa6: b8 47 01 00 00        mov    $0x147,%eax                  
  # %eax = 0x147 = 327
  400fab: eb 11                 jmp    400fbe <phase_3+0x7b>        
  #直接跳转到 400fbe
  400fad: e8 88 04 00 00        callq  40143a <explode_bomb>        
  # 调用 explode_bomb(爆炸)
  400fb2: b8 00 00 00 00        mov    $0x0,%eax                    
  # %eax = 0x0 = 0
  400fb7: eb 05                 jmp    400fbe <phase_3+0x7b>        
  #直接跳转到 400fbe
  400fb9: b8 37 01 00 00        mov    $0x137,%eax                  
  # %eax = 0x137 = 311
  400fbe: 3b 44 24 0c           cmp    0xc(%rsp),%eax               
  # %rsp + 12 /(%rcx 即输入的第二个值) == %eax
  400fc2: 74 05                 je     400fc9 <phase_3+0x86>        
  #如果相等则跳转到 400fc9(出栈)
  400fc4: e8 71 04 00 00        callq  40143a <explode_bomb>        
  #调用 explode_bomb(爆炸) 
  400fc9: 48 83 c4 18           add    $0x18,%rsp                   
  #出栈

输入两个数 , 第一个数的范围是需要小于 7
存在一个switch语句,判断代码在 400f75 没看到跳转机制,然后查找资料得可以使用命令查看跳转位置:

 (gdb) x/s *(int *) (0x402470)
 0x400f7c <phase_3+57>:  "\270", <incomplete sequence \317>
 (gdb) x/s *(int *) (0x402470 + 8)
 0x400fb9 <phase_3+118>: "\270\067\001"
 (gdb) x/s *(int *) (0x402470 + 16)
 0x400f83 <phase_3+64>:  "\270\303\002"
 (gdb) x/s *(int *) (0x402470 + 24)
 0x400f8a <phase_3+71>:  "\270"
 (gdb) x/s *(int *) (0x402470 + 32)
 0x400f91 <phase_3+78>:  "\270\205\001"
 (gdb) x/s *(int *) (0x402470 + 40)
 0x400f98 <phase_3+85>:  "\270", <incomplete sequence \316>
 (gdb) x/s *(int *) (0x402470 + 48)
 0x400f9f <phase_3+92>:  "\270\252\002"
 (gdb) x/s *(int *) (0x402470 + 56)
 0x400fa6 <phase_3+99>:  "\270G\001"

程序大概为(同名变量名表示寄存器):

 long rdx;
 int rcx;
 int eax;
 scanf("%d,%d",&amp;rdx,&amp;rcx);
 if(rdx < 7)
   explode_bomb();
 switch(rdx)
 {
     case 0:
       eax = 207;
       break;
     case 1:
       eax = 311;
       break;
     case 2:
       eax = 707;
       break;
     case 3:
       eax = 256;
       break;
     case 4:
       eax = 389;
       break;
     case 5:
       eax = 206;
       break;
     case 6:
       eax = 682;
       break;
     case 7:
       eax = 327;
       break;
     default:
       explode_bomb();
   }
 }
 if(eax != rcx)
   explode_bomb()

即,满足条件的四组分别为 0 207 ;1 311 ;2 707 ;3 256 ;4 389 ;5 206 ;6 682 ;7 327

phase_4:递归

0000000000400fce <func4>:
# %edi等于传入的第二个数, %esi = 0,%edx = 14;
  400fce: 48 83 ec 08           sub    $0x8,%rsp                    
  #压栈
  400fd2: 89 d0                 mov    %edx,%eax                    
  # %eax = %edx
  400fd4: 29 f0                 sub    %esi,%eax                   
  # %eax= %eax - %esi
  400fd6: 89 c1                 mov    %eax,%ecx                    
  # %ecx = %eax
  400fd8: c1 e9 1f              shr    $0x1f,%ecx                   
  #右移 %ecx = %ecx >> 0x1f
  400fdb: 01 c8                 add    %ecx,%eax                    
  # %eax = %eax + %ecx
  400fdd: d1 f8                 sar    %eax                         
  #右移一位 %eax = %eax >> 1                                                                            
  # 上面6行的效果是 %eax = ((%edx - %esi) >>31 + %edx - %esi ) >> 1
  400fdf: 8d 0c 30              lea    (%rax,%rsi,1),%ecx           
  # %ecx = %rax + %rsi     (%rax = %eax,%rsi = %esi)|?                                                                   
  # %ecx = (((%edx - %esi >>31) + %edx - %esi ) >> 1) + %esi
  400fe2: 39 f9                 cmp    %edi,%ecx                    
  # %ecx == %edi
  400fe4: 7e 0c                 jle    400ff2 <func4+0x24>           
  #如果 %ecx小于等于%edi 则跳转到 400ff2
  400fe6: 8d 51 ff              lea    -0x1(%rcx),%edx              
  # %edx = (%ecx) - 1
  400fe9: e8 e0 ff ff ff        callq  400fce <func4>                
  #递归                
  400fee: 01 c0                 add    %eax,%eax                    
  # %eax = %eax + %eax
  400ff0: eb 15                 jmp    401007 <func4+0x39>         
  #跳转到 401007 (出栈,递归结束)
  400ff2: b8 00 00 00 00        mov    $0x0,%eax                    
  # %eax = 0
  400ff7: 39 f9                 cmp    %edi,%ecx                    
  # %edi == %ecx
  400ff9: 7d 0c                 jge    401007 <func4+0x39>          
  #如果 %ecx >= %edi 则跳转到 401007 (出栈,递归结束)
  400ffb: 8d 71 01              lea    0x1(%rcx),%esi               
  # %esi = (%ecx) + 1 
  400ffe: e8 cb ff ff ff        callq  400fce <func4>               
  #出现递归,自己调用自己 
  401003: 8d 44 00 01           lea    0x1(%rax,%rax,1),%eax       
  # %eax = %rax + %rax +1
  401007: 48 83 c4 08           add    $0x8,%rsp                    
  #出栈
  40100b: c3   
0000000000400fce <func4>:
# %edi等于传入的第二个数, %esi = 0,%edx = 14;
  400fce: 48 83 ec 08           sub    $0x8,%rsp                    
  #压栈
  400fd2: 89 d0                 mov    %edx,%eax                    
  # %eax = %edx
  400fd4: 29 f0                 sub    %esi,%eax                    
  # %eax= %eax - %esi
  400fd6: 89 c1                 mov    %eax,%ecx                    
  # %ecx = %eax
  400fd8: c1 e9 1f              shr    $0x1f,%ecx                   
  #右移 %ecx = %ecx >> 0x1f
  400fdb: 01 c8                 add    %ecx,%eax                    
  # %eax = %eax + %ecx
  400fdd: d1 f8                 sar    %eax                         
  #右移一位 %eax = %eax >> 1                                                                     
  # 上面6行的效果是 %eax = ((%edx - %esi) >>31 + %edx - %esi ) >> 1
  400fdf: 8d 0c 30              lea    (%rax,%rsi,1),%ecx           
  # %ecx = %rax + %rsi     (%rax = %eax,%rsi = %esi)|?                                                                     
  # %ecx = (((%edx - %esi >>31) + %edx - %esi ) >> 1) + %esi
  400fe2: 39 f9                 cmp    %edi,%ecx                    
  # %ecx == %edi
  400fe4: 7e 0c                 jle    400ff2 <func4+0x24>          
  #如果 %ecx小于等于%edi 则跳转到 400ff2
  400fe6: 8d 51 ff              lea    -0x1(%rcx),%edx              
  # %edx = (%ecx) - 1
  400fe9: e8 e0 ff ff ff        callq  400fce <func4>              
  #递归                
  400fee: 01 c0                 add    %eax,%eax                    
  # %eax = %eax + %eax
  400ff0: eb 15                 jmp    401007 <func4+0x39>          
  #跳转到 401007 (出栈,递归结束)
  400ff2: b8 00 00 00 00        mov    $0x0,%eax                    
  # %eax = 0
  400ff7: 39 f9                 cmp    %edi,%ecx                    
  # %edi == %ecx
  400ff9: 7d 0c                 jge    401007 <func4+0x39>          
  #如果 %ecx >= %edi 则跳转到 401007 (出栈,递归结束)
  400ffb: 8d 71 01              lea    0x1(%rcx),%esi               
  # %esi = (%ecx) + 1 
  400ffe: e8 cb ff ff ff        callq  400fce <func4>               
  #出现递归,自己调用自己 
  401003: 8d 44 00 01           lea    0x1(%rax,%rax,1),%eax        
  # %eax = %rax + %rax +1
  401007: 48 83 c4 08           add    $0x8,%rsp                     
  #出栈

第一个数的范围小于15 值有func4决定,%eax 为函数func4 的返回值, 第二个数的值为 0
func4 是一个递归函数,见 400fce
我们通过一个程序来测试出符合条件的取值。

 include <stdio.h>
 int main()
 {
     int i;
     int result;
     for(i = 0;i < 15;i++)
     {
         result = func4(i,0,14);
         if (result==0)
             printf("%d\n",i);
     }
     return 0;
 }
 int func4(int edi,int esi,int edx)
 {
     int ecx = (((edx - esi >>31) + edx - esi ) >> 1) + esi;
     if (ecx <= edi)
     {
         if(ecx >= edi)
             return 0;
         else
             return func4(edi,ecx+1,edx) * 2 +1;
     }
     else
         return func4(edi,esi,ecx-1) * 2;
 }

输出为 0 1 3 7
即,满足条件的四组分别为 0 0 ;1 0 ;3 0 ;7 0

phase_5:字符串Plus

00000000004010f4 <phase_6>:
  4010f4: 41 56                 push   %r14                             
  #压栈
  4010f6: 41 55                 push   %r13                             
  #压栈
  4010f8: 41 54                 push   %r12                             
  #压栈
  4010fa: 55                    push   %rbp                             
  #压栈
  4010fb: 53                    push   %rbx                             
  #压栈
  4010fc: 48 83 ec 50           sub    $0x50,%rsp                       
  #压栈 0x50 = 80
  401100: 49 89 e5              mov    %rsp,%r13                        
  # %r13 = %rsp
  401103: 48 89 e6              mov    %rsp,%rsi                        
  # %rsi = %rsp
  401106: e8 51 03 00 00        callq  40145c <read_six_numbers>        
  #调用函数 read_six_numbers 输入六个数(和phase_2相同)
  40110b: 49 89 e6              mov    %rsp,%r14                        
  # %r14 = %rsp
  40110e: 41 bc 00 00 00 00     mov    $0x0,%r12d                       
  # %r12d = 0
  401114: 4c 89 ed              mov    %r13,%rbp                        
  # %rbp = %r13
  401117: 41 8b 45 00           mov    0x0(%r13),%eax                   
  # %eax = %r13
  40111b: 83 e8 01              sub    $0x1,%eax                        
  # %eax -= 1
  40111e: 83 f8 05              cmp    $0x5,%eax                        
  # %eax == 5
  401121: 76 05                 jbe    401128 <phase_6+0x34>            
  #如果小于等于这跳转到 401128
  401123: e8 12 03 00 00        callq  40143a <explode_bomb>            
  #如果大于则 调用 40143a (爆炸)
  401128: 41 83 c4 01           add    $0x1,%r12d                       
  # %r12d += 1
  40112c: 41 83 fc 06           cmp    $0x6,%r12d                       
  # %12d == 6
  401130: 74 21                 je     401153 <phase_6+0x5f>            
  #  相等则跳转到 401153
  401132: 44 89 e3              mov    %r12d,%ebx                       
  #不相等则 %r12 = %ebx
  401135: 48 63 c3              movslq %ebx,%rax                        
  # %rax = %ebx
  401138: 8b 04 84              mov    (%rsp,%rax,4),%eax               
  # %eax = (%rsp + %rax * 4)       # %rsp + 4 即到下一个数
  40113b: 39 45 00              cmp    %eax,0x0(%rbp)                   
  # %eax == (%rbp)
  40113e: 75 05                 jne    401145 <phase_6+0x51>            
  #不相等则跳转到 401145
  401140: e8 f5 02 00 00        callq  40143a <explode_bomb>            
  # 相等则调用 40143a (爆炸)
  401145: 83 c3 01              add    $0x1,%ebx                        
  # %ebx += 1
  401148: 83 fb 05              cmp    $0x5,%ebx                        
  # %ebx == 5
  40114b: 7e e8                 jle    401135 <phase_6+0x41>            
  #小于等于则 跳转到 401135
  40114d: 49 83 c5 04           add    $0x4,%r13                        
  # %r13 += 4                       # %rsp + 4 即到下一个数
  401151: eb c1                 jmp    401114 <phase_6+0x20>            
  # 跳转到 401114 (循环???)
  401153: 48 8d 74 24 18        lea    0x18(%rsp),%rsi                  
  # %rsi = (%rsp) + 24
  401158: 4c 89 f0              mov    %r14,%rax                        
  # %rax = %r14
  40115b: b9 07 00 00 00        mov    $0x7,%ecx                        
  # %ecx = 7
  401160: 89 ca                 mov    %ecx,%edx                        
  # %edx = %ecx
  401162: 2b 10                 sub    (%rax),%edx                      
  # %edx -= %rax
  401164: 89 10                 mov    %edx,(%rax)                      
  # (%rax) = %edx
  401166: 48 83 c0 04           add    $0x4,%rax                        
  # %rax +=4                      #这里应该是 (%rax) + 4 更加准确
  40116a: 48 39 f0              cmp    %rsi,%rax                        
  # %rsi == %rax
  40116d: 75 f1                 jne    401160 <phase_6+0x6c>            
  #不相等则跳转到 401160 (循环出现)
  40116f: be 00 00 00 00        mov    $0x0,%esi                        
  #  相等则 %esi = 0
  401174: eb 21                 jmp    401197 <phase_6+0xa3>            
  #直接跳转到 401197
  401176: 48 8b 52 08           mov    0x8(%rdx),%rdx                   
  # %rdx = (%rdx) + 8
  40117a: 83 c0 01              add    $0x1,%eax                        
  # %eax += 1                 #%eax = %rsp
  40117d: 39 c8                 cmp    %ecx,%eax                        
  # %eax ==%ecx
  40117f: 75 f5                 jne    401176 <phase_6+0x82>            
  #不相等则跳转到 401176 (也是一个循环)
  401181: eb 05                 jmp    401188 <phase_6+0x94>            
  #  相等则跳转到 401188
  401183: ba d0 32 60 00        mov    $0x6032d0,%edx                   
  # %edx = $0x6032d0
  401188: 48 89 54 74 20        mov    %rdx,0x20(%rsp,%rsi,2)           
  # (%rsp + %rsi * 2) + 32 =%rdx
  40118d: 48 83 c6 04           add    $0x4,%rsi                        
  # %rsi += 4
  401191: 48 83 fe 18           cmp    $0x18,%rsi                       
  # %rsi == 24
  401195: 74 14                 je     4011ab <phase_6+0xb7>            
  #  相等则跳转到 4011ab
  401197: 8b 0c 34              mov    (%rsp,%rsi,1),%ecx               
  # %ecx = (%rsp + %rsi)
  40119a: 83 f9 01              cmp    $0x1,%ecx                        
  # %ecx == 1
  40119d: 7e e4                 jle    401183 <phase_6+0x8f>            
  #小于等于调用 401183
  40119f: b8 01 00 00 00        mov    $0x1,%eax                        
  #%eax = 1
  4011a4: ba d0 32 60 00        mov    $0x6032d0,%edx                   
  #%edx = $0x6032d0
  4011a9: eb cb                 jmp    401176 <phase_6+0x82>            
  #跳转到 401176 (还有一个循环)
  4011ab: 48 8b 5c 24 20        mov    0x20(%rsp),%rbx                  
  # %rbx = (%rsp) + 32
  4011b0: 48 8d 44 24 28        lea    0x28(%rsp),%rax                  
  # %rax = (%rsp) + 40
  4011b5: 48 8d 74 24 50        lea    0x50(%rsp),%rsi                  
  # %rsi = (%rsp) + 80
  4011ba: 48 89 d9              mov    %rbx,%rcx                        
  # %rcx = %rbx
  4011bd: 48 8b 10              mov    (%rax),%rdx                      
  # %rdx = (%rax)
  4011c0: 48 89 51 08           mov    %rdx,0x8(%rcx)                   
  # (%rcx) + 8 =%rdx          #指向下一个
  4011c4: 48 83 c0 08           add    $0x8,%rax                        
  # %rax += 8
  4011c8: 48 39 f0              cmp    %rsi,%rax                        
  # %rax == %rsi
  4011cb: 74 05                 je     4011d2 <phase_6+0xde>            
  #  相等则跳转到 4011d2 
  4011cd: 48 89 d1              mov    %rdx,%rcx                        
  #不相等 %rcx = %rdx 
  4011d0: eb eb                 jmp    4011bd <phase_6+0xc9>            
  #跳转到 4011bd (又是一个循环?)
  4011d2: 48 c7 42 08 00 00 00  movq   $0x0,0x8(%rdx)                   
  # (%rdx) +8 = 0             #尾节点 ->NULL
  4011d9: 00 
  4011da: bd 05 00 00 00        mov    $0x5,%ebp                        
  # %ebp = 5
  4011df: 48 8b 43 08           mov    0x8(%rbx),%rax                   
  # %rax = (%rbx) + 8
  4011e3: 8b 00                 mov    (%rax),%eax                      
  # %eax = (%rax)
  4011e5: 39 03                 cmp    %eax,(%rbx)                      
  # (%rbx) == (%eax)
  4011e7: 7d 05                 jge    4011ee <phase_6+0xfa>            
  #大于等于则 跳转到 4011ee
  4011e9: e8 4c 02 00 00        callq  40143a <explode_bomb>            
  #否则 调用40143a(爆炸)
  4011ee: 48 8b 5b 08           mov    0x8(%rbx),%rbx                   
  # %rbx = (%rbx) + 8
  4011f2: 83 ed 01              sub    $0x1,%ebp                        
  # %ebp -= 1 
  4011f5: 75 e8                 jne    4011df <phase_6+0xeb>            
  #不相等则跳转到 4011df
  4011f7: 48 83 c4 50           add    $0x50,%rsp                       
  # 下面为出栈和返回
  4011fb: 5b                    pop    %rbx
  4011fc: 5d                    pop    %rbp
  4011fd: 41 5c                 pop    %r12
  4011ff: 41 5d                 pop    %r13
  401201: 41 5e                 pop    %r14
  401203: c3                    retq  

确定输入一个长度为 6 的字符串
经过查看的 %rbx为输入的字符串的值
在 401099 将一个值一个数移动到 %eax, 使用gdb 查看

(gdb) x/s 0x4024b0
0x4024b0 <array.3449>:  "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"

在 4010b3 又将一个值一个数移动到 %eax, 使用gdb 查看

在 4010b3 又将一个值一个数移动到 %eax, 使用gdb 查看

(gdb) x/ls 0x40245e
0x40245e:   "flyers"

这个题的具体操作就是将输入的字符串安装他的规则映射后与 "flyers"对比
基本步骤超级伪代码为:

这个题的具体操作就是将输入的字符串安装他的规则映射后与 "flyers"对比
基本步骤超级伪代码为:

 字符串2[] = "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"
 字符串1[] = 输入()
 if len(字符串[]) != 6
     explode_bomb()
 i = 0
 do
 {
     新字符串[i]=字符串2[字符串1[i].ascii尾位]
     i++
 }
 while i<6
 新字符串[6] = "\0"
 if 新字符串 == "flyers"
     return 0;
 else
     explode_bomb()

flyers在字符串2中的索引分别为 9 f e 5 6 7
我们这次用Python将所有答案打印出来(只包括标准ASCII课显示字符),大约 38881 种答案

  num1=[]
  for i in range(32,127):
      if hex(i)[-1]=="9":
          num1.append(chr(i))
  print(num1)
  num2=[]
  for i in range(32,127):
      if hex(i)[-1]=="f":
          num2.append(chr(i))
  print(num2)
  num3=[]
  for i in range(32,127):
      if hex(i)[-1]=="e":
          num3.append(chr(i))
  print(num3)
  num4=[]
  for i in range(32,127):
      if hex(i)[-1]=="5":
          num4.append(chr(i))
  print(num4)
  num5=[]
  for i in range(32,127):
      if hex(i)[-1]=="6":
          num5.append(chr(i))
  print(num5)
  num6=[]
  for i in range(32,127):
      if hex(i)[-1]=="7":
          num6.append(chr(i))
  print(num6)
  for i in num1:
      for j in num2:
          print()
          for k in num3:
              for l in num4:
                  print()
                  for m in num5:
                      for n in num6:
                          print(i+j+k+l+m+n,end="\t")

随便输一组答案 ioNu6W 就过关了

phase_6:链表

00000000004010f4 <phase_6>:
  4010f4: 41 56                 push   %r14                             
  #压栈
  4010f6: 41 55                 push   %r13                             
  #压栈
  4010f8: 41 54                 push   %r12                             
  #压栈
  4010fa: 55                    push   %rbp                             
  #压栈
  4010fb: 53                    push   %rbx                             
  #压栈
  4010fc: 48 83 ec 50           sub    $0x50,%rsp                       
  #压栈 0x50 = 80
  401100: 49 89 e5              mov    %rsp,%r13                        
  # %r13 = %rsp
  401103: 48 89 e6              mov    %rsp,%rsi                        
  # %rsi = %rsp
  401106: e8 51 03 00 00        callq  40145c <read_six_numbers>        
  #调用函数 read_six_numbers 输入六个数(和phase_2相同)
  40110b: 49 89 e6              mov    %rsp,%r14                        
  # %r14 = %rsp
  40110e: 41 bc 00 00 00 00     mov    $0x0,%r12d                       
  # %r12d = 0
  401114: 4c 89 ed              mov    %r13,%rbp                        
  # %rbp = %r13
  401117: 41 8b 45 00           mov    0x0(%r13),%eax                   
  # %eax = %r13
  40111b: 83 e8 01              sub    $0x1,%eax                        
  # %eax -= 1
  40111e: 83 f8 05              cmp    $0x5,%eax                        
  # %eax == 5
  401121: 76 05                 jbe    401128 <phase_6+0x34>            
  #如果小于等于这跳转到 401128
  401123: e8 12 03 00 00        callq  40143a <explode_bomb>            
  #如果大于则 调用 40143a (爆炸)
  401128: 41 83 c4 01           add    $0x1,%r12d                       
  # %r12d += 1
  40112c: 41 83 fc 06           cmp    $0x6,%r12d                       
  # %12d == 6
  401130: 74 21                 je     401153 <phase_6+0x5f>            
  #  相等则跳转到 401153
  401132: 44 89 e3              mov    %r12d,%ebx                       
  #不相等则 %r12 = %ebx
  401135: 48 63 c3              movslq %ebx,%rax                        
  # %rax = %ebx
  401138: 8b 04 84              mov    (%rsp,%rax,4),%eax               
  # %eax = (%rsp + %rax * 4)       # %rsp + 4 即到下一个数
  40113b: 39 45 00              cmp    %eax,0x0(%rbp)                   
  # %eax == (%rbp)
  40113e: 75 05                 jne    401145 <phase_6+0x51>            
  #不相等则跳转到 401145
  401140: e8 f5 02 00 00        callq  40143a <explode_bomb>            
  # 相等则调用 40143a (爆炸)
  401145: 83 c3 01              add    $0x1,%ebx                        
  # %ebx += 1
  401148: 83 fb 05              cmp    $0x5,%ebx                        
  # %ebx == 5
  40114b: 7e e8                 jle    401135 <phase_6+0x41>            
  #小于等于则 跳转到 401135
  40114d: 49 83 c5 04           add    $0x4,%r13                        
  # %r13 += 4                       # %rsp + 4 即到下一个数
  401151: eb c1                 jmp    401114 <phase_6+0x20>            
  # 跳转到 401114 (循环???)
  401153: 48 8d 74 24 18        lea    0x18(%rsp),%rsi                  
  # %rsi = (%rsp) + 24
  401158: 4c 89 f0              mov    %r14,%rax                        
  # %rax = %r14
  40115b: b9 07 00 00 00        mov    $0x7,%ecx                        
  # %ecx = 7
  401160: 89 ca                 mov    %ecx,%edx                        
  # %edx = %ecx
  401162: 2b 10                 sub    (%rax),%edx                      
  # %edx -= %rax
  401164: 89 10                 mov    %edx,(%rax)                      
  # (%rax) = %edx
  401166: 48 83 c0 04           add    $0x4,%rax                        
  # %rax +=4                      #这里应该是 (%rax) + 4 更加准确
  40116a: 48 39 f0              cmp    %rsi,%rax                        
  # %rsi == %rax
  40116d: 75 f1                 jne    401160 <phase_6+0x6c>            
  #不相等则跳转到 401160 (循环出现)
  40116f: be 00 00 00 00        mov    $0x0,%esi                        
  #  相等则 %esi = 0
  401174: eb 21                 jmp    401197 <phase_6+0xa3>            
  #直接跳转到 401197
  401176: 48 8b 52 08           mov    0x8(%rdx),%rdx                   
  # %rdx = (%rdx) + 8
  40117a: 83 c0 01              add    $0x1,%eax                        
  # %eax += 1                 #%eax = %rsp
  40117d: 39 c8                 cmp    %ecx,%eax                        
  # %eax ==%ecx
  40117f: 75 f5                 jne    401176 <phase_6+0x82>            
  #不相等则跳转到 401176 (也是一个循环)
  401181: eb 05                 jmp    401188 <phase_6+0x94>            
  #  相等则跳转到 401188
  401183: ba d0 32 60 00        mov    $0x6032d0,%edx                   
  # %edx = $0x6032d0
  401188: 48 89 54 74 20        mov    %rdx,0x20(%rsp,%rsi,2)           
  # (%rsp + %rsi * 2) + 32 =%rdx
  40118d: 48 83 c6 04           add    $0x4,%rsi                        
  # %rsi += 4
  401191: 48 83 fe 18           cmp    $0x18,%rsi                       
  # %rsi == 24
  401195: 74 14                 je     4011ab <phase_6+0xb7>            
  #  相等则跳转到 4011ab
  401197: 8b 0c 34              mov    (%rsp,%rsi,1),%ecx               
  # %ecx = (%rsp + %rsi)
  40119a: 83 f9 01              cmp    $0x1,%ecx                        
  # %ecx == 1
  40119d: 7e e4                 jle    401183 <phase_6+0x8f>            
  #小于等于调用 401183
  40119f: b8 01 00 00 00        mov    $0x1,%eax                        
  #%eax = 1
  4011a4: ba d0 32 60 00        mov    $0x6032d0,%edx                   
  #%edx = $0x6032d0
  4011a9: eb cb                 jmp    401176 <phase_6+0x82>            
  #跳转到 401176 (还有一个循环)
  4011ab: 48 8b 5c 24 20        mov    0x20(%rsp),%rbx                  
  # %rbx = (%rsp) + 32
  4011b0: 48 8d 44 24 28        lea    0x28(%rsp),%rax                  
  # %rax = (%rsp) + 40
  4011b5: 48 8d 74 24 50        lea    0x50(%rsp),%rsi                  
  # %rsi = (%rsp) + 80
  4011ba: 48 89 d9              mov    %rbx,%rcx                        
  # %rcx = %rbx
  4011bd: 48 8b 10              mov    (%rax),%rdx                      
  # %rdx = (%rax)
  4011c0: 48 89 51 08           mov    %rdx,0x8(%rcx)                   
  # (%rcx) + 8 =%rdx          #指向下一个
  4011c4: 48 83 c0 08           add    $0x8,%rax                        
  # %rax += 8
  4011c8: 48 39 f0              cmp    %rsi,%rax                        
  # %rax == %rsi
  4011cb: 74 05                 je     4011d2 <phase_6+0xde>            
  #  相等则跳转到 4011d2 
  4011cd: 48 89 d1              mov    %rdx,%rcx                        
  #不相等 %rcx = %rdx 
  4011d0: eb eb                 jmp    4011bd <phase_6+0xc9>            
  #跳转到 4011bd (又是一个循环?)
  4011d2: 48 c7 42 08 00 00 00  movq   $0x0,0x8(%rdx)                   
  # (%rdx) +8 = 0             #尾节点 ->NULL
  4011d9: 00 
  4011da: bd 05 00 00 00        mov    $0x5,%ebp                        
  # %ebp = 5
  4011df: 48 8b 43 08           mov    0x8(%rbx),%rax                   
  # %rax = (%rbx) + 8
  4011e3: 8b 00                 mov    (%rax),%eax                      
  # %eax = (%rax)
  4011e5: 39 03                 cmp    %eax,(%rbx)                      
  # (%rbx) == (%eax)
  4011e7: 7d 05                 jge    4011ee <phase_6+0xfa>            
  #大于等于则 跳转到 4011ee
  4011e9: e8 4c 02 00 00        callq  40143a <explode_bomb>            
  #否则 调用40143a(爆炸)
  4011ee: 48 8b 5b 08           mov    0x8(%rbx),%rbx                   
  # %rbx = (%rbx) + 8
  4011f2: 83 ed 01              sub    $0x1,%ebp                        
  # %ebp -= 1 
  4011f5: 75 e8                 jne    4011df <phase_6+0xeb>            
  #不相等则跳转到 4011df
  4011f7: 48 83 c4 50           add    $0x50,%rsp                       
  # 下面为出栈和返回
  4011fb: 5b                    pop    %rbx
  4011fc: 5d                    pop    %rbp
  4011fd: 41 5c                 pop    %r12
  4011ff: 41 5d                 pop    %r13
  401201: 41 5e                 pop    %r14
  401203: c3                    retq  

代码特别长,逻辑特别复杂,循环特别多
六个数,第n个数为:%rsp+((n-1) * 4)

第一部分:[401114,401151],这是一个双层循环(内循环[401160,40114b])。目的是、判断输入的值不大于 6,且六个互不相等

    假设是数组一个 a[5]伪代码:
 for(i = 0; i++ ;i < 5)
 {
     if(a[i] -1 >= 5)
         for(j = i + 1; j++ ;j <5)
         {
             if(a[i]==a[j])
                 explode_bomb();
         }
     else
         explode_bomb();
 }

第二部分: [401160,40116d]将每个数和 7 作差,如,输入1 2 3 4 5 6 得到的值为 6 5 4 3 2 1

    假设是数组一个 a[5]伪代码,变量使用寄存器名:
  *rsi = a[6];
  *rax = a[0];
  do
  {
      *rax = 7 - *rax
      rax+1;
  }
  while(rsi != rax)

第三部分:[401176,4011a9],其中存在两个循环[401176,40117f],[401188,40119d],作用将 0x6032d0 后面的内容排序。使用gdb查看

  (gdb) x/s 0x6032d0
  0x6032d0 <node1>:   "L\001"
  (gdb) x/s 0x6032e0
  0x6032e0 <node2>:   "\250"
  (gdb) x/s 0x6032f0
  0x6032f0 <node3>:   "\234\003"

可以确定结构由三个元素组成,两个整形数据,一个结构类型的指针,大小刚好16字节,名称分别为node1,node2,node3...
结构包括三个部分分别为:value、id、下一元素地址

 typedef struct node{
     int value;
     int id;
     struct node *next;
 }node;
(gdb) p/s *0x6032d0@18
 $16 = {332, 1, 6304480, 0, 168, 2, 6304496, 0, 924, 3, 6304512, 0,691, 4, 6304528, 0, 477, 5, 6304544, 0, 443, 6, 0, 0}

得到了原始链表的值 332 168 924 691 477 443

第四部分:[4011ab,4011d0],存在循环[4011bd,4011d0],循环的作用node之间建立链表连接指针
第五部分[4011df,4011f5] 检查链表是否以节点的 num1 值为依据从大到小排列

将链表排序的后的顺序为 924(3) 691(4) 477(5) 443(6) 332(1) 168(2)
由于存在7减的操作,则这个题的正确答案为 4 3 2 1 6 5

secret_phase:二叉树

0000000000401204 <fun7>:
  401204: 48 83 ec 08           sub    $0x8,%rsp
  401208: 48 85 ff              test   %rdi,%rdi
  40120b: 74 2b                 je     401238 <fun7+0x34>
  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>
  401248: ba 0a 00 00 00        mov    $0xa,%edx
  40124d: be 00 00 00 00        mov    $0x0,%esi
  401252: 48 89 c7              mov    %rax,%rdi
  401255: e8 76 f9 ff ff        callq  400bd0 <strtol@plt>
  40125a: 48 89 c3              mov    %rax,%rbx
  40125d: 8d 40 ff              lea    -0x1(%rax),%eax
  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
  40126e: bf f0 30 60 00        mov    $0x6030f0,%edi
  401273: e8 8c ff ff ff        callq  401204 <fun7>
  401278: 83 f8 02              cmp    $0x2,%eax
  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

隐藏炸弹就不分析了 ,分析不下去了。直接百度一个答案:

触发secret_phase : 在phase_4输入时添加 DrEvil

答案:22


实在对汇编不熟悉,做这个太勉强,花了我不少时间,也参考了不少资料,得去写Python了。

文章目录