EXDI를 사용하여 QEMU 커널 모드 디버깅 설정
이 항목에서는 Windows 디버거에서 EXDI를 사용하여 QEMU 커널 모드 디버깅을 설정하는 방법을 설명합니다.
EXDI 연결 구성 및 문제 해결에 대한 일반적인 내용은 EXDI 디버거 전송 구성을 참조 하세요.
가상화 및 머신 에뮬레이션 소프트웨어인 QEMU를 사용하여 Linux와 같은 호스트 역할을 하는 다른 운영 체제에 연결할 수 있습니다. QEMU 자체는 x64 및 Arm64와 같은 다양한 아키텍처에서 실행할 수 있습니다. ExdiGdb 디버깅 서버는 다른 프로세서도 지원합니다. 예를 들어 WinDbg를 사용하여 x64에서 실행되는 QEMU를 디버그하고 Arm64를 에뮬레이트할 수 있습니다. EXDI를 사용하면 OS가 로드되기 전에도 부팅 프로세스 초기에 VM을 HW 디버그할 수 있습니다.
참고 항목
EXDI는 특정 환경에 대한 고급 특수한 형태의 디버깅입니다. 표준 KDNET 연결을 사용하는 것이 더 쉽게 구성할 수 있으며 권장됩니다. 네트워크 디버깅을 자동으로 설정하려면 KDNET 네트워크 커널 디버깅 자동 설정을 참조 하세요.
EXDI COM 서버
EXDI는 하드웨어 디버거(예: JTAG 기반 또는 GdbServer 기반)에 대한 지원을 추가하여 WinDbg를 확장할 수 있는 인터페이스입니다. 아래 다이어그램은 EXDI-GdbServer의 역할을 보여 줍니다.
Important
EXDI는 KDNET 프로토콜을 사용하지 않으므로 연결된 디버거는 PC에서 실행되는 작업에 대한 정보가 훨씬 적으며 많은 명령이 다르게 작동하거나 전혀 작동하지 않을 수 있습니다. 디버깅 중인 코드에 대한 프라이빗 기호에 액세스하면 디버거가 대상 시스템 코드 실행을 더 잘 이해할 수 있습니다. 자세한 내용은 공용 및 개인 기호를 참조 하세요.
QEMU에서 Windows 이미지에 대한 디버거 연결 설정
다음 단계에서는 Windows에서 실행되는 Windbg 클라이언트(EXDI COM 서버를 사용하는)에 GDB 서버를 노출하는 Windows x64 Virtual Machine에 연결하는 방법을 설명합니다. WinDbg ExdiGdbSrv.dll(GDB 서버 클라이언트)와 QEMU GDB 서버 간의 GdbServer RSP 세션이 사용됩니다.
- Windows에서 QEMU를 다운로드하여 설치합니다.
- 디버깅에 필요한 네트워크 및 BIOS/UEFI 설정으로 시작하도록 대상 QEMU 가상 Windows 이미지를 구성합니다.
- 시작 스크립트를 사용하여 QEMU 환경을 시작합니다.
- QEMU에서 GdbServer를 시작합니다.
- 네트워크 연결을 확인하고 대상 이미지 IP 주소를 찾아 기록합니다. (LocalHost의 HOST IP 기본 주소 및 포트 1234).
- 호스트 시스템에 Windows 디버깅 도구를 다운로드하여 설치합니다.
- 명령줄 또는 UI를 사용하여 WinDbg를 시작하여 EXDI 서버에 연결합니다.
- WinDbg를 사용하여 대상 QEMU 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와 같은 가상화된 환경에서 하드웨어 디바이스에 대한 추상화 계층 역할을 합니다.
VirtIO 드라이버를 Windows 이미지에 삽입하려면 다음 단계를 수행합니다.
- 예를 들어
C:\VirtIo_Drivers
폴더에서 VirtIo 드라이버를 추출합니다. - 파일 탐색기 VHDX를 두 번 클릭하여 Windows x64 가상 머신이 포함된 VHDX를 탑재합니다(diskpart도 사용할 수 있습니다). Windows는 특정 문자(예: "L:")를 사용하여 VHDX를 탑재합니다.
- Dism을 사용하여 탑재된 이미지에 드라이버 삽입:
dism /image:L: /Add-Driver /driver:C:\VirtIo_Drivers
DISM에 대한 자세한 내용은 DISM 개요를 참조하세요. - 프로세스가 완료되면 이미지를 분리하고 VHDX를 QEMU로 변환할 수 있습니다.
VHDX를 QEMU로 변환
이 단계는 필요하지 않지만 VHDX 대신 네이티브 QEMU QCOW 이미지를 사용할 때 성능이 향상되므로 권장됩니다.
다음 qemu-img.exe 명령을 사용하여 vhdx를 변환합니다. 이 유틸리티는 예를 들어 C:\Program Files\qemu
QEMU를 설치한 위치에 있습니다.
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/tree/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를 사용하도록 설정하기 위해 모든 유형의 네트워크에 대한 모든 권한을 앱에 부여합니다.
QEMU 환경에서 Windows Virtual Machine이 시작되면 QEMU UI가 표시됩니다.
QEMU 모니터 콘솔에서 이동하려면 Ctrl+Alt+에 숫자 키 조합을 사용합니다. 이 모니터는 View-compatmonitor를 사용하여 사용할 수도 있습니다.>
QEMU에서 프런트 엔드 GDB 서버를 시작하려면 입력 gdbserver
합니다.
QEMU가 표시되어야 합니다. Waiting for gdb connection on device ‘tcp::1234’
Ctrl+Alt+1 키 조합을 사용하여 주 창으로 돌아갑니다.
팁: GDB 콘솔 창은 에뮬레이션을 신속하게 다시 시작하는 명령을 지원 system_reset
합니다. GDB 콘솔 명령 목록을 입력 help
합니다.
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 "C:\Program Files\qemu\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="C:\Program Files\qemu\MyQEMUFile.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
REM Create a mapping for the RDP service from port 3389 to 3589.
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%
네트워크 연결
로컬 호스트
GDB 서버가 제대로 시작된 경우 GDB 서버가 수신 대기하는 포트 번호가 표시되며 이 포트를 사용하여 호스트 디버거 IP:Port
쌍을 설정해야 합니다.
호스트 디버거가 QEMU 게스트를 호스트하는 동일한 컴퓨터에 있는 경우 Localhost 식별자는 IP:포트 쌍에서 사용됩니다. 이 예제에서는 동일한 PC LocalHost:1234
에서 서버 및 호스트 디버거가 사용됩니다.
원격 호스트
원격 PC에서 작업하는 경우 Windows IP 주소를 찾습니다(디버거 호스트 세션이 QEMU VM과 동일한 Windows 컴퓨터에 위치하지 않는 경우).
대상 QEMU IP <address>
:<port number>
EXDI UI에서 구성됩니다.
QEMU 콘솔(compatmonitor0)에서 다음 명령을 실행하여 네트워크 및 연결 상태에 대한 정보를 표시할 수 있습니다.
info network
info usernet
QEMU 네트워킹에 대한 자세한 내용은 https://wiki.qemu.org/Documentation/Networking
호스트 시스템에 Windows 디버깅 도구 다운로드 및 설치
호스트 시스템에 Windows 디버깅 도구를 설치합니다. 디버거 도구 다운로드 및 설치에 대한 자세한 내용은 Windows용 디버깅 도구를 참조 하세요.
호스트 시스템에서 WinDbg 시작
여기에 설명된 시나리오에서 연결할 EXDI UI에서 다음 옵션을 설정합니다.
대상 유형 - QEMU
대상 아키텍처 - x64
대상 OS - Windows
이미지 스캔 추론 크기 - 0xFFE - NT
Gdb 서버 및 포트 - LocalHost:1234
연결 끊기 - 예
EXDI UI를 사용하는 것이 권장되지만 여기에 표시된 것과 유사한 명령줄 옵션을 사용하여 WinDbg를 시작할 수도 있습니다.
c:\Debuggers> windbg.exe -v -kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,Inproc=ExdiGdbSrv.dll,DataBreaks=Exdi
명령줄을 사용하는 경우 IP 주소와 포트는 exdiConfigData.xml 파일을 사용하여 구성됩니다. 자세한 내용은 EXDI XML 구성 파일을 참조 하세요.
추가 출력을 표시하기 위해 -v: 자세한 정보 표시 세션을 사용할 수 있습니다. WinDbg 옵션에 대한 일반적인 내용은 WinDbg 명령줄 옵션을 참조 하세요.
디버거는 QEMU GdbServer를 시작하고 연결해야 합니다.
디버거는 성공적인 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 콘솔 패킷 창은 *"고급 옵션에서 통신 패킷 로그 표시가 켜진 경우 EXDI 연결 상태에 대한 정보를 표시할 수도 있습니다. 자세한 내용은 EXDI 디버거 전송 구성의 문제 해결 정보를 참조하세요.
WinDbg를 사용하여 대상 QEMU Windows 이미지 디버그
이 dbgeng.dll 추론 알고리즘을 사용하여 break 명령이 발생했을 때 NT 기본 부하 주소의 위치를 찾습니다. 프라이빗 기호를 사용할 수 없는 경우 이 프로세스가 실패합니다.
즉, 많은 연결 시퀀스에서 중단이 예상대로 작동하지 않습니다. 코드를 수동으로 중단하면 해당 시점에 Windows가 실행 중이던 임의의 위치가 됩니다. 대상 코드의 기호를 사용할 수 없으므로 기호를 사용하여 중단점을 설정하기 어려울 수 있습니다.
사용 가능한 디버거 메모리 액세스 명령
메모리에 직접 액세스하는 다음과 같은 명령이 작동합니다.
k, kb, kc, kd, kp, kP, kv(디스플레이 스택 백트레이스)
d, da, db, dc, dd, dD, df, dp, dq, du, dw(메모리 표시)
코드를 단계별로 실행할 수 있습니다.
디버그하려는 코드를 찾는 데 사용할 수 있는 명령도 있습니다.
Imgscan은 기존 KDNET 기반 커널 디버깅과 달리 기호를 기반으로 중단점을 설정할 수 없으므로 EDXI 디버깅에 유용할 수 있습니다. 원하는 대상 이미지를 찾은 경우 해당 위치를 사용하여 메모리 액세스 중단점을 쉽게 설정할 수 있습니다.
.exdicmd(EXDI 명령)
.exdicmd는 활성 EXDI 디버깅 연결을 사용하여 대상 시스템에 EXDI 명령을 보냅니다. 자세한 내용은 .exdicmd(EXDI 명령)를 참조하세요.
문제 해결
EXDI 디버거 전송 구성의 문제 해결 정보를 참조하세요.