2012-11-08 27 views
2

因此,假設我可以訪問程序的寄存器。我可以訪問esp,ebp和eip。 eip指向需要執行的下一條指令,ebp指向另一個幀指針,esp指向堆棧的頂部。我明白這一點,但我不瞭解堆棧的其餘部分或如何解析它。解析堆棧和寄存器(EBP,EIP,ESP)並確定哪個函數與每個幀相關

例如,如果我想獲得一個幀的局部變量,我應該只是減去ebp - esp(明知ebpesp一個更大的地址),然後再通過這些地址和間接引用他們呢?這是從特定幀獲取局部變量的正確方法嗎?

另一個問題是,找出哪個函數與每個幀相關的最佳方法是什麼?如果我將ebp地址減1,然後解除引用該值,我應該得到返回地址「0x804 ...」嗎?這個地址和這個函數之間有什麼關係?例如,如果Foo()具有較高的pc地址0x8045555和較低的pc地址0x8045550,那麼我將在這些地址之間得到的返回地址是什麼?

感謝了很多先進的,讓我知道,如果我不太清楚..

注意:如果有人有更好的標題表明它,我沒有找到一個更好的。

回答

1

這個的細節取決於你的CPU指令集架構(你顯然使用32位x86)和你的編譯器工具鏈(我不能猜到)。一般來說,你不想重寫代碼來自己走棧幀,因爲它很複雜和脆弱,並且取決於你的編譯器的優化和調試設置。

如果你想調試一個程序,你應該先讓調試器爲你的平臺嘗試整理你的堆棧。例如,使用gdb,您可以運行bt以獲得「回溯」。

如果您嘗試從相關程序中執行此操作,並且您使用的是GNU C庫,則可以使用backtrace(3)函數。

如果你只是想了解事情如何工作的,這裏是一個有用的博客文章:http://eli.thegreenplace.net/2011/02/04/where-the-top-of-the-stack-is-on-x86/

爲了更深入的瞭解,儘量維基百科的文章x86 Calling Conventions。如果您要使用基於ELF的體系結構(如Linux),請參閱ELF ABI specifications ..

+0

嗯,我想我想全面瞭解。現在我正在使用Pin來讀取程序中的寄存器,並且我正在開發類似於調試器的東西。問題是我有EBP的地址,我認爲通過減去1然後解除引用我會得到幀的返回地址,但我沒有那樣做。感謝您的鏈接,我會檢查出來! @JameySharp – attis

+1

您可能需要減去4,而不是1,因爲在彙編級別,所有指針算術都是以字節爲導向的。 (至少,在x86上...) –

1

寄存器和堆棧中的數據只是一系列字節。數據由將字節放入系列的各種指令和應用程序構成,但有關字節結構的信息不是字節系列的一部分,而是可能或不可用的附加信息。

例如,當編譯源代碼並且編譯器生成二進制代碼時,二進制代碼將包含附加的描述性信息。額外描述信息的數量將取決於所選擇的編譯器選項以及所使用工具鏈中各種其他工具的功能。

例如,如果選項是用附加信息(例如函數名稱)創建調試版本,並且工具鏈支持使用附加信息顯示二進制代碼,那麼您可以很好地查看變量,函數名稱,並逐步在源代碼級別執行代碼。

另一方面,如果選項是創建沒有附加信息的優化版本,那麼即使工具鏈可以使用附加信息支持二進制代碼的顯示,以便以更人性化的視圖呈現二進制代碼,由於信息不存在,工具鏈無法在源代碼級別顯示源代碼行,變量,函數名稱等的二進制代碼。

因此,要完成您想要完成的任務,您需要將需要有附加信息,以便您可以將二進制代碼與附加信息結合起來。沒有額外的信息,你所擁有的只是內存中的一堆字節。您可以用各種方式顯示這些字節,例如將它們解釋爲彙編代碼或將它們解釋爲文本字符串。然而,如果沒有額外的信息,你只是猜測,但是受過教育。

不同的編譯器和工具鏈在不同的平臺和操作系統上會生成不同類型的附加信息。因此,您需要獲得有關工具鏈提供的特定信息的信息。

+0

我有這些信息,我正在使用程序中的DWARF和ELF信息。問題是,我沒有得到我期望得到的基於我對堆棧的瞭解。 – attis

+1

@attis,我建議你看一下這個http://www.dwarfstd.org/doc/Debugging%20using%20DWARF.pdf,這個網站有一些工具可以使用DWARF http://reality.sgiweb .org/davea/dwarf.html –

+0

@attis,並且此sourceforge項目也可能有所幫助http://sourceforge.net/apps/trac/elftoolchain/ –