1: kd> kvL
# ChildEBP RetAddr Args to Child
00 de94f82c 81534f6b 00000050 915c7488 00000011 nt!KeBugCheckEx
01 de94f8d0 814e2912 915c7488 de94f9a0 00237d80 nt!MiSystemFault+0x83b (FPO: [Non-Fpo])
02 de94f988 815e4941 00000011 915c7488 00000000 nt!MmAccessFault+0x162 (FPO: [Non-Fpo])
03 de94f988 915c7488 00000011 915c7488 00000000 nt!KiTrap0E+0x2c9 (FPO: [0,0] TrapFrame @ de94fa28)
WARNING: Frame IP not in any known module. Following frames may be wrong.
04 de94fbb8 8157c748 8aea3f10 93763078 93763008 0x915c7488
05 de94fbd4 817ffad9 0c002a26 00000208 0014ee94 nt!IofCallDriver+0x48 (FPO: [Non-Fpo])
06 de94fcb8 817ff52a 00000000 00000000 0014eea4 nt!IopXxxControlFile+0x5a9 (FPO: [Non-Fpo])
07 de94fce4 815de4ef 00000208 00000000 00000000 nt!NtDeviceIoControlFile+0x2a (FPO: [Non-Fpo])
08 de94fce4 770b07a0 00000208 00000000 00000000 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame @ de94fd14)
09 0014eec4 00000000 00000000 00000000 00000000 0x770b07a0
크래쉬 시점에 콜 스택을 오면 5번. nt!iofCallDriver 후 Trap 이 걸린걸 확인 할 수 있다.
03 de94f988 915c7488 00000011 915c7488 00000000 nt!KiTrap0E+0x2c9 (FPO: [0,0] TrapFrame @ de94fa28)
1: kd> .trap de94fa28
ErrCode = 00000011
eax=ffffffff ebx=93763008 ecx=87b92875 edx=00010004 esi=ffffffff edi=00000004
eip=915c7488 esp=de94fa9c ebp=de94fbb8 iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010286
915c7488 0500800010 add eax,10008000h
1: kd> kvL
*** Stack trace for last set context - .thread/.cxr resets it
# ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 de94fbb8 8157c748 8aea3f10 93763078 93763008 0x915c7488
01 de94fbd4 817ffad9 0c002a26 00000208 0014ee94 nt!IofCallDriver+0x48 (FPO: [Non-Fpo])
02 de94fcb8 817ff52a 00000000 00000000 0014eea4 nt!IopXxxControlFile+0x5a9 (FPO: [Non-Fpo])
03 de94fce4 815de4ef 00000208 00000000 00000000 nt!NtDeviceIoControlFile+0x2a (FPO: [Non-Fpo])
04 de94fce4 770b07a0 00000208 00000000 00000000 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame @ de94fd14)
05 0014eec4 00000000 00000000 00000000 00000000 0x770b07a0
.trap 명령으로 트랙이 걸린 시점에 context들을 확인 할 수 있다.
nt!IofCallDriver:
8157c700 8bff mov edi,edi
8157c702 55 push ebp
8157c703 8bec mov ebp,esp
8157c705 83e4f8 and esp,0FFFFFFF8h
8157c708 a1b0307281 mov eax,dword ptr [nt!IopDispatchCallDriver (817230b0)]
8157c70d 53 push ebx
8157c70e 56 push esi
8157c70f 8bf1 mov esi,ecx
8157c711 85c0 test eax,eax
8157c713 0f85f57b0a00 jne nt!IofCallDriver+0xa7c0e (8162430e) Branch
nt!IofCallDriver+0x19:
8157c719 fe4a23 dec byte ptr [edx+23h]
8157c71c 8a4223 mov al,byte ptr [edx+23h]
8157c71f 84c0 test al,al
8157c721 0f8ed97b0a00 jle nt!IofCallDriver+0xa7c00 (81624300) Branch
nt!IofCallDriver+0x27:
8157c727 8b4260 mov eax,dword ptr [edx+60h]
8157c72a 83e824 sub eax,24h
8157c72d 894260 mov dword ptr [edx+60h],eax
8157c730 8a18 mov bl,byte ptr [eax]
8157c732 897014 mov dword ptr [eax+14h],esi
8157c735 80fb16 cmp bl,16h
8157c738 7414 je nt!IofCallDriver+0x4e (8157c74e) Branch
nt!IofCallDriver+0x3a:
8157c73a 8b4e08 mov ecx,dword ptr [esi+8]
8157c73d 0fb6c3 movzx eax,bl
8157c740 52 push edx
8157c741 56 push esi
8157c742 8b448138 mov eax,dword ptr [ecx+eax*4+38h]
8157c746 ffd0 call eax
nt!IofCallDriver+0x48:
8157c748 5e pop esi
01 de94fbd4 817ffad9 0c002a26 00000208 0014ee94 nt!IofCallDriver+0x48 (FPO: [Non-Fpo])
콜스택 상 nt!IofCallDriver+0x48 부분에서 크래쉬가 발생하였지만 크래시 발생 시점의 다음 명령주소를 가르킨다.
그래서 실제 크래시 위치는 8157c746 이 된다.
일단 eax를 역분석을 통해 구해 본다.
8157c742 8b448138 mov eax,dword ptr [ecx+eax*4+38h]
eax는 [ecx+eax*4+38h]값의 데이터 이다.
ecx 는 8157c73a 8b4e08 mov ecx,dword ptr [esi+8]에서 구해 오고 있다.
esi는 함수의 시작 위치부분까지 찾아봤을때, 8157c70f 8bf1 mov esi,ecx 이 위치에서 ecx 값으로 대체 된것을 볼수 있다.
해당 함수는 fastcall 방식으로 1번째 인자는 ecx, 2번째 인자는 edx 그리고 나머지를 스택에 저장 한다.
여기서 fastcall 이라고 알 수 있는 이유는 해당 함수를 호출한곳에서 인자를 어떻게 전달하는지 보면 알 수 있다.
817ffac9 0f852d020000 jne nt!IopXxxControlFile+0x7cc (817ffcfc)
817ffacf 8bd6 mov edx,esi
817ffad1 8b4d94 mov ecx,dword ptr [ebp-6Ch]
817ffad4 e827ccd7ff call nt!IofCallDriver (8157c700)
nt!IopXxxControlFile 함수에서 nt!IofCallDriver 함수를 호출하기전에 ecx 와 edx 에 데이터를 넣고 있는것 볼 수 있다. 있는 fastcall 방식임을 암시 한다.
nt!IopXxxControlFile 함수 위 부분을 보면 아래와 같은 코드를 볼수있다.
817ff80c e87fcbd7ff call nt!IopAllocateIrpExReturn (8157c390)
817ff811 8bf0 mov esi,eax
817ff813 8975a4 mov dword ptr [ebp-5Ch],esi
irp 를 생성하고 그 생성된 값을 esi 에 저장 한다음 해당 함수의 BasePointer(Ebp) 에서 -5C 부분에 저장 하고 있다.
결국 esi 값은 irp 임을 알수 있고 해당 데이터는 해당 함수의 BasePointer -5c 부분을 가져 오면된다.
Ebp Ret Arg1
02 de94fcb8 817ff52a 00000000 00000000 0014eea4 nt!IopXxxControlFile+0x5a9 (FPO: [Non-Fpo])
Windbg 에서 kvL 명령으로 콜스택을 보면 2번재 부분이 해당 함수의 EBP 값을 가지고 있다.
[de94fcb8 - 5c] 메모리 값은
1: kd> dd de94fcb8 - 5c L1
de94fc5c 93763008
93763008 이다.
!irp 명령으로 irp 데이터인지 확인
1: kd> !irp 93763008
Irp is active with 1 stacks 1 is current (= 0x93763078)
No Mdl: System buffer=8b44ea80: Thread b2f22a80: Irp stack trace.
cmd flg cl Device File Completion-Context
>[IRP_MJ_DEVICE_CONTROL(e), N/A(0)]
5 0 8aea3f10 915c7488 00000000-00000000
\Driver\JRSKD24
Args: 00000004 0000028c 0x22e018 00000000
IRP 데이터임이 확인 되었다.
nt!IofCallDriver 함수를 호출 할때 esi 데이터가 irp 이므로 두번재 인자로 irp 데이터가 전달되었다.
이제 ecx 값을 구하면 된다 . nt!IofCallDriver 함수 원형을 찾아 보면 첫 번째 인자로 deviceObject 가 전달된다.
817ffad1 8b4d94 mov ecx,dword ptr [ebp-6Ch]
817ffad4 e827ccd7ff call nt!IofCallDriver (8157c700)
nt!IofCallDriver 호출 하기전 바로 위 코드르를 보면 [ebp-6Ch]값을 ecx 로 전달 하고 있다. 예상컨데 해당 값은 deviceObject 가 확실 할 것이다.
[de94fcb8 -0x6c] 데이터를 찾아가 보면
1: kd> dd [de94fcb8 -0x6c]
de94fc4c 8aea3f10 00000001 0000028c 00000000
de94fc5c 93763008 00000000 01000000 00000004
1: kd> !devobj 8aea3f10
Device object (8aea3f10) is for:
JRSKD24 \Driver\JRSKD24 DriverObject c43eb4d0
Current Irp 00000000 RefCount 1 Type 00000022 Flags 00000044
SecurityDescriptor 866ef450 DevExt 00000000 DevObjExt 8aea3fc8
ExtensionFlags (0x00000800) DOE_DEFAULT_SD_PRESENT
Characteristics (0x00000100) FILE_DEVICE_SECURE_OPEN
Device queue is not busy.
deviceObje 임을 확인 할 수 있다.
다시 크래쉬가 발생 한 함수 nt!IofCallDriver 로 돌아가서 분석을 진행 한다.
ecx = 8aea3f10 -> deviceObject
edx = 93763008 -> Irp
최종 ecx 는 구조체 deviceObject 에서 8바이트 떨어진 지점의 데이터 이다.
1: kd> dt _Device_Object 8aea3f10
nt!_DEVICE_OBJECT
+0x000 Type : 0n3
+0x002 Size : 0xb8
+0x004 ReferenceCount : 0n1
+0x008 DriverObject : 0xc43eb4d0 _DRIVER_OBJECT
+0x00c NextDevice : (null)
+0x010 AttachedDevice : (null)
+0x014 CurrentIrp : (null)
+0x018 Timer : (null)
+0x01c Flags : 0x44
+0x020 Characteristics : 0x100
+0x024 Vpb : (null)
+0x028 DeviceExtension : (null)
+0x02c DeviceType : 0x22
+0x030 StackSize : 1 ''
+0x034 Queue : <unnamed-tag>
+0x05c AlignmentRequirement : 0
+0x060 DeviceQueue : _KDEVICE_QUEUE
+0x074 Dpc : _KDPC
+0x094 ActiveThreadCount : 0
+0x098 SecurityDescriptor : 0x866ef450 Void
+0x09c DeviceLock : _KEVENT
+0x0ac SectorSize : 0
+0x0ae Spare1 : 0
+0x0b0 DeviceObjectExtension : 0x8aea3fc8 _DEVOBJ_EXTENSION
+0x0b4 Reserved : (null)
결국 ecx 는 0xc43eb4d0 _DRIVER_OBJECT 임을 알 수 있다.
8157c742 8b448138 mov eax,dword ptr [ecx+eax*4+38h]
8157c746 ffd0 call eax
eax 는 bl 값을 가지고 있다. bl은 2바이트 크기를 가진다.
edx + 60 은 irp +60의 값이다. 메모리 값을 직접 찾아보면
1: kd> dd 93763008+ 0x60 mov eax,dword ptr [edx+60h]
93763068 93763078 915c7488 00000000 00000000
93763078 0005000e 00000004 0000028c 0022e018
1: kd> dd 93763078 mov bl,byte ptr [eax]
93763078 0005000e 00000004 0000028c 0022e018
byte 즉 1바이트많을 bl에 저장 하고 있으므로 bl의 값은 0xe 이다.
최종적으로 eax 값은 0xe를 가진다.
ecx = 0xc43eb4d0 _DRIVER_OBJECT
eax = 0xe
8157c742 8b448138 mov eax,dword ptr [ecx+eax*4+38h]
8157c746 ffd0 call eax
이제 해당 값을 연산해 보면
[0xc43eb4d0 + 0e *4 + 0x38] = >c43eb540
1: kd> dd c43eb540
c43eb540 87b9bc76 87b9ba1e 87b9ba1e 87b9ba1e
1: kd> u 87b9bc76
모 모듈의 함수 임을 알 수 있다. 결론적으로 해당 함수를 호출 하면서 크래쉬가 발생 했다.
[0xc43eb4d0 + 0e *4 + 0x38] = >c43eb540
데이터를 좀더 분석 해 보면
0xc43eb4d0 즉 driveObject의 내부의 데이터이임을 알수 있으므로 driveObject 구조체 내용을 확인해 보면 다음과 같다
1: kd> dt _DRIVER_OBJECT 0xc43eb4d0
nt!_DRIVER_OBJECT
+0x000 Type : 0n4
+0x002 Size : 0n168
+0x004 DeviceObject : 0x8aea3f10 _DEVICE_OBJECT
+0x008 Flags : 0x12
+0x00c DriverStart : 0x87b80000 Void
+0x010 DriverSize : 0x2a800
+0x014 DriverSection : 0x93544008 Void
+0x018 DriverExtension : 0xc43eb578 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "\Driver\JRSKD24"
+0x024 HardwareDatabase : 0x81a78238 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0x87b9cdae long +0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : 0x87b9c23e void +0
+0x038 MajorFunction : [28] 0x87b9b9e2 long +0
1: kd> dx -id 0,0,998fa040 -r1 (*((ntkrpamp!long (*(*)[28])(_DEVICE_OBJECT *,_IRP *))0xc43eb508))
(*((ntkrpamp!long (*(*)[28])(_DEVICE_OBJECT *,_IRP *))0xc43eb508)) [Type: long (* [28])(_DEVICE_OBJECT *,_IRP *)]
[0] : 0x87b9b9e2 [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[1] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[2] : 0x87b9bae2 [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[3] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[4] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[5] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[6] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[7] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[8] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[9] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[10] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[11] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[12] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[13] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[14] : 0x87b9bc76 [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[15] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[16] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[17] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[18] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[19] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[20] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[21] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[22] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[23] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[24] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[25] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[26] : 0x87b9ba1e [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
[27] : 0x8155dae0 [Type: long (*)(_DEVICE_OBJECT *,_IRP *)]
해당 드라이버의 14번 index 의 디스패치 루틴의 주소 값이다.
위 인덱스는 디바이스드라이버 개발 문서를 보면 확인 할 수 있다. 아래 URL 참조 docs.microsoft.com/en-us/windows-hardware/drivers/ifs/registering-irp-dispatch-routines
이상 덤프를 분석하여 문제가 되는 함수를 찾았다.
'개발 > Windows' 카테고리의 다른 글
[windbg] - 1 (0) | 2021.05.26 |
---|---|
[악성코드 분석] (0) | 2021.02.28 |
PE구조 (1) (0) | 2020.09.12 |