操作系统:windows XP

调试器通过CreateProcess传入带有DEBUG_PROCESS和DEBUG_ONLY_THIS_PROCESS的dwCreationFlags创建被调试进程。这种情况下,进程创建的早期(执行NtCreateProcess或NtCreateProcessEx之前),调用DbgUiConnectToDbg()使调用线程和调试子系统建立连接。DbgUiConnectToDbg()内部调用ZwCreateDebugObject创建一个DEBUG_OBJECT内核对象,并将其句柄保存在当前线程环境块(TEB)的的DbgSsReserved[1]中。调试进程与被调试进程就是通过DEBUG_OBJECT进行交互的。之后该线程便被认作是调试工作线程。
 
调用NtCreateProcess或NtCreateProcessEx时,
NTSYSAPI
NTSTATUS
NTAPI
NtCreateProcess(

OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL );
DbgSsReserved[1]中的句柄将传入,内核中进程创建函数PspCreateProcess会检查它是否为空,若不为空,则取得该句柄的对象指针(PDEBUG_OBJECT),并将其存储于新创建进程EPROCESS的DebugPort中。之后新创建进程便被认作是被调试进程。
 
之后PspCreateProcess调用MmCreatePeb创建进程环境块(PEB)时,MmCreatePeb会根据DebugPort是否为空,相应设置PEB中BeingDebugged字段。
 
另一种情况是调试器附加到被调试进程。通过调用 BOOL DebugActiveProcess(DWORD dwProcessId)完成。首先会调用DebugUiConnectToDbg使调用进程与调试子系统建立连接。之后调用ProcessIdToHandle取得句柄。之后调用NTDLL中的DbgUiDebugActiveProcess。该函数调用NtDebugActiveProcess并传入ProcessHandle和DebugObject的handle。NtDebugActiveProcess内部根据句柄取得要被调试进程的EPROCESS和用于调试的调试对象DEBUG_OBJECT,之后向调试对象发送杜撰的调试事件(在调试循环中再说),之后调用DbgkpSetProcessDebugObject将调试对象的指针存储到被调试进程EPROCESS的DebugPort中,并调用DbgkpMarkProcessPeb设置被调试进程PEB的BeingDebugged字段。当NtDebugActiveProcess成功返回后,DbgUiDebugActiveProcess调用DbgUiIssueRemoteBreakIn在被调试进程中创建远程中断线程(后述),使被调试进程中断到调试器中。
 
之后调试器和被调试程序便建立起了调试会话。
 
之后调试线程进入了调试循环。调试线程使用WaitForDebugEvent等待调试事件。
 
调试事件即被调试进程所发生的某些特殊动作。例如线程、进程的创建和销毁等,当然还有非常重要的异常事件。被调试进程通过调试子系统发送给调试器,此时,调试器的WaitForDebugEvent将结束等待,并相应处理调试事件。具体如下:
 
调试子系统内核部分设计了一系列的函数来采集调试事件,并将收集到的调试事件以DBGKM_APIMSG这样的结构存储在调试子系统的调试消息队列中。当被调试进程创建新的进程或线程时,将产生相应的调试事件。在进程管理器创建新线程时,最后将调用PspUserThreadStartup准备启动线程。在该函数中,会调用调试子系统内核函数DbgkCreateThread,DbgkCreateThread将检查DebugPort是否为空,若为空,则立即返回,若不为空,继续检查进程的用户态运行时间(UserTime)是否为0,从而判断是否为进程中第一个线程。若是,若是,则通过DbgkpSendApiMessage()向DebugPort发送DbgKmCreateProcessApi消息,若不是,则发送DbgKmCreateThreadApi消息。
 
NTSTATUS DbgkpSendApiMessage(IN OUT PDGBKM_APIMSG ApiMsg, IN PVOID Port, IN BOOLEAN SuspendProcess)
其中Port一般是DebugPort中的指向DEBUG_OBJECT的指针。SuspendProcess说明是否要挂起被调试进程。若SuspendProcess为真,则该函数调用DbgkpSuspendProcess挂起被调试进程。之后调用DbgkpQueueMessage,该函数根据参数决定是否需要等待,若需要,则通过等待函数,直到收到调试器回复后返回。若是发送杜撰消息,则无需等待直接返回。之后若挂起了调试进程,则调用DbgkpResumeProcess唤醒被调试进程。
 
