zoukankan      html  css  js  c++  java
  • 【旧文章搬运】对抗内存搜索对象

    原文发表于百度空间,2009-07-08
    ==========================================================================

    还是从邪恶的源头--隐藏说起,以隐藏Driver为例,当我们从PsLoadedModuleList、Driver对象目录、TypeList都消失以后,要怎么去找到我们这个Driver呢?
    这时,很多ARK的方法就是暴搜,暴搜DriverObject(比如Sysnap的《内存对象搜索》),或者暴搜PE镜像,这个很多人都知道。
    今天要说的,就是如何对抗暴力搜索内存对象.
    假设这样一个场景:我枚举PspCidTable时得到了一个个的对象,然后如何判断这些对象哪些是EPROCESS,哪些是ETHREAD呢?
    一个常用的方法(当然还有其它判断方法)就是由Object到ObjectHeader,然后判断ObjectHeader->Type是PsProcessType还是PsThreadType.
    我想很多人的代码都是这样写的,包括以前我的也是。但是,这里一定要是PsProcessType或PsThreadType?答案是:NO
    OBJECT_TYPE不过是一块保存着该对象类型的相关信息的内存而已,我们完全可以自己“造”一个出来,来代替原有的ObjectHeader->Type躲过匹配检查。
    这就是为什么要有Fake ObjectType这个东西的理由~
    怎么造?我试过直接分配内存,直接拷贝整个OBJECT_TYPE结构,很不幸问题很多,似乎跟其中某些域的值有关系,我替换PsProcessType之后连进程都创建不了。
    还好,ObCreateObjectType函数是导出的,我们可以直接使用此函数创造自己的内存对象类型。
    创建之前,需要获取原始的ObjectType信息,毕竟你不可能自己实现该对象类型相关的所有操作,因此有些域直接填充原始ObjectType的值,把工作仍然交给系统去做。在获取时ObjectType时,无所谓导出的未导出的类型,都可以通过直接打开"ObjectTypesTypeName"的方式直接获取到,这里不多说。
    有了这些信息,就可以开始我们的“山寨”工作了.代码如下:

    NTSTATUS
    CreateNewObjectTypeByName(
    IN PCWSTR ObjectTypeName,//要创建的对象类型的名字
    IN POBJECT_TYPE pObjectTypeForCopy,//原始的ObjectType
    OUT POBJECT_TYPE *pNewObjectType)//返回新创建的ObjectType
    {
    UNICODE_STRING NameString;
    OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
    NTSTATUS status;
    RtlInitUnicodeString (&NameString, ObjectTypeName);
    RtlZeroMemory (&ObjectTypeInitializer, sizeof (OBJECT_TYPE_INITIALIZER));
    
         ObjectTypeInitializer.Length = sizeof (ObjectTypeInitializer);
         ObjectTypeInitializer.SecurityRequired = TRUE;
         ObjectTypeInitializer.PoolType = NonPagedPool;
         ObjectTypeInitializer.InvalidAttributes = OBJ_PERMANENT |OBJ_EXCLUSIVE |OBJ_OPENIF;
         ObjectTypeInitializer.DefaultPagedPoolCharge = pObjectTypeForCopy->TypeInfo.DefaultPagedPoolCharge;
         ObjectTypeInitializer.DefaultNonPagedPoolCharge = pObjectTypeForCopy->TypeInfo.DefaultNonPagedPoolCharge;
        //以下这些信息并不总是全都需要,比如PsProcessType与IoDriverObjectType就有一些不同~
         ObjectTypeInitializer.DeleteProcedure = pObjectTypeForCopy->TypeInfo.DeleteProcedure;
         ObjectTypeInitializer.ValidAccessMask = pObjectTypeForCopy->TypeInfo.ValidAccessMask;
         ObjectTypeInitializer.GenericMapping = pObjectTypeForCopy->TypeInfo.GenericMapping;
         ObjectTypeInitializer.ParseProcedure = pObjectTypeForCopy->TypeInfo.ParseProcedure;
         ObjectTypeInitializer.DeleteProcedure = pObjectTypeForCopy->TypeInfo.DeleteProcedure;
         ObjectTypeInitializer.SecurityProcedure = pObjectTypeForCopy->TypeInfo.SecurityProcedure;
         ObjectTypeInitializer.QueryNameProcedure = pObjectTypeForCopy->TypeInfo.QueryNameProcedure;
         ObjectTypeInitializer.MaintainTypeList = pObjectTypeForCopy->TypeInfo.MaintainTypeList;
        
    status=ObCreateObjectType (&NameString,
       &ObjectTypeInitializer,
       (PSECURITY_DESCRIPTOR) NULL,
       pNewObjectType);
    if (NT_SUCCESS(status))
    {
       dprintf("NewType=0x%08X
    ",*pNewObjectType);
    }
    else
    {
       dprintf("Failed! status=0x%08X
    ",status);
    }
    return status;
    }

    创建成功之后,我们就有了一个正常的、合法的ObjectType了(可以自己拿WinObj查看之),然后替换掉我们要隐藏的对象的ObjectHeader->Type就可以了。

    (我想在ObCreateObject时直接替换会是什么效果?纯YY,未实践~~)
    以Driver为例:

    POBJECT_TYPE DarkMoonDriverType;
    CreateNewObjectTypeByName(L"DarkMoonDriver",*IoDriverObjectType,&DarkMoonDriverType);

    好了,现在有一个属于我们自己的功能完全一样的ObjectType了.

    设某个驱动名为XXXX,本身无Device,以DarkMoonDriverType替换ObjectHeader->Type后,不抹Driver对象目录,不断TypeList,不抹PE镜像,甚至连PsLoadedModuleList都不用断,直接bypass RKU! 
    为什么呢?因为RKU认定了每个DriverObject的ObjectHeader->Type必须是*IoDriverObjectType,所以我们用Fake ObjectType替换后就直接bypass了,这就是我今天要说的Fake ObjectType大法。
    对于进程隐藏,此法对RKU同样适用,分别用伪造的DarkMoonProcessType,DarkMoonThreadType掉EPROCESS、ETHREAD对象头中的Type域,再结合一些常规隐藏手段,就可以bypass RKU的进程检测了,比bypass其它一些ARK还容易一些~~

    Sysnap的《内核搜索对象》其实存在和RKU类似的问题(这里抱怨一下,YasFindOb在我的虚拟机中总是因内存访问错误而蓝屏),以ScanDriverObject为例,Sysnap以*IoDriverOjbectType->Key做为比对信息。事实上,ObjectType->Key(偏移为0xAC)其实是对象类型名称的前四个字符(不足4个以空格补齐),以这个作为比对信息,自然是找不到上面的DarkMoonDriver的,因为我们的Key是"Dark"。这还不是关键的,关键是DriverObject->DriverName可以抹掉,你又如何拿来和Key对比?
    代码中还有if(pTmpDriObject->Type == 4)这样的判断,4代表了DRIVER,但是如果这里不是4,我们仍然会活得好好的~
    改了这么多,虽然此时DriverObject已经有点面目全非了,但是在抛弃了DeviceObject之后,就已经不需要DriverObject了.
    "若为隐藏故,二者皆可抛"!如此以来,搜DriverObject是无法检测到我们的HideDriver的,即使无Device无DriverObject,我们还是可以进行通信的...

  • 相关阅读:
    Linux指令集
    [日记]贝鲁特煎熬第32天
    2019南京区域赛ABCHJK题解 & KMbfs(O(n^3))板子
    欧拉筛质数以及四大积性数论函数(欧拉函数、莫比乌斯函数、约数个数函数、约数和函数)
    简短的自我介绍
    BSTTreap名次树数组&指针实现板子 Ver1.0
    2019银川区域赛BDFGHIKN题解
    安装vs2010
    SPEmailEventReceiver 之导入附件EXCEL
    为incoming mail绑定事件,SPEmailEventReceiver
  • 原文地址:https://www.cnblogs.com/achillis/p/10181746.html
Copyright © 2011-2022 走看看