在無(wú)法使用ESP定律時(shí)—EBP的妙用
發(fā)布日期:2022-01-03 16:26 | 文章來(lái)源:站長(zhǎng)之家
在寄存器里面有很多寄存器雖然他們的功能和使用沒(méi)有任何的區(qū)別,但是在長(zhǎng)期的編程和使用中,在程序員習(xí)慣中已經(jīng)默認(rèn)的給每個(gè)寄存器賦上了特殊的含義,比如:EAX一般用來(lái)做返回值,ECX用于記數(shù)等等。在win32的環(huán)境下EBP寄存器用與存放在進(jìn)入call以后的ESP的值,便于退出的時(shí)候回復(fù)ESP的值,達(dá)到堆棧平衡的目的。
應(yīng)用以前說(shuō)過(guò)的一段話:
原程序的OEP,通常是一開(kāi)始以 Push EBP 和MOV Ebp,Esp這兩句開(kāi)始的,不用我多說(shuō)大家也知道這兩句的意思是以EBP代替ESP,作為訪問(wèn)堆棧的指針。
為什么要這樣呢?為什么幾乎每個(gè)程序都是的開(kāi)頭能?因?yàn)槿绻覀儗?xiě)過(guò)C等函數(shù)的時(shí)候就應(yīng)該清楚,程序的開(kāi)始是以一個(gè)主函數(shù)main()為開(kāi)始的,而函數(shù)在訪問(wèn)的過(guò)程中最重要的事情就是要確保堆棧的平衡,而在win32的環(huán)境下保持平衡的辦法是這樣的:
1.讓EBP保存ESP的值;
2.在結(jié)束的時(shí)候調(diào)用
mov esp,ebp
pop ebp
retn
或者是
leave
retn
兩個(gè)形式是一個(gè)意思。
這樣做的好處是不用考慮ESP等于多少,PUSH了多少次,要POP多少次了,因?yàn)槲覀冎繣BP里面放的是開(kāi)始時(shí)候的ESP值。
2.推廣的ESP定律
在尋找OEP的時(shí)候,往往下斷HW ESP-4不成功,除了殼代碼將硬件斷點(diǎn)刪除了以外,很可能的情況就是因?yàn)闅ごa在運(yùn)行到OEP的時(shí)候他的ESP已經(jīng)不再是在EP時(shí)候的ESP(12FFC4)了,這樣我們下斷當(dāng)然是不成功的。
那么如何找到在殼到達(dá)OEP的時(shí)候的堆棧的值將是關(guān)鍵。
在這里我們應(yīng)用的關(guān)鍵是
Push EBP
MOV Ebp,Esp----》關(guān)鍵是這句
我來(lái)解釋一下,當(dāng)程序到達(dá)OEP的時(shí)候Push EBP這句對(duì)于ESP的值來(lái)說(shuō)就是ESP-4,然后是ESP-4賦給了EBP,而做為保存ESP值作用的EBP寄存器在這個(gè)“最上層的程序”中的值將始終不會(huì)改變。雖然他可能在進(jìn)入子call里面以后會(huì)暫時(shí)的改變(用于子程序的堆棧平衡)但是在退出了以后依*pop ebp這一句將還原原來(lái)的EBP的值。
以這句做為突破口,就是說(shuō)只要我們能斷在“最上層的程序”中,就能通過(guò)觀察EBP的值得到殼在JMP到OEP的時(shí)候的ESP的值了。
3.實(shí)戰(zhàn)
來(lái)看看pespin1.1的殼,在pespin1.0的殼中,我們使用HW 12FFC0能很容易的找到stolen code的地方,但是到pespin1.1的時(shí)候,我們就不行了。用HW 12FFC0根本斷不下來(lái)。
現(xiàn)在我們就使用這個(gè)推廣的ESP定律,載入程序后來(lái)到最后的一個(gè)異常
0040ED85 2BDB sub ebx,ebx//停在這里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58pop eax
0040ED8B 5Dpop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]
我用使用內(nèi)存斷點(diǎn)辦法來(lái)到FOEP處
004010D3 0000 add byte ptr ds:[eax],al
004010D5 0000 add byte ptr ds:[eax],al
004010D7 0000 add byte ptr ds:[eax],al
004010D9 0000 add byte ptr ds:[eax],al
004010DB 0000 add byte ptr ds:[eax],al
004010DD 0000 add byte ptr ds:[eax],al
004010DF 75 1Bjnz short pespin1_.004010FC//這里是FOEP
004010E1 56push esi
004010E2 FF15 99F44000 call dword ptr ds:[40F499]
004010E8 8BF0 mov esi,eax
004010EA 8A00 mov al,byte ptr ds:[eax]
好了,這里就是“最上層的程序”的地方了,看看寄存器
EAX 00141E22
ECX 0040C708 pespin1_.0040C708
EDX 0040C708 pespin1_.0040C708
EBX 0040C708 pespin1_.0040C708
ESP 0012F978
EBP 0012F9C0//注意這里
ESI 00141EE0
EDI 0040E5CD pespin1_.0040E5CD
EIP 004010DF pespin1_.004010DF
看到了吧,EBP=0012F9C0,我們來(lái)想象一下這個(gè)值是怎么得到的。
首先肯定是通過(guò)MOV ESP,EBP這一句,也就是說(shuō)ESP這時(shí)是0012F9C0的,然而上面還有一句PUSH EBP也就是說(shuō)ESP在到達(dá)OEP的時(shí)候應(yīng)該是0012F9C4的。好了得到這個(gè)結(jié)論我們就能很快的找到stolen code的所在了。
重來(lái)停在最后的異常
0040ED85 2BDB sub ebx,ebx//停在這里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58pop eax
0040ED8B 5Dpop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]
然后下斷HW 0012F9C0 ,F(xiàn)9運(yùn)行,來(lái)到這里
0040D8FB 61popad
0040D8FC 55push ebp
0040D8FD EB 01jmp short pespin1_.0040D900 //停在這里
0040D8FF 318B ECEB01AC xor dword ptr ds:[ebx AC01EBEC],ecx
0040D905 83EC 44 sub esp,44
0040D908 EB 01jmp short pespin1_.0040D90B
0040D90A 72 56jb short pespin1_.0040D962
0040D90C EB 01jmp short pespin1_.0040D90F
0040D90E 95xchg eax,ebp
0040D90F FF15 6CF34000 call dword ptr ds:[40F36C]
0040D915 EB 01jmp short pespin1_.0040D918
于是就很快的找到了stolen code的所在了。
4.總結(jié)
上面的這個(gè)辦法大概可以總結(jié)以下的步驟:
(1).直接或間接的斷在“最上層的程序”的地方。
(2).得到“最上層的程序”的EBP的值。
(3).利用程序初始化的兩個(gè)固定語(yǔ)句找到殼JMP到OEP的堆棧值。這個(gè)辦法有很大的局限性,因?yàn)橹挥蠽C和delphi程序使用這個(gè)初始化的開(kāi)頭。
但是找到“最上層的程序”的辦法除了內(nèi)存斷點(diǎn)還有很多辦法,例如對(duì)于VC來(lái)說(shuō)使用 bp ExitProcess也是一個(gè)很好的斷點(diǎn),可以直接得到EBP的數(shù)值。
5.后話
原來(lái)這個(gè)辦法有很強(qiáng)的前提條件,不是一個(gè)很具普遍性的辦法,我原來(lái)也不想單獨(dú)的提出來(lái),但是對(duì)于jney2兄弟的anti-ESP定律來(lái)說(shuō)這個(gè)辦法卻是一個(gè)解決之道。
當(dāng)然還有更多的辦法,在這里我只想說(shuō)很多事情有矛就有盾,沒(méi)有什么辦法是一定沒(méi)有漏洞的,只是希望這篇文章給大家闊寬思路,起到拋磚引玉的作用。
應(yīng)用以前說(shuō)過(guò)的一段話:
原程序的OEP,通常是一開(kāi)始以 Push EBP 和MOV Ebp,Esp這兩句開(kāi)始的,不用我多說(shuō)大家也知道這兩句的意思是以EBP代替ESP,作為訪問(wèn)堆棧的指針。
為什么要這樣呢?為什么幾乎每個(gè)程序都是的開(kāi)頭能?因?yàn)槿绻覀儗?xiě)過(guò)C等函數(shù)的時(shí)候就應(yīng)該清楚,程序的開(kāi)始是以一個(gè)主函數(shù)main()為開(kāi)始的,而函數(shù)在訪問(wèn)的過(guò)程中最重要的事情就是要確保堆棧的平衡,而在win32的環(huán)境下保持平衡的辦法是這樣的:
1.讓EBP保存ESP的值;
2.在結(jié)束的時(shí)候調(diào)用
mov esp,ebp
pop ebp
retn
或者是
leave
retn
兩個(gè)形式是一個(gè)意思。
這樣做的好處是不用考慮ESP等于多少,PUSH了多少次,要POP多少次了,因?yàn)槲覀冎繣BP里面放的是開(kāi)始時(shí)候的ESP值。
2.推廣的ESP定律
在尋找OEP的時(shí)候,往往下斷HW ESP-4不成功,除了殼代碼將硬件斷點(diǎn)刪除了以外,很可能的情況就是因?yàn)闅ごa在運(yùn)行到OEP的時(shí)候他的ESP已經(jīng)不再是在EP時(shí)候的ESP(12FFC4)了,這樣我們下斷當(dāng)然是不成功的。
那么如何找到在殼到達(dá)OEP的時(shí)候的堆棧的值將是關(guān)鍵。
在這里我們應(yīng)用的關(guān)鍵是
Push EBP
MOV Ebp,Esp----》關(guān)鍵是這句
我來(lái)解釋一下,當(dāng)程序到達(dá)OEP的時(shí)候Push EBP這句對(duì)于ESP的值來(lái)說(shuō)就是ESP-4,然后是ESP-4賦給了EBP,而做為保存ESP值作用的EBP寄存器在這個(gè)“最上層的程序”中的值將始終不會(huì)改變。雖然他可能在進(jìn)入子call里面以后會(huì)暫時(shí)的改變(用于子程序的堆棧平衡)但是在退出了以后依*pop ebp這一句將還原原來(lái)的EBP的值。
以這句做為突破口,就是說(shuō)只要我們能斷在“最上層的程序”中,就能通過(guò)觀察EBP的值得到殼在JMP到OEP的時(shí)候的ESP的值了。
3.實(shí)戰(zhàn)
來(lái)看看pespin1.1的殼,在pespin1.0的殼中,我們使用HW 12FFC0能很容易的找到stolen code的地方,但是到pespin1.1的時(shí)候,我們就不行了。用HW 12FFC0根本斷不下來(lái)。
現(xiàn)在我們就使用這個(gè)推廣的ESP定律,載入程序后來(lái)到最后的一個(gè)異常
0040ED85 2BDB sub ebx,ebx//停在這里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58pop eax
0040ED8B 5Dpop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]
我用使用內(nèi)存斷點(diǎn)辦法來(lái)到FOEP處
004010D3 0000 add byte ptr ds:[eax],al
004010D5 0000 add byte ptr ds:[eax],al
004010D7 0000 add byte ptr ds:[eax],al
004010D9 0000 add byte ptr ds:[eax],al
004010DB 0000 add byte ptr ds:[eax],al
004010DD 0000 add byte ptr ds:[eax],al
004010DF 75 1Bjnz short pespin1_.004010FC//這里是FOEP
004010E1 56push esi
004010E2 FF15 99F44000 call dword ptr ds:[40F499]
004010E8 8BF0 mov esi,eax
004010EA 8A00 mov al,byte ptr ds:[eax]
好了,這里就是“最上層的程序”的地方了,看看寄存器
EAX 00141E22
ECX 0040C708 pespin1_.0040C708
EDX 0040C708 pespin1_.0040C708
EBX 0040C708 pespin1_.0040C708
ESP 0012F978
EBP 0012F9C0//注意這里
ESI 00141EE0
EDI 0040E5CD pespin1_.0040E5CD
EIP 004010DF pespin1_.004010DF
看到了吧,EBP=0012F9C0,我們來(lái)想象一下這個(gè)值是怎么得到的。
首先肯定是通過(guò)MOV ESP,EBP這一句,也就是說(shuō)ESP這時(shí)是0012F9C0的,然而上面還有一句PUSH EBP也就是說(shuō)ESP在到達(dá)OEP的時(shí)候應(yīng)該是0012F9C4的。好了得到這個(gè)結(jié)論我們就能很快的找到stolen code的所在了。
重來(lái)停在最后的異常
0040ED85 2BDB sub ebx,ebx//停在這里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58pop eax
0040ED8B 5Dpop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]
然后下斷HW 0012F9C0 ,F(xiàn)9運(yùn)行,來(lái)到這里
0040D8FB 61popad
0040D8FC 55push ebp
0040D8FD EB 01jmp short pespin1_.0040D900 //停在這里
0040D8FF 318B ECEB01AC xor dword ptr ds:[ebx AC01EBEC],ecx
0040D905 83EC 44 sub esp,44
0040D908 EB 01jmp short pespin1_.0040D90B
0040D90A 72 56jb short pespin1_.0040D962
0040D90C EB 01jmp short pespin1_.0040D90F
0040D90E 95xchg eax,ebp
0040D90F FF15 6CF34000 call dword ptr ds:[40F36C]
0040D915 EB 01jmp short pespin1_.0040D918
于是就很快的找到了stolen code的所在了。
4.總結(jié)
上面的這個(gè)辦法大概可以總結(jié)以下的步驟:
(1).直接或間接的斷在“最上層的程序”的地方。
(2).得到“最上層的程序”的EBP的值。
(3).利用程序初始化的兩個(gè)固定語(yǔ)句找到殼JMP到OEP的堆棧值。這個(gè)辦法有很大的局限性,因?yàn)橹挥蠽C和delphi程序使用這個(gè)初始化的開(kāi)頭。
但是找到“最上層的程序”的辦法除了內(nèi)存斷點(diǎn)還有很多辦法,例如對(duì)于VC來(lái)說(shuō)使用 bp ExitProcess也是一個(gè)很好的斷點(diǎn),可以直接得到EBP的數(shù)值。
5.后話
原來(lái)這個(gè)辦法有很強(qiáng)的前提條件,不是一個(gè)很具普遍性的辦法,我原來(lái)也不想單獨(dú)的提出來(lái),但是對(duì)于jney2兄弟的anti-ESP定律來(lái)說(shuō)這個(gè)辦法卻是一個(gè)解決之道。
當(dāng)然還有更多的辦法,在這里我只想說(shuō)很多事情有矛就有盾,沒(méi)有什么辦法是一定沒(méi)有漏洞的,只是希望這篇文章給大家闊寬思路,起到拋磚引玉的作用。
版權(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)文章