2010-02-17 292 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一样。我解释了你的程序如何最终执行数据而不是代码。 –