程序在使用 GDB 调试时崩溃,但在使用 运行 时不会崩溃

program crashes when debbuged with GDB but not when run with it

我正在做一个简单的crack-me程序,可以下载here,目标是找到密码,据我了解,程序正在修改自己,然后比较输入的密码与真实的。

当我 运行 没有 GDB 的程序时,它可以工作。

当我启动 gdb 时,通过 set environment LD_PRELOAD ./ptrace.so 和 运行 它运行的程序将 ptrace 替换为我自己的一个。

当我在第一次读取后添加一个断点并逐步执行它时,它以段错误结束。让我解释一下我是怎么做到的。

这是读取语句后的程序集(我输入了我的密码):

0x8048563:  mov    esp,ebp
   0x8048565:   mov    edx,eax
   0x8048567:   dec    edx
   0x8048568:   mov    BYTE PTR [eax+0x80484a0],0x0
   0x804856f:   mov    esi,0x80485a4    <- gets the code at this address
   0x8048574:   mov    edi,esi
   0x8048576:   mov    ecx,0x15
   0x804857b:   lods   al,BYTE PTR ds:[esi]    
   0x804857c:   xor    al,0xaa             <-- XORs the code with something
   0x804857e:   call   0x8048583     <-- I dont understand what is the purpose of calling something that is executed right after but that is not the point
   0x8048583:   pop    ebx
   0x8048584:   add    ebx,0x7
   0x8048587:   jmp    ebx
   0x8048589:   call   0x8d9cc30e
   0x804858e:   add    al,0x8
   0x8048590:   int3   
   0x8048591:   jne    0x8048595
   0x8048593:   inc    al
   0x8048595:   stos   BYTE PTR es:[edi],al
   0x8048596:   loop   0x804857b
   0x8048598:   mov    esi,0x80484a1
   0x804859d:   mov    edi,0x80485ae
   0x80485a2:   mov    ecx,edx
   0x80485a4:   push   es       <--- Code being modified
   0x80485a5:   xchg   BYTE PTR [eax+0x4880df04],ch
   0x80485ab:   push   edx
   0x80485ac:   inc    ecx
   0x80485ad:   mov    eax,ds:0xcefedefb
   0x80485b2:   out    dx,eax
   0x80485b3:   cdq    
   0x80485b4:   int3   
   0x80485b5:   retf   

设置断点后,我 运行 程序一步步执行,直到我退出代码修改循环并显示 asm 代码 :

0x8048598:  mov    esi,0x80484a1
   0x804859d:   mov    edi,0x80485ae
   0x80485a2:   mov    ecx,edx
   0x80485a4:   lods   eax,DWORD PTR ds:[esi]  <---final real code
   0x80485a5:   sub    eax,0x2b760403
   0x80485aa:   jecxz  0x80485a5
   0x80485ac:   in     al,dx            <-- Here the code crashes and stops working for some reason
   0x80485ad:   or     al,0x52
   0x80485af:   jne    0x8048606
   0x80485b1:   gs
   0x80485b2:   inc    esi
   0x80485b3:   xor    al,0x67
   0x80485b5:   bound  esi,QWORD PTR [ebx]
   0x80485b7:   arpl   WORD PTR [ecx],ax
   0x80485b9:   mov    ebp,esp
   0x80485bb:   sub    esp,0x4
   0x80485be:   and    esp,0xfffffff0
   0x80485c1:   add    esp,0x4
   0x80485c4:   push   0x80485ef
   0x80485c9:   call   0x8048350
   0x80485ce:   mov    esp,ebp
   0x80485d0:   xor    eax,eax
   0x80485d2:   jmp    0x80485ee
   0x80485d4:   mov    ebp,esp
   0x80485d6:   sub    esp,0x4
   0x80485d9:   and    esp,0xfffffff0
   0x80485dc:   add    esp,0x4
   0x80485df:   push   0x80485f7
   0x80485e4:   call   0x8048340
   0x80485e9:   mov    esp,ebp
   0x80485eb:   xor    eax,eax
   0x80485ed:   inc    eax
   0x80485ee:   ret    

现在 运行ning stepi 给我 :

Program received signal SIGSEGV, Segmentation fault.
[--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------registers---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------]
b'\x1b[;32mEAX\x1b[0m: 0x8bc662e \n\x1b[;32mEBX\x1b[0m: \x1b[;34m0x804858a\x1b[0m --> 0x85983d80 \n\x1b[;32mECX\x1b[0m: 0x9 (b\'\t\')\n\x1b[;32mEDX\x1b[0m: 0x9 (b\'\t\')\n\x1b[;32mESI\x1b[0m: \x1b[;34m0x80484a5\x1b[0m ("56789")\n\x1b[;32mEDI\x1b[0m: \x1b[;34m0x80485ae\x1b[0m ("RuUeF4gb3c\001\211\345\203", <incomplete sequence \354>...)\n\x1b[;32mEBP\x1b[0m: \x1b[;35m0xffffd5fc\x1b[0m --> \x1b[;31m0xf7e34a83\x1b[0m (<__libc_start_main+243>:\tmov    DWORD PTR [esp],eax)\n\x1b[;32mESP\x1b[0m: \x1b[;35m0xffffd5fc\x1b[0m --> \x1b[;31m0xf7e34a83\x1b[0m (<__libc_start_main+243>:\tmov    DWORD PTR [esp],eax)\n\x1b[;32mEIP\x1b[0m: \x1b[;34m0x80485ac\x1b[0m --> 0x75520cec'
[-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------code-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------]
   0x80485a4:   lods   eax,DWORD PTR ds:[esi]
   0x80485a5:   sub    eax,0x2b760403
   0x80485aa:   jecxz  0x80485a5
=> 0x80485ac:   in     al,dx
   0x80485ad:   or     al,0x52
   0x80485af:   jne    0x8048606
   0x80485b1:   gs
   0x80485b2:   inc    esi
[----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------stack-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------]
00:0000| ebp esp 0xffffd5fc --> 0xf7e34a83 (<__libc_start_main+243>:    mov    DWORD PTR [esp],eax)
01:0004|         0xffffd600 --> 0x1 
02:0008|         0xffffd604 --> 0xffffd694 --> 0xffffd7d7 ("/root/current/c"...)
03:0012|         0xffffd608 --> 0xffffd69c --> 0xffffd7f0 ("XDG_SESSION_ID="...)
04:0016|         0xffffd60c --> 0xf7feacea (add    ebx,0x12316)
05:0020|         0xffffd610 --> 0x1 
06:0024|         0xffffd614 --> 0xffffd694 --> 0xffffd7d7 ("/root/current/c"...)
07:0028|         0xffffd618 --> 0xffffd634 --> 0xf92bd643 
[--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------]
Legend: stack, code, data, heap, rodata, value
Stopped reason: SIGSEGV
0x080485ac in ?? ()

是不是我做的不对? 运行ning 有断点和没有断点的代码有什么区别?我在一篇文章中看到这是一个奇怪的行为,crack me的制作者没有这个问题。

感谢您的帮助。

编辑:没有 0x8048598 上的断点,程序完成而不会崩溃。

用GDB设置断点会增加一条指令,代码修改前设置的那条指令本身移动了所有指令地址,因此修改后的代码不同,调试它导致未定义的行为。