格式化字符串漏洞利用 六扶檐、特殊案例

六、特殊案例

原文:Exploiting Format String Vulnerabilities

作者:scut@team-teso.net

譯者:飛龍

日期:2001.9.1

版本:v1.2

有一些可以利用的特定場(chǎng)景吧碾,不需要了解所有偏移烟阐,或者你可以使利用更加簡(jiǎn)單,直接拧晕,最重要的是:可靠隙姿。這里我列出了一些利用格式化字符串漏洞的常見(jiàn)方法。

6.1 替代目標(biāo)

受基于棧的緩沖區(qū)溢出的較長(zhǎng)歷史的影響厂捞,很多人認(rèn)為输玷,覆蓋棧上的返回地址是控制進(jìn)程的唯一方式。但是如果我們利用格式化字符串漏洞靡馁,我們不能準(zhǔn)確知道我們的緩沖區(qū)在哪里欲鹏,并且我們可以覆蓋另外一些東西。常見(jiàn)的基于棧的緩沖區(qū)溢出只能覆蓋返回地址臭墨,因?yàn)樗鼈円泊鎯?chǔ)在棧上赔嚎。但是使用格式化函數(shù),我們可以覆蓋內(nèi)存中的任意地址裙犹,讓我們能夠修改整個(gè)可寫(xiě)入的進(jìn)程空間尽狠。

因此,檢驗(yàn)其它部分或完全控制被利用程序的方式叶圃,就很有意思了袄膏。在特定場(chǎng)景下,這可以產(chǎn)生一種更簡(jiǎn)單的利用方式 -- 我們之前看到 -- 或者可以用于繞過(guò)特定的保護(hù)掺冠。

我會(huì)在這里簡(jiǎn)單討論一下替代的地址沉馆,并給出更深入的文章的引用。

6.1.1 GOT 覆蓋

任何 ELF 二進(jìn)制 [12] 的進(jìn)程空間都包含一個(gè)特殊區(qū)段德崭,叫做“全局偏移表”(GOT)斥黑。每個(gè)程序使用的庫(kù)函數(shù)都在這里擁有一個(gè)條目,它包含一個(gè)真實(shí)函數(shù)的地址眉厨。這樣是為了允許庫(kù)在進(jìn)程內(nèi)存中簡(jiǎn)單地重定向锌奴,而不是使用硬編碼的地址。在程序首次使用函數(shù)之前憾股,條目包含運(yùn)行時(shí)鏈接器(RTL)的地址鹿蜀。如果函數(shù)被程序調(diào)用,控制流就傳遞給了 RTL服球,并且函數(shù)的真實(shí)地址被解析并插入到 GOT茴恰。該函數(shù)的每個(gè)調(diào)用都將控制流直接傳遞給它自己,RTL 不再為該函數(shù)調(diào)用了斩熊。對(duì)于 GOT 利用的更加全面的概覽往枣,請(qǐng)參考 Lam3rZ 兄弟的不錯(cuò)的文章 [19]。

通過(guò)覆蓋程序隨后使用的函數(shù)的 GOT 條目,我們就可以利用格式化字符串漏洞分冈,獲取控制權(quán)圾另,并跳到任何可執(zhí)行的地址。不幸的是丈秩,這意味著任何基于棧的保護(hù)都會(huì)失效盯捌,它們檢查了返回地址。

我們從覆蓋 GOT 條目中獲得的巨大優(yōu)勢(shì)蘑秽,就是它獨(dú)立于環(huán)境變量(例如棧),以及動(dòng)態(tài)內(nèi)存分配(堆)箫攀。GOT 條目的地址在每個(gè)二進(jìn)制中是固定的肠牲,所以如果兩個(gè)系統(tǒng)運(yùn)行了相同的二進(jìn)制,GOT 條目始終是同一地址靴跛。

你可以通過(guò)執(zhí)行這個(gè)命令缀雳,看到 GOT 條目位于函數(shù)的哪里:

objdump --dynamic-reloc binary 

真實(shí)函數(shù)(或者 RTL 鏈接函數(shù))的地址直接就是打印出的地址。

另一個(gè)非常重要的因素梢睛,為什么使用 GOT 條目來(lái)獲取控制權(quán)肥印,而不是返回地址,是代碼的形式(在一些“安全”指紋守護(hù)程序中發(fā)現(xiàn)):

syslog (LOG_NOTICE, user); 
exit (EXIT_FAILURE); 

這里你不能通過(guò)覆蓋返回地址绝葡,來(lái)可靠地獲取控制權(quán)深碱。你可以嘗試覆蓋syslog自己的返回地址,但是更加可靠的方式就是覆蓋exit函數(shù)的 GOT 條目藏畅,它會(huì)將執(zhí)行流傳遞給你指定的地址敷硅,只要exit被調(diào)用。

譯者注:動(dòng)態(tài)鏈接時(shí)愉阎,程序會(huì)調(diào)用libc中的系統(tǒng)調(diào)用的封裝绞蹦。其它系統(tǒng)調(diào)用同理。

但是 GOT 技巧的最實(shí)用的優(yōu)點(diǎn)榜旦,就是它易于使用幽七,你只需要運(yùn)行objdump,就能得到要覆蓋的地址(retloc)溅呢。黑客們都懶得打字(除了粗心)澡屡。

6.1.2 DTORS

實(shí)用 GCC 編譯的二進(jìn)制包含一個(gè)特殊的析構(gòu)器表區(qū)段,叫做DTORS藕届。在真實(shí)的exit系統(tǒng)調(diào)用觸發(fā)之前挪蹭,在所有的常見(jiàn)清理操作完成之后,這里列出的析構(gòu)器會(huì)調(diào)用休偶。DTORS區(qū)段為以下格式:

DTORS: 0xffffffff 0x00000000 ...

其中第一項(xiàng)是一個(gè)計(jì)數(shù)器梁厉,它保存了下面函數(shù)指針的數(shù)量,如果列表為空則為負(fù)一(就像這里)。在所有 DTORS 區(qū)段的實(shí)現(xiàn)中词顾,這個(gè)字段都是被忽略的八秃。之后,在相對(duì)偏移+4的位置肉盹,就是清理函數(shù)的地址昔驱,以 NULL 地址終止。你可以僅僅將這個(gè) NULL 指針覆蓋為你的 shellcode 指針上忍,并且你的 shellcode 就會(huì)在程序退出時(shí)執(zhí)行骤肛。這一技巧更加復(fù)雜的介紹可以在 [17] 找到。

6.1.3 C 標(biāo)準(zhǔn)庫(kù)的鉤子

幾個(gè)月之前窍蓝,Splar Designer 介紹了一種新的技巧來(lái)利用malloc分配的內(nèi)存中基于堆的溢出腋颠。它提倡覆蓋 GNU C 庫(kù)以及其他庫(kù)中的鉤子。通常吓笙,這個(gè)鉤子有內(nèi)存調(diào)試和性能工具使用淑玫,在應(yīng)用使用malloc接口分配或釋放內(nèi)存時(shí)獲取通知。有一些鉤子面睛,但是最常見(jiàn)的是__malloc_hook絮蒿、__realloc_hook__free_hook。通常它們?cè)O(shè)為 NULL叁鉴,但是只要你使用指向你代碼的指針覆蓋了它土涝,你的代碼就會(huì)在mallocreallocfree執(zhí)行時(shí)調(diào)用亲茅。由于鉤子通常用作調(diào)試工具回铛,它們?cè)谡鎸?shí)函數(shù)執(zhí)行之前調(diào)用。

關(guān)于malloc覆蓋技巧的討論在 Solar Designer 關(guān)于 Netspace JPEG 解碼器漏洞的報(bào)告中提供克锣。

6.1.4 __atexit結(jié)構(gòu)

幾個(gè)月之前茵肃,Kalou 介紹了一種利用 Linux 下靜態(tài)鏈接二進(jìn)制的方式,它利用了叫做__atexit的通用處理器袭祟,只要你的程序調(diào)用了exit验残,它就會(huì)執(zhí)行。這允許程序建立很多處理器巾乳,它們會(huì)在退出時(shí)調(diào)用來(lái)釋放資源您没。__atexit結(jié)構(gòu)上的攻擊的詳細(xì)討論,可以在 Pascal Bouchareines 的文章 [16] 中找到胆绊。

6.1.5 函數(shù)指針

如果漏洞應(yīng)用使用了函數(shù)指針氨鹏,我們就有機(jī)會(huì)覆蓋它們。為了充分利用它們压状,你需要覆蓋它并且之后觸發(fā)它們仆抵。一些守護(hù)程序使用函數(shù)指針表來(lái)處理命令跟继,例如 QPOP。同時(shí)镣丑,函數(shù)指針也通常用于模擬類似__atexit的處理器舔糖,例如 SSHD。

6.1.6 jmpbuf

