2014 CodeEngn Conference 10
MS 에게 속았어요
Windows 운영체제가 지원하는 디버거 지원 기능들과 브랜치 트레이서를 구현하기 위한 몇 가지 방법들을 소개하고, Windows 커널에 이미 구현되어있는 하드웨어 기반 브랜치 트레이서 코드 분석과 여기에 존재하는 의도된(?) 버그를 살펴본다.
http://codeengn.com/conference/10
http://codeengn.com/conference/archive
3. Debugger를 만들면서 겪었던 일을 이야기 하고자 합니다.
+ windows kernel 분석 방법도…
+ Vesper project 얘기 쬐~끔…
4. Debugger
kernel mode
user mode
kernel mode functions
nt!KdDisableDebugger
SoftICE, WinDbg
Windows api
CreateProcessW with DEBUG_ONLY_THIS_PROCESS
Olly, WinDbg, Visual Studio
ContinueDebugEvent()
WaitForDebugEvent()
EXCEPTION_DEBUG_EVENT
CREATE_THREAD_DEBUG_EVENT
CREATE_PROCESS_DEBUG_EVENT
EXIT_THREAD_DEBUG_EVENT
EXIT_PROCESS_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
UNLOAD_DLL_DEBUG_EVENT
OUTPUT_DEBUG_STRING_EVENT
Debugger 는
HyperDBG…
by hypervisor !
5. Vesper 는 branch tracing 에 특화된 Debugger 를 만들고자 해요…
네, 이미 많이 있습니다.
process stalker 도 있고,
olly 에서도 다 될 껄요?
그냥 하는…
6. Windows 살펴보기 - CONTEXT structure
GetThreadContext(current_thread, &context);
…
context.Eflags |= TRAP_FLAG; // set single step
…
SetThreadContext(current_thread, &context);
…
LBR Stack 같
은데?
윈도우 커널
에 이미 구현
되어있나?
어떻게 쓰는
거지?
7. Windows 살펴보기 – SetThreadContext 복잡해 보이는데… 하지 말까?..
1: kd> uf /c /D nt!NtSetContextThread
nt!NtSetContextThread (fffff800`02f2d760)
nt!NtSetContextThread+0x43 (fffff800`02f2d7a3):
call to nt!ObReferenceObjectByHandle (fffff800`02fb19a0)
nt!NtSetContextThread+0x63 (fffff800`02f2d7c3):
call to nt!PsSetContextThread (fffff800`02f2d740)
nt!NtSetContextThread+0x74 (fffff800`02f2d7d4):
call to nt!ObfDereferenceObject (fffff800`02ce1d80)
1: kd> uf /c /D 0xfffff800`02f2d740
nt!PsSetContextThread (fffff800`02f2d740)
nt!PsSetContextThread+0xc (fffff800`02f2d74c):
call to nt!PspSetContextThreadInternal (fffff800`02fca4b4)
1: kd> uf /c /D 0xfffff800`02fca4b4
nt!PspSetContextThreadInternal (fffff800`02fca4b4)
... 생략 …
call to nt!KeInsertQueueApc (fffff800`02cb9624)
... 생략 …
8. Windows (좀 더 깊이) 살펴보기 - KiDebugtrapOrFault
Hand-Ray
역시 hand-ray 가 짱이죠!
10. 정리 - DR7 과 IA32_DEBUGCTL MSR 간의 관계
LE (0x100)
GE (0x200)
DR7 레지스터
LBR (bit 0) – 마지막 branch, exception, interrupt 를 LBR stack 에 저장
BTF (bit 1) – Single Step On Branch
IA32_DEBUGCTL MSR
13. 다시 보기 - KiDebugtrapOrFault
GS:[4D4A] 의 값이 2가 아니면 BTF, LBR 기능이 동작하지 않습니다. 저게 대체 뭘까요?
14. GS:[4D4A] 가 뭐길래…
0x19 != 2 이므로
안 되는 것이 맞는 것 같긴 하지만,
CPU 에서 LBR, BTF 를 지원하는데…?
분석 전략 - GS:[4d4a]
# reboot system
# set memory break point at GS:[4D4A]
사실은…
bp 를 설치한 채로 부팅을 계속하면
BSOD 가 발생…
15. GS:[4D4A] 좀 더 자세히…
실제 주소로 매핑 해보니…
- 4바이트 변수의 3번째 바이트
- 비트 필드 스트럭처 일것이다!
- 각 비트가 CPU 의 특정 기능을 나타낼 것으로 예상…
- 대체 어떤 기능일까?
16. _KPCR.Prcb.FeatureBits … 이걸… 계속 해야 하나?...
분석 전략
# KiInitialPCR 포인터이므로 KiInitialXXXX 류의 함수들이 접근할 것
# KiInitialXXX 함수들 몽땅 읽어보면 되겠습니다 :-)
17. nt!KiSetFeatureBits … 이걸…계속 해야 하나?...그만할까…
분석 전략
# 왕도는 없다. 집중해서 보는 것 말고는…
# cpuid 명령어를 많이 호출할 것이고, cpu vender, cpu type, cpu family 등의 값을 이용해 특정 기능 사용 여부 등을 저장하는 기능일 것이다.
시작부터 CPUID…
CpuVender = 1 : AMD
CpuVender = 2 : Intel
18. nt!KiSetFeatureBits … 이걸…계속 해야 하나?...그만할까…그만하고 싶다…
Hand-Ray
IvyBridge, Core i7 - BTF, LBR 지원합니다!!!
intel cpu type & model http://goo.gl/l8nrnW
19. 그래서…결론은…
MS 가 구현해 둔 LBR/BTF 는 쓸 수 없습니다.
AMD CPU 도 아니고, 제 CPU 는 최신이거든요.
의도된 버그일까요? 아님 그냥 사소한 실수일까요?
windows 8.1 도 동일하던데…
좋다가 말았습니다.
결국 Driver 를 구현해야 겠군요…
20. Vesper 는 … 드라이버를 만들었습니다. 아… 귀찮아…인증서도 없는데…
https://github.com/somma/vesper/blob/master/vesper_support/vesper_support.cpp