close

本文為看雪論壇優秀‍‍‍文章看雪論壇作者ID:瑞皇

新的一年想把0day漏洞安全這本書讀完,會一步一步踏踏實實的學完,和大家共享筆記。

環境我想用vs2019運行,老的編譯器很多人不用了,漸漸的會被淘汰。用新的編譯器可以鍛煉下編譯選項的功底。
我的筆記是配合書寫的,理論部分會少用筆墨,着重在實驗上。

1


基礎知識

這一部分書上講解的足夠了,如果暫時看不懂,多看看就好。功夫不負有心人,遲早學會的事情。

2


棧溢出原理與實踐

2.1 系統棧的工作原理

這一部分書上講解的足夠了,如果暫時看不懂,多看看就好。功夫不負有心人,遲早學會的事情。
2.2 修改鄰接變量運行環境:
VS2019 X86 Debug
運行設置:
屬性->c/c++->常規->sdl檢查關閉屬性->c/c++->代碼運行->基本運行時檢查->關閉【堆棧幀 (/RTCs)】然後運行代碼,輸入qqqqqqqq即,可完成簡單的溢出覆蓋。
#include <stdio.h>#include <stdlib.h>#include <string.h>#define PASSWORD "1234567"int verify_password(char* password){ int authenticated; char buffer[8];// add local buffto be overflowed authenticated = strcmp(password, PASSWORD); strcpy(buffer, password);//over flowed here! return authenticated;}void main(){ int valid_flag = 0; char password[1024]; while (1) { printf("please input password: "); scanf("%s", password); valid_flag = verify_password(password); if (valid_flag) { printf("incorrect password!\n\n"); } else { printf("Congratulation! You have passed the verification!\n"); break; } }}

實驗情況:SDL關閉和頭文件的增加為了讓程序代碼跑起來。
堆棧幀 (/RTCs)的關閉,則是為了讓程序不在運行時檢查程序。
如果不關閉堆棧幀 (/RTCs),原本buffer[8]會因為檢查多出8字節。然後程序報錯,我原本以為時字符對齊的問題,檢查後發現不是。是運行時檢查的問題。

