驱动对象

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

驱动对象(驱动隐藏技术)

1._DRIVER_OBJECT结构体

2. xx.sys中的INIT节区

3. DriverObject.DriverSection节区

4. 遍历全部驱动

5. 驱动隐藏

6. 更进一步的驱动隐藏技巧

7. 总结

 

 

1._DRIVER_OBJECT结构体

 

2. xx.sys中的INIT节区

  DriverObject.DriverInit 其就启动该节区中的代码,但是该节区启动之后就会自动删除。

  在调试时应该注意,使用IDA查看在节区的函数但是无法动态调试。

  

 

3. DriverObject.DriverSection节区

  该节区指向 _LDR_DATA_ENTRY_TABLE结构体,保存着该驱动的有关信息。

  同时其存在三个双向链表,可以用其来遍历全部驱动。

  //0x50 bytes (sizeof)
  typedef struct _LDR_DATA_TABLE_ENTRY
  {
      struct _LIST_ENTRY InLoadOrderLinks;                                    //0x0
      struct _LIST_ENTRY InMemoryOrderLinks;                                  //0x8
      struct _LIST_ENTRY InInitializationOrderLinks;                          //0x10
      VOID* DllBase;                                                          //0x18
      VOID* EntryPoint;                                                       //0x1c
      ULONG SizeOfImage;                                                      //0x20
      struct _UNICODE_STRING FullDllName;                                     //0x24
      struct _UNICODE_STRING BaseDllName;                                     //0x2c
      ULONG Flags;                                                            //0x34
      USHORT LoadCount;                                                       //0x38
      USHORT TlsIndex;                                                        //0x3a
      union
      {
          struct _LIST_ENTRY HashLinks;                                       //0x3c
          struct
          {
              VOID* SectionPointer;                                           //0x3c
              ULONG CheckSum;                                                 //0x40
          };
      };
      union
      {
          ULONG TimeDateStamp;                                                //0x44
          VOID* LoadedImports;                                                //0x44
      };
      VOID* EntryPointActivationContext;                                      //0x48
      VOID* PatchInformation;                                                 //0x4c
  }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

4. 遍历全部驱动

#include <ntddk.h>
#include <intrin.h>
#include <ntstrsafe.h>

//0x50 bytes (sizeof)
typedef struct _LDR_DATA_TABLE_ENTRY
{
    struct _LIST_ENTRY InLoadOrderLinks;                                    //0x0
    struct _LIST_ENTRY InMemoryOrderLinks;                                  //0x8
    struct _LIST_ENTRY InInitializationOrderLinks;                          //0x10
    VOID* DllBase;                                                          //0x18
    VOID* EntryPoint;                                                       //0x1c
    ULONG SizeOfImage;                                                      //0x20
    struct _UNICODE_STRING FullDllName;                                     //0x24
    struct _UNICODE_STRING BaseDllName;                                     //0x2c
    ULONG Flags;                                                            //0x34
    USHORT LoadCount;                                                       //0x38
    USHORT TlsIndex;                                                        //0x3a
    union
    {
        struct _LIST_ENTRY HashLinks;                                       //0x3c
        struct
        {
            VOID* SectionPointer;                                           //0x3c
            ULONG CheckSum;                                                 //0x40
        };
    };
    union
    {
        ULONG TimeDateStamp;                                                //0x44
        VOID* LoadedImports;                                                //0x44
    };
    VOID* EntryPointActivationContext;                                      //0x48
    VOID* PatchInformation;                                                 //0x4c
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject) {
    DbgPrint("%s\r\n", "驱动卸载成功");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath) {
    DbgPrint("地址:%x", pDriver);
    pDriver->DriverUnload = DriverUnload;
    
    PLDR_DATA_TABLE_ENTRY pList = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
    PLDR_DATA_TABLE_ENTRY pNext = pList->InLoadOrderLinks.Flink;
    
    DbgPrint("%wZ\n", &pList->BaseDllName); // 输出本地驱动名字
    // 双向链表,如果到结尾则返回头部
    while (pList != pNext) {
        DbgPrint("%wZ\n", &pNext->BaseDllName);
        pNext = pNext->InLoadOrderLinks.Flink; // 输出下一个驱动名字
    }

    return STATUS_SUCCESS;
}

 

5. 驱动隐藏

  我们采用最基本的断链来测试一下:

      PLDR_DATA_TABLE_ENTRY pList = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;
   RemoveEntryList((PLIST_ENTRY)pList);

  如果我们采用上面那种遍历方法自然遍历不到,但是如果使用PcHunter等工具来查看,则明显无法删除干净。

  

 

6. 更进一步的驱动隐藏技巧(代码2-4)

  我们下面使用MiProcessLoaderEntry内核函数来实现驱动隐藏效果。

  1)在IDA中定位其特征码

    

   2)特征码搜索在内核函数中

    

   3)调用内核函数将该链表从节区中移除

    调用内核函数移除之后,我门将该节区的Section指向下一个,之后再用PcHunter扫描其结果如下。

    

  4)对于节区属性更进一步清空

    上面那步之后,我们还可以发现其有关属性,我们下面对其属性进一步清空。

    

  5)在驱动卸载时恢复

    我们在发现卸载驱动时,恢复Section节区,然后调用函数在挂在链表中,让系统自动卸载。

    

 

7. 总结

  首先,我们发现其并没有完全成功绕过PcHunter,我们之后会利用内存加载,句柄表等知识进一步完善驱动隐藏技术。

  对于驱动隐藏,要知道我们分析某些程序时是反PcHunter,其会不断扫描链表发现有PcHunter等工具,然后结束自身进程(另外还有OD等),我们可以利用该策略隐藏自己的PcHunter。

 

posted @ 2020-03-29 10:20  OneTrainee  阅读(1402)  评论(0编辑  收藏  举报