用可执行文件实现堆栈粉碎

时间:2013-12-30 20:04:32

标签: c buffer-overflow stack-smash

当我只有可执行文件时,我尝试实现堆栈粉碎。 我使用objdump获取此源代码的汇编代码:

#include<stdio.h>
#include<string.h>
void func(char *str) { 
char buffer[24]; 
int *ret; 
strcpy(buffer,str); 
}
int main(int argc, char **argv) { 
int x; 
x = 0; 
func(argv[1]); 
x = 1; 
printf("%d\n”,x); 
} 

在运行时./a,out(value)....我需要在这里插入(值)我将NOP插入堆栈位置并且(value)的最后一部分是我的下一个地址指令。 在到达包含fun()的返回地址的位置之前,我有40个字节。

08048444 <func>:
8048444:    55                      push   %ebp
8048445:    89 e5                   mov    %esp,%ebp
8048447:    83 ec 48                sub    $0x48,%esp
804844a:    8b 45 08                mov    0x8(%ebp),%eax
804844d:    89 45 d4                mov    %eax,-0x2c(%ebp)
8048450:    65 a1 14 00 00 00       mov    %gs:0x14,%eax
8048456:    89 45 f4                mov    %eax,-0xc(%ebp)
8048459:    31 c0                   xor    %eax,%eax
804845b:    8b 45 d4                mov    -0x2c(%ebp),%eax
804845e:    89 44 24 04             mov    %eax,0x4(%esp)
8048462:    8d 45 dc                lea    -0x24(%ebp),%eax
8048465:    89 04 24                mov    %eax,(%esp)
8048468:    e8 eb fe ff ff          call   8048358 <strcpy@plt>
804846d:    8b 45 f4                mov    -0xc(%ebp),%eax
8048470:    65 33 05 14 00 00 00    xor    %gs:0x14,%eax
8048477:    74 05                   je     804847e <func+0x3a>
8048479:    e8 fa fe ff ff          call   8048378 <__stack_chk_fail@plt>
804847e:    c9                      leave  
804847f:    c3                      ret    

08048480 <main>:
8048480:    55                      push   %ebp
8048481:    89 e5                   mov    %esp,%ebp
8048483:    83 e4 f0                and    $0xfffffff0,%esp
8048486:    83 ec 20                sub    $0x20,%esp
8048489:    c7 44 24 1c 00 00 00    movl   $0x0,0x1c(%esp)
8048490:    00 
8048491:    8b 45 0c                mov    0xc(%ebp),%eax
8048494:    83 c0 04                add    $0x4,%eax
8048497:    8b 00                   mov    (%eax),%eax
8048499:    89 04 24                mov    %eax,(%esp)
804849c:    e8 a3 ff ff ff          call   8048444 <func>
80484a1:    c7 44 24 1c 01 00 00    movl   $0x1,0x1c(%esp)
80484a8:    00 
80484a9:    b8 90 85 04 08          mov    $0x8048590,%eax
80484ae:    8b 54 24 1c             mov    0x1c(%esp),%edx
80484b2:    89 54 24 04             mov    %edx,0x4(%esp)
80484b6:    89 04 24                mov    %eax,(%esp)
80484b9:    e8 aa fe ff ff          call   8048368 <printf@plt>
80484be:    b8 00 00 00 00          mov    $0x0,%eax
80484c3:    c9                      leave  
80484c4:    c3                      ret    
80484c5:    90                      nop
80484c6:    90                      nop

问题如果我插入00考虑为(31)ASCII。如何插入十六进制值。

......我希望阙清楚

objdump -w -Mintel:

08048444 <func>:
8048444:    55                      push   ebp
8048445:    89 e5                   mov    ebp,esp
8048447:    83 ec 48                sub    esp,0x48
804844a:    8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
804844d:    89 45 d4                mov    DWORD PTR [ebp-0x2c],eax
8048450:    65 a1 14 00 00 00       mov    eax,gs:0x14
8048456:    89 45 f4                mov    DWORD PTR [ebp-0xc],eax
8048459:    31 c0                   xor    eax,eax
804845b:    8b 45 d4                mov    eax,DWORD PTR [ebp-0x2c]
804845e:    89 44 24 04             mov    DWORD PTR [esp+0x4],eax
8048462:    8d 45 dc                lea    eax,[ebp-0x24]
8048465:    89 04 24                mov    DWORD PTR [esp],eax
8048468:    e8 eb fe ff ff          call   8048358 <strcpy@plt>
804846d:    8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
8048470:    65 33 05 14 00 00 00    xor    eax,DWORD PTR gs:0x14
8048477:    74 05                   je     804847e <func+0x3a>
8048479:    e8 fa fe ff ff          call   8048378 <__stack_chk_fail@plt>
804847e:    c9                      leave  
804847f:    c3                      ret    

08048480 <main>:
8048480:    55                      push   ebp
8048481:    89 e5                   mov    ebp,esp
8048483:    83 e4 f0                and    esp,0xfffffff0
8048486:    83 ec 20                sub    esp,0x20
8048489:    c7 44 24 1c 00 00 00 00     mov    DWORD PTR [esp+0x1c],0x0
8048491:    8b 45 0c                mov    eax,DWORD PTR [ebp+0xc]

8048494:    83 c0 04                add    eax,0x4
8048497:    8b 00                   mov    eax,DWORD PTR [eax]
8048499:    89 04 24                mov    DWORD PTR [esp],eax
804849c:    e8 a3 ff ff ff          call   8048444 <func>
80484a1:    c7 44 24 1c 01 00 00 00     mov    DWORD PTR [esp+0x1c],0x1
80484a9:    b8 90 85 04 08          mov    eax,0x8048590
80484ae:    8b 54 24 1c             mov    edx,DWORD PTR [esp+0x1c]
80484b2:    89 54 24 04             mov    DWORD PTR [esp+0x4],edx
80484b6:    89 04 24                mov    DWORD PTR [esp],eax
80484b9:    e8 aa fe ff ff          call   8048368 <printf@plt>
80484be:    b8 00 00 00 00          mov    eax,0x0`

2 个答案:

答案 0 :(得分:1)

您可以使用./a.out $(perl -e "print '\x97';")并将\ x97替换为您要使用的十六进制。

答案 1 :(得分:1)

如果是C,字符串字符的结尾为0x00(如果您愿意,则为'\0')。因此,如果你的字符串长度恰好为39个字符,那么第40个字符将为零 - 它将在正确的位置。除非使用strcpy以外的函数(例如,memcpy),否则无法在C字符串中复制多个零。但如果你依靠argv[1]作为你的零的来源,那么这是唯一的方法。你当然可以在处理它之前从字符串中减去一些东西 - 如果你愿意,你可以做

L = strlen(argv[1]);
for(int ii = 0; ii < L; ii++) if(argv[1][ii] == '0') argv[1][ii] = '\0';

这会将每个'0'变为'\0'。但是,你不能做一个简单的strcpy,你必须做memcpy

你必须希望你不会因为写入你不拥有的记忆而陷入错误......