1. 程式人生 > >[原理分析]Linux下的棧溢位案例分析-GDB除錯操練[2]

[原理分析]Linux下的棧溢位案例分析-GDB除錯操練[2]

摘要:

原版本中的問題主要在於除錯過程中,蠻力的痕跡太重,沒有很好地體現常用的除錯準則;本文在原版本的基礎上融入參考文獻中提及的除錯原則,重新審視和操練該問題,希望儘量體現出除錯中常用的思維法則。

測試的平臺:
1.  ubuntu 9;   gcc 4.4.1;   Gdb 7.0-ubuntu
2.  ubuntu系統安裝在virtual box 3.2.8虛擬機器上;

問題重述:

此處簡要地描述下原來的問題,具體細節檢視原文,我們希望採用stackoverflow aaaabbbbccccddddeeee中的eeee的值覆蓋stackoverflow中overflow到main函式的返回地址,呼叫overflow返回到main函式時,控制

eip,使其中的值為0x63636363;但是實際過程中問題在於eip的值並不是設想的0x63636363,而是0x61616161;

原因何在?

除錯過程:

除錯原則1:要去看,不是去想;

一開始,我們不能假設性地認為問題就出在overflow返回到main的過程中(既然出問題了,就說明系統的行為跟你想象的差別很大,問題發生在何處都不奇怪)而應該實際地單步執行下看看,看看問題到底在什麼地方?通過設定斷點,以及單步執行,我們發現eip的控制並不出現在overflow返回到main的過程,而是main函式退出的

過程;

除錯原則2:理解系統

根據函式的呼叫過程,在call前會將當前主函式的下一句地址壓棧;

在進入函式後,首先執行:push ebp; mov ebp, esp;

退出函式時,mov esp, ebp; pop ebp。最後呼叫ret指令時,將call指令壓入的下一句地址彈出到eip中。根據上述系統模型,大概需要檢視的分支為:

1. main函式返回的地址被修改(也即call main時函式壓入的地址),也即esp所指向的返回地址的內容被改變;

2. 還有,返回地址中的內容沒有改變,esp所指向的返回地址被改變;

除錯原則3:先排除易於驗證的分支;

除錯原則4:非正常的情況與正常的情況進行比較;

上述的兩個除錯分支,其中2的驗證難度小,因為只需要看看esp的值是否改變,所以我們從分支2入手。採用對比的手法,將剛進入main函式後的ebp和esp記錄下來,然後再將main中的ret之前的esp和ebp記錄下來。對比兩者的值是否相同,理論上而言,兩者的值應該相同。以下是我們記錄的資料,在剛進入main函式時,ebp的值為468(省略前面部分數字),而esp的值為43c;以下是我們記錄的正常版本和溢位版本在執行main中的ret指令之前的ebp和esp值:


圖1 正常的版本


圖2 非正常的版本

由此,我們找到問題所在:esp指向的地址被修改了,原來應該指向43c,當此處卻指向404;此時如果我們檢視下404處的值,可以發現其值正好為0x61616161,這就解釋了為什麼執行完ret指令後,eip的值變為0x61616161。在執行完overflow後,返回到main函式時,overflow之所以能返回到main就說明其esp的設定是正確的;否則overflow中執行完ret指令後,還不知道跳到哪去了。那麼此處只可能在leave指令執行完後,esp的值不正常了。考慮leave指令的等價:

mov esp, ebp

pop ebp

使得esp不正常,也即意味著ebp的值不正常;經過驗證,的確發現ebp的值從overflow返回後變得不正常。在進入overflow之前的ebp的值為0x420,但是從overflow返回到main函式後,ebp的值變為400,根據猜測,esp的確是正常的(要不怎麼返回到main呢?)。那此處的ebp為什麼會不正常?

利用除錯原則1:要去看,而不是去想。我們跟入overflow中去檢視的話,進入overflow時,ebp的值為438,隨後變為418;執行完strcpy函式後,ebp的值恢復為418,esp的值此處

