[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 安全技術 > 程序 > 正文
非安全編程演示之高級緩沖區溢出篇
本文出自:http://xfocus.org/ 作者:alert7(alert7@netguard.com.cn) (2002-08-08 06:02:00)
聲明:文中的大部分演示程序來自qera <gera@core-sdi.com>,感謝qera為
我們精心構造這些很能說明的演示程序。

有些程序可能有不只一種的利用方法,而文中又沒有提到的。如果您有
好的idea,記得mailto:alert7@xfocus.org,不正確或者不當之處還
請斧正。

★★ 一  高級緩沖區溢出篇

★ 1.1 演示一----盲目服從(blind obedience)

定義的buf太小,需要copy的數據不足以容納下。


/* abo1.c                                                   *
* specially crafted to feed your brain by gera@core-sdi.com */

/* Dumb example to let you get introduced...                */

int main(int argc,char **argv) {
    char buf[256];

    strcpy(buf,argv[1]);
}


這是個很好的例子程序,很能說明問題:該程序將拷貝argv[1]到buf中,使用了
strcpy函數,沒有做任何的邊界檢查。這就給了我們一個機會,傳一個超長的
argv[1]進去,覆蓋到堆棧中buf面的數據。你需要利用所有的工具來查看
buf面到底是什重要的東西,然才能構造出那些exploit需要的摸板。


★ 1.2 演示二----執行流程(execution flow)

在來看看這個程序

/* abo2.c                                                   *
* specially crafted to feed your brain by gera@core-sdi.com */

/* This is a tricky example to make you think               *
* and give you some help on the next one                   */

int main(int argv,char **argc) {
    char buf[256];

    strcpy(buf,argc[1]);
    exit(1);
}



正如我們看的那樣,在這個例子中,加了個exit(). 發現了不同了嗎?一般利用覆蓋
main的返回地址的方法已經行不通了。在這個例子中,windows下利用windows的異常
機制可以成功的溢出這個程序,而在unix下就沒有這種特性,暫時還不知道如何溢出
這個程序?或者就根本不能利用。歡迎討論,請mailto:alert7@xfocus.org :)


★ 1.3 演示三----覆蓋函數指針


/* abo3.c                                                    *
* specially crafted to feed your brain by gera@core-sdi.com */

/* This'll prepare you for The Next Step                     */

int main(int argv,char **argc) {
    extern system,puts; 
    void (*fn)(char*)=(void(*)(char*))&system;
    char buf[256];

    fn=(void(*)(char*))&puts;
    strcpy(buf,argc[1]);
    fn(argc[2]);
    exit(1);
}


可利用緩沖區溢出覆蓋fn函數指針,達到攻擊目的。


★ 1.4 演示四----覆蓋指針,導致任意地址的覆蓋

/* abo4.c                                                    *
* specially crafted to feed your brain by gera@core-sdi.com */

/* After this one, the next is just an Eureka! away          */

extern system,puts; 
void (*fn)(char*)=(void(*)(char*))&system;

int main(int argv,char **argc) {
    char *pbuf=malloc(strlen(argc[2])+1);
    char buf[256];

    fn=(void(*)(char*))&puts;
    strcpy(buf,argc[1]);
    strcpy(pbuf,argc[2]);
    fn(argc[3]);
    while(1);
}

第一個strcpy時候,可覆蓋到pbuf指針,可使pbuf指向fn地址,所以第二次
strcpy的時候就會覆蓋到fn指針,結果運行fn()函數的時候就可以執行任意
函數調用,比如system();



★ 1.5 演示五----ch-ch-ch-changes


/* abo5.c                                                    *
* specially crafted to feed your brain by gera@core-sdi.com */

/* You take the blue pill, you wake up in your bed,          *
*     and you believe what you want to believe              *
* You take the red pill,                                    *
*     and I'll show you how deep goes the rabbit hole       */

