内核空间与内核模块

一、内核空间

高2G内存里的内容都是一样的,低2G内存都是各进程的

 

 

 二、内核模块

每个驱动程序都是一个模块,称为内核模块,都可以加载到内核中,都遵循PE结构,但本质上讲,任意一个.sys文件与内核文件没有区别

1、DRIVER_OBJECT结构体

每个内核模块都有一个对应的结构体,来描述这个模块在内核中:位置、大小、名称等等

0: kd> dt _DRIVER_OBJECT
ntdll!_DRIVER_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x004 DeviceObject     : Ptr32 _DEVICE_OBJECT
   +0x008 Flags            : Uint4B
   +0x00c DriverStart      : Ptr32 Void  //驱动的位置
   +0x010 DriverSize       : Uint4B    //驱动大小
   +0x014 DriverSection    : Ptr32 Void  
   +0x018 DriverExtension  : Ptr32 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING  //驱动名
   +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING
   +0x028 FastIoDispatch   : Ptr32 _FAST_IO_DISPATCH
   +0x02c DriverInit       : Ptr32     long 
   +0x030 DriverStartIo    : Ptr32     void 
   +0x034 DriverUnload     : Ptr32     void 
   +0x038 MajorFunction    : [28] Ptr32     long 

咱们可以实验一下打印pDriver的地址在查看其结构,测试代码如下

#include<ntddk.h>

VOID DriverUnload(PDRIVER_OBJECT driver)
{
    DbgPrint("驱动停止运行.\r\n");
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{
    DbgPrint("My Driver");
    DbgPrint("Driver addr:%x", pDriver);

    pDriver->DriverUnload = DriverUnload;

    return STATUS_SUCCESS;
}

运行驱动后

 

 

0: kd> dt _DRIVER_OBJECT 89d1c978
ntdll!_DRIVER_OBJECT
   +0x000 Type             : 0n4
   +0x002 Size             : 0n168
   +0x004 DeviceObject     : (null) 
   +0x008 Flags            : 0x12
   +0x00c DriverStart      : 0xf7817000 Void
   +0x010 DriverSize       : 0x6000
   +0x014 DriverSection    : 0x8996d780 Void
   +0x018 DriverExtension  : 0x89d1ca20 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING "\Driver\KMDFDriver1"
   +0x024 HardwareDatabase : 0x8069c210 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch   : (null) 
   +0x02c DriverInit       : 0xf781b000     long SYMSRV:  BYINDEX: 0x5

其中DriverSection是一个指针,指向下一个驱动模块的指针,其相对应的结构体是

_LDR_DATA_TABLE_ENTRY

0: kd> dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
   +0x02c BaseDllName      : _UNICODE_STRING
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 Void
   +0x04c PatchInformation : Ptr32 Void

我们查看上一个样例的试试

0: kd> dt _LDR_DATA_TABLE_ENTRY 8996d780
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x805644c0 - 0x89c57ae0 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0xffffffff - 0xffffffff ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x630069 - 0x0 ]
   +0x018 DllBase          : 0xf7817000 Void
   +0x01c EntryPoint       : 0xf781b000 Void
   +0x020 SizeOfImage      : 0x6000
   +0x024 FullDllName      : _UNICODE_STRING "\??\C:\Documents and Settings\Administrator\桌面\KMDFDriver1.sys"
   +0x02c BaseDllName      : _UNICODE_STRING "KMDFDriver1.sys"
   +0x034 Flags            : 0x9104000
   +0x038 LoadCount        : 1
   +0x03a TlsIndex         : 0x49
   +0x03c HashLinks        : _LIST_ENTRY [ 0xffffffff - 0xc7af ]
   +0x03c SectionPointer   : 0xffffffff Void
   +0x040 CheckSum         : 0xc7af
   +0x044 TimeDateStamp    : 0xfffffffe
   +0x044 LoadedImports    : 0xfffffffe Void
   +0x048 EntryPointActivationContext : (null) 
   +0x04c PatchInformation : 0x004d004b Void

指向的是我们运行的驱动程序

DLLBase成员代表我们的内核模块从哪里开始

InLoadOrderLinks可以遍历下一个内核模块

也就是说只要找到这个成员就可以遍历所有的内核模块

 三、内核模块链表DriverSection

既然我们DriverSection可以遍历链表,那么我们来尝试一下,代码与实验结果如下

 

#include<ntddk.h>

