好吧,所以我真的在试着去理解这个“剥削的艺术”第二版的例子。我正试图通过密切关注书中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 off
或gdb
文件中设置.gdbinit
并重试。每次运行二进制文件时,Libc现在应该加载到不同的地址。运行
watch -n 1 cat /proc/self/maps
还可以看到二进制文件和库是如何在“随机”地址上映射的。关于c - 试图从“剥削的艺术”中了解示例char_array2.c,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24103258/