首页
社区
课程
招聘
[原创] x86内核重载改写成x64内核重载
发表于: 2023-5-23 10:55 5847

[原创] x86内核重载改写成x64内核重载

2023-5-23 10:55
5847

/
说明:Win10 1809
1.为物理地址扩展的 内核模块ntoskrnl.exe申请一块新的SizeOfImage大小的内存
2.将ntoskrnl.exe拉伸读取至新申请的内存
3.修复新申请的ntoskrnl.exe重定位表
4.修复新申请的ntoskrnl.exe系统服务表
5.在KiSystemCall64关键部位加钩子
6.处理你感兴趣的程序 让它调用新的内核模块
/

 

ReX64Knrl.h //文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#pragma once
#include <ntifs.h>
#include <ntimage.h>
 
 
PVOID pNewBuffer = nullptr;
typedef struct _SYSTEM_SERVICE_TABLE    //SSDT结构
{
    PVOID serviceTableBase;
    PVOID serviceCounterTableBase;
    ULONGLONG numberofServices;
    PVOID paramTableBase;
}SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
 
typedef struct _BaseAddr_Size
{
    DWORD_PTR mMoudleBaseAddress;
    DWORD_PTR mMoudleSizeOf;
}BaseAddr_Size, *PBaseAddr_Size;
 
typedef struct _PE
{
    IMAGE_DOS_HEADER DosHeader;
    IMAGE_NT_HEADERS32 NtHeaders;
    IMAGE_SECTION_HEADER SectionHeader;
}PE, *pPE;
 
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
        }u;
    };
    union
    {
        ULONG TimeDateStamp;                                                //0x44
        VOID* LoadedImports;                                                //0x44
    };
    VOID* EntryPointActivationContext;                                      //0x48
    VOID* PatchInformation;                                                 //0x4c
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;//0x50 bytes (sizeof)
 
EXTERN_C{
    VOID UnLoad(PDRIVER_OBJECT pDriver);
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg);
}
NTSTATUS GetKernelImageBase_1(IN PDRIVER_OBJECT pDriver, IN PUNICODE_STRING szMoudeName, OUT PBaseAddr_Size mBeseAddrOfSize);
PVOID GetNewKernelBuffer_1(IN PUNICODE_STRING pStrKernelPathName);
VOID RepirRelocTable(IN DWORD_PTR uNewModule, IN DWORD_PTR uOldModule);
NTSTATUS RepirSSDT(IN PDRIVER_OBJECT pDriver, IN ULONG64 pNewKernelBuffer, IN ULONG64 uOldModule);
NTSTATUS GetSSDT(IN PDRIVER_OBJECT pdriver, OUT PVOID* addr); //通过链表找到ssdt

ReX64Knrl.cpp //文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#pragma once
#include "ReX64Knrl.h"
 
#pragma warning (disable:4310)
VOID UnLoad(PDRIVER_OBJECT pDriver)
{
    UNREFERENCED_PARAMETER(pDriver);
    if (pNewBuffer) ExFreePool(pNewBuffer);   
}
 
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
    UNREFERENCED_PARAMETER(pReg);
    pDriver->DriverUnload = UnLoad;
    DbgBreakPoint();
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    UNICODE_STRING szMoudleName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
    BaseAddr_Size sz = { 0 };   
    status= GetKernelImageBase_1(pDriver, &szMoudleName, &sz);
    if (NT_SUCCESS(status))
    {
        DbgPrintEx(77, 0, "GetKernelImageBase_1 sucess!\n");
    }
    else
    {
        DbgPrintEx(77, 0, "GetKernelImageBase_1 Faild!\n");
        return STATUS_UNSUCCESSFUL;
    }
 
    UNICODE_STRING szFileName = RTL_CONSTANT_STRING(L"\\??\\C:\\Windows\\system32\\ntoskrnl.exe");//ntdll.dll   //\\??\\C:\\WINDOWS\\system32\\ntkrnlpa.exe
    PVOID pNewKernelBuffer = GetNewKernelBuffer_1(&szFileName);
    if (!MmIsAddressValid(pNewKernelBuffer))
    {
        DbgPrintEx(77, 0, "pNewKernelBuffer is faild");
        return STATUS_UNSUCCESSFUL;
    }
    DbgPrintEx(77, 0, "pNewKernelBuffer is: %llx", pNewKernelBuffer);
    //基址重定位
    RepirRelocTable((DWORD_PTR)pNewKernelBuffer, sz.mMoudleBaseAddress);
 
    //系统服务表重定位
    status = RepirSSDT(pDriver, (ULONG64)pNewKernelBuffer, sz.mMoudleBaseAddress);
    if (NT_SUCCESS(status))
    {
        DbgPrintEx(77, 0, "RepirSSDT sucess!\n");
    }
    else
    {
        DbgPrintEx(77, 0, "RepirSSDT Faild!\n");
        return STATUS_UNSUCCESSFUL;
    }
 
    //>>>>>>>>  插入HOOK  代码
 
    return STATUS_SUCCESS;
}
 
