2010-02-17 260 views
1

我有一個堆棧損壞的核心轉儲。 我嘗試拆解,發現如下PLZ幫我anaylyse吧..pusha彙編語言指令

(gdb) bt 
#0 0x55a63c98 in ??() 
#1 0x00000000 in ??() 

(gdb) disassemble 0x55a63c90 0x55a63ca8 

Dump of assembler code from 0x55a63c90 to 0x55a63ca8: 

0x55a63c90:  add %cl,%dh 

0x55a63c92:  cmpsb %es:(%edi),%ds:(%esi) 

0x55a63c93:  push %ebp 

0x55a63c94:  add %al,(%eax) 

0x55a63c96:  add %al,(%eax) 

**0x55a63c98:  pusha** 

0x55a63c99:  lret $0x9 

0x55a63c9c:  subb $0x56,0xd005598(%ebp) 

0x55a63ca3:  push %ebp 

0x55a63ca4:  jo  0x55a63cc5 

0x55a63ca6:  sahf 

0x55a63ca7:  push %ebp 

End of assembler dump. 
(gdb) q 

可這PUSHA指令可能導致核心轉儲?

回答

6

沒有*,所有PUSHA確實是推動所有的通用寄存器堆棧,包括堆棧指針!導致核心轉儲的是pusha之後的指令,lret,這是一個帶有彈出堆棧的長返回。返回地址是最近一次推送到堆棧的值,在這種情況下,它將是esi:edi中的任何值(因爲它們是由pusha指令推送的最後一個值),並且這可能指向隨機的某個地方。

*除非用完堆棧空間。

+0

有什麼辦法可以驗證堆棧溢出嗎? – Arpit

+0

@Arpit:它取決於,在保護模式下,你會得到#SS(0)CPU異常。除此之外,您可能會遇到#PF(x)異常。但是這些會被操作系統所捕獲。 nobugz提出了最可能的原因:代碼跳到了隨機位的內存。您可以通過取消引用無效指針來完成此操作,通常通過在尚未初始化的對象上調用虛擬方法來實現。 – Skizz

0

pusha如果在該點發生堆棧溢出,則只能導致核心轉儲。該指令將所有寄存器的值壓入堆棧,並可能導致溢出。然而,問題的根源可能在其他地方 - 很可能調用堆棧在該點太深,並且恰好會導致這樣的後果,因爲它在這樣的條件下執行。

+0

你能詳細點嗎? – Arpit

0

檢查,如果你看到對齊拆機代碼:

x/i $eip 

同時顯示寄存器的值:

i r 
4

絕對。 PUSHA跟RET是不正確的,返回地址是垃圾。看到ADD AL,[EAX]在你的反彙編中是另外一個死角,那就是反彙編爲0.

換句話說:你是拆解數據而不是代碼。你的程序因爲正在執行數據而被轟炸。發生的經典方式是破壞具有緩衝區溢出的堆棧幀。當函數返回時,它會從損壞的堆棧中彈出一個無效的返回地址,並跳轉到永遠不會降落。沒有得到一個seg故障是非常不幸的。

很難調試,堆棧跟蹤是垃圾。你需要在最後一個已知的良好的代碼地址設置一個斷點並開始單步執行。你在炸彈爆炸前進入的最後一個好功能通常是麻煩製造者。

+0

如果它永遠不是正確的,那麼爲什麼這個指令集生成? – Arpit

+2

你錯過了這一點。您找到的彙編代碼不是代碼。這是數據。分解數據會生成怪胎指令。像POPA和SAHF一樣。我解釋了你的程序如何最終執行數據而不是代碼。 –