-
-
[原创]Windbg调试栈溢出
-
发表于:
2022-7-27 20:37
18562
-
背景:windows开发的老表们,你是否遇到过这类问题,程序崩溃了,也抓到了dmp,windbg打开dmp文件,执行!analyze -v指令,傻眼了,显示的调用堆栈被破坏了,执行kb,看下调用堆栈,也是显示的被破坏的调用堆栈。怎么办老表,你往下看.......
如果你知道这些废话,直接跳过这段,往下看,不要浪费时间, 调查windows栈溢出此类的问题,首先要明白函数的调用原理,实际上,函数的调用是在栈上进行的,栈的生长方向是由高地址向低地址,即栈底为高地址,栈顶为低地址。每个函数在被调用时都对应着各自一个栈帧,用来记录函数自身的一些信息(返回地址、局部变量…),因此栈帧也叫“过程活动记录”,为了衡量栈帧的范围,就需要用到两个寄存器:ESP(Extend Stack Pointer)和EBP(Extend Base Pointer)。ESP就是,也叫栈指针,ESP中始终存放着指向当前栈帧顶部的指针,时刻指向栈帧顶部,即当压入数据时,ESP-=4;弹出数据时ESP+=4。EBP时刻指向当前栈帧的底部(并非栈底),局部变量,参数,返回地址、的访问都是以EBP寄存器为参考点。
表哥,明白下面三个寄存器的作用,你就可以阅读了,以下说的都是x86架构。
始终指向栈顶。
压栈:ESP-4
出栈:ESP_4
Instruction Pointer
EIP寄存器保存CPU将要执行的下一句指令地址。每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加。EIP指向即将执行的代码地址。
拿到dump文件,输入命令~*kbn查看所有线程信息,发现异常出现在14号线程,输入命令~14s切换到出问题的线程,下面是14号线程的调用栈。一般来说,对付“kernel32!UnhandledExceptionFilter+0x1af”的方法是输入命令“.cxr poi(0xXXXXXXXX+4)”,(其中0xXXXXXXXX为第一个参数,即红色标出位置的值)即可看到发生异常前的调用栈。但是在本实例中这个值为0x00000000,是个无效地址,我们已经不能用常规方法看到调用栈了
首先要观察下,栈溢出到什么程度,我给他大致分四种情况。
a)栈中保存的父函数的ebp被覆盖。
当前栈帧的ebp指向父函数的ebp(看下图)
dd ebp,当前帧的ebp指向父函数的ebp,可执行dd ebp指令查看父函数的ebp的值,如果不正常,那就是被覆盖了。观察下父函数ebp寄存器的值和esp寄存器的值相差大不大,如果两者相差不大,如果明显相差很大,完全不在一个区间,证明父函数ebp寄存器被覆盖 了。父函数的ebp被覆盖了,会导致返回父函数时,定位局部变量,参数时发生错误。另外还可以输入命令!teb查看线程的栈空间范围,看下esp和ebp是不是在[StackLimit StackBase]范围之内。
b)栈中保存的返回地址(调用子函数时push eip)被覆盖
返回地址:当前栈帧ebp+4(看下图)
观察下栈中保存的返回地址,是不是在正常的代码段地址返回内,如果明显不合法的代码地址,那么就是返回地址被覆盖了,在当前函数执行完毕后,返回到父函数时,会把返回地址弹出栈到EIP寄存器中,如果栈中保存的返回地址是错误的,那么pop到EIP寄存器的返回地址也就是错误的。会执行到不可访问或者非法的代码地址处。
c)当前执行函数的参数被覆盖
当前执行的函数的第一个参数位置处:ebp + 8(看下图)
当前执行的函数的第二个参数位置处:ebp + 12(看下图)
d)覆盖到父函数的栈帧空间(局部变量)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2022-7-31 01:29
被sanganlei编辑
,原因: