다음을 통해 공유


EXDI를 사용하여 QEMU 커널 모드 디버깅 설정

이 항목에서는 EXDI를 사용하여 QEMU 커널 모드 디버깅을 설정하는 방법을 설명합니다. Windows 디버거는 EXDI를 사용하여 QEMU 환경의 커널 디버깅을 지원합니다. 이 문서에서는 ExdiGdbSrv.dll(GDB 서버 클라이언트)와 QEMU GDB 서버 간에 GdbServer RSP 세션을 설정하는 데 필요한 단계를 설명합니다.

설명된 시나리오에서는 Windows x64 Virtual Machine 및 QEMU GDB 서버를 사용하며 Windows에서도 실행됩니다.

Linux와 같이 호스트 역할을 하는 다른 운영 체제에 연결할 수 있습니다. 가상화 및 머신 에뮬레이션 소프트웨어인 QEMU는 x64 및 Arm64와 같은 다양한 아키텍처에서 실행할 수 있습니다. ExdiGdb 디버깅 서버는 다른 프로세서도 지원합니다. 예를 들어 WinDbg를 사용하여 Arm64에서 실행되는 QEMU를 디버그할 수 있습니다. 이렇게 하면 Windows VM을 디버그하는 여러 옵션이 제공되므로 디버거 호스트 EXDI GDB 서버 클라이언트에 연결된 사용 가능한 QEMU GDB 서버를 통해 Windows VM을 HW 디버그할 수 있습니다.

EXDI 연결 구성 및 문제 해결에 대한 일반적인 내용은 EXDI 디버거 전송 구성을 참조 하세요.

참고 항목

EXDI는 특정 환경에 대한 고급 특수한 형태의 디버깅입니다. 표준 KDNET 연결을 사용하는 것이 더 쉽게 구성할 수 있으며 권장됩니다. 네트워크 디버깅을 자동으로 설정하려면 KDNET 네트워크 커널 디버깅 자동 설정을 참조 하세요.

EXDI COM 서버

EXDI는 하드웨어 디버거(예: JTAG 기반 또는 GdbServer 기반)에 대한 지원을 추가하여 WinDbg를 확장할 수 있는 인터페이스입니다. 아래 다이어그램은 EXDI-GdbServer의 역할을 보여 줍니다.

위에 WinDbg-DbgEng이 있는 EXDI-GdbServer의 역할, EXDI 인터페이스 및 GDB 서버와 통신하는 EXDI COM 서버의 역할을 보여 주는 스택 다이어그램

Important

EXDI는 KDNET 프로토콜을 사용하지 않으므로 연결된 디버거는 PC에서 실행되는 작업에 대한 정보가 훨씬 적으며 많은 명령이 다르게 작동하거나 전혀 작동하지 않을 수 있습니다. 디버깅 중인 코드에 대한 프라이빗 기호에 액세스하면 디버거가 대상 시스템 코드 실행을 더 잘 이해할 수 있습니다. 자세한 내용은 공용 및 개인 기호를 참조 하세요.

QEMU에서 Windows 이미지에 대한 디버거 연결 설정

이 항목에서는 Windows에서 실행되는 QEMU 가상 Windows 이미지에 연결하는 프로세스에 대해 설명합니다.

  1. Windows에서 QEMU를 다운로드하여 설치합니다.
  2. 디버깅에 필요한 네트워크 및 BIOS/UEFI 설정으로 시작하도록 대상 QEMU 가상 Windows 이미지를 구성합니다.
  3. 구성된 시작 스크립트를 사용하여 QEMU 환경을 시작합니다.
  4. QEMU에서 gdbserver를 시작합니다.
  5. 네트워크 연결을 확인하고 대상 이미지 IP 주소를 찾아 기록합니다. (HOST IP 기본 주소 1.2.3.4).
  6. 호스트 시스템에 Windows 디버깅 도구를 다운로드하여 설치합니다.
  7. GitHub에 있는 QEMU용 EXDI 서버를 다운로드, 빌드, 등록 및 구성합니다.
  8. EXDI 구성 XML 파일을 편집하여 디버거 호스트(WinDbg)를 구성합니다.
  9. 명령줄을 사용하여 WinDbg를 시작하여 EXDI 서버에 연결합니다.
  10. WinDbg를 사용하여 대상 QEMU Windows 이미지를 디버그합니다.

