官术网_书友最值得收藏!

3.8 atexit()和on_exit()函數(shù)

atexit()是C標(biāo)準(zhǔn)定義的一個(gè)通用工具函數(shù)。atexit()可以注冊無參函數(shù),并在程序正常結(jié)束后調(diào)用該函數(shù)。C要求實(shí)現(xiàn)支持至少32個(gè)函數(shù)的注冊。SunOS上的on_exit()函數(shù)具有類似的功能。libc4、libc5和glibc也提供了這樣的函數(shù)[Bouchareine 2005]。

在例3.11展示的程序中,第8行(main()中)使用atexit()注冊test()函數(shù)。該程序在退出前將全局變量glob賦值為字符串“Exiting.\n”(第9行)。test()函數(shù)在程序退出后得以執(zhí)行,并且打印出該字符串。

例3.11 使用atexit()的程序


01  char *glob;
02
03  void test(void) {
04    printf("%s", glob);
05  }
06
07  int main(void) {
08    atexit(test);
09    glob = "Exiting.\n";
10  }

atexit()通過向一個(gè)退出時(shí)將被調(diào)用的已有函數(shù)的數(shù)組中添加指定的函數(shù)完成工作。當(dāng)exit()被調(diào)用時(shí),數(shù)組中的每一個(gè)函數(shù)都以“后進(jìn)先出”(Last-in,F(xiàn)irst-out,LIFO)的順序被調(diào)用。由于atexit()和exit()都要訪問該數(shù)組,因此它被分配為一個(gè)全局性的符號(在BSD操作系統(tǒng)中是__atexit,在Linux操作系統(tǒng)中則是__exit_funcs)。

例3.12中使用gdb調(diào)試atexit程序的會(huì)話過程,展示了atexit數(shù)組的位置和結(jié)構(gòu)。在該調(diào)試會(huì)話中,在main()中調(diào)用atexit()之前設(shè)了一個(gè)斷點(diǎn),然后運(yùn)行程序。接下來執(zhí)行atexit(),注冊test()函數(shù)。在test()函數(shù)注冊后,顯示了在__exit_funcs位置處的內(nèi)存。每一個(gè)函數(shù)都保存在由4個(gè)雙字(doubleword)構(gòu)成的結(jié)構(gòu)中。每一個(gè)結(jié)構(gòu)的最后一個(gè)雙字保存著函數(shù)的實(shí)際地址。通過檢查這些地址的內(nèi)存得知,已經(jīng)注冊了3個(gè)函數(shù):

_dl_fini()、__libc_csu_fini()以及我們編寫的test()。可以通過對__exit_funcs結(jié)構(gòu)采用任意內(nèi)存寫或緩沖區(qū)溢出手段將程序的控制權(quán)轉(zhuǎn)移到任意的代碼。請注意,即使受攻擊的程序不顯式調(diào)用atexit()注冊_dl_fini()和__libc_csu_fini()函數(shù),它們也會(huì)存在。

例3.12 使用gdb的atexit程序的調(diào)試會(huì)話


(gdb) b main 
Breakpoint 1 at 0x80483f6: file atexit.c, line 6. 
(gdb) r 
Starting program: /home/rcs/book/dtors/atexit 
Breakpoint 1, main (argc=1, argv=0xbfffe744) at atexit.c:6 
6 atexit(test); 
(gdb) next 
7 glob = "Exiting.\n"; 
(gdb) x/12x __exit_funcs 
0x42130ee0 <init>:    0x00000000 0x00000003 0x00000004 0x4000c660 
0x42130ef0 <init+16>: 0x00000000 0x00000000 0x00000004 0x0804844c 
0x42130f00 <init+32>: 0x00000000 0x00000000 0x00000004 0x080483c8 
(gdb) x/4x 0x4000c660 
0x4000c660 <_dl_fini>: 0x57e58955 0x5ce85356 0x81000054 0x0091c1c3 
(gdb) x/3x 0x0804844c 
0x804844c <__libc_csu_fini>: 0x53e58955 0x9510b850 x102d0804 
(gdb) x/8x 0x080483c8 
0x80483c8 <test>: 0x83e58955 0xec8308ec 0x2035ff08 0x68080496 

主站蜘蛛池模板: 上蔡县| 瑞金市| 会同县| 沧州市| 宜兰市| 安多县| 罗平县| 尤溪县| 万荣县| 读书| 喜德县| 托克托县| 高雄县| 合肥市| 庆阳市| 晴隆县| 沈阳市| 乐山市| 长子县| 上栗县| 望谟县| 铜梁县| 荆州市| 南木林县| 长春市| 兴业县| 镇安县| 木里| 赞皇县| 浙江省| 青岛市| 冷水江市| 兴宁市| 江陵县| 恩施市| 浦北县| 闽侯县| 大方县| 会东县| 石城县| 唐山市|