- C和C++安全編碼(原書第2版)
- (美)Robert C.Seacord
- 721字
- 2020-10-30 17:56:50
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
- The Complete Rust Programming Reference Guide
- Advanced Splunk
- 零基礎(chǔ)學(xué)Visual C++第3版
- AngularJS Testing Cookbook
- JavaScript Unlocked
- Mastering Ubuntu Server
- Java設(shè)計(jì)模式及實(shí)踐
- Java Web開發(fā)技術(shù)教程
- 51單片機(jī)C語言開發(fā)教程
- 零基礎(chǔ)Java學(xué)習(xí)筆記
- Terraform:多云、混合云環(huán)境下實(shí)現(xiàn)基礎(chǔ)設(shè)施即代碼(第2版)
- OpenStack Networking Essentials
- 工業(yè)機(jī)器人離線編程
- 軟件測試(慕課版)
- jMonkeyEngine 3.0 Beginner’s Guide