Windows에서 QEMU 다운로드 및 설치

QEMU는 동적 변환을 유발하는 제네릭 및 오픈 소스 머신 에뮬레이터 및 가상 변환기입니다. QEMU가 컴퓨터 에뮬레이터로 사용되는 경우 다른 컴퓨터(x64 PC)에서 한 프로세서(예: Arm64)에 대해 만들어진 OS 및 프로그램을 실행할 수 있습니다. 또한 다른 OS(Windows/Linux/Mac)에 대한 가상 머신 이미지를 실행/호스트할 수도 있습니다.

QEMU는 KVM과 같은 다른 하이퍼바이저를 사용하여 가상화에 HVM(CPU 확장)을 사용할 수 있습니다. QEMU를 가상화 도우미로 사용하는 경우 QEMU는 호스트 CPU에서 게스트 코드를 직접 실행하여 거의 네이티브 성능을 달성합니다. QEMU는 OS 하이퍼바이저 기능을 활용하여 CPU 및 MMU 에뮬레이션을 실제 하드웨어로 오프로드할 수 있습니다.

QEMU 다운로드 및 설치

이 연습에서는 Windows 디버거가 실행되는 x64 PC에 Windows x64용 QEMU가 설치됩니다.

QEMU 다운로드 페이지에서 QEMU를 다운로드합니다. https://www.qemu.org/download/

QEMU 설치에 대한 자세한 내용은 QEMU 설명서를 참조하세요. https://www.qemu.org/documentation/

대상 가상 디스크 구성

디버그하려는 소프트웨어가 있는 가상 디스크 이미지를 찾거나 만듭니다.

이 예제에서는 Windows x64 VHDX 가상 머신 디스크 이미지가 사용됩니다. Windows 가상 머신 이미지 에 대한 자세한 내용은 Windows 10에서 Hyper-V를 사용하여 Virtual Machine 만들기를 참조하세요.

Windows 이미지에 VirtIO 드라이버 삽입

네트워크 기능 및 적절한 스토리지 디바이스 성능을 허용하려면 VirtIO 드라이버를 Windows 가상 머신 디스크 이미지에 삽입하거나 설치합니다. VirtIo 드라이버는 여기에서 사용할 수 있습니다. https://github.com/virtio-win/kvm-guest-drivers-windows

VirtIO는 가상 머신이 블록 디바이스, 네트워크 어댑터 및 콘솔과 같은 추상화된 하드웨어에 액세스할 수 있도록 하는 표준화된 인터페이스입니다. Virtio는 QEMU와 같은 가상화된 환경에서 하드웨어 디바이스에 대한 추상화 계층 역할을 합니다.

VHDX를 QEMU로 변환

이 단계는 필요하지 않지만 VHDX 대신 네이티브 QEMU QCOW 이미지를 사용할 때 성능이 향상되므로 권장됩니다.

다음 qemu-img.exe 명령을 사용하여 vhdx를 변환합니다. 이 유틸리티는 예를 들어 C:\Program Files\qemuQEMU를 설치한 위치에 있습니다.

C:\Program Files\qemu> qemu-img convert -c -p -O qcow2 MyVHDXFile.vhdx MyQEMUFile.qcow2 

UEFI 펌웨어 다운로드

최상의 결과를 위해 UEFI 펌웨어 파일(OVMF.fd)을 다운로드하거나 컴파일합니다. 그렇지 않으면 기본적으로 QEMU가 이전 BIOS 시스템을 에뮬레이트하기 때문에 펌웨어가 필요합니다.

UEFI 펌웨어의 원본 중 하나는 Open Clear Linux 프로젝트입니다. https://clearlinux.org/

예제 UEFI OVMF.fd 파일은 여기에서 사용할 수 있습니다. https://github.com/clearlinux/common/blob/master/OVMF.fd

