c - 试图从 "the art of exploitation"理解示例 char_array2.c

标签 c debugging assembly gdb

好的,所以我真的很想了解这个“剥削的艺术”第二版示例的内容。我试图通过密切关注书中 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 并包含以下内容:

(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 岁的 child 解释一样,但留下了很多汇编代码让我们自己弄清楚,我在这方面不是很成功。 任何帮助将不胜感激。

最佳答案

显然 gdb 关闭了 ASLR对于被调试的进程,使( session 到 session )调试更容易。

来自 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.

gdb.gdbinit 文件中设置 set disable-randomization off 并重试。每次运行二进制文件时,Libc 现在应该加载到不同的地址。

运行 watch -n 1 cat/proc/self/maps 也很高兴看到二进制文件和库是如何映射到“随机”地址的。

关于c - 试图从 "the art of exploitation"理解示例 char_array2.c,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24103258/

相关文章:

c - 如何在 C 中使用有符号/无符号创建负二进制数?

c# - 在模拟另一个域帐户时进行调试

Java:运行和调试之间的差异(JTextField 的原因)

linux - 在没有 printf 的 NASM 中打印 ARGC

c - 我在接受技术面试时被要求制作这样的结构..

c - 为什么 getline 在 C 函数中失败?

ios - 关于 iOS 汇编语言的说明

windows - assembly :将某些东西打印到屏幕(到命令行)的最佳方法是什么

c - 使用 mmap 将文件读取为字符串

c++ - 为什么我的链接列表在函数调用后被删除?