關閉堆棧幀 (/RTCs)的匯編代碼:
int verify_password(char* password){004015F0 push ebp 004015F1 mov ebp,esp 004015F3 sub esp,50h 004015F6 mov eax,dword ptr [__security_cookie (0407004h)] 004015FB xor eax,ebp 004015FD mov dword ptr [ebp-4],eax 00401600 push ebx 00401601 push esi 00401602 push edi 00401603 mov ecx,offset _06E17EB3_Test@cpp (0409008h) 00401608 call @__CheckForDebuggerJustMyCode@4 (0401285h) int authenticated; char buffer[8];// add local buffto be overflowed authenticated = strcmp(password, PASSWORD);0040160D push offset string "1234567" (0405B30h) 00401612 mov eax,dword ptr [password] 00401615 push eax 00401616 call _strcmp (040103Ch) 0040161B add esp,8 0040161E mov dword ptr [authenticated],eax strcpy(buffer, password);//over flowed here!00401621 mov eax,dword ptr [password] 00401624 push eax 00401625 lea ecx,[buffer] 00401628 push ecx 00401629 call _strcpy (040119Ah) 0040162E add esp,8 return authenticated;00401631 mov eax,dword ptr [authenticated] }00401634 pop edi 00401635 pop esi 00401636 pop ebx 00401637 mov ecx,dword ptr [ebp-4] 0040163A xor ecx,ebp 0040163C call @__security_check_cookie@4 (040111Dh) 00401641 mov esp,ebp 00401643 pop ebp 00401644 ret

開啟堆棧幀 (/RTCs)的匯編代碼:
int verify_password(char* password){00E317A0 push ebp 00E317A1 mov ebp,esp 00E317A3 sub esp,0E0h 00E317A9 push ebx 00E317AA push esi 00E317AB push edi 00E317AC lea edi,[ebp-20h] 00E317AF mov ecx,8 00E317B4 mov eax,0CCCCCCCCh 00E317B9 rep stos dword ptr es:[edi] 00E317BB mov eax,dword ptr [__security_cookie (0E3A004h)] 00E317C0 xor eax,ebp 00E317C2 mov dword ptr [ebp-4],eax 00E317C5 mov ecx,offset _06E17EB3_Test@cpp (0E3C008h) 00E317CA call @__CheckForDebuggerJustMyCode@4 (0E3132Fh) int authenticated; char buffer[8];// add local buffto be overflowed authenticated = strcmp(password, PASSWORD);00E317CF push offset string "1234567" (0E37B30h) 00E317D4 mov eax,dword ptr [password] 00E317D7 push eax 00E317D8 call _strcmp (0E31046h) 00E317DD add esp,8 00E317E0 mov dword ptr [authenticated],eax strcpy(buffer, password);//over flowed here!00E317E3 mov eax,dword ptr [password] 00E317E6 push eax 00E317E7 lea ecx,[buffer] 00E317EA push ecx 00E317EB call _strcpy (0E31212h) 00E317F0 add esp,8 return authenticated;00E317F3 mov eax,dword ptr [authenticated] }00E317F6 push edx 00E317F7 mov ecx,ebp 00E317F9 push eax 00E317FA lea edx,ds:[0E31828h] 00E31800 call @_RTC_CheckStackVars@8 (0E311EFh) 00E31805 pop eax 00E31806 pop edx 00E31807 pop edi 00E31808 pop esi 00E31809 pop ebx 00E3180A mov ecx,dword ptr [ebp-4] 00E3180D xor ecx,ebp 00E3180F call @__security_check_cookie@4 (0E31154h) 00E31814 add esp,0E0h 00E3181A cmp ebp,esp 00E3181C call __RTC_CheckEsp (0E31253h) 00E31821 mov esp,ebp 00E31823 pop ebp 00E31824 ret 00E31825 nop dword ptr [eax] 00E31828 add dword ptr [eax],eax 00E3182A add byte ptr [eax],al 00E3182C xor byte ptr [eax],bl 00E3182E jecxz __$EncStackInitStart+84h (0E31830h) 00E31830 in al,0FFh 00E31832 ?? ??????}00E31833 dec dword ptr [eax] 00E31835 add byte ptr [eax],al 00E31837 add byte ptr [eax+ebx],bh 00E3183A jecxz __$EncStackInitStart+90h (0E3183Ch) 00E3183C bound esi,qword ptr [ebp+66h] 00E3183F jb 00001843

通過代碼的比較,我們可以發現,函數使用@_RTC_CheckStackVars@8進行檢測,跟進去發現該函數容納了兩個_RTC_CheckStackVars.

當檢測不是0CCCCCCCCh的時候,會報錯,並進入_RTC_StackFailure函數。
006E1DD4 mov ecx,dword ptr [ebx+4] 006E1DD7 mov eax,dword ptr [frame] 006E1DDA mov edx,dword ptr [ecx+edi] 006E1DDD cmp dword ptr [edx+eax-4],0CCCCCCCCh 006E1DE5 jne _RTC_CheckStackVars+39h (06E1DF9h) 006E1DE7 mov eax,dword ptr [ecx+edi+4] 006E1DEB add eax,edx 006E1DED mov edx,dword ptr [frame] 006E1DF0 cmp dword ptr [eax+edx],0CCCCCCCCh 006E1DF7 je _RTC_CheckStackVars+49h (06E1E09h) 006E1DF9 push dword ptr [ecx+edi+8] 006E1DFD mov eax,dword ptr [ebp+4] 006E1E00 push eax 006E1E01 call _RTC_StackFailure (06E1352h)
2.3 控制程序的執行流程運行環境:VS2019 X86 Debug運行設置:
屬性->c/c++->常規->sdl檢查關閉屬性->c/c++->代碼運行->基本運行時檢查->關閉【堆棧幀 (/RTCs)】
實驗情況:
修改上述配置後,發現無法正常運行,單步調試發現fopen斷點出現問題。搜索查詢後發現有些編譯器不支持rw+的格式。這裡我們將rw+修改為r+即可正確運行。r和r+的區別是r+擁有寫權限。我大膽猜測,rw+不支持的原因是功能設計上的重複。在這裡我們運行還會遇到一個問題:我們需要把棧保護天使GS關閉。
屬性->c/c++->代碼運行->安全檢查->關閉【禁用安全檢查 (/GS-)】這個時候代碼就會報書上期望我們出現的錯誤,返回值出現錯誤。理論方面書上說的已經很全面,這裡就簡單畫個圖。最終結果如下圖,符合書上預期:
2.4 向進程中植入代碼運行環境:VS2019 X86 Debug運行設置:
屬性->c/c++->常規->sdl檢查關閉屬性->c/c++->代碼運行->基本運行時檢查->關閉【堆棧幀 (/RTCs)】屬性->c/c++->代碼運行->安全檢查->關閉【禁用安全檢查 (/GS-)】
實驗情況:
創建一個文件,password.txt,構造shellcode。這裡按照書上就好,然後看下面的步驟。配置需要進行修改,因為要靜態獲取buffer地址,aslr隨機基址要關閉,因為要在數據區執行代碼,數據執行保護(DEP)也要關閉。屬性->鏈接器->高級->隨機基址->否屬性->鏈接器->高級->數據執行保護(DEP)->否

password.txt,有兩個地方需要修改,根據書中描述。一個是Messagebox的地址,在下圖中會講解如何尋找。一個是buffer的地址,下文中也會詳細介紹細節。我們在程序中添加messagebox,這樣我們的代碼就會調用User32.dll,我們使用dependency可以獲取該模塊函數地址。根據書中方法,計算正確值。
>>> hex(0x69E00000+0x83670)'0x69e83670'

但是可以看到,程序並不能正確運行,這問題常出在現在的windows操作系統里,優先基址常常不是實際加載地址,在PE格式中DLL會給出一個優先加載地址,當程序並未占用該地址時,優先按照該基址進行計算。占用的話,會重新申請空間。
問題發生了,如何解決,這裡使用Ollydbg查看模塊地址。

下面是Ollydbg的正確解決方案

步驟1:點擊E字母

步驟2:找到User32,此時使用該模塊地址計算,可以獲得正確地址,成功彈出messagebox

如果不想算,就按一下User32,快捷鍵ctrl+n,找到messageboxA一樣可以。
>>> hex(0x75cc0000+0x83670)'0x75d43670'


看雪ID:瑞皇

https://bbs.pediy.com/user-home-848111.htm

*本文由看雪論壇 瑞皇原創,轉載請註明來自看雪社區

#往期推薦

1.符號執行挖掘開源庫命令注入

2.CVE-2021-4034 pkexec本地提權漏洞復現與原理分析

3.Microsoft Windows提權漏洞CVE-2013-3660 x86、x64雙平台分析

4.Flutter應用逆向分析相關討論

5.XX彈幕投票助手分析

6.什麼是runC?




球分享

球點讚

球在看

點擊「閱讀原文」,了解更多!

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()