肯定正常(否則不能從strcpy返回到overflow),那我們接下來要看執行完leave後,ebp是否能夠418恢復會438了,遺憾的是並沒有恢復為438,而是變為400;那麼問題只能出在leave指令部分,又因為此處的leave指令等效為:

mov esp, ebp

pop ebp

我們又知道此處的esp恢復的是成功的,那麼問題只能出在pop ebp時;pop ebp時出現問題,也只能是418這個棧裡的值被修改了,原來應該是438被修改為400。經過驗證,的確如此。根據後面的驗證,呼叫strcpy後,將418處的值被修改了,至於怎麼會修改這個位置的,那麼得深入strcpy了。

結論:

本文希望在除錯過程中,儘量展現除錯原則的作用。由於在已有工作上的重新審視,難免陷入從後視鏡看問題的陷阱,讀者大不用深究,關鍵還是原則的運用。

參考文獻:

除錯九法:軟硬體錯誤的排查之道,David J. Agans著,趙俐譯,人民郵電出版社。

相關推薦

[原理分析]Linux溢位案例分析-GDB除錯操練[2]

摘要: 原版本中的問題主要在於除錯過程中,蠻力的痕跡太重,沒有很好地體現常用的除錯準則;本文在原版本的基礎上,融入參考文獻中提及的除錯原則,重新審視和操練該問題,希望儘量體現出除錯中常用的思維法則。 測試的平臺:1.  ubuntu 9;   gcc 4.4.1;   G

linux漏洞分析入門筆記-溢位

ida7.0 ubuntu16.04 lts 0x00:環境配置 使用IDA遠端除錯Linux程式步驟如下: 1. 在進行遠端除錯之前需要對Linux平臺進行一些準備工作。在IDA的安裝目錄中的dbgsrv資料夾中,選擇linux_server或者linux_serverx64複製到需要除錯Linux

Redis 高負載的中斷優化(基於京東redis叢集高負載丟包案例分析)

Redis 高負載下的中斷優化 陳炳宇 背景 2015年年初以來,隨著Redis產品的使用者量越來越大,接入服務越來越多,再加上京東商城Memcache和Redis兩套快取融合,Redis服務端的

Linux的段錯誤分析

2. 段錯誤產生的原因 2.1 訪問不存在的記憶體地址 #include #includevoid main() {int *ptr = NULL;*ptr = 0; } 2.2 訪問系統保護的記憶體地址 #include #includevoid main() {

linuxvlan的實現分析(上)

一. VLAN的核心概念     1. 劃分VLAN的核心目的只有一個:分割廣播域。        通過VLAN對廣播域進行合理分割之後,一是可以縮小ARP攻擊的範圍,從而提高網路的安全性;二是可以縮小廣播域的大小,從而提高網路的效能。        所以要注意的是,劃分V

linuxIIC驅動開發分析

1.IIC規範 IIC(Inter-Integrated Circuit)匯流排是一種由PHILIPS公司開發的兩線式序列匯流排,用於連線微控制器及其外圍裝置。IIC匯流排產生於在80年代,最初為音訊和視訊裝置開發,如今主要在伺服器管理中使用,其中包括單個元件狀態的通訊。例如管理員可對各個元件進行查詢,以

使用Windows上SourceInsight工具建立分析Linuxuboot原始碼工程

SourceInsight軟體可以說是分析查閱大型原始碼工程檔案的神器!介面不錯!功能強大! 第一步:安裝好SourceInsight後開啟軟體 點選上面的Project--->new pro

Linux緩衝區溢位攻擊的原理及對策

前言 從邏輯上講程序的堆疊是由多個堆疊幀構成的,其中每個堆疊幀都對應一個函式呼叫。當函式呼叫發生時,新的堆疊幀被壓入堆疊;當函式返回時,相應的堆疊幀從堆疊中彈出。儘管堆疊幀結構的引入為在高階語言中實現函式或過程這樣的概念提供了直接的硬體支援,但是由於將函式返回地址這樣的

