在第1部分中,我确定了驱动程序的Dispatcher函数以及两个正在初始化驱动程序的某些变量的函数(fn_InitDispatchMethodArray和fn_ObtainKernelFunctions)。
逆向这两个函数,分析一下它们的功能,这会帮助我了解在此驱动程序上实现的Dispatcher函数。
0x01 概述
1. 该驱动程序的一些基本初始化机制
2. 确定用于索引和存储所有可用方法的自定义结构。
3. 确定函数地址在内存中的位置,例如ObRegisterCallbacks。
0x02 fn_InitDispatchMethodArray(0x1400015F8)
该函数的代码片段:
- __int64 sub_1400015F8()
- {
- __int64 result; // rax
- memset(&dword_140009E40, 0, 0x400ui64);
- dword_140009E40 = 774;
- qword_140009E48 = (__int64)sub_140001058;
- qword_140009E58 = (__int64)sub_14000101C;
- qword_140009E68 = (__int64)sub_140001CC8;
- qword_140009E78 = (__int64)sub_140001BFC;
- qword_140009E88 = (__int64)sub_140001DC0;
- qword_140009E98 = (__int64)sub_140001B50;
- qword_140009EA8 = (__int64)sub_140001C3C;
- qword_140009EB8 = (__int64)sub_140001D04;
- qword_140009EC8 = (__int64)sub_14000137C;
- qword_140009ED8 = (__int64)sub_14000191C;
- qword_140009EE8 = (__int64)sub_140001340;
- qword_140009EF8 = (__int64)sub_140001A58;
- qword_140009F08 = (__int64)sub_1400019A4;
- qword_140009F18 = (__int64)sub_140001224;
- qword_140009F28 = (__int64)sub_14000187C;
- qword_140009F38 = (__int64)sub_140001488;
- qword_140009F48 = (__int64)sub_140001548;
- qword_140009F58 = (__int64)sub_1400013B8;
- qword_140009F68 = (__int64)sub_140001264;
- qword_140009F78 = (__int64)sub_14000150C;
- qword_140009F88 = (__int64)sub_140001174;
- qword_140009F98 = (__int64)sub_1400015CC;
- qword_140009FA8 = (__int64)sub_14000107C;
- qword_140009FB8 = (__int64)sub_140001D4C;
- qword_140009FC8 = (__int64)sub_140001D88;
- result = 0i64;
- dword_140009E50 = 775;
- dword_140009E60 = 776;
- dword_140009E70 = 777;
- dword_140009E80 = 778;
- dword_140009E90 = 779;
- dword_140009EA0 = 790;
- dword_140009EB0 = 782;
- dword_140009EC0 = 783;
- dword_140009ED0 = 785;
- dword_140009EE0 = 786;
- dword_140009EF0 = 787;
- dword_140009F00 = 788;
- dword_140009F10 = 789;
- dword_140009F20 = 791;
- dword_140009F30 = 792;
- dword_140009F40 = 793;
- dword_140009F50 = 794;
- dword_140009F60 = 796;
- dword_140009F70 = 797;
- dword_140009F80 = 798;
- dword_140009F90 = 799;
- dword_140009FA0 = 800;
- dword_140009FB0 = 801;
- dword_140009FC0 = 802;
- dword_14000A240 = 25;
- return result;
- }
汇编代码段:
- .text:00000001400015F8 ; =============== S U B R O U T I N E =======================================
- .text:00000001400015F8
- .text:00000001400015F8
- .text:00000001400015F8 sub_1400015F8 proc near ; CODE XREF: DriverEntry+110↓p
- .text:00000001400015F8 ; DATA XREF: .pdata:000000014000D084↓o
- .text:00000001400015F8 sub rsp, 28h
- .text:00000001400015FC xor edx, edx ; Val
- .text:00000001400015FE lea rcx, dword_140009E40 ; Dst
- .text:0000000140001605 mov r8d, 400h ; Size
- .text:000000014000160B call memset
- .text:0000000140001610 lea rax, sub_140001058
- .text:0000000140001617 mov cs:dword_140009E40, 306h
- .text:0000000140001621 mov cs:qword_140009E48, rax
- .text:0000000140001628 lea rax, sub_14000101C
- .text:000000014000162F mov cs:qword_140009E58, rax
- .text:0000000140001636 lea rax, sub_140001CC8
- .text:000000014000163D mov cs:qword_140009E68, rax
- .text:0000000140001644 lea rax, sub_140001BFC
- .text:000000014000164B mov cs:qword_140009E78, rax
- .text:0000000140001652 lea rax, sub_140001DC0
- .text:0000000140001659 mov cs:qword_140009E88, rax
- .text:0000000140001660 lea rax, sub_140001B50
- .text:0000000140001667 mov cs:qword_140009E98, rax
- .text:000000014000166E lea rax, sub_140001C3C
- .text:0000000140001675 mov cs:qword_140009EA8, rax
- .text:000000014000167C lea rax, sub_140001D04
- .text:0000000140001683 mov cs:qword_140009EB8, rax
- .text:000000014000168A lea rax, sub_14000137C
- .text:0000000140001691 mov cs:qword_140009EC8, rax
- .text:0000000140001698 lea rax, sub_14000191C
- .text:000000014000169F mov cs:qword_140009ED8, rax
- .text:00000001400016A6 lea rax, sub_140001340
- .text:00000001400016AD mov cs:qword_140009EE8, rax
- .text:00000001400016B4 lea rax, sub_140001A58
- .text:00000001400016BB mov cs:qword_140009EF8, rax
- .text:00000001400016C2 lea rax, sub_1400019A4
- .text:00000001400016C9 mov cs:qword_140009F08, rax
- .text:00000001400016D0 lea rax, sub_140001224
- .text:00000001400016D7 mov cs:qword_140009F18, rax
- .text:00000001400016DE lea rax, sub_14000187C
- .text:00000001400016E5 mov cs:qword_140009F28, rax
- .text:00000001400016EC lea rax, sub_140001488
- .text:00000001400016F3 mov cs:qword_140009F38, rax
- .text:00000001400016FA lea rax, sub_140001548
- .text:0000000140001701 mov cs:qword_140009F48, rax
- .text:0000000140001708 lea rax, sub_1400013B8
- .text:000000014000170F mov cs:qword_140009F58, rax
- .text:0000000140001716 lea rax, sub_140001264
- .text:000000014000171D mov cs:qword_140009F68, rax
- .text:0000000140001724 lea rax, sub_14000150C
- .text:000000014000172B mov cs:qword_140009F78, rax
- .text:0000000140001732 lea rax, sub_140001174
- .text:0000000140001739 mov cs:qword_140009F88, rax
- .text:0000000140001740 lea rax, sub_1400015CC
- .text:0000000140001747 mov cs:qword_140009F98, rax
- .text:000000014000174E lea rax, sub_14000107C
- .text:0000000140001755 mov cs:qword_140009FA8, rax
- .text:000000014000175C lea rax, sub_140001D4C
- .text:0000000140001763 mov cs:qword_140009FB8, rax
- .text:000000014000176A lea rax, sub_140001D88
- .text:0000000140001771 mov cs:qword_140009FC8, rax
- .text:0000000140001778 xor eax, eax
- .text:000000014000177A mov cs:dword_140009E50, 307h
- .text:0000000140001784 mov cs:dword_140009E60, 308h
- .text:000000014000178E mov cs:dword_140009E70, 309h
- .text:0000000140001798 mov cs:dword_140009E80, 30Ah
- .text:00000001400017A2 mov cs:dword_140009E90, 30Bh
- .text:00000001400017AC mov cs:dword_140009EA0, 316h
- .text:00000001400017B6 mov cs:dword_140009EB0, 30Eh
- .text:00000001400017C0 mov cs:dword_140009EC0, 30Fh
- .text:00000001400017CA mov cs:dword_140009ED0, 311h
- .text:00000001400017D4 mov cs:dword_140009EE0, 312h
- .text:00000001400017DE mov cs:dword_140009EF0, 313h
- .text:00000001400017E8 mov cs:dword_140009F00, 314h
- .text:00000001400017F2 mov cs:dword_140009F10, 315h
- .text:00000001400017FC mov cs:dword_140009F20, 317h
- .text:0000000140001806 mov cs:dword_140009F30, 318h
- .text:0000000140001810 mov cs:dword_140009F40, 319h
- .text:000000014000181A mov cs:dword_140009F50, 31Ah
- .text:0000000140001824 mov cs:dword_140009F60, 31Ch
- .text:000000014000182E mov cs:dword_140009F70, 31Dh
- .text:0000000140001838 mov cs:dword_140009F80, 31Eh
- .text:0000000140001842 mov cs:dword_140009F90, 31Fh
- .text:000000014000184C mov cs:dword_140009FA0, 320h
- .text:0000000140001856 mov cs:dword_140009FB0, 321h
- .text:0000000140001860 mov cs:dword_140009FC0, 322h
- .text:000000014000186A mov cs:dword_14000A240, 19h
- .text:0000000140001874 add rsp, 28h
- .text:0000000140001878 retn
- .text:0000000140001878 sub_1400015F8 endp
- .text:0000000140001878
还原后的代码:
- __int64 fn_InitDispatchMethodArray()
- {
- __int64 result; // rax
- memset(IOCTLFunctionArray, 0, 0x400ui64);
- IOCTLFunctionArray[0].Index = 774; // 9E40
- IOCTLFunctionArray[0].FnPtr = sub_140001058;
- IOCTLFunctionArray[1].FnPtr = sub_14000101C;
- IOCTLFunctionArray[2].FnPtr = sub_140001CC8;
- IOCTLFunctionArray[3].FnPtr = sub_140001BFC;
- IOCTLFunctionArray[4].FnPtr = sub_140001DC0;
- IOCTLFunctionArray[5].FnPtr = sub_140001B50;
- IOCTLFunctionArray[6].FnPtr = sub_140001C3C;
- IOCTLFunctionArray[7].FnPtr = sub_140001D04;
- IOCTLFunctionArray[8].FnPtr = sub_14000137C;
- IOCTLFunctionArray[9].FnPtr = sub_14000191C;
- IOCTLFunctionArray[10].FnPtr = sub_140001340;
- IOCTLFunctionArray[11].FnPtr = sub_140001A58;
- IOCTLFunctionArray[12].FnPtr = sub_1400019A4;
- IOCTLFunctionArray[13].FnPtr = sub_140001224;
- IOCTLFunctionArray[14].FnPtr = sub_14000187C;
- IOCTLFunctionArray[15].FnPtr = sub_140001488;
- IOCTLFunctionArray[16].FnPtr = sub_140001548;
- IOCTLFunctionArray[17].FnPtr = sub_1400013B8;
- IOCTLFunctionArray[18].FnPtr = fn_ReadFileContent_;
- IOCTLFunctionArray[19].FnPtr = fn_IOCTL_ValidatePidPEB;
- IOCTLFunctionArray[20].FnPtr = fn_IOCTL_ControlCallbackRoutines;
- IOCTLFunctionArray[21].FnPtr = sub_1400015CC;
- IOCTLFunctionArray[22].FnPtr = sub_14000107C;
- IOCTLFunctionArray[23].FnPtr = sub_140001D4C; // CR0
- IOCTLFunctionArray[24].FnPtr = sub_140001D88;
- result = 0i64;
- IOCTLFunctionArray[1].Index = 775;
- IOCTLFunctionArray[2].Index = 776;
- IOCTLFunctionArray[3].Index = 777;
- IOCTLFunctionArray[4].Index = 778;
- IOCTLFunctionArray[5].Index = 779;
- IOCTLFunctionArray[6].Index = 790;
- IOCTLFunctionArray[7].Index = 782;
- IOCTLFunctionArray[8].Index = 783;
- IOCTLFunctionArray[9].Index = 785;
- IOCTLFunctionArray[10].Index = 786;
- IOCTLFunctionArray[11].Index = 787;
- IOCTLFunctionArray[12].Index = 788;
- IOCTLFunctionArray[13].Index = 789;
- IOCTLFunctionArray[14].Index = 791;
- IOCTLFunctionArray[15].Index = 792;
- IOCTLFunctionArray[16].Index = 793;
- IOCTLFunctionArray[17].Index = 794;
- IOCTLFunctionArray[18].Index = 796;
- IOCTLFunctionArray[19].Index = 797;
- IOCTLFunctionArray[20].Index = 798;
- IOCTLFunctionArray[21].Index = 799;
- IOCTLFunctionArray[22].Index = 800;
- IOCTLFunctionArray[23].Index = 801;
- IOCTLFunctionArray[24].Index = 802;
- FunctionsCount = 0x19;
- return result;
- }
可以在此函数中看到正在初始化的自定义结构:
- .text:0000000140001617 mov cs:dword_140009E40, 306h
- .text:0000000140001621 mov cs:qword_140009E48, rax
- .text:0000000140001628 lea rax, sub_14000101C
- .text:000000014000162F mov cs:qword_140009E58, rax
- .text:0000000140001636 lea rax, sub_140001CC8
- .text:000000014000163D mov cs:qword_140009E68, rax
上面的汇编代码中,可以看到它们首先将int值分配给特定的内存地址,然后再移动8个字节将指针写入函数,我将这种结构称为IOCTLFunctionArray,该数组将在调度请求时发挥重要作用。
结构如下所示:
- typedef struct DispatcherStruct {
- int Index;
- char padding[4];
- PVOID FnPtr;
- };
在IDA Pro中:
- 00000000 DispatcherStruct struc ; (sizeof=0x10, mappedto_424)
- 00000000 ; XREF: .data:_IOCTLFunctionArray/r
- 00000000 Index dd ? ; XREF: fn_InitDispatchMethodArray+1F/t
- 00000004 padding db 4 dup(?)
- 00000008 FnPtr dq ?
- 00000010 DispatcherStruct ends
此函数重复了25次,所以称其为array,它们在数组中存储相同结构25次。
将dword_14000A240重命名为FunctionsCount的变量:
- .text:000000014000186A mov cs:FunctionsCount , 19h
之后将看到在Dispatcher上如何使用此变量,基于此函数,可以确定驱动程序没有调用所有可用方法的列表,并提供某种索引值,可以调用它们。
最终整理的代码片段:
https://github.com/niemand-sec/Reversing-XignCode3-Driver/blob/master/XC3/fn_InitDispatchMethodArray_reversed.c
- __int64 fn_InitDispatchMethodArray()
- {
- __int64 result; // rax
- memset(IOCTLFunctionArray, 0, 0x400ui64);
- IOCTLFunctionArray[0].Index = 774; // 9E40
- IOCTLFunctionArray[0].FnPtr = sub_140001058;
- IOCTLFunctionArray[1].FnPtr = sub_14000101C;
- IOCTLFunctionArray[2].FnPtr = sub_140001CC8;
- IOCTLFunctionArray[3].FnPtr = sub_140001BFC;
- IOCTLFunctionArray[4].FnPtr = sub_140001DC0;
- IOCTLFunctionArray[5].FnPtr = sub_140001B50;
- IOCTLFunctionArray[6].FnPtr = sub_140001C3C;
- IOCTLFunctionArray[7].FnPtr = sub_140001D04;
- IOCTLFunctionArray[8].FnPtr = sub_14000137C;
- IOCTLFunctionArray[9].FnPtr = sub_14000191C;
- IOCTLFunctionArray[10].FnPtr = sub_140001340;
- IOCTLFunctionArray[11].FnPtr = sub_140001A58;
- IOCTLFunctionArray[12].FnPtr = sub_1400019A4;
- IOCTLFunctionArray[13].FnPtr = sub_140001224;
- IOCTLFunctionArray[14].FnPtr = sub_14000187C;
- IOCTLFunctionArray[15].FnPtr = sub_140001488;
- IOCTLFunctionArray[16].FnPtr = sub_140001548;
- IOCTLFunctionArray[17].FnPtr = sub_1400013B8;
- IOCTLFunctionArray[18].FnPtr = fn_ReadFileContent_;
- IOCTLFunctionArray[19].FnPtr = fn_IOCTL_ValidatePidPEB;
- IOCTLFunctionArray[20].FnPtr = fn_IOCTL_ControlCallbackRoutines;
- IOCTLFunctionArray[21].FnPtr = sub_1400015CC;
- IOCTLFunctionArray[22].FnPtr = sub_14000107C;
- IOCTLFunctionArray[23].FnPtr = sub_140001D4C; // CR0
- IOCTLFunctionArray[24].FnPtr = sub_140001D88;
- result = 0i64;
- IOCTLFunctionArray[1].Index = 775;
- IOCTLFunctionArray[2].Index = 776;
- IOCTLFunctionArray[3].Index = 777;
- IOCTLFunctionArray[4].Index = 778;
- IOCTLFunctionArray[5].Index = 779;
- IOCTLFunctionArray[6].Index = 790;
- IOCTLFunctionArray[7].Index = 782;
- IOCTLFunctionArray[8].Index = 783;
- IOCTLFunctionArray[9].Index = 785;
- IOCTLFunctionArray[10].Index = 786;
- IOCTLFunctionArray[11].Index = 787;
- IOCTLFunctionArray[12].Index = 788;
- IOCTLFunctionArray[13].Index = 789;
- IOCTLFunctionArray[14].Index = 791;
- IOCTLFunctionArray[15].Index = 792;
- IOCTLFunctionArray[16].Index = 793;
- IOCTLFunctionArray[17].Index = 794;
- IOCTLFunctionArray[18].Index = 796;
- IOCTLFunctionArray[19].Index = 797;
- IOCTLFunctionArray[20].Index = 798;
- IOCTLFunctionArray[21].Index = 799;
- IOCTLFunctionArray[22].Index = 800;
- IOCTLFunctionArray[23].Index = 801;
- IOCTLFunctionArray[24].Index = 802;
- FunctionsCount = 0x19;
- return result;
- }
0x03 fn_ObtainKernelFunctions(0x140002A18)
下面的函数很简单,为了继续进行初始化,驱动程序需要一些特定例程的地址:
这样做可以确保这些函数在运行的Windows版本上可用,并获得指向它们的指针,只需要将它们存储在一个变量中,然后通过将其转换为属性函数定义来使用它们来调用这些例程。
也可以在汇编函数中发现:
- .text:0000000140002A1C lea rdx, SourceString ; "ObGetFilterVersion"
- .text:0000000140002A23 lea rcx, [rsp+38h+DestinationString] ; DestinationString
- .text:0000000140002A28 call cs:RtlInitUnicodeString
- .text:0000000140002A2E lea rcx, [rsp+38h+DestinationString] ; SystemRoutineName
- .text:0000000140002A33 call cs:MmGetSystemRoutineAddress
- .text:0000000140002A39 lea rdx, aObregistercall ; "ObRegisterCallbacks"
- .text:0000000140002A40 mov cs:qword_14000A288, rax
- .text:0000000140002A47 lea rcx, [rsp+38h+DestinationString] ; DestinationString
- .text:0000000140002A4C call cs:RtlInitUnicodeString
- .text:0000000140002A52 lea rcx, [rsp+38h+DestinationString] ; SystemRoutineName
- .text:0000000140002A57 call cs:MmGetSystemRoutineAddress
本文翻译自:https://niemand.com.ar/2020/01/16/reversing-xigncode3-driver-part-2-analyzing-init-functions/如若转载,请注明原文地址。