Cauchy
Cauchy

Reputation: 1747

Generating simple shell binary code to be copied to the stack for stack overflow

I am trying to implement the buffer overflow attack, but I need to generate instruction code in binary so I can put it on the stack to be executed. My problem is that the instructions that I am getting now have jumps to different parts of a program which becomes hard to put on the stack. So I have this simple piece of code (not the code to be exploited) that I want to put on the stack to spawn a new shell.

#include <stdio.h>

int main( ) {
        char *buf[2];
        buf[0] = "/bin/bash";
        buf[1] = NULL;
        execve(buf[0], buf, NULL);
}

The code is being compiled with gcc with the following flags:

CFLAGS = -Wall -Wextra -g -fno-stack-protector -m32 -z execstack
LDFLAGS = -fno-stack-protector -m32 -z execstack

Finally using objdump -d -S, I get the following code (parts of it) in hex:

....
....
08048320 <execve@plt>:
 8048320:       ff 25 08 a0 04 08       jmp    *0x804a008
 8048326:       68 10 00 00 00          push   $0x10
 804832b:       e9 c0 ff ff ff          jmp    80482f0 <_init+0x3c>
....
....
int main( ) {
 80483e4:       55                      push   %ebp
 80483e5:       89 e5                   mov    %esp,%ebp
 80483e7:       83 e4 f0                and    $0xfffffff0,%esp
 80483ea:       83 ec 20                sub    $0x20,%esp
        char *buf[2];
        buf[0] = "/bin/bash";
 80483ed:       c7 44 24 18 f0 84 04    movl   $0x80484f0,0x18(%esp)
 80483f4:       08 
        buf[1] = NULL;
 80483f5:       c7 44 24 1c 00 00 00    movl   $0x0,0x1c(%esp)
 80483fc:       00 
        execve(buf[0], buf, NULL);
 80483fd:       8b 44 24 18             mov    0x18(%esp),%eax
 8048401:       c7 44 24 08 00 00 00    movl   $0x0,0x8(%esp)
 8048408:       00 
 8048409:       8d 54 24 18             lea    0x18(%esp),%edx
 804840d:       89 54 24 04             mov    %edx,0x4(%esp)
 8048411:       89 04 24                mov    %eax,(%esp)
 8048414:       e8 07 ff ff ff          call   8048320 <execve@plt>
}
 8048419:       c9                      leave  
 804841a:       c3                      ret    
 804841b:       90                      nop

As you can see this code is hard to copy onto the stack. execve jumps to a different part of the assembly code to be executed. Is there a way to nicely get a program which can be put compactly on the stack without too much space and branches being used?

Upvotes: 0

Views: 198

Answers (2)

Ishay Peled
Ishay Peled

Reputation: 2868

If you want a clean assembly code without coding it yourself, do the following:

  1. Move your code to a separate function
  2. Pass the -O0 compilation flag to gcc in order to prevent optimizations
  3. Compile just an object file - use gcc [input file] -o [output file]

Follow these steps, and use the assembly code generated from objdump.
Please keep in mind, you have an external dependency for execve:
8048414: e8 07 ff ff ff call 8048320 <execve@plt>
so you must either include its implementation explicitly and remove the call, or know in advance that the process you want to attack has this function in its address space, and modify the call address to match the process execve address.

Upvotes: 1

clearlight
clearlight

Reputation: 12625

Welcome to Stack Overflow (pun intended).

This is an unusual request. Are you trying to get hired by the NSA?

Compilers don't structure assembly code in a very human friendly form, obviously. And their idea of optimization might be for performance rather than for compactness. Therefore, you might consider hand-coding it in assembler, using the compiler output as a guideline to achieve the effect you're going for.

What you have there may not be the best representation of what the compiler can do to inform your investigation in any case. Put the code into a function other than main, so you can just get the minimal stack setup and argument handling necessary, and try compiling it with all the different optimization levels to see what it does.

You're probably getting some extra setup overhead for putting it in main(), because it's the main entry point to your program and has to interface with libc and the OS (just guessing), and may be setting things up for the program's operational context in general (which you could presume would have been done for whichever executable you were inserting the code into so it would be redundant).

Upvotes: 0

Related Questions