에서 다운로드한 파일의 콘텐츠를 추출합니다 C:\Program Files\qemu\Firmware.

Intel AMD64 이외의 플랫폼의 경우 EDK2에서 펌웨어를 컴파일해야 합니다. 자세한 내용은 https://github.com/tianocore/tianocore.github.io/wiki/How-to-build-OVMF를 참조하세요.

QEMU 시작 스크립트 구성

QEMU에서 구성 파일을 만듭니다. 예를 들어 QEMU 루트 디렉터리 아래에 파일을 만듭니 StartQEMUx64Windows.bat 다. 아래 예제 파일을 참조하세요.

QEMU 시작 스크립트를 사용하여 QEMU 시작

QEMU 시작 스크립트를 실행하여 QEMU를 시작합니다.

c:\Program Files\qemu\StartQEMUx64Windows.bat

방화벽 Defender 프롬프트가 표시되면 호스트 디버거 컴퓨터에 대한 Windows 방화벽을 통해 Windbg를 사용하도록 설정하기 위해 모든 유형의 네트워크에 대한 모든 권한을 앱에 부여합니다.

세 가지 옵션이 모두 검사 Windows Defender 방화벽 대화 상자

QEMU 환경에서 Windows Virtual Machine이 시작되면 QEMU UI가 표시됩니다.

보기 메뉴 옵션을 표시하는 QEMU의 스크린샷.

QEMU 모니터 콘솔에서 이동하려면 Ctrl+Alt+에 숫자 키 조합을 사용합니다. 이 모니터는 View-compatmonitor를 사용하여 사용할 수도 있습니다.>

QEMU에서 프런트 엔드 GDB 서버를 시작하려면 입력 gdbserver 합니다.

QEMU가 표시되어야 합니다. Waiting for gdb connection on device ‘tcp::1234’

Ctrl+Alt+1 키 조합을 사용하여 기본 창으로 돌아갑니다.

팁: GDB 콘솔 창은 "system_reset" 명령을 지원하여 에뮬레이션을 신속하게 다시 시작합니다. GDB 콘솔 명령 목록에 대한 도움말을 입력합니다.

QEMU x64 Windows VM 시작 스크립트 샘플

다음은 AMD64 Virtual Machines에 사용할 수 있는 예제 QEMU 구성 스크립트입니다. 디스크 및 CDROM 파일을 가리키는 링크를 PC의 위치로 바꿉다.

    REM
    REM  This script is used to run a Windows x64 VM on QEMU that is hosted by a Windows x64 host system
    REM  The Host system is a PC with Intel(R) Xeon(R) CPU.
    REM
    set EXECUTABLE=qemu-system-x86_64
    set MACHINE=-m 6G -smp 4

    REM No acceleration
    REM generic cpu emulation.
    REM to find out which CPU types are supported by the QEMU version on your system, then run:
    REM	 qemu-system-x86_64.exe -cpu help
    REM the see if your host system CPU is listed
    REM

    set CPU=-machine q35 

    REM Enables x64 UEFI-BIOS that will be used by QEMU :
    set BIOS=-bios D:\temp\firmware\OVMF.fd

    REM  Use regular GFX simulation
    set GFX=-device ramfb -device VGA 
    set USB_CTRL=-device usb-ehci,id=usbctrl
    set KEYB_MOUSE=-device usb-kbd -device usb-tablet

    REM # The following line enable the full-speed HD controller (requires separate driver)
    REM # Following line uses the AHCI controller for the Virtual Hard Disk:
    set DRIVE0=-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0

    REM
    REM This will set the Windows VM x64 disk image that will be launched by QEMU
    REM The disk image is in the qcow2 format accepted by QEMU.
    REM You get the .qcow2 image, once you get the VHDX Windows VM x64 image 
    REM and apply the script to inject the virtio x64 drivers and then run the 
    REM the QEMU tool to convert the .VHDX image to .qcow2 format
    REM 	i.e. 
    REM	qemu-img convert -c -p -O qcow2 Windows_VM_VHDX_with_injected_drivers_file.vhdx file.qcow2
    REM file : points to the specified qcow2 image path.
    REM
    set DISK0=-drive id=disk,file=D:\temp\x64_image_qcow2_for_windows\basex64Client.qcow2,if=none

    REM
    REM for kdnet on, then best option:
    REM   NETWORK0="-netdev user,id=net0,hostfwd=tcp::53389-:3389,hostfwd=tcp::50001-:50001 -device virtio-net,netdev=net0,disable-legacy=on"
    REM
    set NETHOST=-netdev user,id=net0,hostfwd=tcp::3589-:3389
    set NETGUEST=-device e1000,netdev=net0

    REM # The following line should enable the Daemon (instead of interactive)
    set DAEMON=-daemonize"
    %EXECUTABLE% %MACHINE% %CPU% %BIOS% %GFX% %USB_CTRL% %DRIVE0% %DISK0% %NETHOST% %NETGUEST%

