第二十九篇: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

相关文章

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

k8s中实现mysql主备过程详解

《k8s中实现mysql主备过程详解》文章讲解了在K8s中使用StatefulSet部署MySQL主备架构,包含NFS安装、storageClass配置、MySQL部署及同步检查步骤,确保主备数据一致... 目录一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.

Java服务实现开启Debug远程调试

《Java服务实现开启Debug远程调试》文章介绍如何通过JVM参数开启Java服务远程调试,便于在线上排查问题,在IDEA中配置客户端连接,实现无需频繁部署的调试,提升效率... 目录一、背景二、相关图示说明三、具体操作步骤1、服务端配置2、客户端配置总结一、背景日常项目中,通常我们的代码都是部署到远程

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例解析

《Java中的分布式系统开发基于Zookeeper与Dubbo的应用案例解析》本文将通过实际案例,带你走进基于Zookeeper与Dubbo的分布式系统开发,本文通过实例代码给大家介绍的非常详... 目录Java 中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例一、分布式系统中的挑战二

90%的人第一步就错了! 顺利登录wifi路由器后台的技巧

《90%的人第一步就错了!顺利登录wifi路由器后台的技巧》登录Wi-Fi路由器,其实就是进入它的后台管理页面,很多朋友不知道该怎么进入路由器后台设置,感兴趣的朋友可以花3分钟了解一下... 你是不是也遇到过这种情况:家里网速突然变慢、想改WiFi密码却不知道从哪进路由器、新装宽带后完全不知道怎么设置?别慌