Ubuntu中使用-m32选项编译32位和64位C代码的区别

Ubuntu中使用-m32选项编译32位和64位C代码的区别,ubuntu,gcc,nasm,32bit-64bit,buffer-overflow,Ubuntu,Gcc,Nasm,32bit 64bit,Buffer Overflow,在这里,我尝试用一个非常简单的C代码实现缓冲区溢出: #include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { /* [1] */ char buf[256]; /* [2] */ strcpy(buf,argv[1]); /* [3] */ printf("Input:%s\n",buf); return 0; }`

在这里,我尝试用一个非常简单的C代码实现缓冲区溢出:

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

int main(int argc, char* argv[]) {
        /* [1] */ char buf[256];
        /* [2] */ strcpy(buf,argv[1]);
        /* [3] */ printf("Input:%s\n",buf);
        return 0;
}`
结果汇编代码为:

   0x0804843b <+0>:     lea    0x4(%esp),%ecx
   0x0804843f <+4>:     and    $0xfffffff0,%esp
   0x08048442 <+7>:     pushl  -0x4(%ecx)
   0x08048445 <+10>:    push   %ebp
   0x08048446 <+11>:    mov    %esp,%ebp
   0x08048448 <+13>:    push   %ecx
   0x08048449 <+14>:    sub    $0x104,%esp
   0x0804844f <+20>:    mov    %ecx,%eax
   0x08048451 <+22>:    mov    0x4(%eax),%eax
   0x08048454 <+25>:    add    $0x4,%eax
   0x08048457 <+28>:    mov    (%eax),%eax
   0x08048459 <+30>:    sub    $0x8,%esp
   0x0804845c <+33>:    push   %eax
   0x0804845d <+34>:    lea    -0x108(%ebp),%eax
   0x08048463 <+40>:    push   %eax
   0x08048464 <+41>:    call   0x8048310 <strcpy@plt>
   0x08048469 <+46>:    add    $0x10,%esp
   0x0804846c <+49>:    sub    $0x8,%esp
   0x0804846f <+52>:    lea    -0x108(%ebp),%eax
   0x08048475 <+58>:    push   %eax
   0x08048476 <+59>:    push   $0x8048510
   0x0804847b <+64>:    call   0x8048300 <printf@plt>
   0x08048480 <+69>:    add    $0x10,%esp
   0x08048483 <+72>:    mov    $0x0,%eax
   0x08048488 <+77>:    mov    -0x4(%ebp),%ecx
   0x0804848b <+80>:    leave  
   0x0804848c <+81>:    lea    -0x4(%ecx),%esp
   0x0804848f <+84>:    ret    
0x0804843b:lea0x4(%esp),%ecx
0x0804843f:和$0xfffffff0,%esp
0x08048442:PUSH-0x4(%ecx)
0x08048445:推送%ebp
0x08048446:mov%esp,%ebp
0x08048448:推送%ecx
0x08048449:sub$0x104,%esp
0x0804844f:mov%ecx,%eax
0x08048451:mov 0x4(%eax),%eax
0x08048454:添加$0x4,%eax
0x08048457:mov(%eax),%eax
0x08048459:子$0x8,%esp
0x0804845c:推送%eax
0x0804845d:lea-0x108(%ebp),%eax
0x08048463:推送%eax
0x08048464:呼叫0x8048310
0x08048469:添加$0x10,%esp
0x0804846c:子$0x8,%esp
0x0804846f:lea-0x108(%ebp),%eax
0x08048475:推送%eax
0x08048476:推送$0x8048510
0x0804847b:呼叫0x8048300
0x08048480:添加$0x10,%esp
0x08048483:mov$0x0,%eax
0x08048488:mov-0x4(%ebp),%ecx
0x0804848b:离开
0x0804848c:lea-0x4(%ecx),%esp
0x0804848f:ret
在操作系统为Ubuntu 12.04(x86)的教程中,它生成了一个不同的代码:

   0x08048414 <+0>:     push   %ebp                      //backup caller's ebp
   0x08048415 <+1>:     mov    %esp,%ebp                 //set callee's ebp to esp

   0x08048417 <+3>:     and    $0xfffffff0,%esp          //stack alignment
   0x0804841a <+6>:     sub    $0x110,%esp               //stack space for local variables
   0x08048420 <+12>:    mov    0xc(%ebp),%eax            //eax = argv
   0x08048423 <+15>:    add    $0x4,%eax                 //eax = &argv[1]
   0x08048426 <+18>:    mov    (%eax),%eax               //eax = argv[1]
   0x08048428 <+20>:    mov    %eax,0x4(%esp)            //strcpy arg2 
   0x0804842c <+24>:    lea    0x10(%esp),%eax           //eax = 'buf' 
   0x08048430 <+28>:    mov    %eax,(%esp)               //strcpy arg1
   0x08048433 <+31>:    call   0x8048330 <strcpy@plt>    //call strcpy
   0x08048438 <+36>:    mov    $0x8048530,%eax           //eax = format str "Input:%s\n"
   0x0804843d <+41>:    lea    0x10(%esp),%edx           //edx = buf
   0x08048441 <+45>:    mov    %edx,0x4(%esp)            //printf arg2
   0x08048445 <+49>:    mov    %eax,(%esp)               //printf arg1
   0x08048448 <+52>:    call   0x8048320 <printf@plt>    //call printf
   0x0804844d <+57>:    mov    $0x0,%eax                 //return value 0
   //Function Epilogue
   0x08048452 <+62>:    leave                            //mov ebp, esp; pop ebp; 
   0x08048453 <+63>:    ret                              //return
0x08048414:推送%ebp//备份调用方的ebp
0x08048415:mov%esp,%ebp//将被叫方的ebp设置为esp
0x08048417:和$0xfffffff0,%esp//堆栈对齐
0x0804841a:sub$0x110,%esp//局部变量的堆栈空间
0x08048420:mov 0xc(%ebp),%eax//eax=argv
0x08048423:添加$0x4,%eax//eax=&argv[1]
0x08048426:mov(%eax),%eax//eax=argv[1]
0x08048428:mov%eax,0x4(%esp)//strcpy arg2
0x0804842c:lea0x10(%esp),%eax//eax='buf'
0x08048430:mov%eax,(%esp)//strcpy arg1
0x08048433:调用0x8048330//调用strcpy
0x08048438:mov$0x8048530,%eax//eax=format str“输入:%s\n”
0x0804843d:lea0x10(%esp),%edx//edx=buf
0x08048441:mov%edx,0x4(%esp)//printf arg2
0x08048445:mov%eax,(%esp)//printf arg1
0x08048448:调用0x8048320//调用printf
0x080484D:mov$0x0,%eax//返回值0
//功能结语
0x08048452:离开//移动ebp,esp;pop-ebp;
0x08048453:返回//返回
为什么开场白和尾声有如此巨大的差异?任何文件和解释都将不胜感激

正如我所尝试的,溢出以前的asm代码并没有产生任何结果。这是因为Ubuntu新版本的一些安全特性吗?
对不起,问题太长了,我别无选择。提前感谢。

不同版本的编译器会生成不同的机器代码。这不应该太令人惊讶。看起来GCC4.9前后发生了很大的变化。在4.9及更高版本中,您得到的输出与您的输出类似。在4.9之前,您会得到与教程类似的输出。传递
-mprefered stack boundary=2
有助于修剪现代版本中的一些fat,但显然也会改变行为。我不知道你到底在问什么。这与Ubuntu的版本无关,而与编译器的版本有关。如果你愿意,你可以降级到以前的版本。谢谢你,这部分回答了我的问题!但是我仍然想知道为什么第一个代码必须使用ecx?如果要恢复esp,我们有ebp对吗?它可以使用它想要使用的任何寄存器!这正是优化器决定要做的。
   0x08048414 <+0>:     push   %ebp                      //backup caller's ebp
   0x08048415 <+1>:     mov    %esp,%ebp                 //set callee's ebp to esp

   0x08048417 <+3>:     and    $0xfffffff0,%esp          //stack alignment
   0x0804841a <+6>:     sub    $0x110,%esp               //stack space for local variables
   0x08048420 <+12>:    mov    0xc(%ebp),%eax            //eax = argv
   0x08048423 <+15>:    add    $0x4,%eax                 //eax = &argv[1]
   0x08048426 <+18>:    mov    (%eax),%eax               //eax = argv[1]
   0x08048428 <+20>:    mov    %eax,0x4(%esp)            //strcpy arg2 
   0x0804842c <+24>:    lea    0x10(%esp),%eax           //eax = 'buf' 
   0x08048430 <+28>:    mov    %eax,(%esp)               //strcpy arg1
   0x08048433 <+31>:    call   0x8048330 <strcpy@plt>    //call strcpy
   0x08048438 <+36>:    mov    $0x8048530,%eax           //eax = format str "Input:%s\n"
   0x0804843d <+41>:    lea    0x10(%esp),%edx           //edx = buf
   0x08048441 <+45>:    mov    %edx,0x4(%esp)            //printf arg2
   0x08048445 <+49>:    mov    %eax,(%esp)               //printf arg1
   0x08048448 <+52>:    call   0x8048320 <printf@plt>    //call printf
   0x0804844d <+57>:    mov    $0x0,%eax                 //return value 0
   //Function Epilogue
   0x08048452 <+62>:    leave                            //mov ebp, esp; pop ebp; 
   0x08048453 <+63>:    ret                              //return