int main(int argv,char **argc) {
    char *pbuf=malloc(strlen(argc[2])+1);
    char buf[256];

    strcpy(buf,argc[1]);
    for (;*pbuf++=*(argc[2]++););
    exit(1);
}


第一個strcpy時候,可覆蓋到pbuf指針,可使pbuf指向exit的GOT或者.dotrs地址+4,
從而可以覆蓋到那些部分,獲得控制權。


★ 1.6 演示六

/* abo6.c                                                   *
/* specially crafted to feed your brain by gera@core-sdi.com */

/* wwwhat'u talkin' about? */

int main(int argv,char **argc) {
    char *pbuf=malloc(strlen(argc[2])+1);
    char buf[256];

    strcpy(buf,argc[1]);
    strcpy(pbuf,argc[2]);
    while(1);
}

第一個strcpy時候,可覆蓋到pbuf指針,可使pbuf指向第二個strcpy函數的返回地址,
從而可以覆蓋到該地址,第二個strcpy一返回就可以獲得控制權。


★ 1.7 演示七

/* abo7.c                                                   *
* specially crafted to feed your brain by gera@core-sdi.com */

/* sometimes you can,       *
* sometimes you don't      *
* that's what life's about */

char buf[256]={1};

int main(int argv,char **argc) {
    strcpy(buf,argc[1]);
}
[alert7@redhat]$ gcc -o test test.c -g
[alert7@redhat]$ gdb test -q
(gdb) l
1       char buf[256]={1};
2
3       int main(int argv,char **argc) {
4               strcpy(buf,argc[1]);
5       }
(gdb) b 4
Breakpoint 1 at 0x80483cb: file test.c, line 4.
(gdb) r 999
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/alert7/test 999

Breakpoint 1, main (argv=2, argc=0xbffffbc4) at test.c:4
4               strcpy(buf,argc[1]);
(gdb) p &buf
$1 = (char (*)[256]) 0x8049460

buf的地址為0x8049460,也就是說如果0x8049460地址有什重要的話我們
可以得到控制權的數據的話,那我們就可以溢出成功。
在這裡:
[alert7@redhat]$ objdump -s -j .dtors test

test:     file format elf32-i386

Contents of section .dtors:
804956c ffffffff 00000000                    ........
我們可以覆蓋.dtors,達到獲得控制權的目的。


★ 1.8 演示八

Don't stay static


/* abo8.c                                                    *
* specially crafted to feed your brain by gera@core-sdi.com */

/* spot the difference */



char buf[256];

int main(int argv,char **argc) {
    strcpy(buf,argc[1]);
}


[alert7@redhat]$ gcc -o  test test.c -g
[alert7@redhat]$ objdump --dynamic-reloc test

test:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
0804947c R_386_GLOB_DAT    __gmon_start__
0804946c R_386_JUMP_SLOT   __register_frame_info
08049470 R_386_JUMP_SLOT   __deregister_frame_info
08049474 R_386_JUMP_SLOT   __libc_start_main
08049478 R_386_JUMP_SLOT   strcpy
[alert7@redhat]$ gdb test -q
(gdb) l
1
2       char buf[256];
3
4       int main(int argv,char **argc) {
5               strcpy(buf,argc[1]);
6       }
7
(gdb)  b 5
Breakpoint 1 at 0x80483cb: file test.c, line 5.
(gdb) r 11
Starting program: /home/alert7/test 11

Breakpoint 1, main (argv=2, argc=0xbffffbc4) at test.c:5
5               strcpy(buf,argc[1]);
(gdb) p & buf
$1 = (char (*)[256]) 0x8049540
(gdb) q
The program is running.  Exit anyway? (y or n) y
[alert7@redhat]$ objdump -s -j .dtors test

test:     file format elf32-i386

Contents of section .dtors:
8049458 ffffffff 00000000                    ........
[alert7@redhat]$ gcc -o  test test.c -g -static
[alert7@redhat]$ gdb test -q
(gdb) l
1
2       char buf[256];
3
4       int main(int argv,char **argc) {
5               strcpy(buf,argc[1]);
6       }
7
(gdb) b 5
Breakpoint 1 at 0x804819b: file test.c, line 5.
(gdb) r 11
Starting program: /home/alert7/test 11

