zoukankan      html  css  js  c++  java
  • 内核空间与内核模块

    一、内核空间

    高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("驱动停止运行.
    ");
    }
    
    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 "DriverKMDFDriver1"
       +0x024 HardwareDatabase : 0x8069c210 _UNICODE_STRING "REGISTRYMACHINEHARDWAREDESCRIPTIONSYSTEM"
       +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 SettingsAdministrator桌面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("驱动停止运行.
    ");
    }
    
    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
    ", 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师傅,我的博客都是学着他写的,因为他写的很有调理,所以非常感谢

  • 相关阅读:
    无限分类 引用传值
    jQeury 自动、手动左右切换
    $_POST 为空时 真正的值
    php isset 备忘
    php empty 备忘
    无限分级函数 简单 引用绑值
    无限分级 层次输出 demo
    利用新版ShareSDK进行手动分享(自定义分享界面)
    eclipse 快捷方式大全
    ViewPager onPageChangeListener总结
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/13948331.html
Copyright © 2011-2022 走看看