第二十九篇:USER MODE DLL开发过程中的调试技巧心得分享

2024-08-29 17:08

本文主要是介绍第二十九篇:USER MODE DLL开发过程中的调试技巧心得分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近由于项目需要,被老板安排开发一个WINDOWS USER MODE DLL, 即WINDOWS用户模式下的动态链接库。


写代码,实现具体的功能这类初等工作,对于大多数软件开发工程师来讲,只是时间与工作量上的问题,具体的WINDOWS DLL的知识点,本人参考了Jeffrey Richter的《WINDOWS核心编程》中的DLL几章,不再熬述。


这里谈一下关于USER MODE DLL在调试过程中所涉及到的一些知识点,以及它们彼此之间的关系:

1. DebugBreak / int 3;

2. OutputDebugString

3. bcdedit /debug (on/off)

4. Windbg user/kernel mode debug

5. IsDebuggerPresent() 函数返回值

6. DebugView.exe

7. EPROCESS.debugport

8. PEB.beingdebugged


1. DebugBreak / __asm int 3; 起到中断到调试器的功能。

在DLL初步编码完成,第一次上系统跑的时候,可以在DllMain中尝试加入它们,以确定DLL是否被服务或者EXE正确调用。

当然,也可以在其它阶段的函数中调用,不过,笔者在该断点HIT之时,通过.reload /f命令,正确加载了调试符号,就可以通过动态设置、取消断点的方式来继续进一步的调试。


2. OutputDebugString & DebugView.exe & Windbg user/kernel mode & IsDebuggerPresent

以及EPROCESS.debugport & PED.beingdebugged

这些个因素有他们之间的彼此关联。

首先,必须的一步,在Win7,8,8.1上使用DebugView.exe必须在注册表中加入:

HKLM/SYSTEM/CurrentControlSet/Control/Session Manager

Debug Print Filter (Key)

DWORD(type),DEFAULT (name)0xF(value)

其次,OutputDebugSting函数本质上是通过异常机制工作的(raise exception), 具体的理论方面的内容请参考张银奎《software debugging》, chapter 10.

这里只谈本人的一点实践经验。

第一,在目标进程没有被Windbg Attach的时候,即目标进程不处于被调试状态,在这种状态下,目标程序的EPROCESS.debugport == NULL, PEB.beingdebugged == FALSE.

IsDebuggerPresent()函数的判断依据实则为PEB.beingdebugged, 在没有被windbg attach时,返回为FALSE。


如果在你的代码中,有下面的代码段,OutputDebugString输出"Debugger not Present"到DebugView.exe中.

if(IsDebuggerPresent()){
OutputDebugString(TEXT("Debugger Present\n"));
}else{
OutputDebugString(TEXT("Debugger not Present\n"));
}

但是,当有windbg attach到目标进程,该目标进程进入到被调试状态,以上代码则输出“Debugger Present”到Windbg的Command窗口。

值得注意的是,IsDebuggerPresent()只与windbg attach有关,与系统是否处于kernel debug无关。

进一步讲,当目标进程被windbg attach后,上述进程处于user mode debug状态,进入user mode debug状态,则影响了EPROCESS.debugport与PEC.beingdebugged.

而通过设置NET双机调试,利用DebugBreak/int 3; 将DLL中断到windbg, 该行为并不影响以上两个变量,因为,此时目标进程处于kernel mode debug,从而IsDebuggerPresent返回为FALSE。


3. bcdedit /debug on/off & DebugBreak/int 3;

bcdedit /debug on的状态下, DebugBreak/int 3;会中断到调试器,如果此时系统没有双机联调,或者进程没有被attach, 具体表现则是系统一直pending.

bcdedit /debug off的状态下,DebugBreak/int 3;产生异常, 但由于该异常并未中断到调试器,该异常得不到正确处理,系统最终将该进程结束。


4. bcdedit /debug on/off & Windbg user/kernel mode & DebugBreak/int 3;

最后,来讲一讲他们之间的关系。

DebugBreak/int 3;作为一种异常,总归要有东西去处理。

假设, 被调试机器(target),既通过NET连接到了调试主机(host,此时bcdedit /debug on), 又在本地通过WINDBG ATTACH到了目标进程。

在这种情况下,DebugBreak/int 3;首先被本地WINDBG处理, 既中断到本地的WINDBG。

如果目标进程未被WINDBG ATTACH,则该异常中断到主机的WINDBG。

但是,如果此时也没有远程(NET)HOST WINDBG连接,则造成一个无东西处理的内核异常,则出现上面所说的,系统PENDING。


而在bcdedit /debug off并且既没有远程也没有本地WINDBG,则这是无东西处理的用户异常,最终,系统将该进程终止掉了。



后记:

EPROCESS的成员DebugPort是一个数据结构,作为调试子系统与调试器交互的一种通道(手段)。

其主要的数据成员包括一个EVENT用来信号通知,一个MUTEX用来同步链表操作,以及LIST_ENTRY用来排列调试事件。


DebugBreak的内核函数为DbgBreakPoint.


写代码是正面交战,敌人在明处,花时间与功夫,一点点地编码调试总归能够完成任务。

调试则正好相反,调试环境的搭建,调试关键知识的掌握,以及躲在暗处的BUG,从经验与系统知识上来讲,需要更加扎实的功底。


前阵子翻过一下张银奎的《software debugging》, 1000多页的内容,让人看了后面,忘了前面。

纠其原因,就是看书的方法不当,以软件开发的的思维习惯与软件开发的经验去看这本书,只能是花了时间功夫多,收获甚少。

但在开发这个DLL项目过程当中,实实在在地将一些调试方面的知识应用在实际当中,有了问题查找资料,然后再实践,之后,通过《software debugging》这本书,confirm遇到的这些调试知识点,调试技巧,达到举一反三,融会贯通的效果,将调试的基本观念用在软件开发的过程当中,才是实实在在的积小流,积跬步的过程。

这篇关于第二十九篇:USER MODE DLL开发过程中的调试技巧心得分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1118456

相关文章

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Python ZIP文件操作技巧详解

《PythonZIP文件操作技巧详解》在数据处理和系统开发中,ZIP文件操作是开发者必须掌握的核心技能,Python标准库提供的zipfile模块以简洁的API和跨平台特性,成为处理ZIP文件的首选... 目录一、ZIP文件操作基础三板斧1.1 创建压缩包1.2 解压操作1.3 文件遍历与信息获取二、进阶技

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

PyInstaller打包selenium-wire过程中常见问题和解决指南

《PyInstaller打包selenium-wire过程中常见问题和解决指南》常用的打包工具PyInstaller能将Python项目打包成单个可执行文件,但也会因为兼容性问题和路径管理而出现各种运... 目录前言1. 背景2. 可能遇到的问题概述3. PyInstaller 打包步骤及参数配置4. 依赖