windbg通过qemu的gdbserver调试虚机windows的方法

2023-12-24 23:20

本文主要是介绍windbg通过qemu的gdbserver调试虚机windows的方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 概述

1.1. 原理

通过qemu-system程序启动的虚机,命令行里一般带有monitor。连接上这个monitor,可以启动gdbserver。通过此gdbserver,可以查看虚机的cpu寄存器,虚拟地址内存等。同时,qemu-system提供了一个tcpserver。另一台机的windbg可以连接上这个tcpserver,进而调试虚机。

1.2. 推荐场景

虚机windows未开启调试,但是虚机偶发的卡死发生时。

1.3. 优劣

优势:

A. 不需被调试机bcdedit事先配置

B. 若开启嵌套虚拟化,还能观察L1虚机的hvix64的代码运行

缺陷和限制:

仅限于qemu-system启动的虚机,tci产品不支持。

windbg里定位pe模块比较复杂。

2. qemu主机配置

2.1. 以新平台的idv为例

在qemu-system的命令行中可以看到-qmp unix:/tmp/vm.monitor,server,nowait,由此,在linux shell里执行qmp-shell -H /tmp/vm.monitor即可进入qmp的交互终端。

输入gdbserver tcp::35100得到Waiting for gdb connection on device 'tcp::35100'即表明gdbserver开启成功。gdbserver默认端口1234,会被ranios的防火墙拦截。这里推荐端口选35100,它在rainos防火墙的白名单中。

退出qmp交互终端用Ctrl+d,不可用Ctrl+c,它会让qemu-system进程终止。

2.2 vdi

先找出vdi虚机的id和所在运行服务器。ssh连上服务器,先找出虚机对应的domain:

virsh list|grep 120fb070-6b04-4766-b534-38e3131a6c11

得到315   120fb070-6b04-4766-b534-38e3131a6c11   running

遂用libvirt打开它的gdbserver

virsh qemu-monitor-command 315 --hmp gdbserver tcp::35900

3. 调试机配置

参考使用 EXDI 设置 QEMU 内核模式调试

ExdiGdbSrv.dll(64位),exdiConfigData.xml,systemregisters.xml我已集成到\\rcc.ruijie.net\Upload\lida\Microsoft.WinDbg_1.2202.7001.0.zip

设置环境变量:

EXDI_GDBSRV_XML_CONFIG_FILE为"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\exdiConfigData.xml"

EXDI_SYSTEM_REGISTERS_MAP_XML_FILE为"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\systemregisters.xml"

解压此zip,在里面有这个dll和两个xml。以管理员权限执行如下:

注册dll:

regsvr32 ExdiGdbSrv.dll

编辑exdiconfigData.xml,找到<  = "QEMU">里的<Value HostNameAndPort=",这里的值改为qemu主机的ip和gdbserver的port

