作者:k0shl
前言
這次在 HITB GSEC CTF 打醬油,也有了一次學習的機會,這次CTF出現了兩道 Windows pwn,我個人感覺質量非常高,因為題目出了本身無腦洞的漏洞之外,更多的讓選手們專註於對 Windows 系統的防護機制(seh)原理的研究,再配合漏洞來完成對機制的突破和利用,在我做完之後重新整理整個解題過程,略微有一些窒息的感覺,感覺整個利用鏈環環相扣,十分精彩,不得不膜一下Atum大佬,題目出的真的好!對於菜鳥來說,是一次非常好的鍛煉機會。
因此我認真總結了我們從拿到題目,多種嘗試,不斷改進 exp,到最後獲得 shell 的整個過程,而不僅僅是針對題目,希望能對同樣奮鬥在 win pwn 的小夥伴有一些幫助。
Babyshellcode Writeup with SEH and SafeSEH From Windows xp to Windows 10
拿到題目的時候,我們發現程序存在一個很明顯的棧溢出,而且題目給的一些條件非常好,在棧結構中存在 SEH 鏈,在常規的利用 SEH 鏈進行棧溢出從而控制 eip 的過程中,我們會使用棧溢出覆蓋 seh handler,這是一個 seh chain 中的一個指針,它指向了異常處理函數。
但是程序中開啟了 safeseh,也就是說,單純的通過覆蓋 seh handler 跳轉是不夠的,我們首先需要 bypass safeseh。
OK,我們來看題目。
在題目主函數中,首先在 scmgr.dll
中會初始化存放 shellcode 的堆,調用的是 VirtualAlloc 函數,並且會打印堆地址。
v0 = VirtualAlloc(0, 20 * SystemInfo.dwPageSize, 0x1000u, 0x40u);//注意這裡的flprotect是0x40
dword_1000338C = (int)v0;
if ( v0 )
{
sub_10001020("Global memory alloc at %p/n", (char)v0);//打印堆地址
result = dword_1000338C;
dword_10003388 = dword_1000338C;
}
這裡 VirtualAlloc 中有一個參數是 flprotect,值是 0x40,表示擁有 RWE 權限。
#define PAGE_EXECUTE_READWRITE 0x40
這個堆地址會用於存放 shellcode,在 CreateShellcode 函數中會將 shellcode 拷貝到 Memory 空間里。
v4 = 0;//v4在最開始拷貝的時候值是0
⋯⋯
v11 = (int)*(&Memory + v4);//將Memory地址指針交給v11
v13 = getchar();
v14 = 0;
if ( v12 )
{
do
{
*(_BYTE *)(v14++ + v15) = v13;//為Memory賦值
v13 = getchar();
}
while ( v14 != v12 );
v4 = v16;
}
執行結束之後可以看到 shellcode 已經被拷貝到目標空間中。