Breakpoint 1, main (argv=2, argc=0xbffffc14) at test.c:5
5               strcpy(buf,argc[1]);
(gdb) p &buf
$1 = (char (*)[256]) 0x807bb60
(gdb) p __exit_funcs
$2 = (struct exit_function_list *) 0x807b160
[alert7@redhat62 alert7]$ objdump -s -j .dtors test

test:     file format elf32-i386

Contents of section .dtors:
807b100 ffffffff 00000000                    ........
buf的地址都比其他的地址要大,所以覆蓋不到他們。
這個例子還不知道如何得到控制權呢?用超長字符串覆蓋main函數的
返回地址是不現實的,並且在還沒有覆蓋到main函數返回地址之前就會
Segmentation fault,原因是訪問了一個沒有映射的地址(地址
映射是不連續的) 。
這個演示程序讓我鬱悶了好久,在我的linux上還真的無法成功溢出這個
程序,還是qera又一次專門為windows設計的!?(如果您有好的idea,
記得mailto:alert7@xfocus.org)。在windows下成功溢出這個演示程
序是沒有問題的。


★ 1.9 演示九----兩次free技術

/* abo9.c                                                  *
* specially crafted to feed your brain by gera@core-sdi.com */

/* free(your mind) */

/* I'm not sure in what operating systems it can be done */

int main(int argv,char **argc) {
    char *pbuf1=(char*)malloc(256);
    char *pbuf2=(char*)malloc(256);

    gets(pbuf1);
    free(pbuf2);
    free(pbuf1);
}
請參考waring3的<<一種新的Heap區溢出技術分析>>
那片文章上已經講的很明白了,不想多說,不想做重復的勞動:)

★ 1.10 演示十----一次free技術

/* abo10.c                                                  *
* specially crafted to feed your brain by gera@core-sdi.com */

/* Deja-vu*/

char buf[256];

int main(int argv,char **argc) {
    char *pbuf=(char*)malloc(256);

    gets(buf);
    free(pbuf);
}
[alert7@redhat]$ gcc -o test test.c -g
/tmp/ccO6gW96.o: In function `main':
/home/alert7/test.c:6: the `gets' function is dangerous and should not be used.
[alert7@redhat]$ gdb test -q
(gdb) l
1       char buf[256];
2
3       int main(int argv,char **argc) {
4               char *pbuf=(char*)malloc(256);
5
6               gets(buf);
7               free(pbuf);
8       }
(gdb) b 6
Breakpoint 1 at 0x8048440: file test.c, line 6.
(gdb) r
Starting program: /home/alert7/test

Breakpoint 1, main (argv=1, argc=0xbffffbc4) at test.c:6
6               gets(buf);
(gdb) p &buf
$1 = (char (*)[256]) 0x80495c0
(gdb) p pbuf
$2 = 0x80496c8 ""
可覆蓋到pbuf的chunk塊,利用一次free技術也可覆蓋到.dotrs,main的返回地址等等。
演示九和演示十都是由緩沖區溢出而導致的內存管理函數處理出錯,從而利用內存管理
函數中的寫操作,覆蓋到自己想要覆蓋的任何地址空間。 (http://www.fanqiang.com)
    進入【UNIX論壇

相關文章
如何編寫自己的緩沖區溢出利用程序? (2002-07-26 13:31:26)
C源碼:Linux的nfsd存在溢出漏洞允許入侵者遠程獲取root (2002-07-08 06:02:00)
部分防止Solaris溢出的方法 (2001-09-12 15:00:01)
緩沖區溢出:十年來攻擊和防衛的弱點 (2001-08-01 15:00:00)
不能登錄到CDE,出現錯誤:file table overflow(文件表溢出) (2001-05-30 07:00:00)
 

★  樊強制作 歡迎分享  ★