首页 > 解决方案 > 为什么buf的地址是0x12而不是10?

问题描述

我的代码如下:

#include <stdlib.h>
#include <unistd.h>
void myread () {
    char s[10];
    read(0, s, 100);
}

void getshell ()
{
     system("/bin/bash");
}

int main () 
{
    myread();
    return 0;
}

我编译代码并使用ida pro打开二进制文件(gcc版本为5.4.0,操作系统为ubuntu 16.04,编译命令为“gcc -m32 -no-pie -fno-stack-protector stack_overflow.c - o stack_overflow "),我发现反汇编代码显示缓冲区s的地址是ebp - 12h,我只是想知道为什么不是ebp - 10?

ssize_t myread()
{
  char buf; // [esp+6h] [ebp-12h]

  return read(0, &buf, 0x64u);
}

myread()的反汇编代码如下:

.text:0804843B
.text:0804843B ; Attributes: bp-based frame
.text:0804843B
.text:0804843B                 public myread
.text:0804843B myread          proc near               ; CODE XREF: main+11↓p
.text:0804843B
.text:0804843B buf             = byte ptr -12h
.text:0804843B
.text:0804843B ; __unwind {
.text:0804843B                 push    ebp
.text:0804843C                 mov     ebp, esp
.text:0804843E                 sub     esp, 18h
.text:08048441                 sub     esp, 4
.text:08048444                 push    64h             ; nbytes
.text:08048446                 lea     eax, [ebp+buf]
.text:08048449                 push    eax             ; buf
.text:0804844A                 push    0               ; fd
.text:0804844C                 call    _read
.text:08048451                 add     esp, 10h
.text:08048454                 nop
.text:08048455                 leave
.text:08048456                 retn
.text:08048456 ; } // starts at 804843B
.text:08048456 myread          endp

myread()的栈如下,好像和栈保护机制无关

-00000018 ; D/A/*   : change type (data/ascii/array)
-00000018 ; N       : rename
-00000018 ; U       : undefine
-00000018 ; Use data definition commands to create local variables and function arguments.
-00000018 ; Two special fields " r" and " s" represent return address and saved registers.
-00000018 ; Frame size: 18; Saved regs: 4; Purge: 0
-00000018 ;
-00000018
-00000018                 db ? ; undefined
-00000017                 db ? ; undefined
-00000016                 db ? ; undefined
-00000015                 db ? ; undefined
-00000014                 db ? ; undefined
-00000013                 db ? ; undefined
-00000012 buf             db ?
-00000011                 db ? ; undefined
-00000010                 db ? ; undefined
-0000000F                 db ? ; undefined
-0000000E                 db ? ; undefined
-0000000D                 db ? ; undefined
-0000000C                 db ? ; undefined
-0000000B                 db ? ; undefined
-0000000A                 db ? ; undefined
-00000009                 db ? ; undefined
-00000008                 db ? ; undefined
-00000007                 db ? ; undefined
-00000006                 db ? ; undefined
-00000005                 db ? ; undefined
-00000004                 db ? ; undefined
-00000003                 db ? ; undefined
-00000002                 db ? ; undefined
-00000001                 db ? ; undefined
+00000000  s              db 4 dup(?)
+00000004  r              db 4 dup(?)
+00000008
+00000008 ; end of stack variables

标签: assemblystack-overflowidactfpwntools

解决方案


为堆栈保护变量分配了额外的空间 - 我用红色突出显示了这个地方(我的代码编译为 x64 - 这不会改变本质)。如果你的缓冲区溢出,安全变量将被损坏,___stack_chk_fail 将被调用。

Hex-rays 反编译器在输出中隐藏了这个变量:

ssize_t myread()
{
  char v1[10]; // [rsp+Eh] [rbp-12h] BYREF

  return read(0, v1, 0x64uLL);
}

1

小提示:如果你想分析堆栈变量 - 双击反汇编器或反编译器输出中的任何变量 - 堆栈窗口将打开:

-0000000000000020 var_20          dq ?
-0000000000000018                 db ? ; undefined
-0000000000000017                 db ? ; undefined
-0000000000000016                 db ? ; undefined
-0000000000000015                 db ? ; undefined
-0000000000000014                 db ? ; undefined
-0000000000000013                 db ? ; undefined
-0000000000000012 s               db 10 dup(?)
-0000000000000008 stack_protection dq ?
+0000000000000000  s              db 8 dup(?)
+0000000000000008  r              db 8 dup(?)
+0000000000000010
+0000000000000010 ; end of stack variables

推荐阅读