//[获取当前内核模块基址_1]
NTSTATUS GetKernelImageBase_1(IN PDRIVER_OBJECT pDriver, IN PUNICODE_STRING szMoudeName, OUT PBaseAddr_Size mBeseAddrOfSize)
{
    PLIST_ENTRY pCurrObject = (PLIST_ENTRY)pDriver->DriverSection;
    PLIST_ENTRY pNextObject = pCurrObject->Flink;
    PLDR_DATA_TABLE_ENTRY szTemp = nullptr;
    while (pCurrObject != pNextObject)
    {
        szTemp = (PLDR_DATA_TABLE_ENTRY)pNextObject;
        if (RtlCompareUnicodeString(&szTemp->BaseDllName, szMoudeName, TRUE) == NULL)
        {
            mBeseAddrOfSize->mMoudleBaseAddress = (DWORD_PTR)(szTemp->DllBase);
            mBeseAddrOfSize->mMoudleSizeOf = szTemp->SizeOfImage;
            DbgPrintEx(77, 0, "DllBase:0x%llX SizeOfImage:0x%X  BaseDllName:%wZ FullDllName:%wZ ", szTemp->DllBase, szTemp->SizeOfImage, szTemp->BaseDllName, szTemp->FullDllName);
            return STATUS_SUCCESS;
        }
        pNextObject = pNextObject->Flink;
    }
    return STATUS_UNSUCCESSFUL;
}
 
// [1、获取新的内核模块虚拟缓存]
PVOID GetNewKernelBuffer_1(IN PUNICODE_STRING pStrKernelPathName)
{
    PE pe = { 0 };
    HANDLE hFile = NULL;
    OBJECT_ATTRIBUTES objectAttributes = { 0 };
    IO_STATUS_BLOCK ioStatusBlock = { 0 };
    InitializeObjectAttributes(&objectAttributes, pStrKernelPathName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
    NTSTATUS ntStatus = ZwCreateFile(&hFile, GENERIC_READ, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL, 0);
    if (!NT_SUCCESS(ntStatus))
    {
        KdPrint(("ZwCreateFile错误:%x\n", ntStatus));
        return NULL;
    }
    LARGE_INTEGER fileOffset = { 0 };
    fileOffset.QuadPart = 0;
    //读取DOS头
    ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, &pe.DosHeader, sizeof(IMAGE_DOS_HEADER), &fileOffset, NULL);
    if (!NT_SUCCESS(ntStatus))
    {
        KdPrint(("ZwReadFile错误:%x\n", ntStatus));
        goto exit;
    }
    fileOffset.QuadPart += pe.DosHeader.e_lfanew;
    //读取NT头
    ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, &pe.NtHeaders, sizeof(IMAGE_NT_HEADERS), &fileOffset, NULL);
    if (!NT_SUCCESS(ntStatus))
    {
        KdPrint(("ZwReadFile错误:%x\n", ntStatus));
        goto exit;
    }
 
    pNewBuffer = ExAllocatePool(NonPagedPool, pe.NtHeaders.OptionalHeader.SizeOfImage);
    if (pNewBuffer == NULL)
    {
        KdPrint(("pNewBuffer错误\n"));
        goto exit;
    }
    PVOID pTempBuffer = pNewBuffer;
    RtlCopyMemory(pTempBuffer, &pe.DosHeader, sizeof(IMAGE_DOS_HEADER));
    pTempBuffer = (PVOID)((DWORD_PTR)pTempBuffer + pe.DosHeader.e_lfanew);
    RtlCopyMemory(pTempBuffer, &pe.NtHeaders, sizeof(IMAGE_NT_HEADERS));
    fileOffset.QuadPart += sizeof(IMAGE_NT_HEADERS);
    pTempBuffer = (PVOID)((DWORD_PTR)pTempBuffer + sizeof(IMAGE_NT_HEADERS));
    //读取节表
    ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, pTempBuffer, (sizeof(IMAGE_SECTION_HEADER) * pe.NtHeaders.FileHeader.NumberOfSections), &fileOffset, NULL);
    if (!NT_SUCCESS(ntStatus))
    {
        KdPrint(("ZwReadFile错误:%x\n", ntStatus));
        pNewBuffer = nullptr;
        goto exit;
    }
    PIMAGE_SECTION_HEADER pTempSectionHeader = (PIMAGE_SECTION_HEADER)pTempBuffer;
 
    //读取节内容
    for (ULONG32 uCount = 0; uCount < pe.NtHeaders.FileHeader.NumberOfSections; uCount++)
    {
        pTempBuffer = (PVOID)((DWORD_PTR)pNewBuffer + pTempSectionHeader->VirtualAddress);
        fileOffset.QuadPart = pTempSectionHeader->PointerToRawData;
        ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, pTempBuffer, pTempSectionHeader->SizeOfRawData, &fileOffset, NULL);
        if (!NT_SUCCESS(ntStatus))
        {
            KdPrint(("ZwReadFile错误:%x\n", ntStatus));
            pNewBuffer = nullptr;
            goto exit;
        }
        pTempSectionHeader++;
    }
