好吧,所以我真的在试着去理解这个“剥削的艺术”第二版的例子。我正试图通过密切关注书中GDB的输出来了解这个例子到底发生了什么。我最大的问题是最后一部分,我把整个事情都包括在内,这样每个人都能看到发生了什么。当然,我只有非常(非常)基本的汇编代码知识。我确实懂基本的C。
在最后一部分中,作者说,在strcpy()指向的地址中,程序的第二次运行与最后一次运行略有不同,我只是看不到。
程序很简单

#include<stdio.h>
#include<string.h>

int main() {

  char str_a[20];
  strcpy(str_a, "Hello, world!\n");
  printf(str_a);
  }

在我用必要的选项编译它以便能够调试它之后,我将它加载到
并包括以下内容:
(gdb) break 6
Breakpoint 1 at 0x80483c4: file char_array2.c, line 6.
(gdb) break strcpy

Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (strcpy) pending.
(gdb) break 8
Breakpoint 3 at 0x80483d7: file char_array2.c, line 8.
(gdb)

我对此没有意见,我的理解是
调试器只能使用用户定义的函数执行此类操作。我还知道如何解决gcc选项的这个问题。
我还知道当程序运行时,strcpy断点被解析。让我继续。
(gdb) run
Starting program: /home/reader/booksrc/char_array2
Breakpoint 4 at 0xb7f076f4
Pending breakpoint "strcpy" resolved

Breakpoint 1, main() at char_array2.c:7
7   strcpy(str_a, "Hello, world!\n");
(gdb) i r eip
eip 0x80483c4   0x80483c4 <main+16>
(gdb) x/5i $eip
0x80483c4   <main+16>:  mov    DWORD PTR [esp+4],0x80484c4
0x80483cc   <main+24>:  lea    eax,[ebp-40]
0x80483cf   <main+27>:  mov    DWORD PTR [esp],eax
0x80483d2   <main+30>:  call   0x80482c4 <strcpy@plt>
0x80483d7   <main+35>:  lea    eax,[ebp-40]
(gdb) continue
Continuing.


Breakpoint 4, 0xb7f076f4 in strcpy () from /lib/tls/i686/cmov/libc.so.6
(gdb) i r eip
eip    0xb7f076f4    0xb7f076f4 <strcpy+4>
(gdb) x/5i $eip
0xb7f076f4 <strcpy+4>:  mov   esi,DWORD PTR [ebp+8]
0xb7f076f7 <strcpy+7>:  mov   eax,DWORD PTR [ebp+12]
0xb7f076fa <strcpy+10>: mov   ecx,esi
0xb7f076fc <strcpy+12>: sub   ecx,eax
0xb7f076fe <strcpy+14>: mov   edx,eax
(gdb) continue
Continuing.

Breakpoint 3, main () at char_array2.c:8
8
printf(str_a);
(gdb) i r eip
eip    0x80483d7    0x80483d7 <main+35>
(gdb) x/5i $eip
0x80483d7 <main+35>:   lea    eax,[ebp-40]
0x80483da <main+38>:   mov    DWORD PTR [esp],eax
0x80483dd <main+41>:   call   0x80482d4 <printf@plt>
0x80483e2 <main+46>:   leave
0x80483e3 <main+47>:   ret
(gdb)

这是程序的第二次运行,其中strcpy的地址可能与其他地址不同。
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/reader/booksrc/char_array2
Error in re-setting breakpoint 4:
Function "strcpy" not defined.

Breakpoint 1, main () at char_array2.c:7
7
strcpy(str_a, "Hello, world!\n");
(gdb) bt
#0 main () at char_array2.c:7
(gdb) cont
Continuing.

Breakpoint 4, 0xb7f076f4 in strcpy () from /lib/tls/i686/cmov/libc.so.6
(gdb) bt
#0 0xb7f076f4 in strcpy () from /lib/tls/i686/cmov/libc.so.6
#1 0x080483d7 in main () at char_array2.c:7
(gdb) cont
Continuing.

Breakpoint 3, main () at char_array2.c:8
8
printf(str_a);
(gdb) bt
#0 main () at char_array2.c:8
(gdb)

区别在哪里?我认为0xb7f076f4是strcpy的地址是错的吗?在第二次运行时,如果我是正确的,则所有内容都表明地址是0xb7f076f4。
还有,什么是?我在书的前面找不到这个的解释。如果有人能从上到下向我解释这一点,我会非常感激,因为我不知道任何专家在现实生活中可以帮助我。我发现解释很模糊,他解释变量和循环,就像他向一个5岁的孩子解释一样,但是留下了很多程序集代码让我们自己去解决,我在这方面不是很成功。
任何帮助都将不胜感激。

最佳答案

显然gdb会关闭ASLR以便调试进程使(会话到会话)调试更容易。
https://sourceware.org/gdb/current/onlinedocs/gdb/Starting.html

set disable-randomization
set disable-randomization on
    This option (enabled by default in GDB) will turn off the native
    randomization of the virtual address space of the started program.
    This option is useful for multiple debugging sessions to make the
    execution better reproducible and memory addresses reusable across
    debugging sessions.

set disable-randomization offgdb文件中设置.gdbinit并重试。每次运行二进制文件时,Libc现在应该加载到不同的地址。
运行watch -n 1 cat /proc/self/maps还可以看到二进制文件和库是如何在“随机”地址上映射的。

关于c - 试图从“剥削的艺术”中了解示例char_array2.c,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24103258/

10-11 22:50
查看更多