네트워크 연결 확인

Windows IP 주소를 가져와야 합니다(디버거 호스트 세션이 QEMU VM과 동일한 Windows 컴퓨터에 위치하지 않는 경우).

GDB 서버가 제대로 시작된 경우 GDB 서버가 수신 대기하는 포트 번호가 표시되고 이 포트를 사용하여 exdiConfigData.xml 호스트 디버거(IP:포트 쌍)를 설정해야 합니다.

호스트 디버거가 QEMU 게스트를 호스트하는 동일한 컴퓨터에 있는 경우 localhost 식별자는 exdiconfigdata.xml IP:포트 쌍(예: LocalHost:Port:1234)으로 사용됩니다. 이 예제에서는 서버와 호스트 디버거가 동일한 PC에 있는 경우 기본값이 사용됩니다.

ExdiConfigData.xml 파일에서 현재 대상 이름 특성(CurrentTarget) 값을 "QEMU"로 설정합니다.

원격 PC에서 작업하는 경우 대상 QEMU IP <address> : GDB 서버가 수신 대기하는 포트 <number> 를 설정합니다.

  • exdiCondifgData.xml QEMU 구성 요소 Tag 요소를 찾습니다.
  • 다음을 통해 QEMU GDB 서버에 대한 IP:포트 번호(디버거가 QEMU VM과 동일한 호스트에서 실행되는 경우 LocalHost)를 설정합니다.
  • EXDI_GDBSRV_XML_CONFIG_FILE 환경 변수로 지정된 경로에 있는 exdiConfigdata.xml 파일에 변경 내용을 저장합니다.

QEMU 네트워킹에 대한 자세한 내용은 https://wiki.qemu.org/Documentation/Networking

QEMU 콘솔(compatmonitor0)에서 다음 명령을 실행하여 네트워크 및 연결 상태 대한 정보를 표시할 수 있습니다.

info network
info usernet

호스트 시스템에 Windows 디버깅 도구 다운로드 및 설치

호스트 시스템에 Windows 디버깅 도구를 설치합니다. 디버거 도구 다운로드 및 설치에 대한 자세한 내용은 Windows용 디버깅 도구를 참조 하세요.

EXDI 서버 DLL 다운로드, 빌드 및 등록

microsoft/WinDbg-Samples, GitHub https://github.com/microsoft/WinDbg-Samples에서 해당 ExdiGdbSrv.dll 이진(EXDI COM 서버 클라이언트) 소스 코드를 다운로드합니다.

git clone https://github.com/microsoft/WinDbg-Samples

Exdi/exdigdbsrv에 있는 호스트 디버거 설치의 아키텍처에 따라 VS 솔루션(ExdiGdbSrv.sln)을 빌드합니다.

빌드에서 생성된 ExdiGdbSrv.dll 찾습니다.

EXDI com 서버(ExdiGdbSrv.dll)를 호스트 컴퓨터에 디버거가 포함된 디렉터리(.g)에 복사합니다. C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 또는 C:\Debuggers)

