导语:这是逆向XignCode3(XC3)Driver一系列文章中的第一篇,我在2019年初开始进行这项工作,逆向这种驱动程序不仅很有趣,而且还可以学习很多有关Windows Internals的知识。
这是逆向XignCode3(XC3)Driver一系列文章中的第一篇,我在2019年初开始进行这项工作,逆向这种驱动程序不仅很有趣,而且还可以学习很多有关Windows Internals的知识。我将尽可能地简短和准确记录下一些我认为是该驱动程序的有趣代码段或函数片段。
0x01 概述
1. 了解有关DriverEntry的信息
2. 在二进制驱动文件上识别此函数
3. 识别如何创建驱动程序对象
4. 分析已实现的主要函数,尤其是调度程序
5. 检测其他代码。
函数DriverEntry的代码片段:
_int64 __fastcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { PDRIVER_OBJECT _DriverObject; // rdi signed int ntStatus; // ebx UNICODE_STRING *v5; // rcx char Dest[16]; // [rsp+40h] [rbp-30h] UNICODE_STRING DeviceName; // [rsp+50h] [rbp-20h] UNICODE_STRING SymbolicLinkName; // [rsp+60h] [rbp-10h] PDEVICE_OBJECT DeviceObject; // [rsp+88h] [rbp+18h] _DriverObject = DriverObject; DeviceObject = 0i64; if (!RegistryPath->Length || fn_strcat(Dest, RegistryPath) < 0) return 0xC0000001i64; if (sub_140003A50(&SymbolicLinkName, Dest) < 0) { Real_Driver_Entry(Dest); return 0xC0000001i64; } if (sub_1400039B0(&DeviceName, Dest) >= 0) { _DriverObject->DriverUnload = fn_DriverUnloadDispatcher; _DriverObject->MajorFunction[0] = fn_DispatchCreate;// IRP_MJ_CREATE _DriverObject->MajorFunction[2] = fn_DispatchClose;// IRP_MJ_CLOSE _DriverObject->MajorFunction[4] = fn_DriverIOCTLDistpacher;// IRP_MJ_WRITE ntStatus = IoCreateDevice(_DriverObject, 0, &DeviceName, 0x22u, 0, 0, &DeviceObject); if (ntStatus < 0) { Real_Driver_Entry(Dest); Real_Driver_Entry(&DeviceName); goto LABEL_10; } DeviceObject->Flags |= 4u; _mm_storeu_si128(&xmmword_14000CD78, *Dest); _mm_storeu_si128(&::SymbolicLinkName, SymbolicLinkName); fn_InitDispatchMethodArray(); ntStatus = fn_InitRegistrationNotifyAndCallbackRoutines(); if (ntStatus >= 0) { ntStatus = fn_ObtainKernelFunctions(); if (ntStatus >= 0) { ntStatus = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (ntStatus >= 0) { ntStatus = 0; goto LABEL_18; } nullsub_1(); } fn_RegisterCreateProcessNotifyRoutine(); nullsub_1(); } IoDeleteDevice(DeviceObject); LABEL_18: v5 = &DeviceName; goto LABEL_19; } Real_Driver_Entry(Dest); ntStatus = 0xC0000001; LABEL_10: v5 = &SymbolicLinkName; LABEL_19: Real_Driver_Entry(v5); return ntStatus; }
https://github.com/niemand-sec/Reversing-XignCode3-Driver/blob/master/XC3/DriverEntry_reversed.c
0x02 开始分析
获取.sys文件,这些是我使用的文件的哈希值:
· md5:C82DE0BC9A3A08E351B9BFA960F8757A
· sha1:F3AE1406B4CD7D1394DAC529C62BB01F3EB46D4A
· sha256:E7994B56152955835B5025049ABEE651E9C52A6CCAD7E04F2C458C8568967245
我逆向驱动程序时,我通常喜欢从DriverEntry开始。在此函数中,我可以找到一些有趣的细节,这些细节将有助于我识别驱动程序已实现的大多数函数。
IDA Pro和Ghidra通常能够自动检测到此函数,但是有时可能必须手动分析。
“ DriverEntry是驱动程序加载后第一个由驱动程序提供的例程。它负责初始化驱动程序。”
基本上,我需要寻找一个调用IoCreateDevice的函数,这通常在DriverEntry内部完成,并用于创建新的设备对象。这只是做到这一点的一种方法,但是由于IDA为我自动完成了这一步,因此直接进入逆向阶段。
0x03 DriverEntry(0x1400047B8)
下面是通过IDA Pro对DriverEntry进行反编译的代码:
https://github.com/niemand-sec/Reversing-XignCode3-Driver/blob/master/XC3/DriverEntry_original.c
__int64 __fastcall DriverEntry(PDRIVER_OBJECT DriverObject, _WORD *a2) { PDRIVER_OBJECT v2; // rdi NTSTATUS v4; // ebx UNICODE_STRING *v5; // rcx __m128i v6; // [rsp+40h] [rbp-30h] UNICODE_STRING DeviceName; // [rsp+50h] [rbp-20h] UNICODE_STRING SymbolicLinkName; // [rsp+60h] [rbp-10h] PDEVICE_OBJECT DeviceObject; // [rsp+88h] [rbp+18h] v2 = DriverObject; DeviceObject = 0i64; if (!*a2 || (signed int)sub_140004A58(&v6) < 0) return 3221225473i64; if ((signed int)sub_140003A50(&SymbolicLinkName, &v6) < 0) { sub_140004AC0(&v6); return 3221225473i64; } if ((signed int)sub_1400039B0(&DeviceName, &v6) >= 0) { v2->DriverUnload = (PDRIVER_UNLOAD)sub_140004938; v2->MajorFunction[0] = (PDRIVER_DISPATCH)&sub_1400045D0; v2->MajorFunction[2] = (PDRIVER_DISPATCH)&sub_140004580; v2->MajorFunction[4] = (PDRIVER_DISPATCH)&sub_140004604; v4 = IoCreateDevice(v2, 0, &DeviceName, 0x22u, 0, 0, &DeviceObject); if (v4 < 0) { sub_140004AC0(&v6); sub_140004AC0(&DeviceName); goto LABEL_10; } DeviceObject->Flags |= 4u; _mm_storeu_si128((__m128i *)&xmmword_14000CD78, v6); _mm_storeu_si128((__m128i *)&::SymbolicLinkName, (__m128i)SymbolicLinkName); sub_1400015F8(); v4 = sub_140003550(v2); if (v4 >= 0) { v4 = sub_140002A18(); if (v4 >= 0) { v4 = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (v4 >= 0) { v4 = 0; goto LABEL_18; } nullsub_1(); } sub_1400034D8(); nullsub_1(); } IoDeleteDevice(DeviceObject); LABEL_18: v5 = &DeviceName; goto LABEL_19; } sub_140004AC0(&v6); v4 = -1073741823; LABEL_10: v5 = &SymbolicLinkName; LABEL_19: sub_140004AC0(v5); return (unsigned int)v4; }
下面是对应的汇编代码:
https://github.com/niemand-sec/Reversing-XignCode3-Driver/blob/master/XC3/DriverEntry.asm
.text:00000001400047B8 ; =============== S U B R O U T I N E ======================================= .text:00000001400047B8 .text:00000001400047B8 ; Attributes: bp-based frame .text:00000001400047B8 .text:00000001400047B8 ; __int64 __fastcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) .text:00000001400047B8 DriverEntry proc near ; CODE XREF: start+25↓j .text:00000001400047B8 ; DATA XREF: .pdata:000000014000D3E4↓o ... .text:00000001400047B8 .text:00000001400047B8 DeviceCharacteristics= dword ptr -50h .text:00000001400047B8 Exclusive = byte ptr -48h .text:00000001400047B8 DeviceObject = qword ptr -40h .text:00000001400047B8 var_30 = xmmword ptr -30h .text:00000001400047B8 DeviceName = UNICODE_STRING ptr -20h .text:00000001400047B8 SymbolicLinkName= UNICODE_STRING ptr -10h .text:00000001400047B8 var_s0 = byte ptr 0 .text:00000001400047B8 arg_0 = qword ptr 10h .text:00000001400047B8 arg_8 = qword ptr 18h .text:00000001400047B8 arg_10 = qword ptr 20h .text:00000001400047B8 arg_18 = qword ptr 28h .text:00000001400047B8 .text:00000001400047B8 mov [rsp-8+arg_0], rbx .text:00000001400047BD mov [rsp-8+arg_10], rsi .text:00000001400047C2 mov [rsp-8+arg_18], rdi .text:00000001400047C7 push rbp .text:00000001400047C8 mov rbp, rsp .text:00000001400047CB sub rsp, 70h .text:00000001400047CF xor esi, esi .text:00000001400047D1 mov rdi, rcx .text:00000001400047D4 mov [rbp+arg_8], rsi .text:00000001400047D8 cmp [rdx], si .text:00000001400047DB jnz short loc_1400047E7 .text:00000001400047DD .text:00000001400047DD loc_1400047DD: ; CODE XREF: DriverEntry+3A↓j .text:00000001400047DD ; DriverEntry+56↓j .text:00000001400047DD mov eax, 0C0000001h .text:00000001400047E2 jmp loc_140004922 .text:00000001400047E7 ; --------------------------------------------------------------------------- .text:00000001400047E7 .text:00000001400047E7 loc_1400047E7: ; CODE XREF: DriverEntry+23↑j .text:00000001400047E7 lea rcx, [rbp+var_30] .text:00000001400047EB call sub_140004A58 .text:00000001400047F0 test eax, eax .text:00000001400047F2 js short loc_1400047DD .text:00000001400047F4 lea rdx, [rbp+var_30] .text:00000001400047F8 lea rcx, [rbp+SymbolicLinkName] .text:00000001400047FC call sub_140003A50 .text:0000000140004801 test eax, eax .text:0000000140004803 jns short loc_140004810 .text:0000000140004805 lea rcx, [rbp+var_30] .text:0000000140004809 call sub_140004AC0 .text:000000014000480E jmp short loc_1400047DD .text:0000000140004810 ; --------------------------------------------------------------------------- .text:0000000140004810 .text:0000000140004810 loc_140004810: ; CODE XREF: DriverEntry+4B↑j .text:0000000140004810 lea rdx, [rbp+var_30] .text:0000000140004814 lea rcx, [rbp+DeviceName] .text:0000000140004818 call sub_1400039B0 .text:000000014000481D test eax, eax .text:000000014000481F jns short loc_140004831 .text:0000000140004821 lea rcx, [rbp+var_30] .text:0000000140004825 call sub_140004AC0 .text:000000014000482A mov ebx, 0C0000001h .text:000000014000482F jmp short loc_1400048A2 .text:0000000140004831 ; --------------------------------------------------------------------------- .text:0000000140004831 .text:0000000140004831 loc_140004831: ; CODE XREF: DriverEntry+67↑j .text:0000000140004831 lea rax, sub_140004938 .text:0000000140004838 mov r9d, 22h ; DeviceType .text:000000014000483E mov [rdi+68h], rax .text:0000000140004842 lea r8, [rbp+DeviceName] ; DeviceName .text:0000000140004846 lea rax, sub_1400045D0 .text:000000014000484D xor edx, edx ; DeviceExtensionSize .text:000000014000484F mov [rdi+70h], rax .text:0000000140004853 mov rcx, rdi ; DriverObject .text:0000000140004856 lea rax, sub_140004580 .text:000000014000485D mov [rdi+80h], rax .text:0000000140004864 lea rax, sub_140004604 .text:000000014000486B mov [rdi+90h], rax .text:0000000140004872 lea rax, [rbp+arg_8] .text:0000000140004876 mov [rsp+70h+DeviceObject], rax ; DeviceObject .text:000000014000487B mov [rsp+70h+Exclusive], sil ; Exclusive .text:0000000140004880 mov [rsp+70h+DeviceCharacteristics], esi ; DeviceCharacteristics .text:0000000140004884 call cs:IoCreateDevice .text:000000014000488A mov ebx, eax .text:000000014000488C test eax, eax .text:000000014000488E jns short loc_1400048A8 .text:0000000140004890 lea rcx, [rbp+var_30] .text:0000000140004894 call sub_140004AC0 .text:0000000140004899 lea rcx, [rbp+DeviceName] .text:000000014000489D call sub_140004AC0 .text:00000001400048A2 .text:00000001400048A2 loc_1400048A2: ; CODE XREF: DriverEntry+77↑j .text:00000001400048A2 lea rcx, [rbp+SymbolicLinkName] .text:00000001400048A6 jmp short loc_14000491B .text:00000001400048A8 ; --------------------------------------------------------------------------- .text:00000001400048A8 .text:00000001400048A8 loc_1400048A8: ; CODE XREF: DriverEntry+D6↑j .text:00000001400048A8 mov rax, [rbp+arg_8] .text:00000001400048AC or dword ptr [rax+30h], 4 .text:00000001400048B0 movups xmm0, [rbp+var_30] .text:00000001400048B4 movups xmm1, xmmword ptr [rbp+SymbolicLinkName.Length] .text:00000001400048B8 movdqu cs:xmmword_14000CD78, xmm0 .text:00000001400048C0 movdqu xmmword ptr cs:SymbolicLinkName.Length, xmm1 .text:00000001400048C8 call sub_1400015F8 .text:00000001400048CD mov rcx, rdi .text:00000001400048D0 call sub_140003550 .text:00000001400048D5 mov ebx, eax .text:00000001400048D7 test eax, eax .text:00000001400048D9 js short loc_140004909 .text:00000001400048DB call sub_140002A18 .text:00000001400048E0 mov ebx, eax .text:00000001400048E2 test eax, eax .text:00000001400048E4 js short loc_1400048FF .text:00000001400048E6 lea rdx, [rbp+DeviceName] ; DeviceName .text:00000001400048EA lea rcx, [rbp+SymbolicLinkName] ; SymbolicLinkName .text:00000001400048EE call cs:IoCreateSymbolicLink .text:00000001400048F4 mov ebx, eax .text:00000001400048F6 test eax, eax .text:00000001400048F8 jns short loc_140004915 .text:00000001400048FA call nullsub_1 .text:00000001400048FF .text:00000001400048FF loc_1400048FF: ; CODE XREF: DriverEntry+12C↑j .text:00000001400048FF call sub_1400034D8 .text:0000000140004904 call nullsub_1 .text:0000000140004909 .text:0000000140004909 loc_140004909: ; CODE XREF: DriverEntry+121↑j .text:0000000140004909 mov rcx, [rbp+arg_8] ; DeviceObject .text:000000014000490D call cs:IoDeleteDevice .text:0000000140004913 jmp short loc_140004917 .text:0000000140004915 ; --------------------------------------------------------------------------- .text:0000000140004915 .text:0000000140004915 loc_140004915: ; CODE XREF: DriverEntry+140↑j .text:0000000140004915 mov ebx, esi .text:0000000140004917 .text:0000000140004917 loc_140004917: ; CODE XREF: DriverEntry+15B↑j .text:0000000140004917 lea rcx, [rbp+DeviceName] .text:000000014000491B .text:000000014000491B loc_14000491B: ; CODE XREF: DriverEntry+EE↑j .text:000000014000491B call sub_140004AC0 .text:0000000140004920 mov eax, ebx .text:0000000140004922 .text:0000000140004922 loc_140004922: ; CODE XREF: DriverEntry+2A↑j .text:0000000140004922 lea r11, [rsp+70h+var_s0] .text:0000000140004927 mov rbx, [r11+10h] .text:000000014000492B mov rsi, [r11+20h] .text:000000014000492F mov rdi, [r11+28h] .text:0000000140004933 mov rsp, r11 .text:0000000140004936 pop rbp .text:0000000140004937 retn .text:0000000140004937 DriverEntry endp .text:0000000140004937
DriverEntry会接收两个参数:_DRIVER_OBJECT指针和带有注册表路径的PUNICODE_STRING。因此,我可以更改这两个变量的名称和类型。
需要考虑的是,默认情况下,IDA Pro上不提供逆向时需要的许多结构类型。因此,我可以通过以下方式将它们导入:“文件->加载文件->解析C头文件…”。
回到代码中,我对SymbolicLinkName和DeviceName进行了一些验证,没有发现什么有意思的地方,他们只是在设置所需的字符串:
_DriverObject = DriverObject; DeviceObject = 0i64; if (!RegistryPath->Length || fn_strcat(Dest, RegistryPath) < 0) return 0xC0000001i64; if (sub_140003A50(&SymbolicLinkName, Dest) < 0) { Real_Driver_Entry(Dest); return 0xC0000001i64; }
DriverEntry需要进行一些特殊处理的解释在这里,看看他们在调用IoCreateDevice之前是如何做到的:
_DriverObject->DriverUnload = fn_DriverUnloadDispatcher; _DriverObject->MajorFunction[0] = fn_DispatchCreate;// IRP_MJ_CREATE _DriverObject->MajorFunction[2] = fn_DispatchClose;// IRP_MJ_CLOSE _DriverObject->MajorFunction[4] = fn_DriverIOCTLDispatcher;// IRP_MJ_WRITE ntStatus = IoCreateDevice(_DriverObject, 0, &DeviceName, 0x22u, 0, 0, &DeviceObject);
我重命名了一些变量和函数来描述它们的主要作用,解释一下如何轻松识别它们:
在这里,我可以看到Windows上所有可用的IRP主要函数代码。在上一段代码中,仅实现了0、2和4:
· IRP_MJ_CREATE 0x00
· IRP_MJ_CLOSE 0x02
· IRP_MJ_WRITE 0x04
完整列表如下:
/// IRP Major Codes #define IRP_MJ_CREATE 0x00 #define IRP_MJ_CREATE_NAMED_PIPE 0x01 #define IRP_MJ_CLOSE 0x02 #define IRP_MJ_READ 0x03 #define IRP_MJ_WRITE 0x04 #define IRP_MJ_QUERY_INFORMATION 0x05 #define IRP_MJ_SET_INFORMATION 0x06 #define IRP_MJ_QUERY_EA 0x07 #define IRP_MJ_SET_EA 0x08 #define IRP_MJ_FLUSH_BUFFERS 0x09 #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a #define IRP_MJ_SET_VOLUME_INFORMATION 0x0b #define IRP_MJ_DIRECTORY_CONTROL 0x0c #define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d #define IRP_MJ_DEVICE_CONTROL 0x0e #define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f #define IRP_MJ_SHUTDOWN 0x10 #define IRP_MJ_LOCK_CONTROL 0x11 #define IRP_MJ_CLEANUP 0x12 #define IRP_MJ_CREATE_MAILSLOT 0x13 #define IRP_MJ_QUERY_SECURITY 0x14 #define IRP_MJ_SET_SECURITY 0x15 #define IRP_MJ_POWER 0x16 #define IRP_MJ_SYSTEM_CONTROL 0x17 #define IRP_MJ_DEVICE_CHANGE 0x18 #define IRP_MJ_QUERY_QUOTA 0x19 #define IRP_MJ_SET_QUOTA 0x1a #define IRP_MJ_PNP 0x1b #define IRP_MJ_MAXIMUM_FUNCTION 0x1b
IRP_MJ_CREATE和IRP_MJ_CLOSE只是通用函数,有趣的是IRP_MJ_WRITE将处理来自用户模式的请求,并在fn_DriverIOCTLDispatcher上实现。我将在另一篇文章中解释此函数如何工作以及如何分派每个IRP请求。
现在,我只专注于分析DriverEntry调用的函数。
在对所调用函数的内部行为进行一些分析之后,可以看到以下代码:
fn_InitDispatchMethodArray(); ntStatus = fn_InitRegistrationNotifyAndCallbackRoutines(); if (ntStatus >= 0) { ntStatus = fn_ObtainKernelFunctions(); if (ntStatus >= 0) { ntStatus = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (ntStatus >= 0) { ntStatus = 0; goto LABEL_18; } nullsub_1(); } fn_RegisterCreateProcessNotifyRoutine(); nullsub_1(); }
一些有趣的函数名字:
· fn_InitDispatchMethodArray
· fn_InitRegistrationNotifyAndCallbackRoutines
· fn_ObtainKernelFunctions
· fn_RegisterCreateProcessNotifyRoutine
这些名称是否正确,取决于我稍后在逆向过程中发现的内容。正如我提到的,大部分工作是在几个月前完成的,有时,逆向需要做很多猜测,因此我需要开始想象每个函数可能会做什么,并给它们命名,以便我可以描绘出每个函数的作用。
该名称基于我对这些函数的推断。我将在后面的文章中深入了解它们。
我可以根据它们的作用将它们基本上分为两组。注册某种回调的函数;fn_InitRegistrationNotifyAndCallbackRoutines和fn_RegisterCreateProcessNotifyRoutine。并具有驱动程序运行所需的基本信息的函数;fn_InitDispatchMethodArray和fn_ObtainKernelFunctions。
本文翻译自:https://niemand.com.ar/2020/01/08/reversing-xigncode3-driver-part-1-identifying-the-driver-entry-point/如若转载,请注明原文地址: