Windbg查看调用堆栈(k*)

简介: https://www.52pojie.cn/thread-664189-1-1.html      无论是分析程序崩溃原因,还是解决程序hang问题,我们最常查看的就是程序调用堆栈。

https://www.52pojie.cn/thread-664189-1-1.html     

 无论是分析程序崩溃原因,还是解决程序hang问题,我们最常查看的就是程序调用堆栈。学会windbg调用堆栈命令,以及理解堆栈中的各个参数的意义就显得至关重要。

上图就是一个典型的Windbg堆栈,如果不理解ChildEBP、RetAddr、Args to Child等参数意义,以及它们之间的来龙去脉,调试工作将很难进行下去。

1. 函数参数

        函数的参数传递有二种方式:堆栈方式、寄存器方式。如果是堆栈方式传递的,就需要定义参数在堆栈中的传递顺序,并约定函数被调用之后,由谁来平衡堆栈;如果是寄存器方式传递的,就需要确定参数存放在哪个寄存器中。每一种方式都有其优缺点,而且与使用的编程语言有关系,不存在哪种方式好与坏。

如Visual Studio中的C++工程,可以C++ --> 高级 --> 调用约定中进行设置:

        常用的调用约定类型有__cdecl、stdcall、PASCAL、fastcall。除了fastcall可以支持以寄存器的方式来传递函数参数外,其他的都是通过堆栈的方式来传递函数参数的。

利用堆栈传递参数

        堆栈是一种“后进先出”的数据结构,ESP寄存器始终指向栈顶。栈中数据地址从底部到顶部依次减小,也就是说,栈底对应高地址,栈顶对应低地址。
调用函数时,调用者依次把参数压栈,然后调用函数,函数被调用之后,在堆栈中取得参数数据。函数调用结束以后,堆栈需要恢复到函数调用之前的样子,具体由调用者来恢复还是由函数自身来恢复,根据不同的调用约定类型采用不同的方式。

约定类型 __cdecl stdcall PASCAL fastcall
参数传递顺序 从右到左 从右到左 从左到右 使用寄存器
平衡堆栈者 调用者 函数自身 函数自身 函数自身

cdcel是C/C++/MFC程序默认的调用约定。
stdcall是Win32中绝大多数 API函数的约定方式,也有少部分使用
cdcel约定方式,如wsprintf等。

        在windows C/C++开发中常用的就是__cdecl和stdcall这2种调用约定。
假设调用函数int add(int a, int b), 按照不同的调用约定来调用它。从调用者的视角来看,其汇编代码分别表示如下:

__cdecl

push b     ;参数按从右到左传递
push a
call add
add esp, 8 ;调用者在函数外部平衡堆栈

stdcall

push b     ;参数按从右到左传递
push a
call add   ;函数自己内部平衡堆栈

在函数调用过程中,参数入栈的过程:

上图中,EBP和函数返回地址都是地址,在32位程序中地址占4个字节。在函数的一次调用过程中EBP是不会变化的,函数调用完之后会将EBP恢复为暂存在堆栈中的原EBP值。所以,通过EBP可以获取函数各个参数的值:
参数a = EBP + 0x8
参数b = EBP + 0xC

2. Windbg堆栈命令

2.1 显示堆栈信息k*

[~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] [FrameCount] [~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] = BasePtr [FrameCount] [~Thread] k[b|p|P|v] [c] [n] [f] [L] [M] = BasePtr StackPtr InstructionPtr [~Thread] kd [WordCount]

参数:
Thread  指定显示哪个线程的调用堆栈。如果省略该参数,则显示当前线程的调用堆栈。*显示所有线程的调用堆栈。

b  显示每个函数的前3个参数。

p  显示每个函数的所有参数。参数列表包括每个参数的类型、名称、值。

        如上图,可以看到函数的每个参数的类型,名称,值。但是这个需要有对应的符号文件(pdb),没有应用程序的符号文件只能显示系统API的参数信息。

P  类似p。不同之处在于,每个参数显示在单独的行上面。

n  显示调用堆栈中每帧的序号(一般称栈帧,如栈帧3)。

FrameCount  指定显示调用堆栈的帧数,即调用堆栈的深度。默认为16进制格式。默认帧数为0x14=20

2.2 切换到指定帧信息.frame

        调用堆栈显示出来之后,如果想知道调用某帧时的相关信息,可以使用.frame 来切换指定帧,然后就可以使用如dv命令显示局部变量等。

.frame [/c] [/r] [FrameNumber] 

/c

/r  显示执行该帧时寄存器的值。

FrameNumber  指定要切换到的帧号。

3. 实例分析

kbn 显示堆栈信息:

栈帧12
调用add函数,参数1=00000001,参数2=000000002,EBP=0015fc0c
根据图1得知,函数返回地址=EBP+4,我们使用dw命令来验证。

参考:
《软件调试》张银奎 著
《格蠹汇编》张银奎 著
《加密与解密》第三版 段刚编著

怎么删除?
目录
相关文章
|
自然语言处理 安全 C++
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
11070 4
|
内存技术
STM32F103 五个时钟源
STM32F103 五个时钟源
1135 0
|
4月前
|
SQL 缓存 数据库
毕设答辩现场翻车合集:15个让人社死的突发状况及自救指南
计算机毕设答辩翻车多因技术卡点、演示故障、论文格式问题。本文结合500+真实案例,拆解15个高频社死场景+可落地自救方案,并分享如何用效率工具提前规避风险,助力开发者从"天级开发"缩短至"小时级",稳拿答辩通关
|
数据可视化 Java uml
IDEA这个功能真强大!一键把整个项目代码绘制成UML类图...
IDEA这个功能真强大!一键把整个项目代码绘制成UML类图...
7181 0
IDEA这个功能真强大!一键把整个项目代码绘制成UML类图...
|
监控 Windows
Hook函数三步走(SetWindowsHookEx、UnhookWindowsHookEx、CallNextHookEx)
Hook函数三步走(SetWindowsHookEx、UnhookWindowsHookEx、CallNextHookEx)
1842 0
Hook函数三步走(SetWindowsHookEx、UnhookWindowsHookEx、CallNextHookEx)
|
运维 安全 网络安全
"革新远程访问体验:Docker化部署webssh2,一键启动Web SSH客户端,让远程管理如虎添翼!"
【8月更文挑战第2天】Docker作为软件开发与运维的关键工具,以其轻量级、可移植及强隔离特性简化了应用部署。结合webssh2这一开源Web SSH客户端,可通过浏览器安全便捷地访问SSH服务器,无需额外软件。首先确保已安装Docker,接着拉取webssh2镜像并运行容器,映射端口以便外部访问。配置好SSH服务器后,通过浏览器访问指定URL即可开始SSH会话。此方案不仅提升了用户体验,还加强了访问控制与系统安全。
1688 7
|
测试技术 编译器 C#
一篇文章讲明白hook(钩子程序)(转载)
一篇文章讲明白hook(钩子程序)(转载)
999 0
|
SQL 监控 网络协议
DM8数据守护集群安装部署详细教程
DM8数据守护集群安装部署详细教程
808 0
|
NoSQL 关系型数据库 MySQL
|
存储 算法 安全
[数据结构与算法]哈希算法
[数据结构与算法]哈希算法