首先莺匠,jmpbuf覆蓋技巧用于堆緩沖區(qū)的利用金吗。使用格式化字符串,jmpbuf的行為就像函數(shù)指針趣竣,因?yàn)槲覀兛梢愿采w內(nèi)存的任意地方摇庙,不僅限于jmpbuf到我們的緩沖區(qū)的相對(duì)位置。深入討論可以在 Shok 關(guān)于堆溢出的文章中發(fā)現(xiàn)遥缕。

6.2 Return-to-libc

你可以使用常見(jiàn)的 Return-to-libc 技巧跟匆,同樣是由 Solar Designer 提出的 [14]。但是有時(shí)會(huì)有捷徑通砍,它會(huì)產(chǎn)生更簡(jiǎn)單的利用。

FILE * f; 
char foobuf[512];

snprintf (foobuf, sizeof (foobuf), user); 
foobuf[sizeof (foobuf) - 1] = ’\0’; 
f = fopen (foobuf, "r");

你可以將fopen的 GOT 地址替換為system的函數(shù)地址烤蜕。之后使用這樣的格式化字符串:

"cd /tmp;cp /bin/sh .;chmod 4777 sh;exit;" "addresses|stackpop|write"

其中addresses封孙、stackpopwrite是常見(jiàn)的格式化字符串利用?。它們用于架構(gòu)fopen GOT 條目覆蓋為system的地址讽营。fopen調(diào)用的時(shí)候虎忌,字符串轉(zhuǎn)遞給了system函數(shù)〕髋簦或者你可以使用常用的舊方法膜蠢,向上面描述的那樣。

6.3 多重打印

如果你可以在相同進(jìn)程中多次觸發(fā)格式化字符串漏洞(就像 wu-ftpd 那樣)莉兰,你就可以不僅僅覆蓋返回地址挑围。例如,你可以將整個(gè) shellcode 儲(chǔ)存在堆上來(lái)繞過(guò)任何不可執(zhí)行的棧保護(hù)糖荒。和其它這里解釋的技巧一起使用杉辙,你就可以繞過(guò)下面的保護(hù)措施(顯然是不完全的):

  • StackGuard
  • StackShield
  • Openwall 內(nèi)核補(bǔ)丁(由 Solar Designer)
  • libsafe

在 2000 年十月中旬捶朵,一群人發(fā)布了一系列 Linux 內(nèi)核補(bǔ)丁蜘矢,叫做 PaX [11],能夠高效實(shí)現(xiàn)可讀可寫(xiě)但不可執(zhí)行的頁(yè)面综看。由于它不燜好后在 x86 CPU 系列上這么做品腹,這個(gè)補(bǔ)丁用了一些技巧,它們被 Plex CPU 模擬器項(xiàng)目所發(fā)明红碑。在運(yùn)行這個(gè)補(bǔ)丁的系統(tǒng)中舞吭,幾乎不可能執(zhí)行引入該進(jìn)程的任意 shellcode。但是多數(shù)情況下,在進(jìn)程空間中已經(jīng)有了實(shí)用的代碼镣典。我們可以執(zhí)行這個(gè)代碼來(lái)做通常在 shellcode 中所做的事情兔毙。

使用通常的 Return-to-libc 技巧 [14],你可以繞過(guò)這個(gè)保護(hù)兄春。最簡(jiǎn)單的案例就是返回到system庫(kù)函數(shù)澎剥,使用格式化字符串作為參數(shù)。

通過(guò)稍微優(yōu)化字符串赶舆,你可以將需要了解的強(qiáng)制性偏移減為一個(gè):system函數(shù)地址哑姚。為了調(diào)用程序,你可以在格式化字符串的尾部使用這個(gè)序列:

";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;id > /tmp/owned;exit;"

任何指向;字符的地址芜茵,傳遞給system函數(shù)時(shí)叙量,都會(huì)執(zhí)行該命令,因?yàn)?code>;字符在 shell 的命令中是 NOP九串。

6.4 堆中的格式化字符串

到現(xiàn)在為止绞佩,我們假設(shè)格式化字符串始終在棧上。但是猪钮,有些情況下品山,它儲(chǔ)存在堆上。如果棧上有另一個(gè)我們可以影響的緩沖區(qū)烤低,我們就可以使用它來(lái)提供要寫(xiě)入的地址肘交,但是如果沒(méi)有這種緩沖區(qū),我們有幾種替代方案扑馁。

如果目標(biāo)緩沖區(qū)在棧上涯呻,我們首先可以打印它,之后使用那里的地址腻要,來(lái)使用%n參數(shù)寫(xiě)入:

