暴力搜索、调用内核模块未导出函数

利用未导出函数结束进程

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

知识理论

  1. 内核模块
    • 内核模块是什么?
    • 内核模块如何布局的?
  2. 暴力搜索
    • 如何通过特征码暴力搜索未导出函数?

内核模块

内核模块是什么?

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

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

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

内核模块布局

image.png

内核模块遍历

模块A的pDataTableEntry->InLoadOrderLinks.Flink 就是模块B DRIVER_OBJECT其实地址
PLDR_DATA_TABLE_ENTRY pDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection
image.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

遍历模块

利用_LDR_DATA_TABLE_ENTRY->InLoadOrderLinks遍历所有内核模块。

#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;

VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
    DbgPrint("Goodbye world!\n");
    return STATUS_SUCCESS;
}

VOID EnumDriver(PDRIVER_OBJECT pDriverObject)
{
    LDR_DATA_TABLE_ENTRY* pDataTableEntry, * pTempDataTableEntry;
    PLIST_ENTRY pList;
    pDataTableEntry = (LDR_DATA_TABLE_ENTRY*)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 PDRIVER_OBJECT  pDriverObject, IN PUNICODE_STRING  RegistryPath)
{
    EnumDriver(pDriverObject);
    pDriverObject->DriverUnload = Unload;
    return STATUS_SUCCESS;
}

image.png

暴力搜索未导出函数

内存遍历

  1. 找到内核模块,然后按照特征码进行搜索。
  2. windbg u + 函数名。
  3. 根据硬编码进行匹配。根据功能比较特殊的。跳着提取
  4. 与重定位相关的不能作为特征码
  5. 常用的功能不能作为特征码
  6. 先匹配第一个值,如果一样加偏移在匹配第二个值,如果一样在加偏移匹配第三个值。
01 01 01 01 ?? ?? ?? ?? 02 02 02 02 ?? ?? ?? 03 03 03 03

image.png

代码

#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;

}

image.png
image.png