exit:
    if (hFile) ZwClose(hFile);
    //if (pNewBuffer) ExFreePool(pNewBuffer);   
    return pNewBuffer;
}
 
//修复重定位表
VOID RepirRelocTable(IN DWORD_PTR uNewModule,IN DWORD_PTR uOldModule)
{
    UNREFERENCED_PARAMETER(uOldModule);
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNtHeaders = NULL;
    PIMAGE_BASE_RELOCATION pRelocation = NULL;
    PIMAGE_DATA_DIRECTORY pData = NULL;
 
    pDosHeader = (PIMAGE_DOS_HEADER)uNewModule;
    pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
    pData = pNtHeaders->OptionalHeader.DataDirectory;
    //定位重定位表
    pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)uNewModule + pData[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
    //由于新的内核里面的全局变量地址都是用的老的 所以要加上它们之间的偏移量 就等于我们新的内核全局变量地址   
    DWORD_PTR uOffset = uNewModule - pNtHeaders->OptionalHeader.ImageBase;       //需要改正的偏移
    while (pRelocation->VirtualAddress != 0 && pRelocation->SizeOfBlock != 0 && pRelocation->VirtualAddress != 01)
    {
        LONG32 uNumOfRelocs = (pRelocation->SizeOfBlock - 8) / 2//取得重定位数量
        PUSHORT pUShort = (PUSHORT)((DWORD_PTR)pRelocation + 8);
        for (DWORD_PTR uCount = 0; uCount < uNumOfRelocs; uCount++, pUShort++)
        {
            if (((*pUShort) >> 12) == IMAGE_REL_BASED_DIR64)
            {
                PULONG64 pUlong32 = (PULONG64)(((*pUShort) & 0x0FFF) + pRelocation->VirtualAddress + uNewModule);
                *pUlong32 += uOffset;   //改好数据写入目的地址
            }
        }
        pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)pRelocation + pRelocation->SizeOfBlock);
    }
}
 