void func (char *user_at_heap) { 
    char outbuf[512];
    snprintf (outbut, sizeof (outbuf), user_at_heap);
    outbuf[sizeof (outbuf) - 1] = ’\0’;
    return;
}

這里我們使用了一個(gè)格式化字符串复罐,它包含我們想要寫(xiě)入的地址,像通常一樣闯第。但是它特別的是市栗,我們不能從格式化字符串本身來(lái)訪問(wèn)這些地址,而是通過(guò)目標(biāo)緩沖區(qū)咳短。為此我們首先需要在棧上儲(chǔ)存地址填帽,通過(guò)簡(jiǎn)單打印它們。因此寫(xiě)入的序列需要在格式化字符串的地址后面咙好。

如果兩個(gè)緩沖區(qū)都不在棧上篡腌,問(wèn)題就來(lái)了:

void func (char *user_at_heap) { 
    char * outbuf = calloc (1, 512);
    snprintf (outbut, 512, user_at_heap); 
    outbuf[511] = ’\0’;
    return;
}

現(xiàn)在它取決于我們是否可能在棧上提供數(shù)據(jù)。例如勾效,一些 wu-ftpd 的利用使用密碼字段來(lái)儲(chǔ)存數(shù)據(jù)(shellcode嘹悼,并不是地址 -- 這些利用程序不能利用非匿名的賬戶)叛甫。

每個(gè)漏洞和利用都是不同的,在說(shuō)它不可利用之前杨伙,你應(yīng)該花費(fèi)幾個(gè)小時(shí)來(lái)學(xué)習(xí)漏洞其监,并且你有可能是錯(cuò)的,因?yàn)檫@里展示的不僅僅是格式化字符串漏洞的歷史限匣。(你好抖苦,OpenBSD 團(tuán)隊(duì)!)

6.5 特殊的考慮

除了利用自身米死,也有一些需要考慮的東西锌历。如果格式化字符串含有 shellcode,它不能包含\x25%)或者空字節(jié)峦筒。但是由于沒(méi)有重要的操作碼是0x25或者0x00究西,你在構(gòu)造 shellcode 時(shí)不會(huì)有什么麻煩。如果地址儲(chǔ)存在格式化字符串中物喷,是一樣的卤材。如果你想要寫(xiě)入的地址包含空字符,你可以將其替換為某個(gè)奇數(shù)地址的短整形寫(xiě)入峦失,它位于你想要寫(xiě)入的地址下方商膊。雖然它在所有架構(gòu)上都是不可能的。同樣宠进,你也可以使用兩個(gè)單獨(dú)的格式化字符串。第一個(gè)在內(nèi)存中藐翎,整個(gè)字符串的后面創(chuàng)建你打算寫(xiě)入的地址材蹬。第二個(gè)使用這個(gè)地址來(lái)寫(xiě)入它。

這可能變得有些復(fù)雜吝镣,但是可以可靠地利用堤器,并且有時(shí)值得花費(fèi)精力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末末贾,一起剝皮案震驚了整個(gè)濱河市闸溃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拱撵,老刑警劉巖辉川,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拴测,居然都是意外死亡乓旗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門集索,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)屿愚,“玉大人汇跨,你說(shuō)我怎么就攤上這事∽本啵” “怎么了穷遂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)娱据。 經(jīng)常有香客問(wèn)我蚪黑,道長(zhǎng),這世上最難降的妖魔是什么吸耿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任祠锣,我火速辦了婚禮,結(jié)果婚禮上咽安,老公的妹妹穿的比我還像新娘伴网。我一直安慰自己,他們只是感情好妆棒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布澡腾。 她就那樣靜靜地躺著,像睡著了一般糕珊。 火紅的嫁衣襯著肌膚如雪动分。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天红选,我揣著相機(jī)與錄音澜公,去河邊找鬼。 笑死喇肋,一個(gè)胖子當(dāng)著我的面吹牛坟乾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蝶防,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼甚侣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了间学?” 一聲冷哼從身側(cè)響起殷费,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎低葫,沒(méi)想到半個(gè)月后详羡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘿悬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年殷绍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鹊漠。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡主到,死狀恐怖茶行,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情登钥,我是刑警寧澤畔师,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站牧牢,受9級(jí)特大地震影響看锉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塔鳍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一伯铣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧轮纫,春花似錦腔寡、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至糯彬,卻和暖如春凭语,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撩扒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工似扔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搓谆。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓虫几,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親挽拔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容