DUMP檔案分析4:溢位

前面說到過,棧溢位型別的異常通過程式設計的方式獲取DUMP可能不成功,因為棧溢位會破壞SEH(結構化異常處理)框架。實際上,通過DUMP檔案來除錯棧溢位同樣是困難的,因為棧溢位本身一般不會造成異常,異常往往發生在棧溢位破壞棧上的資料之後,同時,由於棧溢位破壞了棧上的資料,

linux協議ip層分析

學習目標: 熟悉ip層的職責? 熟練資料包如何通過ip層? 熟練ip資料重組的設計思路? 熟悉ip路由的思路? 熟悉netfilter的鉤子函式處理? 1資料流路徑   2職責 ip層的主要任務有下面5個方面:  1、ip資料包的校驗(包括資料包的完整性、格式正確性、

linux協議pf_packet相關分析

一:名詞解釋: 1,BSD socket層: bsd socket是Berkeley套接字應用程式介面(API)包括了一個用C語言寫成的應用程式開發庫,主要用於實現程序間通訊,在計算機網路通訊方面被廣泛使用。 Berkeley套接字介面的定義在幾個標頭檔案中。這些檔案的

LDA線性判別分析原理及python應用(葡萄酒案例分析

目錄 線性判別分析(LDA)資料降維及案例實戰   一、LDA是什麼   二、計算散佈矩陣   三、線性判別式及特徵選擇   四、樣本資料降維投影   五、完整程式碼   結語   一、LDA是什麼 LDA概念及與PCA區別 LDA線性判別分析(Linear Discriminant Anal

java JNI 實現原理 (二) Linux 如何 load JNILibrary

unlock this error clear jvm 動態鏈接 dlink 參考 保護 在博客java JNI (一)虛擬機中classloader的JNILibrary 中討論了java中的Library 是由classloader 來load的,那我們來看看 clas

linux溢位實驗和一些tips

#include<stdio.h> #include<stdlib.h> #include <malloc.h> int main (int argc, char *argv[]) { char *bu

Linux緩衝區溢位攻擊及Shellcode

4.3.2 Linux32環境下函式的返回地址 編譯、連結、執行程式buffer_overflow.c,並關閉Linux的棧保護機制,參見截圖: 下面用gdb除錯程式: 在foo函式的入口、呼叫st

LinuxDebug模式啟動Tomcat遠端除錯

一.      應用場景 在實際的測試過程中,可能會遇到由於程式執行的不間斷性,我們無法構造測試場景來驗證某個功能的正確性,只有通過程式碼級的除錯才能驗證功能是否正確。然而開發本地除錯的話,不具有說服力,這時我們測試人員必須連線到linux下的基線版本程式碼進行遠端除錯

Linux的C/C++開發與除錯工具

  Linux開發環境相當完善,且功能完整,它主要由GNU的編譯器和庫,以及大量的系統例程及庫組成,能夠支援C++、C和組合語言程式,重點是針對C++和C語言。因為Linux的原始碼主要是用C語言實現的,開發人員可以方便地獲取並進行修改和重新編譯,因此為Linux作業系統提供

嵌入式 Linux段錯誤的原因和除錯方式

[email protected]:~/segfault$ catchsegv ./segfault3 Segmentation fault (core dumped) *** Segmentation fault Register dump: EAX: 00000000 EBX: 00fb3f

Linux 的段錯誤(Segmentation fault)除錯方法(轉)

轉自:http://blog.sina.com.cn/s/blog_3e28c8a50100bnin.html 我們在用C/C++語言寫程式的時侯,記憶體管理的絕大部分工作都是需要我們來做的。實際上,記憶體管理是一個比

LinuxSegmentation fault(core dumped)簡單除錯方法

** 什麼是Segmentation fault? ** Segmentation fault就是段錯誤,一般指訪問的記憶體超出了系統給這個程式所設定的記憶體空間,例如訪問了不存在的記憶體地址、訪問了系統保護的記憶體地址、訪問了只讀的記憶體地址等等情況