溢出原理講解時間:2010-11-25 00:36來源:網(wǎng)絡 作者:小甲魚 點擊:123次備注:此處說講的溢出主要針對堆棧溢出的攻擊實現(xiàn)。 一:基礎知識 計算機內(nèi)存運行分配的區(qū)域分為3個 程序段區(qū)域:不允許寫的 數(shù)據(jù)段區(qū)域:靜態(tài)全局變量是位于數(shù)據(jù)段并且在程序開始運行的時候被加載 堆棧區(qū)域:放置程序的動態(tài)溫馨提示:為了方便大家收藏和打印或者用手機觀看,小甲魚一律將比較有價值的文章整理成TXT格式供下載,地址在文章末尾!
-------------------------------------------------------------------------------- 備注:此處說講的溢出主要針對堆棧溢出的攻擊實現(xiàn)。
-------------------------------------------------------------------------------- 贊助商廣告:
- -------------------------------------------------------------------------------- 一:基礎知識 計算機內(nèi)存運行分配的區(qū)域分為3個 程序段區(qū)域:不允許寫的 數(shù)據(jù)段區(qū)域:靜態(tài)全局變量是位于數(shù)據(jù)段并且在程序開始運行的時候被加載 堆棧區(qū)域:放置程序的動態(tài)的用于計算的局部和臨時變量則分配在堆棧里面和在過程調(diào)用中壓入的返回地址數(shù)據(jù)。堆棧是一個先入后出的隊列。一般計算機系統(tǒng)堆棧的方向與內(nèi)存的方向相反。壓棧的操作push=ESP-4,出棧的操作是pop=ESP+4. 在一次函數(shù)調(diào)用中,堆棧中將被依次壓入:參數(shù),返回地址,EBP。如果函數(shù)有局部變量,接下來,就在堆棧中開辟相應的空間以構造變量。函數(shù)執(zhí)行結束,這些局部變量的內(nèi)容將被丟失。但是不被清除。在函數(shù)返回的時候,彈出EBP,恢復堆棧到函數(shù)調(diào)用的地址,彈出返回地址到EIP以繼續(xù)執(zhí)行程序。 在C語言程序中,參數(shù)的壓棧順序是反向的。比如func(a,b,c)。在參數(shù)入棧的時候,是:先壓c,再壓b,最后a.在取參數(shù)的時候, 指令執(zhí)行的圖例: 指令區(qū)域 執(zhí)行程序區(qū) 0 1 2 3 0 4 8 調(diào)用100處的函數(shù),參數(shù)1(3位),2(10位) C 10 0 1 2 3 100 執(zhí)行處理 104 108 10C 110 返回調(diào)用 堆棧區(qū)域 0 1 2 3 如果EBP分配的空間不夠操作就是產(chǎn)生溢出的地方 200 保存以前的EBP4位(數(shù)據(jù)段的指針,用于可以使用局部動態(tài) 變量)現(xiàn)在的EBP等于當前的ESP-動態(tài)數(shù)據(jù)的大小值 , ESP=200 204 0C 00 00 00 此處是程序的返回地址 208 參數(shù)1,填充1位 20C 參數(shù)2填充2位 210 講解例子WIN下的程序DEMO,演示參數(shù)導致的返回地址的變化 講清主要4位的填充問題 另外溢出還會導致數(shù)據(jù)段的改變 3:如何利用堆棧溢出 原理可以概括為:由于字符串處理函數(shù)(gets,strcpy等等)沒有對數(shù)組越界加以監(jiān)視和限制,我們利用字符數(shù)組寫越界,覆蓋堆棧中的老元素的值,就可以修改返回地址。 在DEMO的例子中,這導致CPU去訪問一個不存在的指令,結果出錯。事實上,我們已經(jīng)完全的控制了這個程序下一步的動作。如果我們用一個實際存在指令地址來覆蓋這個返回地址,CPU就會轉而執(zhí)行我們的指令。 那么有什么用呢,就算使得我們的程序可以跳轉執(zhí)行一些代碼,如何用他來突破系統(tǒng)限制來獲得權限呢? 二:系統(tǒng)權限知識 UNIX系統(tǒng)在運行的時候的權限檢查主要是根據(jù)UID,GID,SID 三個標來檢查的,主要根據(jù)SID來檢查權限 SU系統(tǒng)調(diào)用就是SID變成SU的對象 S粘貼位使得運行程序的人具有該程序擁有者一樣的權限 中斷ROOT的S粘貼位的程序就可以獲得超級用戶的權限,SID位置沒被調(diào)用返回修改回來。 VI的S粘貼位可以中斷的例子 在UINX系統(tǒng)中,我們的指令可以執(zhí)行一個shell,這個shell將獲得和被我們堆棧溢出的程序相同的權限。如果這個程序是setuid的,那么我們就可以獲得root shell。 三:溢出突破權限的實現(xiàn) 首先要編寫SHELLCODE的2進制代碼作為溢出的參數(shù)進行傳入: shellcode的C程序 注意:execve函數(shù)將執(zhí)行一個程序。他需要程序的名字地址作為第一個參數(shù)。一個內(nèi)容為該程序的argv(argv[n-1]=0)的指針數(shù)組作為第二個參數(shù),以及(char*) 0作為第三個參數(shù)。 我們來看以看execve的匯編代碼: 0x804ce7c <__execve>: push %ebp ‘保存以前的數(shù)據(jù)段地址 0x804ce7d <__execve+1>: mov %esp,%ebp ‘使得當前數(shù)據(jù)段指向堆棧 0x804ce7f <__execve+3>: push %edi 0x804ce80 <__execve+4>: push %ebx ‘保存 0x804ce81 <__execve+5>: mov 0x8(%ebp),%edi ‘ebp+8是第一個參數(shù)"/bin/sh\0" 0x804ce84 <__execve+8>: mov $0x0,%eax ‘清0 0x804ce89 <__execve+13>: test %eax,%eax 0x804ce8b <__execve+15>: je 0x804ce92 <__execve+22> 0x804ce8d <__execve+17>: call 0x0 0x804ce92 <__execve+22>: mov 0xc(%ebp),%ecx ‘設置NAME[0]參數(shù),4字節(jié)對齊 0x804ce95 <__execve+25>: mov 0x10(%ebp),%edx,設置NAME[1]參數(shù),4字節(jié)對齊 0x804ce98 <__execve+28>: push %ebx 0x804ce99 <__execve+29>: mov %edi,%ebx 0x804ce9b <__execve+31>: mov $0xb,%eax ‘設置XB號調(diào)用 0x804cea0 <__execve+36>: int $0x80 ‘調(diào)用執(zhí)行 0x804cea2 <__execve+38>: pop %ebx 0x804cea3 <__execve+39>: mov %eax,%ebx 0x804cea5 <__execve+41>: cmp $0xfffff000,%ebx 0x804ceab <__execve+47>: jbe 0x804cebb <__execve+63> 0x804cead <__execve+49>: call 0x8048324 <__errno_location> 0x804ceb2 <__execve+54>: neg %ebx 0x804ceb4 <__execve+56>: mov %ebx,(%eax) 0x804ceb6 <__execve+58>: mov $0xffffffff,%ebx 0x804cebb <__execve+63>: mov %ebx,%eax 0x804cebd <__execve+65>: lea 0xfffffff8(%ebp),%esp 0x804cec0 <__execve+68>: pop %ebx 0x804cec1 <__execve+69>: pop %edi 0x804cec2 <__execve+70>: leave 0x804cec3 <__execve+71>: ret 精練的調(diào)用方法是 0x804ce92 <__execve+22>: mov 0xc(%ebp),%ecx ‘設置NAME[0]參數(shù),4字節(jié)對齊 0x804ce95 <__execve+25>: mov 0x10(%ebp),%edx,設置NAME[1]參數(shù),4字節(jié)對齊 0x804ce9b <__execve+31>: mov $0xb,%eax ‘設置XB號調(diào)用 0x804cea0 <__execve+36>: int $0x80 ‘調(diào)用執(zhí)行 另外要執(zhí)行一個exit()系統(tǒng)調(diào)用,結束shellcode的執(zhí)行。 0x804ce60 <_exit>: mov %ebx,%edx 0x804ce62 <_exit+2>: mov 0x4(%esp,1),%ebx 設置參數(shù)0 0x804ce66 <_exit+6>: mov $0x1,%eax ‘1號調(diào)用 0x804ce6b <_exit+11>: int $0x80 0x804ce6d <_exit+13>: mov %edx,%ebx 0x804ce6f <_exit+15>: cmp $0xfffff001,%eax 0x804ce74 <_exit+20>: jae 0x804d260 <__syscall_error> 那么總結一下,合成的匯編代碼為: mov 0xc(%ebp),%ecx mov 0x10(%ebp),%edx mov $0xb,%eax int $0x80 mov 0x4(%esp,1),%ebx mov $0x1,%eax int $0x80 本文來自:魚C工作室<a href=http://www.> 詳細出處參考:http://www./a/bianchengjiqiao/heike/804.html |
|
來自: qinjie2010 > 《我的圖書館》