利用未导出函数结束进程

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 利用未导出函数结束进程

~~本文所有内容均为胡诌,如有不正确的地方,随时私信。~~


知识理论


内核模块

内核模块是什么?

内核模块如何布局的?


暴力搜索

如何通过特征码暴力搜索未导出函数?



内核模块



内核模块是什么?

驱动程序每一个都是一个模块,称为“内核模块”。


  1. 都可以加载到内核中。
  2. 都遵守PE格式。
  3. 任意一个sys文件与内核文件没有区别。
  4. 运行的时候 - DriverEntry一旦开始运行的时候,就已经加载完毕了。


每一个内核都有一个DRIVEROBJECT的描述结构体 NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath) PDRIVER_OBJECT 指向内核模块的结构体 PUNICODE_STRING 每次向注册表写入的一个值 。




内核模块布局





内核模块遍历


模块A的


pDataTableEntry->InLoadOrderLinks.Flink

就是模块B


DRIVER_OBJECT

地址


PLDR_DATA_TABLE_ENTRY pDataTableEntry = (PLDRDATA_TABLE_ENTRY)pDriverObject->DriverSection )


35a45521b44968a5aad0dafd6d6db8f9_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png




vkd> dt _DRIVER_OBJECT 822CEC08
ntdll!_DRIVER_OBJECT
+0x000 Type             : 0n4
+0x002 Size             : 0n168
+0x004 DeviceObject     : (null) //3环与0环通信,正常这里有一个设备地址
+0x008 Flags            : 0x12
+0x00c DriverStart      : 0xf8880000 Void//这个驱动被加载到的地址。类似ImageBase
+0x010 DriverSize       : 0x6000//占用大小
+0x014 DriverSection    : 0x81a8e288 Void//这里是一个结构体链表,可以遍历。指向一个_LDR_DATA_TABLE_ENTRY结构
+0x018 DriverExtension  : 0x822cecb0 _DRIVER_EXTENSION
+0x01c DriverName       : _UNICODE_STRING "\Driver\MyDriver2"
+0x024 HardwareDatabase : 0x80690a90 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch   : (null)
+0x02c DriverInit       : 0xf8884000     long  MyDriver2!GsDriverEntry+0
+0x030 DriverStartIo    : (null)
+0x034 DriverUnload     : 0xf8881030     void  MyDriver2!DriverUnload123+0
+0x038 MajorFunction    : [28] 0x804fb87e     long  nt!IopInvalidDeviceRequest+0 //这里存放28个回调函数
kd> g


kd> dt _DRIVER_EXTENSION 0x822cecb0
ntdll!_DRIVER_EXTENSION
+0x000 DriverObject     : 0x822cec08 _DRIVER_OBJECT
+0x004 AddDevice        : (null)
+0x008 Count            : 0
+0x00c ServiceKeyName   : _UNICODE_STRING "MyDriver2"
+0x014 ClientDriverExtension : (null)
+0x018 FsFilterCallbacks : (null)


kd> dt _LDR_DATA_TABLE_ENTRY  0x81a8e288
ntdll!_LDR_DATA_TABLE_ENTRY
// 执行下一个模块的起始位置
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x8055c1c0 - 0x820cfd98 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0xffffffff - 0xffffffff ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x630069 - 0x0 ]
+0x018 DllBase          : 0xf8880000 Void//起始地址
+0x01c EntryPoint       : 0xf8884000 Void
+0x020 SizeOfImage      : 0x6000
+0x024 FullDllName      : _UNICODE_STRING "\??\C:\Documents and Settings\Administrator\桌面\MyDriver2.sys"
+0x02c BaseDllName      : _UNICODE_STRING "MyDriver2.sys"
+0x034 Flags            : 0x9104000
+0x038 LoadCount        : 1
+0x03a TlsIndex         : 0x49
+0x03c HashLinks        : _LIST_ENTRY [ 0xffffffff - 0xfe65 ]
+0x03c SectionPointer   : 0xffffffff Void
+0x040 CheckSum         : 0xfe65
+0x044 TimeDateStamp    : 0xfffffffe
+0x044 LoadedImports    : 0xfffffffe Void
+0x048 EntryPointActivationContext : (null)
+0x04c PatchInformation : 0x0079004d Void


遍历模块


利用:

LDRDATATABLEENTRY->InLoadOrderLinks

遍历所有内核模块。


include 
typedef struct LDRDATATABLEENTRY { LISTENTRY InLoadOrderLinks; LISTENTRY InMemoryOrderLinks; LISTENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODESTRING FullDllName; UNICODESTRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LISTENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { struct { ULONG TimeDateStamp; }; struct { PVOID LoadedImports; }; }; } LDRDATATABLEENTRY, * PLDRDATATABLEENTRY;
VOID Unload(IN PDRIVEROBJECT pDriverObject) { DbgPrint("Goodbye world!\n"); return STATUSSUCCESS; }
VOID EnumDriver(PDRIVEROBJECT pDriverObject) { LDRDATATABLEENTRY* pDataTableEntry, * pTempDataTableEntry; PLISTENTRY pList; pDataTableEntry = (LDRDATATABLEENTRY*)pDriverObject->DriverSection;
if (!pDataTableEntry)
{
return;
}
pList = pDataTableEntry->InLoadOrderLinks.Flink;
KdPrint(("系统中所有驱动模块的枚举"));
while (pList != &pDataTableEntry->InLoadOrderLinks)
{
pTempDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pList;
KdPrint(("驱动名称  :%wZ , 模块地址:0x%x", &pTempDataTableEntry->FullDllName, &pTempDataTableEntry->EntryPoint));
pList = pList->Flink;
}
}
NTSTATUS DriverEntry(IN PDRIVEROBJECT pDriverObject, IN PUNICODESTRING RegistryPath) { EnumDriver(pDriverObject); pDriverObject->DriverUnload = Unload; return STATUS_SUCCESS; }

4ff57eaf5f60431d33f447dc4e487ce5_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


暴力搜索未导出函数


内存遍历


1. 找到内核模块,然后按照特征码进行搜索。

2. windbg u + 函数名。

3. 根据硬编码进行匹配,根据功能比较特殊的,跳着提取。

4. 与重定位相关的不能作为特征码。

5. 常用的功能不能作为特征码。

6. 先匹配第一个值,如果一样加偏移在匹配第二个值,如果一样在加偏移匹配第三个值。


01 01 01 01 ?? ?? ?? ?? 02 02 02 02 ?? ?? ?? 03 03 03 03


代码


#include <ntifs.h>
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
struct
{
ULONG TimeDateStamp;
};
struct
{
PVOID LoadedImports;
};
};
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
typedef NTSTATUS(*PSPTERMINATETPROCESS)(PEPROCESS Process, NTSTATUS ExitStatus);
ULONG GetPspTerminateProcess(ULONG ModuleBase, ULONG ModuleSize);
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Goodbye world!\n");
return STATUS_SUCCESS;
}
ULONG EnumDriver(PDRIVER_OBJECT pDriverObject)
{
LDR_DATA_TABLE_ENTRY* pDataTableEntry, * pTempDataTableEntry;
ULONG flag = -1;
PLIST_ENTRY pList;
pDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pDriverObject->DriverSection;
if (!pDataTableEntry)
{
return 0;
}
pList = pDataTableEntry->InLoadOrderLinks.Flink;
KdPrint(("系统中所有驱动模块的枚举"));
while ((pList != &pDataTableEntry->InLoadOrderLinks) && (flag == -1))
{
pTempDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pList;
flag = GetPspTerminateProcess(pTempDataTableEntry->DllBase, pTempDataTableEntry->SizeOfImage);
pList = pList->Flink;
}
return flag;
}
ULONG GetPspTerminateProcess(ULONG ModuleBase, ULONG ModuleSize)
{
ULONG code1 = 0x8b55ff8b, code2 = 0xa16456ec, code3 = 0x00000124, code4 = 0x3b08758b;   //SP2
ULONG i;
ULONG address;
DbgPrint("0x%x 0x%x\n", ModuleBase, ModuleSize);
if (ModuleBase == 0x0)
{
return -1;
}
for (i = ModuleBase; i <= ModuleBase + ModuleSize; i++)
{
if (MmIsAddressValid((PULONG)i))
{  //蓝屏原因:搜索到之后就应该退出,少句代码return address
if ((*(PULONG)i == code1) && (*(PULONG)(i + 4) == code2) && (*(PULONG)(i + 8) == code3) && (*(PULONG)(i + 12) == code4))
{
address = (ULONG)i;
KdPrint(("[GetPspTerminateProcess] address :0x%x\n", address));  //打印地址
return address;
}
}
}
return -1;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  pDriverObject, IN PUNICODE_STRING  RegistryPath)
{
PSPTERMINATETPROCESS MyPspTerminateProcess;
PEPROCESS pEProc;
NTSTATUS FLAG;
ULONG Address = EnumDriver(pDriverObject);
//DbgPrint("函数地址:0x%x\n",Address);
FLAG = PsLookupProcessByProcessId((HANDLE)1048, &pEProc);
if (MmIsAddressValid((PULONG)Address))
{
MyPspTerminateProcess = (PSPTERMINATETPROCESS)Address;  //定位PspTerminateProcess
MyPspTerminateProcess(pEProc, 0);              //杀进程
}
DbgPrint("函数强制结束成功\n");
ObDereferenceObject(pEProc);
pDriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}

e513fd2d47fa62432ba13f125fbf78a2_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


c94790b030767329b1ee819b964882ac_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
相关文章
|
7月前
|
Linux
进程等待(wait和wait函数)【Linux】
进程等待(wait和wait函数)【Linux】
132 0
|
4天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
44 13
|
3月前
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。
|
3月前
|
编译器
【收藏】内核级利用通用Hook函数方法检测进程
【收藏】内核级利用通用Hook函数方法检测进程
|
4月前
|
Linux API
Linux源码阅读笔记07-进程管理4大常用API函数
Linux源码阅读笔记07-进程管理4大常用API函数
|
6月前
|
运维 JavaScript Serverless
Serverless 应用引擎产品使用合集之函数计算里中FC出现函数还没有执行完进程就关闭了是什么导致的
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
7月前
|
Linux Shell 程序员
【进程控制】进程程序替换的原理以及exec函数族
【进程控制】进程程序替换的原理以及exec函数族
|
7月前
|
存储 算法 Unix
【创建进程】fork函数与写时拷贝
【创建进程】fork函数与写时拷贝
|
7月前
|
消息中间件 Unix Linux
【探索Linux】P.14(进程间通信 | 匿名管道 | |进程池 | pipe() 函数 | mkfifo() 函数)
【探索Linux】P.14(进程间通信 | 匿名管道 | |进程池 | pipe() 函数 | mkfifo() 函数)
108 0