regsvr32를 사용하여 관리istrator 명령 프롬프트에 DLL을 등록합니다.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>regsvr32 ExdiGdbSrv.dll

RegSvr32는 DLLRegisterServer in ExdiGdbSrv.dll succeeded.

이 단계는 한 번만 수행해야 하지만 ExdiGdbSrv.dll 위치를 변경하는 경우 COM 서버를 다시 등록해야 합니다.

또 다른 옵션은 예제 PowerShell 스크립트를 사용하여 EXDI DLL을 설치하고 디버거를 처음 시작하는 것입니다. 자세한 내용은 EXDI 디버거 전송 구성의 예제 EXDI PowerShell 스크립트를 참조하세요.

EXDI 구성 XML 파일을 편집하여 디버거 호스트(WinDbg) 구성

필요한 두 구성 파일을 WinDbg-Samples/Exdi/exdigdbsrv/ 찾아서 로컬에 디버거가 설치된 호스트 디버거 컴퓨터에 복사합니다.

  • exdiConfigData.xml
  • systemregisters.xml

EXDI_GDBSRV_XML_CONFIG_FILE – EXDI xml 구성 파일의 전체 경로를 설명합니다.

EXDI_SYSTEM_REGISTERS_MAP_XML_FILE – EXDI xml 시스템 레지스터 맵 파일의 전체 경로를 설명합니다.

EXDI 연결 구성 및 문제 해결에 대한 일반적인 정보와 exdiConfigData.xml 태그 및 특성은 EXDI 디버거 전송 구성을 참조 하세요.

환경 변수 EXDI_GDBSRV_XML_CONFIG_FILE 설정하고 EXDI_SYSTEM_REGISTERS_MAP_XML_FILE exdi xml 구성 파일의 전체 경로를 설명합니다.

명령 프롬프트

명령 프롬프트를 열고 다음 환경 변수를 설정합니다.

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

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

지정된 경로를 ExdiGdbSrvSample.dll 위치에서 사용할 수 있는지 확인하는 형식 SET 입니다.

Powershell

PowerShell 프롬프트를 열고 다음 환경 변수를 설정합니다.

$env:EXDI_GDBSRV_XML_CONFIG_FILE = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\exdiConfigData.xml'

$env:EXDI_SYSTEM_REGISTERS_MAP_XML_FILE = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\systemregisters.xml'

지정된 경로를 ExdiGdbSrvSample.dll 위치에서 사용할 수 있는지 확인하는 형식 dir env: 입니다.

호스트 시스템에서 WinDbg 시작

환경 변수(EXDI_GDBSRV_XML_CONFIG_FILE 및 EXDI_SYSTEM_REGISTERS_MAP_XML_FILE)를 설정하는 동일한 명령 프롬프트에서 exdi 인터페이스를 통해 windbg 세션을 시작합니다.

c:\Debuggers> windbg.exe -v -kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi

추가 출력을 표시하기 위해 -v: 자세한 정보 표시 세션을 사용할 수 있습니다. WinDbg 옵션에 대한 일반적인 내용은 WinDbg 명령줄 옵션을 참조 하세요.

또 다른 옵션은 예제 PowerShell 스크립트를 사용하여 EXDI DLL을 설치하고 디버거를 처음 시작하는 것입니다. 자세한 내용은 EXDI 디버거 전송 구성에서 예제 EXDI PowerShell 스크립트를 참조하세요.

PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"

디버거는 QEMU GdbServer를 시작하고 연결해야 합니다.

창 제목에 EXDI CLSID를 표시하는 기본 WinDbg 세션입니다.

디버거는 성공적인 EXDI 전송 초기화를 표시합니다.

EXDI: DbgCoInitialize returned 0x00000001
EXDI: CoCreateInstance() returned 0x00000000
EXDI: QueryInterface(IExdiServer3) returned 0x00000000
Target command response: QEMU
exdiCmd: The function: 'ExdiDbgType' was completed.
EXDI: Server::GetTargetInfo() returned 0x00000000
EXDI: Server::SetKeepaliveInterface() returned 0x00000000
EXDI: Server::GetNbCodeBpAvail() returned 0x00000000
EXDI: ExdiNotifyRunChange::Initialize() returned 0x00000000
EXDI: LiveKernelTargetInfo::Initialize() returned 0x00000000
EXDI: Target initialization succeeded

exDIGdbServer 콘솔 패킷 창은 displayCommPackets="yes"가 exdiConfigData.xml 파일에 설정된 경우 EXDI 연결의 상태 대한 정보를 표시할 수도 있습니다. 자세한 내용은 EXDI 디버거 전송 구성의 문제 해결 정보를 참조하세요.

WinDbg를 사용하여 대상 QEMU Windows 이미지 디버그

이 dbgeng.dll 추론 알고리즘을 사용하여 break 명령이 발생했을 때 NT 기본 부하 주소의 위치를 찾습니다. 프라이빗 기호를 사용할 수 없는 경우 이 프로세스가 실패합니다.

즉, 많은 연결 시퀀스에서 중단이 예상대로 작동하지 않습니다. 코드를 수동으로 중단하면 해당 시점에 Windows가 실행 중이던 임의의 위치가 됩니다. 대상 코드의 기호를 사용할 수 없으므로 기호를 사용하여 중단점을 설정하기 어려울 수 있습니다.

메모리에 직접 액세스하는 다음과 같은 명령이 작동합니다.

k, kb, kc, kd, kp, kP, kv(디스플레이 스택 백트레이스)

r(레지스터)

d, da, db, dc, dd, dD, df, dp, dq, du, dw(메모리 표시)

u(언어셈블)

코드를 단계별로 실행할 수 있습니다.

p(단계)

디버그하려는 코드를 찾는 데 사용할 수 있는 명령도 있습니다.

s(메모리 검색)

.imgscan(이미지 헤더 찾기)

Imgscan은 기존 KDNET 기반 커널 디버깅과 달리 기호를 기반으로 중단점을 설정할 수 없으므로 EDXI 디버깅에 유용할 수 있습니다. 원하는 대상 이미지를 찾은 경우 해당 위치를 사용하여 메모리 액세스 중단점을 쉽게 설정할 수 있습니다.

.exdicmd(EXDI 명령)

.exdicmd는 활성 EXDI 디버깅 연결을 사용하여 대상 시스템에 EXDI 명령을 보냅니다. 자세한 내용은 .exdicmd(EXDI 명령)를 참조하세요.

EXDI XML 구성 파일

EXDI GDB COM 서버(ExdiGdbSrv.dll)에서 사용하는 두 개의 필수 xml 파일이 있습니다.

  1. exdiConfigData.xml - 이 파일에는 GDB 서버 클라이언트가 HW 디버거 GDB 서버 대상과 성공적으로 GDB 세션을 설정하는 데 필요한 기본 구성 데이터가 포함되어 있으므로 파일 위치가 EXDI_GDBSRV_XML_CONFIG_FILE 환경 변수에 의해 설정되지 않은 경우 GDB 서버 클라이언트가 실행되지 않습니다. 각 xml 태그를 사용하면 특정 GDB 서버 기능 집합을 구성할 수 있습니다. XML에서 수정할 수 있는 특성 목록과 샘플 XML은 아래를 참조하세요.

  2. Systemregister.xml - 이 파일에는 시스템 레지스터와 해당 액세스 코드 간의 매핑이 포함되어 있습니다. 액세스 코드는 GDB 서버에서 xml 파일에서 제공되지 않고 디버거가 액세스 코드를 통해 각 시스템 레지스터에 액세스하기 때문에 필요합니다.

XML 구성 파일에 정의된 GDBServer 태그 및 특성에 대한 자세한 내용과 설명은 EXDI 디버거 전송 구성을 참조 하세요.

문제 해결

EXDI 디버거 전송 구성의 문제 해결 정보를 참조하세요.

참고 항목

EXDI 디버거 전송 구성

.exdicmd(EXDI 명령)

자동으로 KDNET 네트워크 커널 디버깅 설정

수동으로 KDNET 네트워크 커널 디버깅 설정