DbgkpSuspendProcess调用KeFreezeAllThreads()冻结除被调试进程中产生调试事件的线程的所有线程。之后如上文,该线程调用DbgkpQueueMessage发送消息并在大部分情况下调用KeWaitForSingleObject等待调试器的返回。之后调试子系统会通知调试器读取调试事件。调试器调试线程WaitForDebugObject返回,调试线程处理调试事件。完成之后调用ContinueDebugEvent。之后调试子系统唤醒被调试进程在等待的那个线程。该线程醒来后,会调用KeThawAllThreads()唤醒被调试进程中的所有线程。

windows下的用户态调试的底层与上层实现的更多相关文章

  1. systemtap 用户态调试

    #include <stdio.h> int main( void) { ; a=fun(,); printf("%d\n",a); } int fun(int a,i ...

  2. windows 下使用 mingw编译器 调试时 无法跟进源码

    windows 下使用 mingw编译器 调试时 无法跟进源码 最近在公司使用QT 开发,官方在线下载的 安装的QT mingw 都是没有debug版本的 由于没有debug版本动态库 所以你调试的时 ...

  3. 总在用户态调试 C# 程序,终还是搭了一个内核态环境

    一:背景 一直在用 WinDbg 调试用户态程序,并没有用它调试过 内核态,毕竟不是做驱动开发,也没有在分析 dump 中需要接触用内核态的需求,但未知的事情总觉得很酷,加上最近在看 <深入解析 ...

  4. [补] 如何在windows下用IDA优雅调试ELF

    在windows下如何用IDA优雅调试ELF brief: 构建一个IDA-linux_server-docker镜像,优雅地IDA远程调试 使用传统虚拟机来运行一个linux程序就得跑一个完整的li ...

  5. 浅谈一下Windows下的用户权限

    大学毕业后,选择做了苹果开发,一直是使用的Mac系统,所以对Windows的基本操作忘得几乎一干二净:因为做内网穿透的需要,要用到Windows下的权限问题,所以重新研究了一下Windows设置用户权 ...

  6. 如何在windows下用IDA优雅调试ELF

    在windows下如何用IDA优雅调试ELF brief: 构建一个IDA-linux_server-docker镜像,优雅地IDA远程调试 使用传统虚拟机来运行一个linux程序就得跑一个完整的li ...

  7. windows下源码安装调试postgresql

    环境:windows 10 postgresql版本:postgresql-9.6.5 使用工具:vs2017社区版 辅助工具:perl.diff.flex.bison 相关工具下载地址: perl下 ...

  8. Windows下搭建FFmpeg开发调试环境

    背景 如果你是一个FFmpeg的使用者,那么绝大部分情况下只需要在你的程序中引用FFmpeg的libav*相关的头文件,然后在编译阶段链接相关的库即可. 但是如果你想调试FFmpeg内部相关的逻辑,或 ...

  9. 初探Windows用户态调试机制

    我们在感叹Onlydbg强大与便利的同时,是否考虑过它实现的原理呢? 作为一个技术人员知其然必知其所以然,这才是我们追求的本心. 最近在学习张银奎老师的<软件调试>,获益良多.熟悉Wind ...

随机推荐

  1. HDU4452 Running Rabbits

    涉及知识点: 1. direction数组. 2. 一一映射(哈希). Running Rabbits Time Limit: 2000/1000 MS (Java/Others)    Memory ...

  2. MySQL查看数据库、表的占用空间大小

    SELECT TABLE_NAME,DATA_LENGTH+INDEX_LENGTH,TABLE_ROWS FROM information_schema.tables WHERE TABLE_SCH ...

  3. 微软在线测试题String reorder

    问题描述: Time Limit: 10000msCase Time Limit: 1000msMemory Limit: 256MB DescriptionFor this question, yo ...

  4. hdu 4585 Shaolin(STL map)

    Problem Description Shaolin temple is very famous for its Kongfu monks.A lot of young men go to Shao ...

  5. Java使用poi包读取Excel文档

    项目需要解析Excel文档获取数据,就在网上找了一些资料,结合自己这次使用,写下心得: 1.maven项目需加入如下依赖: <dependency> <groupId>org. ...

  6. 根据请求头跳转判断Android&iOS

    if(navigator.userAgent.match(/Android/i)) { window.location = 'http://apk.hiapk.com/m/downloads?id=c ...

  7. 用SHELL与列表处理了件尴尬事

    与列表语法 command-1 && command-2 && command-3 && command-4 && ...command ...

  8. hdu2795Billboard(线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=2795 单点更新,树存储的为某一行内剩余的长度 // File Name: hdu2795.cpp // Auth ...

  9. Socket 理解

    TCP/IP要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协 ...

  10. i春秋30强挑战赛pwn解题过程

    80pts: 栈溢出,gdb调试发现发送29控制eip,nx:disabled,所以布置好shellcode后getshell from pwn import * #p=process('./tc1' ...