精华内容
下载资源
问答
  • 掌握Windows内核调试技术是学习与研究Windows内核的基础,调试Windows内核的方式大致分为两种: (1)通过Windbg工具在Windows系统运行之初连接到Windows内核,连接成功之后便可以调试,此时即可以调试Windows...

    掌握Windows内核调试技术是学习与研究Windows内核的基础,调试Windows内核的方式大致分为两种:

    (1)通过Windbg工具在Windows系统运行之初连接到Windows内核,连接成功之后便可以调试,此时即可以调试Windows内核启动过程,又可以在Windows启动之后调试某内核组件或应用程序。或使用Windbg的Kernel debugging of the local mechine功能,在Windows系统完全启动之后,调试Windows内核组件或应用程序。这种方式需要配置Windows系统以DEBUG模式启动。

    (2)通过Bochs来运行Windows系统,可以在Windows运行的任意时刻调试任意信息,但最大的缺点就是,这种方式目前不支持使用Windows Symbols,与第一种方式相比,汇编代码读起来并不直观。

    本文介绍方式(1)即通过Windbg工具调试Windows内核。

    1、Windbg工具简介及获取方式

    Windbg工具是微软团队开发和公布的一款专门用于调试Windows内核及应用程序的调试器,既支持内核级(Ring0)调试,也支持应用程序级(Ring3)调试。如今的Windows系统调试器有多种,出了Windbg以外,还有Olldbg、Immunity Debugger等。Olldbg和Immunity Debugger不支持内核级调试。

    Windbg工具包含在Windows Driver Kit(WDK,Windows驱动开发包)中,当然也可以单独下载。

    (1)如果要通过WDK方式获取的话,Windows XP及之前的环境只要下载WDK即可,整个资源大约300M~500M,但是在Windows Vista/Windows 7等系统之后,微软将WDK与Visual Studio环境集成到一起,因此整个下载资源大约6.0G~7.0G。由于Windows XP系统不再支持,并且笔者的实验环境为Windows 7系统,在后续的文章中也会涉及到Windows驱动开发,所以笔者建议下载WDK与VS集成包,虽然资源比较大。

    (2)如果只是暂时学习Windows内核调试的话,可以单独下载Windbg工具,整个资源大约150M。

    以上资源皆可以在MSDN上获取,获取链接为:http://msdn.microsoft.com/zh-cn/windows/hardware/hh852365.aspx

    2、Windows Symbols简介及获取方式

    Windows Symbols是微软公开的Windows系统符号表,使用Windbg调试WIndows内核和应用程序时可以很直观地看到部分变量名称、结构体结构、函数名称等。

    Windows Symbols可以直接在MSDN上获取,其获取页面与上述给出的获取Windbg工具的页面链接相同。

    但是笔者不建议直接下载并安装Windows Symbols,因为在使用Windbg工具调试时,可以根据需要即时获取相关模块的符号信息(如果网络正常的话)。

    3、Windows内核调试方法

    通过虚拟机调试Windows系统是种常见的方式,即首先搭建虚拟机环境,即将Windows系统安装在虚拟机中,然后配置虚拟机Windows系统的启动模式为DEBUG模式,并且配置好Windbg工具与虚拟机Windows系统之间的通信通道,在Windbg进入等待调试通信的时候,重启虚拟机Windows系统,双方的调试链接建立以后,即可使用Windbg工具调试/控制Windows内核,详细步骤如下:

    (1)配置虚拟机Windows系统以DEBUG模式启动。

    进入虚拟机Windows系统,以管理员身份运行cmd.exe,执行以下命令:

    bcdedit /debug on    //启用Windows内核调试支持

    bcdedit /bootdebug on  //启用应用程序的启动过程调试支持

    关于bcdedit命令的详细信息,可以在MSDN中了解:http://msdn.microsoft.com/zh-cn/library/dn653986(v=vs.85).aspx

    上述方式仅在Windows Vista/7系统及以后版本的Windows系统中有效,如不做特殊说明,笔者的实验环境默认为VirtualBox/Windows 7系统。

    对于Windows XP系统的配置,请自行GOOGLE。

    展开全文
  • Windows 内核驱动程序入门什么是内核驱动程序二级目录三级目录 什么是内核驱动程序 在理解内核驱动程序之前,首先理解什么是驱动程序: 就最基本的意义而言,驱动程序是一个软件组件,可让操作系统和设备彼此通信。 ...

    Windows 驱动程序入门文档

    什么是内核驱动程序

    在理解内核驱动程序之前,首先理解什么是驱动程序:
    就最基本的意义而言,驱动程序是一个软件组件,可让操作系统和设备彼此通信。
    driver
    值得注意的是,并非所有的驱动程序都直接与设备通信。对于给定的 I/O 请求(如从设备读取数据),通常有一些驱动程序(在堆栈中进行分层)参与该请求。
    function driver堆栈中直接与设备通信的一个驱动程序称为“函数驱动程序” ;
    执行辅助处理的驱动程序称为“筛选器驱动程序” 。某些筛选器驱动程序观察并记录有关 I/O 请求的信息,但不会主动参与这些请求。 例如,某些筛选器驱动程序充当验证程序以确保堆栈中的其他驱动程序正确处理 I/O 请求。

    不过我们考虑的仍然不全面,因为有些驱动程序根本不与任何硬件设备相关联。例如,假设你需要编写可以访问核心操作系统数据结构的工具,这些结构仅可以由内核模式下运行的代码进行访问。 可以通过将工具拆分成两个组件来执行该操作。 第一个组件在用户模式下运行且提供用户界面。 第二个组件在内核模式下运行且可以访问核心操作系统数据。 在用户模式下运行的组件称为应用程序,在内核模式下运行的组件称为“软件驱动程序” 。
    kernel
    关于组件的理解可以参考Linux内核系统架构
    linux kernel architecture驱动可以分为不同的类型,如NT驱动、WDM驱动、WDF驱动等。
    简单来说,NT驱动是最简单的驱动模型,不支持硬件特性;
    WDM驱动是NT驱动基础上引入的一套驱动模型,支持即插即用、电源事件等特性;
    WDF驱动是对WDM驱动的封装与升级,屏蔽了部分细节,简化了大量接口。
    其中NT驱动是所有驱动类型中的基础,也是本文的中心。

    因为内核驱动程序没有明确的定义,在我看来内核驱动程序是完成硬件抽象层(HAL)与用户组件之间通信的内核组件。(如果有更好的概括,欢迎指正)

    kernel

    驱动以Windows服务的方式存在

    注: 服务有不同的类型,驱动只是其中一种类型的服务。
    一般来说,服务的基本操作有注册(创建)、启动、暂停、停止、卸载操作,但内核驱动类型的服务不支持暂停操作。你可以把内核看作是不断对请求进行响应的服务器,这些请求可能来自在CPU执行的进程,也可能来自发出中断请求的外部设备。 这里需要强调一点,内核的各个部分不是严格按照顺序依次执行的,而是采取交错执行的方式,因此,这些请求可能引起竞争条件,我们必须采用适当的同步机制对这种情况进行控制。

    服务管理器(Service Manager)

    服务管理器的主要工作是管理操作系统上的所有服务,其中包括跟踪、维护服务的各种状态,以及对服务器发起具体的操作。

    而开发者通过API操作服务时,API内部首先会通过一个称为“LPC”(Local Procedure Call本地过程调用)的方式,把请求发送给服务管理器,服务管理器再处理具体的请求。

    打开服务管理器

    打开服务管理器的函数尾OpenSCManager,原型如下

    SC_HANDLE WINAPI OpenSCManager(	//该函数返回一个SC_HANDLE的句柄,表示服务管理器的句柄
    								//开发者可以通过这个句柄,结合其他API来操作服务
    								
    	LPCTSTR	lpMachineName,		//机器的名字,字符串常量,
    								//可以简单传递NULL,表示打开的是本机的服务管理器
    	LPCTSTR lpDataBaseName,		//数据库的名字,字符串常量
    								//也可以简单传递一个NULL,表示打开的是一个Active数据库
    	DWORD	dwDesiredAccess);	//权限,DWORD (关键)
    								//开发者通过服务管理器去操作服务时,不同的操作需要不同的权限
    								//常见的服务管理器权限:
    								//SC_MANAGER_CREATE_SERVICE : 表示拥有注册(创建)服务的权限
    								//SC_MANAGER_ENUMERATE_SERVICE : 表示拥有枚举系统服务的权限
    								//SC_MANAGER_ALL_ACCESS : 表示拥有一切权限
    

    服务的注册(创建)

    注册(创建)一个服务使用的函数为CreateService,该函数原型如下

    SC_HANDLE WINAPI CreateService(		//该函数返回值为一个服务的句柄
    									//服务成功创建后,CreateService函数内部会打开这个服务
    									//开发者可以通过CreateService返回的服务句柄来操作服务
    									//使用完毕后需要调用CloseServiceHandle函数关闭句柄
    
    	SC_HANDLE	hSCManager,			//“服务管理器”句柄
    									//需要使用SC_MANAGER_CREATE_SERVICE权限
    	LPCTSTR 	lpServiceName,		//需要创建服务的名字,
    									//是服务的唯一标识,所以不能与其他存在服务的名字相同
    	LPCTSTR		lpDisplayName,		//服务的显示名字,就是为了显示,与lpServiceName不同
    	DWORD		dwDesiredAccess,	//这个权限是指创建服务成功后,再操作这个服务的权限
    									//常见的服务权限:
    									//SERVICE_START : 拥有启动服务的权限
    									//SERVICE_STOP : 拥有停止服务的权限
    									//SERVICE_QUERY_STATUS : 拥有查询服务状态的权限
    									//SERVICE_ALL_ACCESS : 拥有一切权限
    	DWORD		dwServiceType,		//服务类型
    									//SERVICE_FILE_SYSTEM_DRIVER : 文件系统服务
    									//SERVICE_KERNEL_DRIVER : 内核驱动服务
    									//SERVICE_WIN32_OWN_PROCESS : 应用层服务
    									//SERVICE_WIN32_SHARE_PROCESS : 应用层共享EXE服务
    									//对于创建驱动类型的服务,需要指定SERVICE_KERNEL_DRIVER
    	DWORD		dwStartType,		//服务的启动方式,这个启动方式是以操作系统的启动顺序来划分的
    									//常见的启动方式(按照启动顺序):
    									//SERVICE_BOOT_START : 操作系统引导阶段启动的服务,
    									//						一般由Winload模块负责加载服务对应的可执行文件到内存
    									//SERVICE_SYSTEM_START : 操作系统的启动阶段启动的服务,
    									//						  由系统NT模块负责加载服务对应的可执行文件到内存
    									//SERVICE_AUTO_START : 操作系统启动完毕后启动的服务,
    									//SERVICE_DEMAND_START : 需要手动启动的服务
    	DWORD		dwErrorControl,		//错误控制,指服务启动失败的情况下,操作系统需要执行何种操作
    									//常见的有:
    									//SERVICE_ERROR_CRITICAL
    									//SERVICE_ERROR_IGNORE(内核驱动一般指定这个)
    									//SERVICE_ERROR_NORMAL
    									//SERVOCE_ERROR_SEVERE
    	LPCTSTR		lpBinaryPathName,	//表示该服务对应可执行文件的全路径(.sys文化所在的路径)
    	LPCRSTR		lpLoadOrderGroup,	//服务所在分组的名字
    									//操作系统内置了一系列服务的分组,开发者也可以创建新的分组
    									//一个分组里面可以有很多服务,但是一个服务最多只能关联一个分组
    									//不同分组的启动顺序不同
    									//如果开发者关心服务的启动顺序,可以通过这个参数来设置
    									//如果不担心,可以把该参数设为NULL,
    									//分组信息在注册表中的位置为 
    									//HKEY_LOCAL_MACHINE\system\CurrentControlSet\Control\ServiceGroupOrder,
    									//名字为list的值保存了所有分组的信息
    	LPDWORD		lpdwTagId,			//服务在分组内的一个标识(针对SERVICE_BOOT_START和SERVICE_SYSTEM_START类型的服务)
    	LPCTSTR		lpDependencies,		//当前所注册的服务需要依赖的其他服务名的列表
    	LPCRSTR		lpServiceStartName,	//	\	表示当前以什么用户身份启动服务,
    	LPCTSTR		lpPassword			//	/	对于驱动类型的服务,简单指定NULL即可
    );
    

    打开服务的函数OpenService,函数原型如下:

    SC_HANDLE WINAPI OpenService(
    	SC_HANDLE	hSCManager,			//服务管理器句柄
    	LPCTSTR		lpServiceName,		//需要打开的服务名(唯一标识)
    	DWORD		dwDesiredAccess		//需要以何种权限打开服务
    );
    

    服务的启动与停止

    启动服务的函数StartService,函数原型如下:

    BOOL WINAPI StartService(
    	SC_HANDLE 	hService,				//服务的句柄
    	DWORD		dwNumServiceArgs,		//	\	服务启动时需要的参数
    	LPCTSTR*	lpServiceArgVectors		//	/	对于内核驱动服务,可以忽略这两个参数,直接设为NULL
    );
    

    对于内核驱动服务来说,StartService意味着把磁盘的sys文件加载到内核中,具体过程为:
    StartService函数内部通过服务管理器,让SYSTEM进程加载驱动并调用内核驱动的DriverEntry入口函数,这一系列操作都是同步的。
    此外,StartService内部还会等待DriverEntry入口函数执行返回,获取其返回值,如果DriverEntry函数返回成功,则StartService函数也相应地返回成功,否则返回失败(StartService返回失败不仅仅这一个原因,还有其他原因)

    启动服务后也会有相应的停止操作。
    停止一个内核驱动类型的服务意味着驱动模块从内存中删除,站在开发者的角度来看,当内核类型服务停止时,必须清理掉所使用的资源,避免造成资源泄露或异常。

    对于驱动来说,如何感知自身要被停止呢

    通过DriverUnload函数
    

    停止服务/暂停服务/恢复服务的函数ControlService,函数原型如下

    BOOL WINAPI ControlService(
    	SC_HANDLE			hService,		//服务的句柄
    	DWORD				dwControl,		//控制码,表示需要对服务进行何种操作
    										//SERVICE_CONTROL_PAUSE
    										//SERVICE_CONTROL_STOP
    										//SERVICE_CONTROL_CONTINUE
    	LPSERVICE_STATUS	lpServiceStatus	//返回参数,表示服务当前最新的状态
    										//这些状态保存在SERVICE_STATUS结构体中
    );
    

    服务的删除

    删除服务DeleteService,函数原型如下:

    BOOL WINAPI DeleteService( SC_HANDLE hService );  
    

    函数中hService为服务的句柄,表示需要删除的服务。

    常见的操作为:
    开发者调用OpenService函数(dwDesiredAccess为DELETE权限)打开一个需要删除的服务,成功打开后获取到需要删除的服务句柄,然后把服务句柄传递给DeleteService函数。

    服务的例子

    #include "windows.h"
    #include "stdio.h"
    
    #include "tchar.h"
    
    #define SER_NAME _T("FirstDriver")
    
    int main()
    {
    	SC_HANDLE	hSCM = NULL;
    	SC_HANDLE	hSer = NULL;
    
    	do
    	{
    		hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    		if (hSCM == NULL)
    		{
    			break;
    		}
    		//TCHAR *p = SER_NAME;
    
    		hSer = CreateService(
    			hSCM,
    			SER_NAME,
    			SER_NAME,
    			SERVICE_ALL_ACCESS,
    			SERVICE_KERNEL_DRIVER,
    			SERVICE_DEMAND_START,
    			SERVICE_ERROR_IGNORE,
    			_T("C:\\FirstDriver.sys"),
    			NULL,
    			NULL,
    			NULL,
    			NULL,
    			NULL
    		);
    		if (hSer == NULL)
    		{
    			DWORD dwErrorCode = GetLastError();
    			if (dwErrorCode == ERROR_SERVICE_EXISTS)
    			{
    				//ERROR_SERVICE_EXISTS 表示服务已经存在,不能重复注册,属于正常的情况
    				hSer = OpenService(hSCM, SER_NAME, SERVICE_ALL_ACCESS);
    				if (hSer == NULL)
    				{
    					break;
    				}
    			}
    			else
    			{
    				break;
    			}
    		}
    		printf("CreateService or OpenService succ \n");
    		getchar();
    		//准备启动服务
    		BOOL bSucc = StartService(hSer, NULL, NULL);
    		printf("StartService : %u\n", bSucc);
    		getchar();
    		//停止服务
    		SERVICE_STATUS SerStatus = { 0 };
    		bSucc = ControlService(hSer, SERVICE_CONTROL_STOP, &SerStatus);
    		printf("ControlService : %u\n", bSucc);
    		getchar();
    		//下面开始删除服务
    		DeleteService(hSer);
    	}
    	while (FALSE);
    	if (hSCM != NULL)
    	{
    		CloseServiceHandle(hSCM);
    		hSCM = NULL;
    	}
    	if (hSer != NULL)
    	{
    		CloseServiceHandle(hSer);
    		hSer = NULL;
    	}
    		
    	
    	return 0;
    }
    

    驱动的调试

    虚拟机配置

    虚拟机中管理员运行
    1.输入bcdedit /debug on
    2.输入bcdedit /dbgsettings net hostip:192.168.1.205 port:50010
    hostip后面接的是自己主机的IP地址
    得到Key,保存
    Key=24yzo2i76xzym.2lw2icor0uyty.35j1549q3mdkt.31z9xpw5v8tfmkey

    主机配置

    1.打开VS(之前的FirstDriver项目),在菜单栏中找到扩展->Driver->Test->Configure Devices
    在这里插入图片描述
    2.点击Add New Device,然后按图进行配置

    add device3.点击下一步,继续配置,最后的Bus Parameter,如果被调试机器只有一个网卡,则可不填,否则根据PCI规范,填入相应设备的总线号、设备号以及功能号。
    device configuration

    开始调试

    配置成功后,以之前的FirstDriver为例(FirstDriver代码如下,详细链接驱动编程学习4/第一个驱动程序的编写(by 奥丁)

    #include "ntddk.h"
    
    VOID DriverUnload(PDRIVER_OBJECT DriverObject)
    {
    	if (DriverObject != NULL)
    	{
    		DbgPrint("[%ws]Driver Upload,Driver Object Address:%p",__FUNCTIONW__,DriverObject);
    	}
    	return;
    }
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
    {
    	DbgPrint("[%ws]Hello Kernel World",__FUNCTIONW__);
    	if (RegistryPath != NULL)
    	{
    		DbgPrint("[%ws]Driver RegistryPath:%wZ\n",__FUNCTIONW__,RegistryPath);
    	}
    	if (DriverObject != NULL)
    	{
    		DbgPrint("[%ws]Driver Object Address:%p\n", __FUNCTIONW__, DriverObject);
    		DriverObject->DriverUnload = DriverUnload;
    	}
    	return STATUS_SUCCESS;
    }
    

    1.在DriverEntry入口函数中加入一个KdBreakPoint断点(Debug版本)或者DbgBreakPoint(Release版本)

    修改后的DriverEntry函数(Debug版本)

    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
    {
    	KdBreakPoint();
    	DbgPrint("[%ws]Hello Kernel World",__FUNCTIONW__);
    	if (RegistryPath != NULL)
    	{
    		DbgPrint("[%ws]Driver RegistryPath:%wZ\n",__FUNCTIONW__,RegistryPath);
    	}
    	if (DriverObject != NULL)
    	{
    		DbgPrint("[%ws]Driver Object Address:%p\n", __FUNCTIONW__, DriverObject);
    		DriverObject->DriverUnload = DriverUnload;
    	}
    	return STATUS_SUCCESS;
    }
    

    2.重新生成FirstDriver.sys文件,然后在vs菜单中选择调试->附加到进程,然后按图配置
    附加到进程3.点击附加后会显示Debugger Immediate Window界面
    Debugger Immediate Window4.重启被调试机,会主动连接设置的50010端口,连接建立好后,可以在Debugger Immediate Window中看到图中信息

    Debugger Immediate Window
    5.把FirstDriver.sys文件放入被调试机的C盘根目录下
    然后cmd管理员运行执行命令
    sc create FirstDriver binPath= "C:\FirstDriver.sys" type= kernel start= demand
    sc start FirstDriver
    就会停在KdBreakPoint处
    vs中F10单步调试驱动代码

    也可以用Windbg调试

    展开全文
  • 这是一个windows 上的调试工具,按照他要求的格式打印调试信息,程序运行期间会被debug view抓获,并显示在信息窗口中,便于调试
  • 终于有机会真正使用windbg了,一个小小的任务,用了两天时间,总算从一问三不知进化到可以进行简单的调试。 任务:分析PING.EXE程序,找到系统调用API,分析获得IP地址存放位置; 首先需要弄清楚的是PING.EXE执行...
    开始使用Windbg
    终于有机会真正使用windbg了,一个小小的任务,用了两天时间,总算从一问三不知进化到可以进行简单的调试。
    任务:分析PING.EXE程序,找到系统调用API,分析获得IP地址存放位置;
    首先需要弄清楚的是PING.EXE执行过程,以及该过程中所调用的系统调用。师兄推荐了一个很好用的软件:
    API Monitor(链接:http://www.rohitab.com/apimonitor/)
    截图:

    主要用的三个模块 :设置API过滤器,进程监控窗口Process Monitor ,点击相应API查看具体参数;
    软件捕获到的API很多,而Ping程序真正使用的程序只有几个,4000多个API翻到3500左右才会发现有用信息;

    Ping程序中调用的两个重要函数:一个是IcmpSendEcho2Ex,一个是NtDeviceIoControlFile;
    参数设置如下,其中最重要的两个参数 IoControlCode 和 InputBuffer,接下来的工作就是在Windbg下获取当IoControlCode值为0x00120013时,InputBuffer中的IP地址;

    使用Windbg进行调试,最基本的操作为加断点及查看内存。
    加断点的方法可以参考以下几篇文档:
    http://www.dbgtech.net/windbghelp/hh/debugger/t01_basic_a4ebd4e7-bb0c-4d6b-b04a-11e823bae62c.xml.htm (设置条件断点)
    http://blog.csdn.net/vangoals/article/details/4458051 (Windbg常用断点设置)
    首先打开Windbg.exe,file-》Open Executable->

    将C:\\windows\system32\Ping.exe加入Windbg;
    使用bu命令分别设置如下断点,语法:bu 符号;

    使用bu代替bp设置断点的好处为,bu设置的为永久断点,断点保存在工作空间中,bp设置的为临时断点,下次加载程序调试,需要重新设置;但bu的缺点是,没有添加条件。每次都需要使用dd指令查看NtDeviceIoControlFile的参数判断是否为需要捕获的API;
    一篇很好的文章推荐给大家:http://www.cnblogs.com/huangyong9527/archive/2012/08/22/2650948.html

    通过理解上面的文章,我明白了一下几个寄存器内容的含义:
    首先想要查看当前捕获到的函数具体信息,需要执行dd 指令,用来查看内存;
    而ChildEBP中存放的则为本函数地址,RetAddr存放的为返回地址,之后为参数;
    也可以通过Windbg菜单栏中View-》Memory,直接查看内存;
    通过学习,找到了本程序中添加条件断点的方法:
    bu ntdll!NtDeviceIoControlFile  " j (IoControlCode=00120013)  ' ' ; ' gc '  "
    这里有一个技巧就是学会分析内存内容,楼主在查看InputBuffer内容时发现该地址下没有存储任何IP地址信息,而是一些指针,但通过Windbg并不能真正看到内核中这些地址信息的变化(注意此处楼主只是调试了可执行程序,并没有进入内核调试,目前Windbg仅支持WinXP系统的本地内核调试),通过不断尝试ping 不同的IP地址,楼主发现每次IP地址的存放位置为
    InputBuffer地址+0x5ec!!!!!!
    通过不停的尝试加断点查看内存,终于找到了需要的内容,任务完成。

    展开全文
  • 内核调试主要用来调试驱动代码、分析内核结构等。 WinDbg通过两台电脑可以实现内核调试,其中一台电脑运 行WinDbg,被称为主机;另外一台电脑运行被调试的程序或系统,被称为目标机。一般情况下两台电脑都是真实机 ...

      内核调试主要用来调试驱动代码、分析内核结构等。 WinDbg通过两台电脑可以实现内核调试,其中一台电脑运
    行WinDbg,被称为主机;另外一台电脑运行被调试的程序或系统,被称为目标机。一般情况下两台电脑都是真实机
    器,这样调试最符合实际情况,两台电脑通过串口线、 1394线或USB对联线连接起来实现双机内核调试。如果没 有
    两台电脑,也可以用虚拟机来模拟目标机,主机上运行WinDbg ,虚拟机中安装Windows运行被调试的程序,虚拟
    机通过模拟的串口输出为主机上的一个命名管道,从而和主机上的WinDbg连接起来实现双机 内核调试。
        除双机内核调试外, WindowsXP后还引入了一种本机内核调试方式,只需要一台电脑,直接运行WinDbg就 能
    查看修改系统内核结构等,不过所有和中断目标机系统相关的命令都不能执行,如断点命令。
         如果采用虚拟机模拟目标机,调试响应速度有时候是个问题,比1394线连接的真实双机调试速度要慢不少,特
    别是执行操作大量内存的命令时(如搜索内存命令),感觉非常明星。所以针对这种情况还会介绍一个特殊的辅助调 试
    工具vmkd ,该工具可以大大加速内核调试的速度,为咱们带来不少方便。
        下面分节详细介绍各种内核调试情景下的配置,尽量每个步骤都截图说明。

    真实机双机内核调试

        真实机之间的内核调试首先需要准备连接线,可以用串口线、 1394线或者USB对联线。
        串口线速度太慢,而且电脑城一般买不到可以直接使用的串口线,需要把线和接头买回来自己焊,按照WinDbg
    帮助中的说明交叉焊接,就能得到一根可用来调试的串口线。用串口线把两台电脑连接上后,先用Windows自带的
    超级终端工具,选择好串口和波特率连接。如果在超级终端中按键能在另外一台电脑的超级终端上显示按键,则表示
    串口线连接成功。接下来就可以用WinDbg连接串口调试。某些笔记本上可能没有串口,可以买一个USB转串口的
    接头,然后设置USB转换后的串口号,就能把这台笔记本当作主机使用。
       1394线速度快,价格也便宜,如果电脑上没有1394口,可以再另外买一个1394卡,价格也很便宜。 1394分
    大口和小口,只需按照电脑上的接口大小购买合适的线就行。如果没有1394口,装一个1394卡又很麻烦,则也可
    以买一个USB转1394口的接头,不过一样只能当作主机使用。
       USB对联线是Vista系统以后支持的内核调试连接方式,没见到哪里能买到这样的线,估计速度会更快一点吧!
       因为1394线连接调试最方便,速度也比较快,所以建议使用这种方式。
        电脑、连接线等准备好后,先设置目标机系统,启用内嵌在系统中的内核调试引擎。 Vista之前的系统,用记事 本
    打开系统盘根目录下的boot.ini文件,添加新的启动项,在新的启动项上添加调试选项。如下表,红色行表示新加的
    启动项, /debug表示打开内核调试引擎, /debugport=1394表示采用1394连接方式, /channel=10表示设置 通
    道号为10。

    [csharp] view plain copy

    1. [bootloader]  
    2. timeout=30  
    3. default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS  
    4. [operatingsystems]  
    5. multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="MicrosoftWindowsXPProfessional"  
    6. /noexecute=optin/fastdetect  
    7. multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="WINXP-Debug"/noexecute=optin/debug  
    8. /debugport=1394/channel=10  


       Vista之后的系统需要修改BCD数据库,利用bcdedit工具添加启动项,设置调试选项。如下表,以管理员方 式

    运行命令行程序,先复制当前项生成新的启动项,然后在新的启动项上操作,打开内核调试、设置调试连接方式、设
    置1394通道号。

    [csharp] view plain copy

    1. C:\>bcdedit/copy{default}/d"Vista-RemoteDebug"  
    2. 已将该项成功复制到{13fbbedc-756a-11dc-aed8-0016e68bceb3} 。  
    3. C:\>bcdedit/set{13fbbedc-756a-11dc-aed8-0016e68bceb3}debugtype1394  
    4. 操作成功完成。  
    5. C:\>bcdedit/set{13fbbedc-756a-11dc-aed8-0016e68bceb3}channel10  
    6. 操作成功完成。  
    7. C:\>bcdedit/debug{13fbbedc-756a-11dc-aed8-0016e68bceb3}on  
    8. 操作成功完成  


         设置完目标系统后重启,在选择启动菜单时停下来,在主机上通过如下命令行运行WinDbg准备连接到目标机

    [csharp] view plain copy

    1. D:\WinDbg>windbg-d-k1394:channel=10  


    -d表示在连接上目标系统后马上中断下来,这个也是最早的断点,该选项主要是为了在目标系统初始化早期就断下 来
    查看系统状态,当前情况下可以不要,1394:channel=10表示连接方式和通道号。第一次采用1394内核调试时,
    WinDbg可能会显示启动驱动失败,再次运行WinDbg应该就好了。运行WinDbg后,显示如下界面:

    表示WinDbg已经准备好,正在等待1394连接。然后返回目标机,选择前面添加的启动项(也就是打开了内核调 试
    选项的启动项),如下图,真实机器无法截图,这里用虚拟机截图代替。

    选择该启动项后,系统就会加载内核,初始化内核调试引擎,不一会(几秒钟)就能在主机的WinDbg上看到输出信
    息,接着中断在WinDbg中,如下图(写这篇文章时还是用的虚拟机截图,呵呵):

    可以看到WinDbg显示已经连接到WindowsXP系统上,并显示了符号路径、内核基址等信息,然后中断下来得到 控
    制权,输入k命令可以看到当前调用栈,输入g命令让目标系统继续启动。开始调试后,在WinDbg中可以随时按

    Ctrl+Break组合键或通过工具栏按钮中断目标系统。

        如果前面运行WinDbg时不习惯命令行方式,也可以先打开WinDbg ,然后选择菜单File/KernelDebug打开
    内核调试连接对话框,切换到第二个 “ 1394” 选项卡,在channel下面的编辑框中输入通道号10,点击 “ 确定 ” 按
    钮开始连接目标机。

    这样和前面命令行运行WinDbg的效果一样,就是没了 -d选项,可以在等待连接的界面上按两次Ctrl+Alt+k组合 键
    达到相同的效果

          真实机采用1394调试时,如果目标机系统是Windows2003 (未安装ServicePack )或者WindowsXPSP 1,
    则连接调试前,需要先在目标机上的 “ 设备管理器” 中禁用1394控制器。如果目标机上是Vista、 Windows2003SP1
    或者WindowsXPSP2等系统之后的系统,则不要禁用1394控制器。另外,如果主机是Vista之前的系统,用1 394
    调试时连接有问题,则可以尝试在主机的 “ 设备管理器” 中禁用1394网络适配器。

    虚拟机双机内核调试

         真实机毕竟硬件成本高,需要两台电脑,还得买连接线。如果调试要求不高,很多情况下可以用虚拟机模拟目标
    机,实现双机内核调试。当前常用的虚拟机有两种: VMWare和VirtualPC ,都提供了免费版本,运行速度相当于主
    机的一半左右。估计现在大家都是双核的电脑,运行虚拟机还是没问题的。 VMWare似乎速度要快一点点,而且提 供
    的快照功能非常方便,可以随时把系统还原到以前保存的状态。 VirtualPC似乎兼容性要好一点,有时候在VMWare
    上安装系统蓝屏,用VirtualPC就没问题。
        首先也是选择连接方式,用虚拟机只有一种串口方式,通过虚拟机模拟的串口输出到主机上的命名管道,然后
    WinDbg连接这个命名管道,从而实现主机和虚拟机的连接。
       在虚拟机中安装好系统后,关闭虚拟机系统,打开虚拟机系统的设置框, VMWare中如下图:

    选择Editvirtualmachinesettings ,打开设置对话框:

    首先选择Add... 按钮添加Serial设备,然后按照上图设置Serial属性。命名管道名称为WinDbg连接时需要用到的
    管道名, \\.\pipe\前缀不可少,后面接一个容易理解的名称即可。
    VirtualPC虚拟机也差不多,先安装好系统,选择系统,点击Settings按钮:

    打开虚拟机系统设置对话框,选择左边的COM1项,在右边设置输出的命名管道名称。

         设置好硬件连接方式后(这里是虚拟硬件),启动虚拟机中的系统,添加调试启动项。因为虚拟机只是虚拟了串 口,
    所以设置系统启动项时只能使用串口方式。 Vista之前的系统通过修改boot.ini文件实现,如下表。红色项表示新添
    加的启动项, /debug表示打开内核调试引擎, /debugport=com1表示采用串口1通信, /baudrate=115200设
    置串口1的波特率为115200 。

    [csharp] view plain copy

    1. [bootloader]  
    2. timeout=30  
    3. default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS  
    4. [operatingsystems]  
    5. multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="MicrosoftWindowsXPProfessional"  
    6. /noexecute=optin/fastdetect  
    7. multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="WINXP-Debug"/noexecute=optin/debug  
    8. /debugport=com1/baudrate=115200  

    Vista之后的系统,以管理员权限打开命令行窗口,通过bcdedit工具修改BCD数据添加启动项。

    [csharp] view plain copy

    1. C:\>bcdedit/copy{default}/d"Vista-RemoteDebug-1394"  
    2. 已将该项成功复制到{13fbbedc-756a-11dc-aed8-0016e68bceb3} 。  
    3. C:\>bcdedit/set{13fbbedc-756a-11dc-aed8-0016e68bceb3}debugtypeSERIALDEBUGPORT:1  
    4. BAUDRATE:115200  
    5. 操作成功完成。  
    6. C:\>bcdedit/debug{13fbbedc-756a-11dc-aed8-0016e68bceb3}on  
    7. 操作成功完成  


    设置好启动项后,重启虚拟机中的系统,在选择启动菜单项时停下来,返回主机,通过命令行启动WinDbg。

    [csharp] view plain copy

    1. D:\WinDbg>windbg-d-kcom:pipe,port= \\.\pipe\vmdbg_winxpen,baud=115200  


     

    注意红色字表示的管道名称,需要和虚拟机中的设置一样。这里照样可以通过菜单打开内核调试连接对话框来操作。


    注意管道名称要一致,选中Pipe项,然后确定,WinDbg则会开始等待连接。

    此时返回虚拟机中选择调试启动项,一会就能看到WinDbg中显示连接上虚拟机的信息

         建立连接后,就和调试真实机一样,操作也一样。只有当调试某些和特殊硬件相关的驱动,或者调试和3D游戏

    相关的程序时,还是得用到真实机。另外,运行虚拟机毕竟影响主机速度,特别是读取硬盘时感觉比较明显。而且当
    WinDbg中断下目标系统后,虚拟机基本上就把CPU给占满了,双核时还好,单核时搞的主机都没办法动。当然调试
    速度也是个问题,照理说都是一台电脑(虚拟机也还是运行在主机上),传输速度应该很快。但因为串口是完全模拟 的,
    串口设计决定了速度不可能快,所以下面介绍一个用于虚拟机调试时的加速工具: vmkd 。

     

                  Vmkd是内核调试高手Skywing推出的一个工具,主要用于加快VMWare内核调试的速度,官方网站在:
    http://www.nynaeve.net/?page_id=168 。 vmkd相当于接管了内核调试引擎传输通道,以前是:虚拟机系统内
    核 <->模拟串口 <->命名管道 <->WinDbg,使用vmkd后变成:虚拟机系统内核<->vmkd内核模块kdvmware <->vmkd注入模块vmxpatch<->新的命名管道 <->WinDbg,因为不走虚拟机的模拟串口传输数据,而是虚拟机端
    的kdvmware和主机端的vmxpath直接复制内存,所以传输速度大大加快。

     

    详细使用步骤如下:
    1.在虚拟机中安装好系统,并按照前一节所述设置好串口调试。
    2.把vmkd带的kdvmware.sys复制到虚拟机中C:\WINDOWS\system32\drivers目录下,在虚拟机中使
    用 命 令 行sccreatekdvmwarestart=demandtype=kernelbinPath=
    c:\windows\system32\drivers\kdvmware.sysDisplayName=kdvmware安装驱动。

     

    3.重新启动虚拟机中的系统,选择调试启动项进系统。



    4.在主机上找到启动虚拟机的vmware-vmx.exe进程的pid ,利用vmxinject.exepid命令把vmxpatch. dll
    注入到vmware-vmx.exe进程

    [csharp] view plain copy

    1. D:\DbgTools\vmkd>tlist-mvmware-vmx.exe  
    2. D:\ProgramFiles\VMware\VMwareServer\bin\vmware-vmx.exe-6096vmware-vmx.exe  
    3. OleMainThreadWndName  
    4. D:\DbgTools\vmkd>vmxinject6096  
    5. OK  

    5.在虚拟机中通过netstartkdvmware命令启动驱动。

    6.在主机上启动WinDbg连接虚拟机中的系统开始调试,命名管道名称中的winxpen是虚拟机系统的安装文
    件夹(比如: d:\VMs\winxpen )。

    [csharp] view plain copy

    1. windbg-kcom:pipe,port=\\.\pipe\kdvmware_winxpen,baud=115200  

    命名管道名称如果不确定,可用WinObjEx工具查看系统中的所有命名管道名,如下图,最下面的就是vm kd
    使用的管道名。

    连接后如下图:

    此时再调试会发现单步速度非常快,运行一下搜索命令s就能感觉出来,甚至.dump命令也很快能执行完。

    本机内核调试

         本机内核调试是WindowsXP之后的系统引入的一种内核调试方式,说调试其实有点不准确,因为没有单步、 断
    点等调试必备的功能,只能读写内存。不过用来查看系统内核信息时还是非常方便的,不需要两台电脑(连虚拟机也
    不需要,完全在本机运行),能够利用大部分WinDbg自带的扩展命令,在XP以后的系统上都能使用,包括32/64
    系统。

          在Windows2003SP1之前的系统上,系统通过ntdll!ZwSystemDebugControl函数提供本机内核调试支 持。
    之后的系统通过WinDbg自带的kldbgdrv.sys驱动调用nt!KdSystemDebugControl函数提供本机内核调试支持 。
    官方文档建议在启动项中添加 /Debug选项启动系统,然后使用本机内核调试功能。但一般情况下不需要这么做, Vista
    之前的系统上,可以直接运行WinDbg打开本机内核调试;Vista及之后的32位系统,可以利用笔者写的一个小工
    具VistaLKD开启本机内核调试功能,再运行WinDbg打开本机内核调试;Vista及之后的64位系统暂时只能修改
    启动项添加 /Debug选项来开启本机内核调试功能。
         启动本机内核调试非常简单,加上 -kl命令行启动WinDbg即可

    [csharp] view plain copy

    1. D:\WinDbg>windbg-kl  

    显示界面如下:

    也可以运行WinDbg后打开内核调试连接对话框,选择Local选项页,点击 “ 确定 ” 按钮打开本机内核调试功能

        Vista及以后的系统,记得先以管理员权限运行VistaLKD工具,点击Enablelocalkerneldebug按钮开启本
    机内核调试功能,然后再以管理员权限运行WinDbg打开本机内核调试。

     

    本机内核调试下可以做很多事情,比如查看内核结构定义、反汇编内核函数、显示内核Hook等。

    展开全文
  • Windows 调试程序 (WinDbg) 可用于调试内核模式和用户模式代码、分析故障转储以及在代码执行时检查 CPU 寄存器。
  • 首先是NtCreateDebugObject函数,用于创建一个内核调试对象,分析程序可知,其实只是一层对ObCreateObject的封装,并初始化一些结构成员而已。 我后面会写一些与window对象管理方面的笔记,会分析到对象的创建过程...
  • 首先你要配置好测试环境:参考VMware+Windgb+Win7 内核驱动调试在你的主机上配置Symbols 配置sympath,C:\Users\Admin\Desktop\first\objchk_win7_x86\i386是你编译好的sys目录: SRV*C:\Symbols*...
  • 昨天阅读了内核池的一些原理,与Linux堆还是有很多相似的。今天继续调试HEVD中池溢出攻击。参考的原文: 传送门 0x01:漏洞原理 漏洞源码: NTSTATUS TriggerPoolOverflow(IN PVOID UserBuffer, IN SIZE_T Size) { ...
  • 我使用的书是《寒江独钓Windows内核安全编程》,这个系列将围绕三本书进行,一本就是刚刚所提到的,还有两本分别为《天数夜读从汇编语言到Windows内核编程》和《Windows内核安全与驱动开发》。 首先来总结一下双机...
  • Windows内核开发调试环境配置详解

    千次阅读 2011-08-31 16:27:51
    应用程序使用开发包SDK,类似的,内核编程使用"Windows Driver Kit",简称WDK。WDK已经自带所有需要的头文件、库、C/C++语言及汇编语言的编译器和链接器 如何获取WDK 参见 http://msdn.microsof
  • 使用VMWare workstation调试Windows内核驱动的方法在网上很容易就能找到一大堆文章,不过方法只有那么一个,其原理上都是通过重定向虚拟机串口设备到管道然后使用Windbg程序关联管道进行调试。不过其中有两个小地方...
  • 内核驱动运行、调试 驱动的运行 由于Windows数字签名的原因,没有签名或者使用测试签名的都不能放到64位系统上运行。 两个解决办法。 一、将系统设置为调试模式 二、关闭系统的驱动签名校验。 服务的基本操作 服务...
  • 通过编译所需的更改文件并将创建的obj文件与内存中已加载的代码链接,从而在调试中更新源代码/全局变量,而无需卸载驱动程序或重新启动计算机,然后替换旧的功能obj由新obj中的新函数组成(即使这些函数相同,现在...
  • 内核驱动运行与调试 驱动的运行 驱动的运行通过服务来实现。 微软规定,驱动文件必须经过微软的数字签名后,才可以运行在64位系统上,如果把没有经过签名的驱动直接放在64位操作系统中运行,结果是驱动加载失败,...
  • windows内核编程(或者说驱动编程,因为本人喜欢这个霸气)
  • 在驱动程序的开发中,经常会遇到系统崩溃一情况,我们很难想像用VC的调试器那样单步调试程序。但还是有一些高级驱动程序调试技巧, 可以帮助找出驱动程序中的Bug。另外,利用一些第三方工具软件,也可以帮助...
  • 虽然是一个典型的GUI应用程序,但是它的大多数调试功能还是以手工输入命令的方式来工作的。目前版本的WinDbg提供了130多条标准命令,140多条元命令和难以计数的扩展命令。 WinDbg使用工作空间来描述和存储调试项目...
  • 本文将对Windows平台下的内核调试中,对我们想要调试的用户态进程进行下断点等探索 1. 准备工作 见初探 2. 对调试目标程序下断点 我们在初探中已经提到对记事本进程进行观察的方法,这里我们将尝试对自己的进程下...
  • Windbg内核调试Windows Server 2008

    千次阅读 2012-05-10 16:32:55
    本文介绍利用Windbg和VMware调试驱动程序的配置过程,关于VMware设置的部分网上有很多教程,就不再阐述。 这里给一个参考的文章:http://blog.csdn.net/goodwinds/article/details/2487819 一般的教程都以XP为例...
  • Windows+vm双机调试内核

    2019-12-30 14:19:51
    参考链接 编写通用 Hello World 驱动程序 (KMDF) - Windows drivers | Microsoft Docs ...调试环境 通常,在测试和调试驱动程序时,调试程序和...
  • 使用WinDbg内核调试

    2010-10-30 15:58:08
    本教程的目标是给予一个已经有其他调试工具使用经验的开发者足够信息,使其能通过参考WINDOWS调试工具的帮助文件进行内核调试。本文将假定开发者熟悉一般WINDOWS操作系统和进程的建立过程。 本文的重点是集成内核...
  • 调试程序是参照《寒江独钓——Windows内核编程》敲的,算是一次整理加深印象。 一、准备工作:  1、WDK  可以在:http://www.microsoft.com/en-us/download/details.aspx?id=11800,下载到,注意最好选择完整...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 858
精华内容 343
关键字:

windows内核调试程序