0

My code is as follows:

#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;
}

I compiled the code and used ida pro to open the binary file(the gcc version is 5.4.0 and the OS is ubuntu 16.04, The compile command is "gcc -m32 -no-pie -fno-stack-protector stack_overflow.c -o stack_overflow "), I found the disassembled code shows that the address of the buffer s is ebp - 12h, I just wonder why it is not ebp - 10 ?

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

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

The disassembled code of myread() is as follows:

.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

The stack of myread() is as follows, It seems to have nothing to do with the stack protection mechanism

-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
wangyong
  • 11
  • 2

1 Answers1

3

Additional space is allocated for the stack protection variable - I highlighted this place in red (my code is compiled as x64 - this does not change the essence). If your buffer overflows, the security variable will be damaged and ___stack_chk_fail will be called.

Hex-rays decompiler hides this variable from the output:

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

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

1

Small hint: if you want to analyze the stack variables - double click any variable in the output of disassembler or decompiler - the stack window will open:

-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
re_things
  • 679
  • 1
  • 8
  • 29
  • I provide the disassembled code and the stack window of myread() function, It seems to have notiing to do with the stack protection because I used -fno-stack-protector to close stack protection. – wangyong May 25 '20 at 02:08
  • Ok, you have provided more information now. But I don't see your compiler and its version. What compiler options are used (I mean - all options)? What OS is used? I tried clang on macOS: with " -fno-stack-protector" I can't see extra bytes. Another thing - two “sub esp, ...” instructions one by one means that you are probably building your code without optimizations enabled. – re_things May 25 '20 at 18:37
  • the gcc version is 5.4.0 and the OS is ubuntu 16.04, The compile command is "gcc -m32 -no-pie -fno-stack-protector stack_overflow.c -o stack_overflow " – wangyong May 26 '20 at 02:48
  • I checked with GCC 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) - no extra bytes. So I guess it's due to the old GCC version. Probably your GCC allocates the stack for buffer and stack protection and after that checks for "-fno-stack-protector". Try "-o2" to enable optimization. – re_things May 27 '20 at 09:00