Search code examples
buffer-overflowshellcodekali-linux

linker flag `execstack` not applied at `.rodata`, `.data`, or `.bss` section.... What is Wrong?


Currently I am studying system exploit, and find some interesting system exploit called buffer overflow using shellcode. I wrote shellcode terminating current process using exit(0) systemcall. Below, there is my code.

#include <stdio.h>

char shell[100] =
       "\xb0\x01"      // mov al, 1
       "\x31\xdb"      // xor ebx, ebx
       "\xcd\x80"    ; // int 0x80

int main() {
    ((void(*)())shell)();
    printf("this not should be printed\n");
    return 0;
}

After writing code above, I compiled with gcc using -m32 flag for compiling x86 architecture(My CPU Architecture is AMD x86_64), and using -fno-stack-protector, -z execstack to make .data, .rodata, and stack section executable. So the command for compiling is like this.

gcc -m32 -fno-stack-protector -z execstack -o shellcode shellcode.c.

And after that, I execute the test program (shellcode.c), but, result says there is segmentation fault (Even having compiled with memory protection!!). Here is the result:

zsh: segmentation fault ./shellcode

So, I double-checked shellcode binary using checksec, readelf. First readelf says .rodata, .data, .bss section is unexecutable. Like this.

Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x00160 0x00160 R   0x4
  INTERP         0x000194 0x08048194 0x08048194 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x002e8 0x002e8 R   0x1000
  LOAD           0x001000 0x08049000 0x08049000 0x0022c 0x0022c R E 0x1000
  LOAD           0x002000 0x0804a000 0x0804a000 0x00190 0x00190 R   0x1000
  LOAD           0x002f0c 0x0804bf0c 0x0804bf0c 0x00198 0x0019c RW  0x1000
  DYNAMIC        0x002f14 0x0804bf14 0x0804bf14 0x000e8 0x000e8 RW  0x4
  NOTE           0x0001a8 0x080481a8 0x080481a8 0x00044 0x00044 R   0x4
  GNU_EH_FRAME   0x002024 0x0804a024 0x0804a024 0x00044 0x00044 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
  GNU_RELRO      0x002f0c 0x0804bf0c 0x0804bf0c 0x000f4 0x000f4 R   0x1

As you can see above, stack became executable. But, not .data, .rodata, and .bss section. Below there is extra information about memory protection of shellcode (using checksec).

ELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable     FILE
Partial RELRO   No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   65) Symbols       No    0               0               ./shellcode

As you can see, there is no stack-canary, NX Bit set... But, shellcode program continues to segmentation fault.... What is Wrong with this...??/??

P.S I' am using kali linux 2021.02


Solution

  • The title says "execstack not applied at .rodata, .data, or .bss sections".

    That's correct: execstack is a linker flag that "Marks the object as requiring executable stack."

    It does nothing about .data, .bss or .rodata.

    When I run your program (on x86_64), I get:

    (gdb) r
    Starting program: /tmp/foo 
    Missing separate debuginfos, use: zypper install glibc-debuginfo-2.31-7.30.x86_64
    
    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000601040 in shell ()
    (gdb) bt
    #0  0x0000000000601040 in shell ()
    #1  0x0000000000400517 in main () at foo.c:9
    (gdb) disassemble /s 0x0000000000601040
    Dump of assembler code for function shell:
    => 0x0000000000601040 <+0>: mov    $0x1,%al
       0x0000000000601042 <+2>: xor    %ebx,%ebx
       0x0000000000601044 <+4>: int    $0x80
       0x0000000000601046 <+6>: add    %al,(%rax)
       0x0000000000601048 <+8>: add    %al,(%rax)
    ...
    

    However when I change the code to this:

    include <stdio.h>
      
    int main() {
            char shell[100] =
                   "\xb0\x01"      // mov al, 1
                   "\x31\xdb"      // xor ebx, ebx
                   "\xcd\x80"    ; // int 0x80
    
        ((void(*)())shell)();
        printf("this not should be printed\n");
        return 0;
    }
    

    Execution without -z execstack also gets SIGSEGV, but with the option it just exits (with zero):

    (gdb) r
    Starting program: /tmp/foo 
    Missing separate debuginfos, use: zypper install glibc-debuginfo-2.31-7.30.x86_64
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00007fffffffdd50 in ?? ()
    (gdb) bt
    #0  0x00007fffffffdd50 in ?? ()
    #1  0x000000000040054e in main () at foo.c:9
    (gdb) disassemble /s 0x00007fffffffdd50
    No function contains specified address.
    ### "make CFLAGS="-Wall -g -zexecstack"  foo"
    Starting program: /tmp/foo 
    Missing separate debuginfos, use: zypper install glibc-debuginfo-2.31-7.30.x86_64
    [Inferior 1 (process 24663) exited normally]
    (gdb) q