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;
}