한국어 | English
Windows VEH(Vectored Exception Handler) 기반 디버거. DAP(Debug Adapter Protocol) 완전 지원.
Windows Debug API(NtSetInformationThread, IsDebuggerPresent 등)를 사용하지 않으므로 PEB.BeingDebugged = 0 상태를 유지합니다. Themida, VMProtect 등 PEB/NtQuery 기반 안티디버그 체크를 자연스럽게 우회합니다. 단, VEH 자체를 검사하는 보호(EAC 등 커널 안티치트)는 감지될 수 있습니다.
Windows Debug API 디버거(x64dbg, WinDbg, Visual Studio 등)는 프로세스당 하나만 붙을 수 있지만, VEH Debugger는 Windows 디버거와 동시에 같은 프로세스에 붙을 수 있습니다. 커널 디버거나 다른 유저모드 디버거로 분석하면서, VEH Debugger로 보조 브레이크포인트/메모리 감시를 병행할 수 있습니다.
MCP(Model Context Protocol) 도구 서버를 내장하여 Claude, Cursor, Windsurf, Codex 등 AI 에이전트가 디버거를 직접 제어합니다. "이 함수에 브레이크포인트 걸고 RAX 값 확인해줘"처럼 자연어로 디버깅을 지시할 수 있습니다.
별도 디버거 GUI 없이 VSCode 디버그 패널에서 모든 것을 수행합니다. 디스어셈블리 뷰, 레지스터 조회/수정, 메모리 읽기/쓰기, 하드웨어 브레이크포인트까지 VSCode 안에서 완결됩니다.
- VEH 기반: Windows Debug API 대신 VEH를 사용하여 안티디버그 우회에 유리
- DAP 전체 지원: VSCode, MCP debug 도구 등 모든 DAP 호환 클라이언트에서 사용 가능
- MCP 도구 서버: AI 에이전트(Claude, Codex 등)가 직접 디버거를 제어하는 36개 도구 제공
- TCP 모드:
--tcp --port=PORT로 원격 디버깅/MCP 연동 지원 - 원격 접속:
--remote/--bind=0.0.0.0으로 VM/네트워크 너머 디버깅 - 32/64비트 지원: x86/x64 프로세스 모두 디버깅 가능 (별도 32비트 DLL 빌드)
- 소프트웨어 브레이크포인트: INT3 (0xCC) 패치
- 하드웨어 브레이크포인트: DR0~DR3 (메모리 읽기/쓰기 감시 = Find What Writes/Accesses)
- PDB 심볼 지원: 소스 파일/줄 번호 매핑, 함수 이름으로 브레이크포인트
- 디스어셈블리: Zydis x86/x64 디스어셈블러 (기본) + 내장 경량 디코더 (폴백)
- 메모리 읽기/쓰기: DAP readMemory/writeMemory 지원
- MT(정적 CRT) 빌드: DLL 인젝션 시 vcruntime 의존성 없음
VSCode / DAP Client Claude / AI Agent
↕ DAP (stdin/stdout or TCP) ↕ MCP (stdin/stdout, JSON-RPC 2.0)
veh-debug-adapter.exe veh-mcp-server.exe
↕ Named Pipe IPC ↕ Named Pipe IPC
└──────── veh-debugger.dll (타겟 프로세스 내부) ────────┘
| 컴포넌트 | 역할 |
|---|---|
veh-debugger.dll (vcruntime_net.dll) |
타겟 프로세스에 인젝션. VEH 핸들러 등록, 브레이크포인트 관리, 스레드/스택/메모리 조회 |
veh-debug-adapter.exe |
DAP 프로토콜 서버. DLL 인젝션, Named Pipe 통신, JSON-RPC 처리 |
veh-mcp-server.exe |
MCP 도구 서버. AI 에이전트가 36개 도구로 디버거 직접 제어 |
| VSCode Extension | launch.json 스키마 정의, 어댑터 경로 설정 (최소 래퍼) |
- Windows 10+ x64
- CMake 3.20+
- Visual Studio 2022 (MSVC)
- Node.js 18+ (VSCode 익스텐션용, 선택)
cmake -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release출력물:
build/bin/Release/veh-debug-adapter.exe— DAP 어댑터build/bin/Release/veh-mcp-server.exe— MCP 도구 서버build/bin/Release/vcruntime_net.dll— VEH 디버거 DLL (위장 이름)
32비트 프로세스 디버깅 시 필요:
cmake -B build32 -G "Visual Studio 17 2022" -A Win32
cmake --build build32 --config Release --target veh-debugger
# 출력: build32/bin/Release/vcruntime_net32.dll
# build/bin/Release/ 에 복사하여 사용
copy build32\bin\Release\vcruntime_net32.dll build\bin\Release\cd extension
npm install
npm run compile.vscode/launch.json에 추가:
프로세스 실행 (Launch)
{
"type": "veh",
"request": "launch",
"name": "VEH Debug - Launch",
"program": "C:/path/to/target.exe",
"args": ["arg1", "arg2"],
"stopOnEntry": true
}program: 디버깅할 실행 파일 경로args: 실행 인자 (선택)stopOnEntry: 진입점에서 정지 여부runAsInvoker: UAC 권한 상승 프롬프트 없이 현재 권한으로 실행 (기본: false)
실행 중인 프로세스에 붙기 (Attach)
{
"type": "veh",
"request": "attach",
"name": "VEH Debug - Attach",
"processId": 1234
}processId: 대상 프로세스 PID (작업 관리자에서 확인)
어댑터를 별도 프로세스로 실행한 뒤 DAP 클라이언트에서 TCP로 연결:
veh-debug-adapter.exe --tcp --port=4711기본적으로 127.0.0.1에만 바인딩되어 로컬에서만 접속 가능.
VM 내부나 원격 머신에서 실행하고 호스트/외부에서 접속:
# 대상 머신에서 실행 (0.0.0.0 바인딩)
veh-debug-adapter.exe --tcp --port=4711 --remote
# 또는
veh-debug-adapter.exe --tcp --port=4711 --bind=0.0.0.0외부에서 DAP 클라이언트로 <대상머신IP>:4711에 연결.
보안 주의: --remote는 모든 네트워크 인터페이스에 바인딩합니다. 신뢰할 수 있는 네트워크에서만 사용하거나 방화벽으로 접근을 제한하세요.
# TCP 모드로 어댑터 실행
veh-debug-adapter.exe --tcp --port=4711
# MCP debug 도구에서 TCP 연결
debug(operation: "launch", address: "localhost:4711", ...)
DAP 프로토콜을 모르는 AI 에이전트가 함수 호출처럼 디버거를 제어할 수 있는 별도 MCP 서버.
자동 설치 (권장)
# 모든 에이전트에 한 번에 설치
veh-mcp-server.exe --install
# 특정 에이전트만 설치
veh-mcp-server.exe --install claude-code
veh-mcp-server.exe --install cursor
# 제거
veh-mcp-server.exe --uninstall지원 에이전트: claude-code, claude-desktop, cursor, windsurf, codex
자기 자신의 절대경로를 자동 감지하여 각 에이전트의 설정 파일에 등록합니다.
| 에이전트 | 설정 파일 | 형식 |
|---|---|---|
| Claude Code | ~/.claude/settings.json |
JSON (mcpServers) |
| Claude Desktop | %APPDATA%/Claude/claude_desktop_config.json |
JSON (mcpServers) |
| Cursor | ~/.cursor/mcp.json |
JSON (mcpServers) |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
JSON (mcpServers) |
| Codex CLI | ~/.codex/config.toml |
TOML (mcp_servers) |
수동 설치 (설정 파일 직접 편집)
Claude Code / Claude Desktop / Cursor / Windsurf (JSON 형식):
{
"mcpServers": {
"veh-debugger": {
"command": "C:/path/to/veh-mcp-server.exe",
"args": ["--log=veh-mcp.log"]
}
}
}Codex CLI (TOML 형식):
[mcp_servers.veh-debugger]
command = "C:/path/to/veh-mcp-server.exe"
args = ["--log=veh-mcp.log"]
enabled = true설정 후 에이전트/IDE를 재시작하면 활성화됩니다.
MCP 도구 목록 (36개)
| 도구 | 인자 | 설명 |
|---|---|---|
veh_attach |
pid |
프로세스에 DLL 인젝션 + 파이프 연결 |
veh_launch |
program, args?, stopOnEntry? |
프로세스 생성 + 인젝션 |
veh_detach |
- | 디버거 분리 |
veh_set_breakpoint |
address, condition?, hitCondition?, logMessage?, action? |
소프트웨어 BP. action으로 히트 시 자동 실행 (veh_batch 형식) |
veh_remove_breakpoint |
id |
소프트웨어 BP 제거 |
veh_set_source_breakpoint |
source, line, condition?, hitCondition?, logMessage? |
소스 파일+줄번호 BP (PDB 필요) |
veh_set_function_breakpoint |
name, condition?, hitCondition?, logMessage? |
함수명 BP (PDB 필요) |
veh_list_breakpoints |
- | 활성 SW/HW BP 목록 조회 |
veh_set_data_breakpoint |
address, type, size |
HW BP (write/readwrite/execute) |
veh_remove_data_breakpoint |
id |
HW BP 제거 |
veh_continue |
threadId?, wait?, timeout?, pass_exception?, ignore_exceptions? |
실행 계속. ignore_exceptions=[0x80000003]으로 특정 예외만 SEH 전달 |
veh_step_in |
threadId |
Step Into |
veh_step_over |
threadId |
Step Over |
veh_step_out |
threadId |
Step Out |
veh_pause |
threadId? |
일시정지 |
veh_threads |
- | 스레드 목록 |
veh_stack_trace |
threadId, maxFrames? |
스택 트레이스 |
veh_registers |
threadId |
레지스터 조회 |
veh_set_register |
threadId, name, value |
레지스터 값 변경 |
veh_evaluate |
expression, threadId |
레지스터/메모리/포인터/세그먼트 평가 ([reg+offset], gs:[0x60] 등) |
veh_read_memory |
address, size |
메모리 읽기 (hex) |
veh_write_memory |
address, data 또는 patches |
메모리 쓰기. 배치: patches=[{address,data},...] |
veh_dump_memory |
address, size, output_path |
메모리를 바이너리 파일로 덤프 (최대 64MB) |
veh_allocate_memory |
size?, protection? |
타겟 프로세스에 메모리 할당 (VirtualAlloc) |
veh_free_memory |
address |
할당된 메모리 해제 (VirtualFree) |
veh_execute_shellcode |
shellcode, timeout_ms? |
셸코드 실행 (RWX 할당+복사+스레드 생성+대기+해제) |
veh_modules |
- | 모듈 목록 |
veh_disassemble |
address, count? |
디스어셈블리 (Zydis) |
veh_exception_info |
- | 마지막 예외 정보 조회 |
veh_trace_register |
threadId, register, mode?, value?, max_steps? |
레지스터 변화 추적 (DLL 내부 스텝 루프, IPC 오버헤드 0) |
veh_trace_memory |
address, size?, timeout_ms? |
메모리 쓰기 추적 (임시 HW BP로 빠르게 감지) |
veh_resolve_imports |
threadId, addresses, max_steps?, follow_exceptions?, system_only?, target_modules? |
난독화 import 일괄 해석 (thunk -> DLL 스텝 추적, 최대 2000개) |
veh_batch |
steps |
다중 명령 일괄 실행 ($N 결과 참조, if/loop/for_each 제어 흐름) |
veh_trace_callers |
address, duration_sec? |
함수 호출자 프로파일링 (자동 resume -> N초간 caller 수집 -> 자동 pause). 유니크 caller별 히트 카운트 반환. x64: RtlVirtualUnwind (정확). x86: [ESP] (함수 진입점에서만 정확) |
veh_trace_calls |
addresses, duration_sec?, resolve?, system_only? |
call/jmp 명령이 런타임에 어디로 가는지 모니터링. 콜 사이트에 BP 설치 후 N초간 실행, 실제 타겟 주소 + API 이름 수집. resolve=true: thunk/trampoline을 자연스러운 call 컨텍스트에서 따라가 최종 API까지 추적 (예외 기반 난독화 대응). system_only=true: 시스템 DLL 타겟만 반환. 패킹된 바이너리의 IAT 복원용. |
Tip: 주소 인자는 hex (
"0x401000"), 10진수 (4198400), 모듈+RVA ("crackme.exe+0x1000") 모두 허용합니다. 모듈+RVA는 ASLR 계산 없이 사용 가능합니다.
veh-mcp-server.exe
| 옵션 | 설명 |
|---|---|
--install [AGENT] |
AI 에이전트 설정에 MCP 서버 등록 (전체 또는 특정) |
--uninstall [AGENT] |
AI 에이전트 설정에서 MCP 서버 제거 |
--log=FILE |
로그 파일 경로 |
--log-level=LEVEL |
로그 레벨: debug, info, warn, error |
--help |
도움말 출력 |
veh-debug-adapter.exe
| 옵션 | 설명 |
|---|---|
--tcp |
TCP 전송 모드 (기본: stdin/stdout) |
--port=PORT |
TCP 포트 번호 (기본: 4711) |
--remote |
0.0.0.0에 바인딩 (원격 접속 허용) |
--bind=0.0.0.0 |
--remote와 동일 |
--log=FILE |
로그 파일 경로 |
--log-level=LEVEL |
로그 레벨: debug, info, warn, error (기본: info) |
--help |
도움말 출력 |
소프트웨어 브레이크포인트 (INT3)
setBreakpoints— 소스 파일:줄 번호 기반 (PDB 필요)setFunctionBreakpoints— 함수 이름 기반 (PDB 필요)setInstructionBreakpoints— 주소 기반 (PDB 불필요)
하드웨어 브레이크포인트 (DR0~DR3)
setDataBreakpoints— 메모리 주소 읽기/쓰기 감시- 치트엔진의 "Find out what writes/accesses to this address"와 동일 원리
- 최대 4개 동시 감시 (CPU 하드웨어 제한)
- 감시 크기: 1/2/4/8 바이트
타겟 프로세스의 PDB 파일이 있으면:
- 소스 파일명 + 줄 번호로 브레이크포인트 설정
- 함수 이름으로 브레이크포인트 설정
- 스택 트레이스에서 함수명/소스 파일/줄 번호 표시
PDB 없이도 주소 기반 디버깅은 가능.
| 명령 | 동작 |
|---|---|
next (F10) |
Step Over — 한 줄/명령어 실행 (호출 건너뜀) |
stepIn (F11) |
Step Into — 함수 내부로 진입 |
stepOut (Shift+F11) |
Step Out — 현재 함수 완료까지 실행 |
Windows 디버거의 "실행하며 디버깅" 기능과 동일. DAP(launch 요청)와 MCP(veh_launch) 모두 지원.
동작 순서:
CreateProcess+CREATE_SUSPENDED— 프로세스를 정지 상태로 생성- DLL 인젝션 — VEH 핸들러 등록, Named Pipe 서버 시작
stopOnEntry=true이면 진입점에서 정지 유지,false이면ResumeThread로 실행 계속
이미 실행 중인 프로세스에는 attach / veh_attach로 연결.
4가지 인젝션 방식 지원 (자동 선택):
- CreateRemoteThread — 기본 방식
- NtCreateThreadEx — 보호된 프로세스 대응
- Thread Hijacking — 기존 스레드 하이재킹
- QueueUserAPC — APC 큐 방식
readMemory/writeMemory— 임의 메모리 읽기/쓰기disassemble— x86/x64 디스어셈블리- Zydis 백엔드 (기본): 완전한 오퍼랜드 표시 (
mov rax, qword ptr [rbp-0x10]) - Simple 백엔드 (폴백): 니모닉만 (
mov,call— 외부 의존성 없음) IDisassembler인터페이스로 추상화,CreateDisassembler()팩토리로 생성
- Zydis 백엔드 (기본): 완전한 오퍼랜드 표시 (
evaluate— 메모리 주소 표현식 평가
| 카테고리 | 명령 |
|---|---|
| 라이프사이클 | initialize, launch, attach, disconnect, terminate |
| 브레이크포인트 | setBreakpoints, setFunctionBreakpoints, setExceptionBreakpoints, setInstructionBreakpoints, setDataBreakpoints, dataBreakpointInfo |
| 실행 제어 | configurationDone, continue, next, stepIn, stepOut, pause |
| 상태 조회 | threads, stackTrace, scopes, variables, evaluate |
| 메모리/디스어셈블리 | readMemory, writeMemory, disassemble |
| 기타 | modules, loadedSources, exceptionInfo, completions, source, cancel, gotoTargets |
├── CMakeLists.txt # 루트 CMake (MT 정적 CRT)
├── src/
│ ├── dll/ # VEH 디버거 DLL
│ │ ├── dllmain.cpp # DLL 진입점
│ │ ├── veh_handler.* # VEH 예외 핸들러
│ │ ├── breakpoint.* # 소프트웨어 BP 관리
│ │ ├── hw_breakpoint.* # 하드웨어 BP (DR0~DR3)
│ │ ├── memory.* # 메모리 읽기/쓰기
│ │ ├── threads.* # 스레드 열거/제어
│ │ ├── stack_walk.* # 스택 워킹 (DbgHelp)
│ │ └── pipe_server.* # Named Pipe IPC 서버
│ ├── adapter/ # DAP 어댑터 EXE
│ │ ├── main.cpp # 진입점 (모드 파싱)
│ │ ├── dap_server.* # DAP 프로토콜 핸들러
│ │ ├── dap_types.h # DAP 타입 정의
│ │ ├── transport.* # stdin/stdout & TCP 전송
│ │ ├── injector.* # DLL 인젝션 (4가지 방식)
│ │ ├── pipe_client.* # Named Pipe IPC 클라이언트
│ │ ├── disassembler.h # IDisassembler 인터페이스
│ │ ├── disassembler.cpp # SimpleDisassembler (내장 경량 디코더)
│ │ └── zydis_disassembler.cpp # ZydisDisassembler (Zydis v4 기반)
│ ├── mcp/ # MCP 도구 서버
│ │ ├── main.cpp # 진입점 (--install, --log 등)
│ │ ├── mcp_server.* # MCP 프로토콜 + 26개 도구 구현
│ │ └── installer.* # 에이전트별 자동 설치/제거
│ └── common/ # 공유 코드
│ ├── ipc_protocol.h # IPC 명령/응답 정의
│ └── logger.h # 로깅 유틸리티
├── third_party/ # 외부 라이브러리
│ └── nlohmann/json.hpp # JSON 파서 (MIT)
│ # Zydis v4.1 (vendored in third_party/)
└── extension/ # VSCode 익스텐션
├── package.json
├── tsconfig.json
└── src/extension.ts
- 관리자 권한으로 VSCode/어댑터 실행
- 타겟 프로세스의 비트 수(32/64) 확인 — DLL 비트가 일치해야 함
- 안티바이러스가 인젝션을 차단하는지 확인
- 기본 타임아웃은 7초. 느린 시스템에서는 DLL 로드에 시간이 걸릴 수 있음
- 로그 파일로 진행 상황 확인:
--log=debug.log --log-level=debug
- PDB 파일이 타겟 EXE와 같은 디렉토리에 있는지 확인
- PDB 없이는 주소 기반 BP(
setInstructionBreakpoints)만 가능 - 하드웨어 BP는 최대 4개 제한
--remote또는--bind=0.0.0.0옵션을 사용했는지 확인- 방화벽에서 해당 포트가 열려있는지 확인
- VM의 네트워크 어댑터가 브릿지 모드인지 확인
| 라이브러리 | 용도 | 라이선스 |
|---|---|---|
| nlohmann/json | JSON 파싱 (header-only) | MIT |
| Zydis v4.1 | x86/x64 디스어셈블리 (third_party에 포함) | MIT |
MIT License