typedef struct
{
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    UINT32 SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    UINT32 Flags;
    UINT16 LoadCount;
    UINT16 TlsIndex;
    LIST_ENTRY HashLinks;
    PVOID SectionPointer;
    UINT32 CheckSum;
    UINT32 TimeDateStamp;
    PVOID LoadedImports;
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;

}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

VOID DriverUnload(PDRIVER_OBJECT driver)
{
    DbgPrint("驱动停止运行.\r\n");
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{
    DbgPrint("My Driver");
    DbgPrint("Driver addr:%x", pDriver);
    pDriver->DriverUnload = DriverUnload;

    PLDR_DATA_TABLE_ENTRY pdte = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
    PLDR_DATA_TABLE_ENTRY head = pdte;
    do
    {
        PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pdte, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
        DbgPrint("DllBase: %p, SizeOfImage: %08X %wZ\n", pdte->DllBase, pdte->SizeOfImage, &(pdte->FullDllName));
        pdte = (PLDR_DATA_TABLE_ENTRY)pdte->InLoadOrderLinks.Flink;
    } while (pdte != head);

    return STATUS_SUCCESS;
}

 通过特征码查找函数PspTerminateProcess

#include<ntifs.h>
#include<ntddk.h>

typedef struct
{
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    UINT32 SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    UINT32 Flags;
    UINT16 LoadCount;
    UINT16 TlsIndex;
    LIST_ENTRY HashLinks;
    PVOID SectionPointer;
    UINT32 CheckSum;
    UINT32 TimeDateStamp;
    PVOID LoadedImports;
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;

}LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;

typedef NTSTATUS(*_PspTerminateProcess)(PEPROCESS pEprocess, NTSTATUS ExitCode);


VOID DriverUnLoad(PDRIVER_OBJECT driver)
{
    DbgPrint("Driver already shut off");
}

VOID FindDriver(PDRIVER_OBJECT pDriver,PVOID* KernelBase,PUINT32 uKernelImageSize)
{
    PLDR_DATA_TABLE_ENTRY pldte=(PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
    PLDR_DATA_TABLE_ENTRY head = pldte;
    UNICODE_STRING usKernelBaseDllName;
    
    RtlInitUnicodeString(&usKernelBaseDllName, L"ntoskrnl.exe");

    do
    {
        if (RtlCompareUnicodeString(&pldte->BaseDllName, &usKernelBaseDllName, TRUE) == 0)
        {
            *KernelBase=pldte->DllBase;
            *uKernelImageSize = pldte->SizeOfImage;
            return;
        }
        pldte=(PLDR_DATA_TABLE_ENTRY)pldte->InLoadOrderLinks.Flink;
    } while (head != pldte);
    return;
}

PVOID MemorySearch(PVOID KernelBase, UINT32 uKernelImageSize, PVOID ByteCode,UINT32 ByteLength)
{
    PVOID cur=KernelBase;
    while ((UINT32)cur!=(UINT32)KernelBase+uKernelImageSize)
    {
        if (RtlCompareMemory(cur, ByteCode, ByteLength) == ByteLength)
        {
            __asm int 3;
            return (PVOID)(((UINT32)cur) - 0x6);
        }
        cur = (PVOID)((UINT32)cur+1);
    }
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver,PUNICODE_STRING reg_path)
{
    pDriver->DriverUnload = DriverUnLoad;

    PVOID pKernelBase=NULL;
    UINT32 uKernelImageSize;
    
    UINT32 ByteCode[] = { 0x0124a164, 0x758b0000, 0x44703b08, 0x0db80775,
        0xebc00000, 0xbe8d575a, 0x00000248, 0x200147f6,
        0x868d1274, 0x00000174
    };

    _PspTerminateProcess PspTerminateProcess;


    FindDriver(pDriver, &pKernelBase, &uKernelImageSize);
    PspTerminateProcess=(_PspTerminateProcess)MemorySearch(pKernelBase, uKernelImageSize, ByteCode, sizeof(ByteCode));
    DbgPrint("PspTerminateProcess Addr:%p", PspTerminateProcess);

    PEPROCESS pE;
    PsLookupProcessByProcessId((HANDLE)1244, &pE);
    PspTerminateProcess(pE, 0);
    DbgPrint("记事本关闭了");
    return STATUS_SUCCESS;
}

非常感谢hambaga师傅,我的博客都是学着他写的,因为他写的很有调理,所以非常感谢

posted @ 2020-11-09 14:12  PYozo_free  阅读(270)  评论(0编辑  收藏  举报