在第1部分中,我确定了驱动程序的Dispatcher函数以及两个正在初始化驱动程序的某些变量的函数(fn_InitDispatchMethodArray和fn_ObtainKernelFunctions)。
逆向这两个函数,分析一下它们的功能,这会帮助我了解在此驱动程序上实现的Dispatcher函数。
![逆向XignCode3驱动程序:分析init初始化函数(part2) 逆向XignCode3驱动程序:分析init初始化函数(part2)]()
0x01 概述
1. 该驱动程序的一些基本初始化机制
2. 确定用于索引和存储所有可用方法的自定义结构。
3. 确定函数地址在内存中的位置,例如ObRegisterCallbacks。
![逆向XignCode3驱动程序:分析init初始化函数(part2) 逆向XignCode3驱动程序:分析init初始化函数(part2)]()
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;
}
![逆向XignCode3驱动程序:分析init初始化函数(part2) 逆向XignCode3驱动程序:分析init初始化函数(part2)]()
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/
本文始发于微信公众号(嘶吼专业版):逆向XignCode3驱动程序:分析init初始化函数(part2)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论