일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- canary leak
- windows
- pwndbg
- kaslr
- RAO
- windows kernel
- PLT
- cmake
- ioploaddrivers
- return to libraty
- randtbl
- dangling pointer
- frida-dump
- sgerrand
- fastbin
- JOP
- SCP
- WinDBG
- libc-database
- 계산기
- ntwritefile
- top chunk
- Android
- kernel debug
- libc.so
- brop
- house of force
- HOS
- patchelf
- elf 헤더
- Today
- Total
sh711 님의 블로그
Windows Kernel Driver Load 본문
윈도우 부팅 과정
드라이버 로드 과정 확인을 위해 nt!IopInitializeBootDrivers 함수에 bp를 설정했다
이어서, nt!IopLoadDriver 함수에 브레이크 설정 후 Go 하면 브레이크가 잡힌다
IopLoadDriver 함수는 로드할 드라이버의 경로, 각 드라이버에 존재하는 DRIVER_OBJECT를 인자로 받는다
// IopLoadDriver 함수 원형
NTSTATUS IopLoadDriver(
IN PUNICODE_STRING DriverName,
IN PDRIVER_OBJECT *DriverObject
);
인자인 rcx, rdx 의 값 확인 시 현재 확인이 불가하다
이어서, nt!MmLoadSystemImageEx 함수에 브레이크를 걸고 진행시킨다
이제 드라이버 내 DriverEntry로 점프하는 곳을 찾아가보자
nt!MiDriverLoadSucceeded 함수에 브레이크 후 진입한다
해당 함수 MiCacheImageSymbols는 rcx 인자로 로드할 드라이버의 베이스 주소를 입력 받는다
0xfffff80179400000
rcx 값 확인시 PE 파일(커널드라이버) 식별
이어서 _wcsnicmp 함수를 호출한다
_wcsnicmp 함수는 문자열을 대소문자 구분없이 비교하는 함수이고 원형은 다음과 같다.
int _wcsnicmp(
const wchar_t *str1,
const wchar_t *str2,
size_t count
);
rcx 값
현재 로드할 드라이버 경로 ==> \SystemRoot\System32\drivers\pacer.sys
따라서 아직 모듈이 로드되지 않아 심볼을 확인할 수 없다
rdx 값
cc 값은 값 경계를 위한 더미코드
r8 값 (size)
결과적으로 일치하므로 반환값은 0이 나왔다
결과 검증
이후, DbgLoadImageSymbolsUnicode 함수 호출 후 모듈이 등록되는 것을 확인할 수 있다
DbgLoadImageSymbolsUnicode 내부 진입 시 ntkrnlmp!RtlImageNtHeaderEx 함수를 호출한다
해당 함수는 PE파일(로드할 커널드라이브)의 헤더를 찾는 함수이고 커널 내에서 PE구조를 파싱할 때 사용된
// 함수 원형
NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeaderEx(
ULONG Flags,
PVOID Base,
ULONG64 Size,
PIMAGE_NT_HEADERS *OutHeaders
);
return : PIMAGE_NT_HEADERS (NT 헤더 구조체의 주소)
각각의 값 확인이 가능하다
해당 함수 내에서 파일에서 추출한 "PE" 파일 문자열과 0x4550("PE")를 비교하여 같지 않을 경우 rax에 0xc000007b 값을 넣고 ret를 한다.
지금은 올바르게 되어서 rax 값을 r9 값 주소에 넣은 후 r10(0) 반환값 설정 후 ret 한다
이후 DebugService2 함수가 호출되는데 아마 지금 디버깅 중이어서 호출되는것 같다
내부 명령은 0x2D 시그널 인터럽트를 발생시킨다
x86 및 x86-64 아키텍처에서는 4개의 권한 레벨(Ring)이 존재한다
Ring 0 (CPL = 0): 커널 모드 (Kernel Mode)
Ring 3 (CPL = 3): 유저 모드 (User Mode)
유저 모드(Ring 3)에서 syscall 또는 int 명령을 사용하면 커널 모드(Ring 0)로 전환됨
커널 모드에서 실행 중이라면 그대로 Ring 0을 유지함
인터럽트 신호 값은 IDT(Interrupt Descriptor Table) 테이블을 참조하여 인터럽트 핸들러가 실행됨
r 명령을 통한 cs(code segment) 값 확인
cs = 0033일땐 유저 모드
cs = 0010일땐 커널 모드
이어서 확인 시 KiDebugServiceTrap 함수를 호출하였다
현재 디버깅 여부를 알 수 있다.
KdDebuggerEnabled L1 = 1 // 디버거 활성화
KdDebuggerNotPresent L1 = 1 // 디버거 존재하지 않음
인터럽트 이후 모듈이 로드되었다 (pacer.sys 이후라 netbios 모듈 로드)
'Study > Windows' 카테고리의 다른 글
windows API 프로그래밍 (0) | 2025.03.13 |
---|---|
Windbg 윈도우 커널 분석 - 1 (0) | 2025.03.10 |
Windbg 프로그램 분석 (0) | 2025.03.08 |