//修复新的系统服务表
NTSTATUS RepirSSDT(IN PDRIVER_OBJECT pDriver, IN ULONG64 pNewKernelBuffer, IN ULONG64 uOldModule)
{
    ULONG64 g_uOffset = pNewKernelBuffer - uOldModule;
    PVOID szAddr = nullptr;
    NTSTATUS status = GetSSDT(pDriver, &szAddr);
    if (!NT_SUCCESS(status))
    {
        DbgPrintEx(77, 0, "GetSSDT Faile!\n");
        return STATUS_UNSUCCESSFUL;
    }
    PSYSTEM_SERVICE_TABLE    m_pOldSSDT = { 0 };
    m_pOldSSDT = (PSYSTEM_SERVICE_TABLE)szAddr;
    PSYSTEM_SERVICE_TABLE m_pNewSSDT = (PSYSTEM_SERVICE_TABLE)((ULONGLONG)m_pOldSSDT + g_uOffset);
    m_pNewSSDT->numberofServices = m_pOldSSDT->numberofServices;
    ULONG64 m_uOffset = (ULONG64)m_pOldSSDT->serviceTableBase - uOldModule;
    m_pNewSSDT->serviceTableBase = (PULONG32)(pNewKernelBuffer + m_uOffset);
 
    m_uOffset = ((ULONGLONG)m_pOldSSDT->serviceCounterTableBase - uOldModule);
    m_pNewSSDT->serviceCounterTableBase = (PULONG32)(pNewKernelBuffer + m_uOffset);
    m_uOffset = ((ULONGLONG)m_pOldSSDT->paramTableBase - uOldModule);
    m_pNewSSDT->paramTableBase = (PCHAR)(pNewKernelBuffer + m_uOffset);
    RtlCopyMemory((PULONGLONG)m_pNewSSDT->paramTableBase, (PULONGLONG)m_pOldSSDT->paramTableBase, (ULONG64)m_pNewSSDT->numberofServices);//复制参数
    m_uOffset = (ULONG64)m_pNewSSDT->serviceTableBase - pNewKernelBuffer;
    //计算ssdt表中函数地址  注:win10 ssdt表中函数地址为:高28位为偏移 低4位为参数个数-4   不足4个参数时为零
    for (ULONG32 uCount = 0; uCount < m_pNewSSDT->numberofServices; uCount++)
    {
        ((PULONG32)(UCHAR*)(m_pNewSSDT->serviceTableBase))[uCount] = (ULONG32)((((PULONG32)(UCHAR*)(m_pNewSSDT->serviceTableBase))[uCount] - m_uOffset) << 4) + (((CHAR)((UCHAR*)(m_pNewSSDT->paramTableBase))[uCount]) >> 2);
    }
    return STATUS_SUCCESS;
}
 
NTSTATUS GetSSDT(IN PDRIVER_OBJECT pdriver, OUT PVOID* addr)  //通过链表找到ssdt
{
    PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY)pdriver->DriverSection;
    PLDR_DATA_TABLE_ENTRY head = entry;
    UNICODE_STRING temp = { 0 };
    RtlInitUnicodeString(&temp, L"ntoskrnl.exe");
    PCHAR start = NULL;
    ULONG size = 0;
    do
    //通过链表找到ntoskrnl.exe   内核文件。
        if (RtlCompareUnicodeString(&temp, &entry->BaseDllName, TRUE) == NULL)
        {
            //DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "%wZ\n", &entry->BaseDllName);
            start = (PCHAR)entry->DllBase;
            size = entry->SizeOfImage;
            break;
        }
        entry = (PLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink;
    } while (entry != head);
    for (ULONG i = 0; i < size; i++)
    {
        if (MmIsAddressValid(start))
        {
            if (*start == (CHAR)0x4c && *(CHAR*)(start + 1) == (CHAR)0x8d && *(CHAR*)(start + 2) == (CHAR)0x15//注:必需强制转换字符串类型
            {
                start += 7;
                if (MmIsAddressValid(start))
                {
                    if (*start == (CHAR)0x4c && *(CHAR*)(start + 1) == (CHAR)0x8d && *(CHAR*)(start + 2) == (CHAR)0x1d)
                    {
                        *(PULONGLONG)addr = *(PULONG)(start - 4) + (ULONGLONG)start;
                        return STATUS_SUCCESS;
                    }
                }
            }
        }
        if (MmIsAddressValid(start))
        {
            start++;
        }
    }
    return STATUS_UNSUCCESSFUL;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-5-23 11:04 被foxkinglxq编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 457
活跃值: (314)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
有没有大佬说一下 hook KiSystemCall64 会不会pg 我记得好像会的
2023-5-23 11:41
0
雪    币: 1485
活跃值: (1135)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
楼主试试X64重载后HOOK 保护进程看看是否蓝屏
2023-7-27 14:44
0
游客
登录 | 注册 方可回帖
返回
//