cmd进入windbg路径,执行.\dbgx.shell.exe -v -kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi,随后能看到新的cmd窗口和windbg preview的窗口出现。在windbg中看到Connected to eXDI Device 0 x64 target at (即可认为连上了被调试机

4. windbg内定位pe模块

4.1 定位nt(ntoskrnl.exe)模块

在windbg里输入Ctrl+break或已经发现windbg暂停了target机,输入k,lm,.reload等命令发现没有任何模块被识别。具体原因不明。但是我们可以自行帮windbg定位符号。暂停时,通过r rip查看rip寄存器,若为fffff802`3c7f5e8f前5位是fffff如此字样则表示暂停在内核态,若为00007ffa`f2ebc742前四位是0如此字样则表明暂停在用户态,此时可g再暂停或~1s切换一个cpu线程,直到rip走到内核态。

以rip=fffff802`3c7f5e8f为例,猜测这段地址处于nt模块中,而nt模块的载入地址一般是0x100000的整数倍。用windbg的!dh来解析这个pe头,挨个输入700000,600000,500000……直到解析成功

0: kd> !dh fffff8023c700000
No file header
0: kd> !dh fffff8023c600000
No file header
0: kd> !dh fffff8023c500000
No file header
0: kd> !dh fffff8023c400000

File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
    8664 machine (X64)
      21 number of sections
C3F2329E time date stamp Mon Mar  5 06:56:30 2074

如上,表明fffff8023c400000是个pe头位置。翻阅pe信息,查看

OPTIONAL HEADER VALUES
     20B magic #
   14.20 linker version
  8BB400 size of code
  1B7400 size of initialized data
  48E000 size of uninitialized data
  98F010 address of entry point
    1000 base of code
         ----- new -----
fffff8023c400000 image base
    1000 section alignment
     200 file alignment
       1 subsystem (Native)
   10.00 operating system version
   10.00 image version
   10.00 subsystem version
 1046000 size of image

可知这个pe文件占据空间0x1046000字节。

查看

Debug Directories(3)
        Type       Size     Address  Pointer
        cv           25       406e0    3fee0        Format: RSDS, guid, 1, ntkrnlmp.pdb

可知这个pe文件是nt。

如此,可用.reload指定这段空间为nt:.reload /f nt=fffff802`3c400000,1046000

之后,可以使用!process 0 0查看所有进程。

4.2 lm后又失去所有模块的指定了。注意不要随便lm。原因未知

4.3 定位用户态dll的位置

例如给新进程的诞生处下断点:bp nt!PspInsertProcess;g。待断点触发时,看到栈回溯是:

Breakpoint 0 hit
nt!PspInsertProcess:
0010:fffff8023cae52a4 488bc4          mov     rax,rsp
0: kd> k
 # Child-SP          RetAddr               Call Site
00 ffff85052613aeb8 fffff8023cac9028     nt!PspInsertProcess
01 ffff85052613aec0 fffff8023c80d8f5     nt!NtCreateUserProcess+0xd88
02 ffff85052613bb90 00007ffaf2ece9b4     nt!KiSystemServiceCopyEnd+0x25
03 00000062d50fcd08 00007ffaf0529053     0x00007ffaf2ece9b4
04 00000062d50fcd10 0000000000000000     0x00007ffa`f0529053

看RetAddr,猜测地址7ffaf2ece9b4位于用户态,而且一般是ntdll.dll或kernelbase.dll。输入!dh 7ffa`f0520000,果然它是kernelbase.dll:

0: kd> !dh 7ffa`f0520000

File Type: DLL
FILE HEADER VALUES
    8664 machine (X64)
       7 number of sections
E8E9AC9B time date stamp Thu Oct 29 12:16:27 2093

……

  2D2000 size of image

……

Debug Directories(4)
        Type       Size     Address  Pointer
        cv           27      26a170   269370        Format: RSDS, guid, 1, kernelbase.pdb

如此可指定kernelbase的地址:.reload /f /user kernelbase=7ffa`f0520000,2D2000

输入k查看栈回溯:

0: kd> k
 # Child-SP          RetAddr               Call Site
00 ffff85052613aeb8 fffff8023cac9028     nt!PspInsertProcess
01 ffff85052613aec0 fffff8023c80d8f5     nt!NtCreateUserProcess+0xd88
02 ffff85052613bb90 00007ffaf2ece9b4     nt!KiSystemServiceCopyEnd+0x25
03 00000062d50fcd08 00007ffaf0529053     0x00007ffaf2ece9b4
04 00000062d50fcd10 00007ffaf05265e3     kernelbase!CreateProcessInternalW+0xfe3
05 00000062d50fe2e0 00007ffaf26ee2e0     kernelbase!CreateProcessAsUserW+0x63
06 00000062d50fe350 0000000000000001     0x00007ffaf26ee2e0
07 00000062d50fe358 00007ffaee361e09     0x1
08 00000062d50fe360 00007ffaee488dd0     0x00007ffaee361e09
09 00000062d50fe368 00007ffaee3a3a48     0x00007ffaee488dd0
0a 00000062d50fe370 0000000000000000     0x00007ffa`ee3a3a48

猜测7ffaf2ece9b4位于ntdll,从7ffaf2ec0000逐个递减0x1000用!dh翻译,直到找出了pe头:

0: kd> !dh 7ffa`f2e30000

File Type: DLL
FILE HEADER VALUES
    8664 machine (X64)

……

  1F8000 size of image

……

Debug Directories(4)
        Type       Size     Address  Pointer
        cv           22      140160   13d360        Can't read debug data cb=0

这里Debug Directories无法显示pdb文件名,原因未知。强行把它指定为ntdll:

.reload /f /user ntdll=7ffa`f2e30000,1f8000

查看栈回溯:

 # Child-SP          RetAddr               Call Site
00 ffff85052613aeb8 fffff8023cac9028     nt!PspInsertProcess
01 ffff85052613aec0 fffff8023c80d8f5     nt!NtCreateUserProcess+0xd88
02 ffff85052613bb90 00007ffaf2ece9b4     nt!KiSystemServiceCopyEnd+0x25
03 00000062d50fcd08 00007ffaf0529053     ntdll!NtCreateUserProcess+0x14
04 00000062d50fcd10 00007ffaf05265e3     kernelbase!CreateProcessInternalW+0xfe3
05 00000062d50fe2e0 00007ffaf26ee2e0     kernelbase!CreateProcessAsUserW+0x63
06 00000062d50fe350 0000000000000001     0x00007ffaf26ee2e0
07 00000062d50fe358 00007ffaee361e09     0x1
08 00000062d50fe360 00007ffaee488dd0     0x00007ffaee361e09
09 00000062d50fe368 00007ffaee3a3a48     0x00007ffaee488dd0
0a 00000062d50fe370 0000000000000000     0x00007ffa`ee3a3a48

猜测7ffa`f26ee2e0地址位于user32.dll里。果然7ffa`f26d0000是个pe头。但是也是不显示pdb名。那强行指定吧:.reload /user /f user32=7ffa`f26d0000,BF000

5. 其它windbg命令

!running.crash.dump都不行。原因有待继续研究。

这篇关于windbg通过qemu的gdbserver调试虚机windows的方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Windows系统宽带限制如何解除?

《Windows系统宽带限制如何解除?》有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文就跟大家一起来看看Windows系统解除网络限制的操作方法吧... 有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

判断PyTorch是GPU版还是CPU版的方法小结

《判断PyTorch是GPU版还是CPU版的方法小结》PyTorch作为当前最流行的深度学习框架之一,支持在CPU和GPU(NVIDIACUDA)上运行,所以对于深度学习开发者来说,正确识别PyTor... 目录前言为什么需要区分GPU和CPU版本?性能差异硬件要求如何检查PyTorch版本?方法1:使用命

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依

python获取网页表格的多种方法汇总

《python获取网页表格的多种方法汇总》我们在网页上看到很多的表格,如果要获取里面的数据或者转化成其他格式,就需要将表格获取下来并进行整理,在Python中,获取网页表格的方法有多种,下面就跟随小编... 目录1. 使用Pandas的read_html2. 使用BeautifulSoup和pandas3.

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