试图理解“来自”的示例char“u array2.c”;“剥削的艺术”;

试图理解“来自”的示例char“u array2.c”;“剥削的艺术”;,c,debugging,assembly,gdb,C,Debugging,Assembly,Gdb,好的,所以我真的在努力理解第二版《剥削的艺术》的例子。我正试图通过密切关注书中GDB的输出来了解这个示例到底发生了什么。我最大的问题是最后一部分,我把整件事都包括进去,这样每个人都能看到发生了什么。当然,我只有非常(非常)基本的汇编代码知识。我懂基本的C。 在最后一部分中,作者说,在strcpy()指向的地址中,程序的第二次运行与最后一次运行略有不同,我就是看不到 这个节目很简单 #include<stdio.h> #include<string.h> int main

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

这个节目很简单

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

int main() {

  char str_a[20];
  strcpy(str_a, "Hello, world!\n");
  printf(str_a);
  }
我对此没有问题,据我所知 调试器只能使用用户定义的函数执行此类操作。我还知道如何使用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)
区别在哪里?我认为0xb7f076f4是strcpy的地址是错误的吗?在第二次运行时,如果我正确,则所有内容都表明地址为0xb7f076f4

还有,是什么?我在这本书前面的任何地方都找不到对此的解释。如果有人能从上到下向我解释这一点,我会非常感激,因为我不知道现实生活中有任何专家可以帮助我。我发现解释很模糊,他解释变量和循环,就像他在向一个5岁的孩子解释一样,但把大部分汇编代码留给我们自己去弄清楚,我在这方面不是很成功。
任何帮助都将不胜感激。

正如@Voo在上面的评论中所说,这本书可能提到了ASLR(地址空间布局随机化),这是一种安全特性。它改变了每次执行时地址空间的使用方式,因此您不能依赖于总是在同一个位置查找内容


如果您在
gdb
中没有看到它,则表示您已关闭ASLR。在
gdb
中全局或局部。您可以使用
cat/proc/sys/kernel/randomize\u va\u space
检查前者,在
gdb
提示符下使用
show disable randomization
命令检查后者。

显然
gdb
会关闭已调试的进程,以使(会话到会话)调试更容易

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


运行
watch-n1 cat/proc/self/maps
也可以看到二进制文件和库如何映射到“随机”地址。

Yes 0xb7f076f4是strcpy中断点的地址。问题是什么?只有汇编和c的基本知识,当我想试图理解诸如堆栈溢出之类的低级漏洞时,恐怕是行不通的。@Voo不想显得粗鲁,但我确实在三个不同的部分解决了我的困惑:开始、中间和结束。我再问一次,作者说strcpy的地址从第一次运行到最后一次更改,我看不到它从0xb7f076f4更改,更改在哪里?我只看到strcpy的地址显示为0xb7f076f4。我不知道你答案的最后一部分是什么意思。没有理由假设一个库在重复运行时会加载到不同的基址。考虑到这是libc,它很可能是第一个加载的库,人们通常可以假设,只要ASLR不处于活动状态(虽然我有点惊讶它不是),它在重复运行时将位于相同的内存位置@Voo我没有假设任何东西,这不是我的代码,这来自一本书(如问题顶部所述)被称为“黑客攻击剥削的艺术”这是作者描述的一个问题。他在这一部分可能是错的,这就是为什么我求助于比我更有经验的人。嘿,Alex#u adl04,如果你想练习剥削,我建议你在和上查看战争游戏。另外,在战争游戏中IRC有很多非常好的支持。太好了!!我真的很感激你感谢这条建议。我知道要有人回答这个问题需要相当长的时间,因为我认为没有很多人使用GDB。再次感谢mofoe
(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)
(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)
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.