购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.2 初始化模拟调试

在kd和osloader工程项目菜单中设置“SIMULATE_DEBUG”(在配置属性→C/C++→预处理器下的预处理器定义中),选中“控制台(/SUBSYSTEM:CONSOLE)”(在配置属性→链接器→系统下的子系统中),输入“kd.lib rtl.lib kernel32.lib”(在配置属性→链接器→输入下的附加依赖项中)。不同的编译环境,链接过程有可能链接不了,所以有时需要调整编译和链接参数。图3.2显示了在Visual Studio 2008中如何跟踪模拟调试系统的初始化过程,在KdpInitSystem函数内按F9键下源码断点,按F5键直接运行,中断下来后,可以单步跟踪每一行代码。

图3.2

由于WinDbg是通过命名管道与虚拟机系统通信的,在windbg.exe快捷方式中,如果指定为com:port=\\.\pipe\com_1,那么在创建命名管道时也要指定\\.\pipe\com_1。PIPE_ACCESS_DUPLEX(3)标识通信双方都能读/写,一次最大读/写4096B。

创建好命名管道后,ConnectNamedPipe函数会一直等待,直到接收到连接,流程再继续向下运行,SetUnhandledExceptionFilter函数设置异常回调。如果osloader.exe自身在Visual Studio 2008中处于被调试状态,则会略过回调;如果osloader.exe没有被调试器调试,而在运行时产生了异常,这个回调例程会接管处理。

我们使用命名管道读/写数据,但传入参数Value(端口值)就被忽略了,由全局句柄变量g_hPipe代替。在读命名管道之前必须调用PeekNamedPipe函数来探测管道有没有数据,否则线程会一直等待。因为API函数ReadFile函数阻塞式读管道,读不到不会返回,这一点在编程时特别需要注意。每次读/写都是一字节一字节进行,使用IN/OUT指令读/写端口也是按一字节进行的。SIMULATE_READ_PORT_UCHAR、SIMULATE_WRITE_PORT_UCHAR和READ_PORT_UCHAR、WRITE_PORT_UCHAR一样都能读/写一字节。

这样的定义兼容两种调试模式(模拟调试和内核调试),参数p是PUCHAR指针类型,x86指针都占4B,p需要指明从哪个端口中读取1B。前面说过,对于模拟调试输入的参数p(端口值)被忽略。

对于内核调试端口的读/写,使用IN/OUT两个指令,实际上系统和外围设备的通信,大部分都使用这两个指令。因为端口的范围是0000—0xffff,所以通常用dx寄存器代表端口,eax代表输入的数据。读/写函数基本分为8位、16位和32位。这些函数的实现大都是在hal.dll模块中,是导出函数,当然也可以在模块中自己定义,因为实现比较简单。 4N8MMdkMdf/w5xtAGk8qxnEt2MlufoLGoiXSx8/6JaHWgm7/YHs6Is89dMFHtQfu

点击中间区域
呼出菜单
上一章
目录
下一章
×