一、NtCreateFile
0环:
#include <ntifs.h>
// 系统调用号
// NtCreateFile 0x25
#define SYSCODE 0x25
PVOID g_pHookMemAddr;//InlineHook跳转地址
ULONG g_dwKernelFuncAddr;//内核函数的地址
// 系统服务表
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG ServiceTableBase; // 函数地址表
PULONG ServiceCounterTableBase; // SSDT 函数被调用的次数
ULONG NumberOfService; // 函数个数
PULONG ParamTableBase; // 函数参数表
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
// SSDT表
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
KSYSTEM_SERVICE_TABLE ntoskrnl; // 内核函数
KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函数
KSYSTEM_SERVICE_TABLE unUsed1;
KSYSTEM_SERVICE_TABLE unUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 声明全局变量
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
// 开启页保护
VOID PageProtectOn();
// 关闭页保护
VOID PageProtectOff();
// HOOK过程
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr);
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr);
// HOOK后的执行函数
VOID __stdcall RealFunc();
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
ULONG dwExecFuncAddr;//执行函数地址
DbgPrint("驱动已启动\r\n");
pDriver->DriverUnload = DriverUnload;
//获取执行函数的地址
dwExecFuncAddr = (ULONG)RealFunc;
//修正函数地址
if (*(PUCHAR)dwExecFuncAddr == 0xe9)
{
DbgPrint("执行函数的地址,修正前:0x%.8x\r\n",dwExecFuncAddr);
dwExecFuncAddr = *(PULONG)(dwExecFuncAddr + 1) - (dwExecFuncAddr + 5);
DbgPrint("执行函数的地址,修正后:0x%.8x\r\n",dwExecFuncAddr);
}
else
{
DbgPrint("执行函数的地址,无需修正\r\n");
}
//根据系统调用号找到内核函数的地址
g_dwKernelFuncAddr = *(PULONG)((ULONG)(KeServiceDescriptorTable->ntoskrnl.ServiceTableBase) + SYSCODE * 4);
DbgPrint("NtCreateFile函数地址:0x%.8x\r\n",g_dwKernelFuncAddr);
//HOOK
if (!Hook(g_dwKernelFuncAddr,dwExecFuncAddr))
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
// 关闭页保护
VOID PageProtectOff()
{
__asm
{
cli; // 关闭中断
mov eax, cr0;
and eax, not 0x10000; // WP位置0
mov cr0, eax;
}
}
// 开启页保护
VOID PageProtectOn()
{
__asm
{
mov eax, cr0;
or eax, 0x10000; // WP位置1
mov cr0, eax;
sti; // 恢复中断
}
}
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
//UN-HOOK
UnHook(g_dwKernelFuncAddr);
//释放内存
ExFreePool(g_pHookMemAddr);
DbgPrint("驱动已停止\r\n");
}
// HOOK过程
// 将dwSrc函数HOOK至Dst函数
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr)
{
ULONG i;//for循环的参数
ULONG dwJumpPara;//E9Jmp的参数
ULONG dwCallPara;//E8Call参数
DbgPrint("\r\nHook\r\n");
//申请内存
g_pHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
if (g_pHookMemAddr == NULL)
{
DbgPrint("\r\nExAllocatePool失败\r\n");
return FALSE;
}
DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pHookMemAddr);
RtlFillMemory(g_pHookMemAddr, 0x100, 0x90);
//DbgBreakPoint();
//pushad pushfd
*((PUCHAR)g_pHookMemAddr + 0) = 0x60;//pushad
*((PUCHAR)g_pHookMemAddr + 1) = 0x9c;//pushfd
//int 3
*((PUCHAR)g_pHookMemAddr + 2) = 0x90;//int 3
//在申请的内存空间偏移+3处编辑ShellCode:call ExecFunc(RealFunc)
DbgPrint("\r\n在申请的内存空间偏移+3处编辑ShellCode:Call HookFunc\r\n");
*((PUCHAR)g_pHookMemAddr + 3) = 0xe8;//call
dwCallPara = dwDstFuncAddr - ((ULONG)g_pHookMemAddr + 3 + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)((ULONG)g_pHookMemAddr + 3 + i) = *(PUCHAR)((ULONG)(&dwCallPara) + i - 1);
}
//popfd popad
*((PUCHAR)g_pHookMemAddr + 8) = 0x9d;//popfd
*((PUCHAR)g_pHookMemAddr + 9) = 0x61;//popad
//DbgBreakPoint();
//保存内核函数前5字节的数据到申请的内存区域偏移+10处
DbgPrint("\r\n保存内核函数前5字节的数据到申请的内存空间中\r\n");
for (i = 0; i < 5; i++)
{
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
*((PUCHAR)g_pHookMemAddr + 10 + i) = *(PUCHAR)(dwSrcFuncAddr + i);
DbgPrint("No.%d AllocMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, (ULONG)g_pHookMemAddr + 10 + i, *((PUCHAR)g_pHookMemAddr + 10 + i));
}
//DbgBreakPoint();
//在申请的内存空间偏移+15处编辑ShellCode:Jump Back To KernelFuncAddr + 5
DbgPrint("\r\n在申请的内存空间偏移+15处编辑ShellCode:Jump Back To KernelFuncAddr + 5\r\n");
*((PUCHAR)g_pHookMemAddr + 15) = 0xe9;//jmp
dwJumpPara = dwSrcFuncAddr + 5 - ((ULONG)g_pHookMemAddr + 15 + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)((ULONG)g_pHookMemAddr + 15 + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
}
//DbgBreakPoint();
//修改内核函数前5字节进行InlineHook
DbgPrint("\r\n修改内核函数前5字节\r\n关闭页保护\r\n");
PageProtectOff();
*(PUCHAR)dwSrcFuncAddr = 0xe9;//jmp
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", 1, dwSrcFuncAddr, *(PUCHAR)dwSrcFuncAddr);
//跳转至申请的内存区域偏移+0处的Jmp参数
dwJumpPara = (ULONG)g_pHookMemAddr - (dwSrcFuncAddr + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
}
DbgPrint("开启页保护\r\n");
PageProtectOn();
//披露重要数据
DbgPrint("\r\nHOOK完成\r\n原函数地址:0x%.8x\r\n跳转区域地址:0x%.8x\r\n执行函数地址:0x%.8x\r\n",dwSrcFuncAddr,g_pHookMemAddr,dwDstFuncAddr);
return TRUE;
}
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr)
{
ULONG i;
DbgPrint("\r\nUnHook\r\n");
//关闭页保护
PageProtectOff();
//将申请的内存区域偏移+10处的前5字节的数据还原到内核函数
for (i = 0; i < 5; i++)
{
DbgPrint("还原前,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)g_pHookMemAddr + 10 + i);
DbgPrint("还原后,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
}
//开启页保护
PageProtectOn();
}
// HOOK后的执行函数
/*
KernelFunc(NtCreateFile):
此时
{
esp + 0x00 = NtCreateFile的返回地址
esp + 0x04 = FileHandle
esp + 0x08 = DesiredAccess
esp + 0x0c = ObjectAttributes
esp + 0x10 = IoStatusBlock
esp + 0x14 = AllocationSize
esp + 0x18 = FileAttributes
esp + 0x1c = ShareAccess
esp + 0x20 = CreateDisposition
esp + 0x24 = CreateOptions
esp + 0x28 = EaBuffer
esp + 0x2c = EaLength
}
8056f27c jmp HookMemory
8056f281 xor eax,eax
......
******************************************
HookMemory:
pushad
pushfd
int 3
此时
{
esp + 0x00 = eflags
esp + 0x04 = edi
esp + 0x08 = esi
esp + 0x0c = ebp
esp + 0x10 = esp
esp + 0x14 = ebx
esp + 0x18 = edx
esp + 0x1c = ecx
esp + 0x20 = eax
esp + 0x24 = NtCreateFile的返回地址
esp + 0x28 = FileHandle
esp + 0x2c = DesiredAccess
esp + 0x30 = ObjectAttributes
esp + 0x34 = IoStatusBlock
esp + 0x38 = AllocationSize
esp + 0x3c = FileAttributes
esp + 0x40 = ShareAccess
esp + 0x44 = CreateDisposition
esp + 0x48 = CreateOptions
esp + 0x4c = EaBuffer
esp + 0x50 = EaLength
}
call ExecFunc(RealFunc)
popfd
popad
mov edi,edi
push ebp
mov ebp,esp
jmp nt!NtCreateFile + 0x5(8056f281)
******************************************
ExecFunc(RealFunc):
此时
{
esp + 0x00 = ExecFunc(RealFunc)的返回地址
esp + 0x04 = eflags
esp + 0x08 = edi
esp + 0x0c = esi
esp + 0x10 = ebp
esp + 0x14 = esp
esp + 0x18 = ebx
esp + 0x1c = edx
esp + 0x20 = ecx
esp + 0x24 = eax
esp + 0x28 = NtCreateFile的返回地址
esp + 0x2c = FileHandle
esp + 0x30 = DesiredAccess
esp + 0x34 = ObjectAttributes
esp + 0x38 = IoStatusBlock
esp + 0x3c = AllocationSize
esp + 0x40 = FileAttributes
esp + 0x44 = ShareAccess
esp + 0x48 = CreateDisposition
esp + 0x4c = CreateOptions
esp + 0x50 = EaBuffer
esp + 0x54 = EaLength
}
push ebp
此时
{
esp + 0x00 = ebp(原)
esp + 0x04 = ExecFunc(RealFunc)的返回地址
esp + 0x08 = eflags
esp + 0x0c = edi
esp + 0x10 = esi
esp + 0x14 = ebp
esp + 0x18 = esp
esp + 0x1c = ebx
esp + 0x20 = edx
esp + 0x24 = ecx
esp + 0x28 = eax
esp + 0x2c = NtCreateFile的返回地址
esp + 0x30 = FileHandle
esp + 0x34 = DesiredAccess
esp + 0x38 = ObjectAttributes
esp + 0x3c = IoStatusBlock
esp + 0x40 = AllocationSize
esp + 0x44 = FileAttributes
esp + 0x48 = ShareAccess
esp + 0x4c = CreateDisposition
esp + 0x50 = CreateOptions
esp + 0x54 = EaBuffer
esp + 0x58 = EaLength
}
mov ebp,esp
此时,esp == ebp
{
ebp + 0x00 = ebp(原)
ebp + 0x04 = ExecFunc(RealFunc)的返回地址
ebp + 0x08 = eflags
ebp + 0x0c = edi
ebp + 0x10 = esi
ebp + 0x14 = ebp
ebp + 0x18 = ebp
ebp + 0x1c = ebx
ebp + 0x20 = edx
ebp + 0x24 = ecx
ebp + 0x28 = eax
ebp + 0x2c = NtCreateFile的返回地址
ebp + 0x30 = FileHandle
ebp + 0x34 = DesiredAccess
ebp + 0x38 = ObjectAttributes
ebp + 0x3c = IoStatusBlock
ebp + 0x40 = AllocationSize
ebp + 0x44 = FileAttributes
ebp + 0x48 = ShareAccess
ebp + 0x4c = CreateDisposition
ebp + 0x50 = CreateOptions
ebp + 0x54 = EaBuffer
ebp + 0x58 = EaLength
}
sub esp,30h
cli
......
*/
VOID __stdcall RealFunc()
{
ULONG FileHandle;
ULONG DesiredAccess;
ULONG ObjectAttributes;
ULONG IoStatusBlock;
ULONG AllocationSize;
ULONG FileAttributes;
ULONG ShareAccess;
ULONG CreateDisposition;
ULONG CreateOptions;
ULONG EaBuffer;
ULONG EaLength;
ULONG dwRetAddr;
__asm
{
cli;
mov eax,[ebp + 0x04];//当前函数的返回地址
mov [dwRetAddr],eax;
mov eax,[ebp + 0x30];//NtCreateFile参数01:FileHandle
mov [FileHandle],eax;
mov eax,[ebp + 0x34];//NtCreateFile参数02:DesiredAccess
mov [DesiredAccess],eax;
mov eax,[ebp + 0x38];//NtCreateFile参数03:ObjectAttributes
mov [ObjectAttributes],eax;
mov eax,[ebp + 0x3c];//NtCreateFile参数04:IoStatusBlock
mov [IoStatusBlock],eax;
mov eax,[ebp + 0x40];//NtCreateFile参数05:AllocationSize
mov [AllocationSize],eax;
mov eax,[ebp + 0x44];//NtCreateFile参数06:FileAttributes
mov [FileAttributes],eax;
mov eax,[ebp + 0x48];//NtCreateFile参数07:ShareAccess
mov [ShareAccess],eax;
mov eax,[ebp + 0x4c];//NtCreateFile参数08:CreateDisposition
mov [CreateDisposition],eax;
mov eax,[ebp + 0x50];//NtCreateFile参数09:CreateOptions
mov [CreateOptions],eax;
mov eax,[ebp + 0x54];//NtCreateFile参数10:EaBuffer
mov [EaBuffer],eax;
mov eax,[ebp + 0x58];//NtCreateFile参数11:EaLength
mov [EaLength],eax;
}
if (ShareAccess == 0xffff)
{
__asm pushfd;
DbgPrint("\r\n");
DbgPrint("NtCreateFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
DbgPrint("NtCreateFile参数02:DesiredAccess:0x%.8x\r\n",DesiredAccess);
DbgPrint("NtCreateFile参数03:ObjectAttributes:0x%.8x\r\n",ObjectAttributes);
DbgPrint("NtCreateFile参数04:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
DbgPrint("NtCreateFile参数05:AllocationSize:0x%.8x\r\n",AllocationSize);
DbgPrint("NtCreateFile参数06:FileAttributes:0x%.8x\r\n",FileAttributes);
DbgPrint("NtCreateFile参数07:ShareAccess:0x%.8x\r\n",ShareAccess);
DbgPrint("NtCreateFile参数08:CreateDisposition:0x%.8x\r\n",CreateDisposition);
DbgPrint("NtCreateFile参数09:CreateOptions:0x%.8x\r\n",CreateOptions);
DbgPrint("NtCreateFile参数10:EaBuffer:0x%.8x\r\n",EaBuffer);
DbgPrint("NtCreateFile参数11:EaLength:0x%.8x\r\n",EaLength);
//DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
__asm popfd;
}
//验证堆栈
/*
if (dwRetAddr == ((ULONG)g_pHookMemAddr + 8))
{
DbgPrint("\r\n");
DbgPrint("NtCreateFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
DbgPrint("NtCreateFile参数02:DesiredAccess:0x%.8x\r\n",DesiredAccess);
DbgPrint("NtCreateFile参数03:ObjectAttributes:0x%.8x\r\n",ObjectAttributes);
DbgPrint("NtCreateFile参数04:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
DbgPrint("NtCreateFile参数05:AllocationSize:0x%.8x\r\n",AllocationSize);
DbgPrint("NtCreateFile参数06:FileAttributes:0x%.8x\r\n",FileAttributes);
DbgPrint("NtCreateFile参数07:ShareAccess:0x%.8x\r\n",ShareAccess);
DbgPrint("NtCreateFile参数08:CreateDisposition:0x%.8x\r\n",CreateDisposition);
DbgPrint("NtCreateFile参数09:CreateOptions:0x%.8x\r\n",CreateOptions);
DbgPrint("NtCreateFile参数10:EaBuffer:0x%.8x\r\n",EaBuffer);
DbgPrint("NtCreateFile参数11:EaLength:0x%.8x\r\n",EaLength);
DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
}
*/
__asm sti;
return;
}
/*
函数调用过程
CreateFileA(kernel32) ==> CreateFileW(kernel32) ==> NtCreateFile(ntdll) ==> NtCreateFile(ntoskrnl) ==> IoCreateFile(ntoskrnl)
kernel32:
HANDLE __stdcall CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
kernel32:
HANDLE __stdcall CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
ntdll:
NTSTATUS __stdcall NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize, IN ULONG FileAttributes,
IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer, IN ULONG EaLength)
FileHandle = dword ptr 04h
DesiredAccess = dword ptr 08h
ObjectAttributes = dword ptr 0Ch
IoStatusBlock = dword ptr 10h
AllocationSize = dword ptr 14h
FileAttributes = dword ptr 18h
ShareAccess = dword ptr 1Ch
CreateDisposition = dword ptr 20h
CreateOptions = dword ptr 24h
EaBuffer = dword ptr 28h
EaLength = dword ptr 2Ch
mov eax, 25h //系统调用号
mov edx, 7FFE0300h
call dword ptr [edx]
retn 2Ch
ntoskrnl:
NTSTATUS __stdcall NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize, IN ULONG FileAttributes,
IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer, IN ULONG EaLength)
FileHandle = dword ptr 08h
DesiredAccess = dword ptr 0Ch
ObjectAttributes = dword ptr 10h
IoStatusBlock = dword ptr 14h
AllocationSize = dword ptr 18h
FileAttributes = dword ptr 1Ch
ShareAccess = dword ptr 20h
CreateDisposition = dword ptr 24h
CreateOptions = dword ptr 28h
EaBuffer = dword ptr 2Ch
EaLength = dword ptr 30h
8B FF mov edi, edi
55 push ebp
8B EC mov ebp, esp
xor eax, eax
push eax ; Options
push eax ; InternalParameters
push eax ; CreateFileType
push dword ptr [ebp+30h] ; EaLength
push dword ptr [ebp+2Ch] ; EaBuffer
push dword ptr [ebp+28h] ; CreateOptions
push dword ptr [ebp+24h] ; Disposition
push dword ptr [ebp+20h] ; ShareAccess
push dword ptr [ebp+1Ch] ; FileAttributes
push dword ptr [ebp+18h] ; AllocationSize
push dword ptr [ebp+14h] ; IoStatusBlock
push dword ptr [ebp+10h] ; ObjectAttributes
push dword ptr [ebp+0Ch] ; DesiredAccess
push dword ptr [ebp+08h] ; FileHandle
call _IoCreateFile@56 ; IoCreateFile(x,x,x,x,x,x,x,x,x,x,x,x,x,x)
pop ebp
retn 2Ch //11个参数
*/
3环:
#include <WINDOWS.H>
#include <STDIO.H>
#define FILENAME "C:\\Program Files\\PETool 1.0.0.5.exe"
#define FILE_SHARE_OTHER 0xffff
int main()
{
//获取3环函数地址
DWORD dwFunc3Addr = (DWORD)CreateFileA;
printf("CreateFileA的地址为:0x%.8x\n\n",dwFunc3Addr);
//正常测试
HANDLE hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
{
printf("CreateFileA失败,错误代码:%d\n", GetLastError());
system("pause");
return -1;
}
printf("CreateFileA成功,句柄:0x%x\n",(DWORD)hFile);
//特殊通信
/*
WINBASEAPI HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
正常参数
#define FILE_SHARE_READ 0x00000001
#define FILE_SHARE_WRITE 0x00000002
#define FILE_SHARE_DELETE 0x00000004
特殊参数
#define FILE_SHARE_OTHER 0x0000FFFF
*/
hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_OTHER, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
printf("lpFileName:0x%.8x\ndwDesiredAccess:0x%.8x\ndwShareMode:0x%.8x\nlpSecurityAttributes:0x%.8x\ndwCreationDisposition:0x%.8x\ndwFlagsAndAttributes:0x%.8x\nhTemplateFile:0x%.8x\n",
(DWORD)FILENAME,(DWORD)GENERIC_ALL,(DWORD)FILE_SHARE_OTHER,(DWORD)NULL,(DWORD)OPEN_EXISTING,(DWORD)FILE_ATTRIBUTE_NORMAL,(DWORD)NULL);
CloseHandle(hFile);
system("pause");
return 0;
}
二、NtReadFile(仅HOOK传入参数)
0环:
#include <ntifs.h>
// 系统调用号
// NtCreateFile 0x25
// NtReadFile 0xB7
#define SYSCODE 0xB7
PVOID g_pHookMemAddr;//InlineHook跳转地址
ULONG g_dwKernelFuncAddr;//内核函数的地址
PVOID g_pSpyBuffer;//偷换的缓冲区
// 系统服务表
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG ServiceTableBase; // 函数地址表
PULONG ServiceCounterTableBase; // SSDT 函数被调用的次数
ULONG NumberOfService; // 函数个数
PULONG ParamTableBase; // 函数参数表
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
// SSDT表
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
KSYSTEM_SERVICE_TABLE ntoskrnl; // 内核函数
KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函数
KSYSTEM_SERVICE_TABLE unUsed1;
KSYSTEM_SERVICE_TABLE unUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 声明全局变量
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
// 开启页保护
VOID PageProtectOn();
// 关闭页保护
VOID PageProtectOff();
// HOOK过程
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr);
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr);
// HOOK后的执行函数
VOID __stdcall RealFunc();
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
ULONG dwExecFuncAddr;//执行函数地址
DbgPrint("驱动已启动\r\n");
pDriver->DriverUnload = DriverUnload;
//获取执行函数的地址
dwExecFuncAddr = (ULONG)RealFunc;
//修正函数地址
if (*(PUCHAR)dwExecFuncAddr == 0xe9)
{
DbgPrint("执行函数的地址,修正前:0x%.8x\r\n",dwExecFuncAddr);
dwExecFuncAddr = *(PULONG)(dwExecFuncAddr + 1) - (dwExecFuncAddr + 5);
DbgPrint("执行函数的地址,修正后:0x%.8x\r\n",dwExecFuncAddr);
}
else
{
DbgPrint("执行函数的地址,无需修正\r\n");
}
//根据系统调用号找到内核函数的地址
g_dwKernelFuncAddr = *(PULONG)((ULONG)(KeServiceDescriptorTable->ntoskrnl.ServiceTableBase) + SYSCODE * 4);
DbgPrint("内核函数地址:0x%.8x\r\n",g_dwKernelFuncAddr);
//HOOK
if (!Hook(g_dwKernelFuncAddr,dwExecFuncAddr))
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
// 关闭页保护
VOID PageProtectOff()
{
__asm
{
cli; // 关闭中断
mov eax, cr0;
and eax, not 0x10000; // WP位置0
mov cr0, eax;
}
}
// 开启页保护
VOID PageProtectOn()
{
__asm
{
mov eax, cr0;
or eax, 0x10000; // WP位置1
mov cr0, eax;
sti; // 恢复中断
}
}
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
//UN-HOOK
UnHook(g_dwKernelFuncAddr);
//释放内存
ExFreePool(g_pHookMemAddr);
DbgPrint("驱动已停止\r\n");
}
// HOOK过程
// 将dwSrc函数HOOK至Dst函数
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr)
{
ULONG i;//for循环的参数
ULONG dwJumpPara;//E9Jmp的参数
ULONG dwCallPara;//E8Call参数
DbgPrint("\r\nHook\r\n");
//申请内存
g_pHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
if (g_pHookMemAddr == NULL)
{
DbgPrint("\r\nExAllocatePool失败\r\n");
return FALSE;
}
DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pHookMemAddr);
RtlFillMemory(g_pHookMemAddr, 0x100, 0x90);
//DbgBreakPoint();
//pushad pushfd
*((PUCHAR)g_pHookMemAddr + 0) = 0x60;//pushad
*((PUCHAR)g_pHookMemAddr + 1) = 0x9c;//pushfd
//int 3
*((PUCHAR)g_pHookMemAddr + 2) = 0x90;//int 3
//在申请的内存空间偏移+3处编辑ShellCode:call ExecFunc(RealFunc)
DbgPrint("\r\n在申请的内存空间偏移+3处编辑ShellCode:Call HookFunc\r\n");
*((PUCHAR)g_pHookMemAddr + 3) = 0xe8;//call
dwCallPara = dwDstFuncAddr - ((ULONG)g_pHookMemAddr + 3 + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)((ULONG)g_pHookMemAddr + 3 + i) = *(PUCHAR)((ULONG)(&dwCallPara) + i - 1);
}
//popfd popad
*((PUCHAR)g_pHookMemAddr + 8) = 0x9d;//popfd
*((PUCHAR)g_pHookMemAddr + 9) = 0x61;//popad
//DbgBreakPoint();
//保存内核函数前7字节的数据到申请的内存区域偏移+10处
DbgPrint("\r\n保存内核函数前5字节的数据到申请的内存空间中\r\n");
for (i = 0; i < 7; i++)
{
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
*((PUCHAR)g_pHookMemAddr + 10 + i) = *(PUCHAR)(dwSrcFuncAddr + i);
DbgPrint("No.%d AllocMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, (ULONG)g_pHookMemAddr + 10 + i, *((PUCHAR)g_pHookMemAddr + 10 + i));
}
//DbgBreakPoint();
//在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr + 5
DbgPrint("\r\n在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr + 5\r\n");
*((PUCHAR)g_pHookMemAddr + 20) = 0xe9;//jmp
dwJumpPara = dwSrcFuncAddr + 5 - ((ULONG)g_pHookMemAddr + 20 + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)((ULONG)g_pHookMemAddr + 20 + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
}
//DbgBreakPoint();
//修改内核函数前7字节进行InlineHook
DbgPrint("\r\n修改内核函数前7字节\r\n关闭页保护\r\n");
PageProtectOff();
*(PUCHAR)dwSrcFuncAddr = 0xe9;//jmp
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", 1, dwSrcFuncAddr, *(PUCHAR)dwSrcFuncAddr);
//跳转至申请的内存区域偏移+0处的Jmp参数
dwJumpPara = (ULONG)g_pHookMemAddr - (dwSrcFuncAddr + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
}
//多余处填充nop
*(PUCHAR)(dwSrcFuncAddr + 5) = 0x90;//nop
*(PUCHAR)(dwSrcFuncAddr + 6) = 0x90;//nop
DbgPrint("开启页保护\r\n");
PageProtectOn();
//披露重要数据
DbgPrint("\r\nHOOK完成\r\n原函数地址:0x%.8x\r\n跳转区域地址:0x%.8x\r\n执行函数地址:0x%.8x\r\n",dwSrcFuncAddr,g_pHookMemAddr,dwDstFuncAddr);
return TRUE;
}
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr)
{
ULONG i;
DbgPrint("\r\nUnHook\r\n");
//关闭页保护
PageProtectOff();
//将申请的内存区域偏移+10处的前7字节的数据还原到内核函数
for (i = 0; i < 7; i++)
{
DbgPrint("还原前,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)g_pHookMemAddr + 10 + i);
DbgPrint("还原后,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
}
ExFreePool(g_pSpyBuffer);
//开启页保护
PageProtectOn();
}
// HOOK后的执行函数
/*
NTSTATUS __stdcall NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer, ULONG dwLength, PLARGE_INTEGER ByteOffset, PULONG Key)
KernelFunc(NtReadFile):
此时
{
esp + 0x00 = NtReadFile的返回地址
esp + 0x04 = FileHandle
esp + 0x08 = Event
esp + 0x0c = ApcRoutine
esp + 0x10 = ApcContext
esp + 0x14 = IoStatusBlock
esp + 0x18 = Buffer
esp + 0x1c = dwLength
esp + 0x20 = ByteOffset
esp + 0x24 = Key
}
jmp HookMemory
nop
nop
nop
call __SEH_prolog
......
******************************************
HookMemory:
pushad
pushfd
int 3
此时
{
esp + 0x00 = eflags
esp + 0x04 = edi
esp + 0x08 = esi
esp + 0x0c = ebp
esp + 0x10 = esp
esp + 0x14 = ebx
esp + 0x18 = edx
esp + 0x1c = ecx
esp + 0x20 = eax
esp + 0x24 = NtReadFile的返回地址
esp + 0x28 = FileHandle
esp + 0x2c = Event
esp + 0x30 = ApcRoutine
esp + 0x34 = ApcContext
esp + 0x38 = IoStatusBlock
esp + 0x3c = Buffer
esp + 0x40 = dwLength
esp + 0x44 = ByteOffset
esp + 0x48 = Key
}
call ExecFunc(RealFunc)
popfd
popad
push 68h
push 0041A310h
jmp nt!NtReadFile + 0x5(805727af)
******************************************
ExecFunc(RealFunc):
此时
{
esp + 0x00 = ExecFunc(RealFunc)的返回地址
esp + 0x04 = eflags
esp + 0x08 = edi
esp + 0x0c = esi
esp + 0x10 = ebp
esp + 0x14 = esp
esp + 0x18 = ebx
esp + 0x1c = edx
esp + 0x20 = ecx
esp + 0x24 = eax
esp + 0x28 = NtReadFile的返回地址
esp + 0x2c = FileHandle
esp + 0x30 = Event
esp + 0x34 = ApcRoutine
esp + 0x38 = ApcContext
esp + 0x3c = IoStatusBlock
esp + 0x40 = Buffer
esp + 0x44 = dwLength
esp + 0x48 = ByteOffset
esp + 0x4c = Key
}
push ebp
此时
{
esp + 0x00 = ebp(原)
esp + 0x04 = ExecFunc(RealFunc)的返回地址
esp + 0x08 = eflags
esp + 0x0c = edi
esp + 0x10 = esi
esp + 0x14 = ebp
esp + 0x18 = esp
esp + 0x1c = ebx
esp + 0x20 = edx
esp + 0x24 = ecx
esp + 0x28 = eax
esp + 0x2c = NtReadFile的返回地址
esp + 0x30 = FileHandle
esp + 0x34 = Event
esp + 0x38 = ApcRoutine
esp + 0x3c = ApcContext
esp + 0x40 = IoStatusBlock
esp + 0x44 = Buffer
esp + 0x48 = dwLength
esp + 0x4c = ByteOffset
esp + 0x50 = Key
}
mov ebp,esp
此时,esp == ebp
{
ebp + 0x00 = ebp(原)
ebp + 0x04 = ExecFunc(RealFunc)的返回地址
ebp + 0x08 = eflags
ebp + 0x0c = edi
ebp + 0x10 = esi
ebp + 0x14 = ebp
ebp + 0x18 = ebp
ebp + 0x1c = ebx
ebp + 0x20 = edx
ebp + 0x24 = ecx
ebp + 0x28 = eax
ebp + 0x2c = NtReadFile的返回地址
ebp + 0x30 = FileHandle
ebp + 0x34 = Event
ebp + 0x38 = ApcRoutine
ebp + 0x3c = ApcContext
ebp + 0x40 = IoStatusBlock
ebp + 0x44 = Buffer
ebp + 0x48 = dwLength
ebp + 0x4c = ByteOffset
ebp + 0x50 = Key
}
sub esp,30h
cli
......
*/
VOID __stdcall RealFunc()
{
ULONG FileHandle;
ULONG Event;
ULONG ApcRoutine;
ULONG ApcContext;
ULONG IoStatusBlock;
ULONG Buffer;
ULONG dwLength;
ULONG ByteOffset;
ULONG Key;
ULONG dwRetAddr;
UCHAR i;
__asm
{
cli;
mov eax,[ebp + 0x04];//当前函数的返回地址
mov [dwRetAddr],eax;
mov eax,[ebp + 0x30];//NtReadFile参数01:FileHandle
mov [FileHandle],eax;
mov eax,[ebp + 0x34];//NtReadFile参数02:Event
mov [Event],eax;
mov eax,[ebp + 0x38];//NtReadFile参数03:ApcRoutine
mov [ApcRoutine],eax;
mov eax,[ebp + 0x3c];//NtReadFile参数04:ApcContext
mov [ApcContext],eax;
mov eax,[ebp + 0x40];//NtReadFile参数05:IoStatusBlock
mov [IoStatusBlock],eax;
mov eax,[ebp + 0x44];//NtReadFile参数06:Buffer
mov [Buffer],eax;
mov eax,[ebp + 0x48];//NtReadFile参数07:Length
mov [dwLength],eax;
mov eax,[ebp + 0x4c];//NtReadFile参数08:ByteOffset
mov [ByteOffset],eax;
mov eax,[ebp + 0x50];//NtReadFile参数09:Key
mov [Key],eax;
}
if (dwLength == 0xffffffff)
{
__asm pushfd;
DbgPrint("\r\n");
DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
__asm popfd;
//修改缓冲区大小
dwLength = 0x50;
__asm mov eax,[dwLength];
__asm mov [ebp + 0x48],eax;
__asm pushfd;
DbgPrint("已修改参数07:dwLength的值为0x%.8x\r\n",dwLength);
__asm popfd;
//修改缓冲区
g_pSpyBuffer = ExAllocatePool(PagedPool, dwLength);
}
/*
//验证堆栈
if (dwRetAddr == ((ULONG)g_pHookMemAddr + 8))
{
__asm pushfd;
DbgPrint("\r\n");
DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
__asm popfd;
}
*/
__asm sti;
return;
}
/*
函数调用过程
ReadFilekernel32) ==> NtReadFile(ntdll) ==> NtReadFile(ntoskrnl)
kernel32:
BOOL __stdcall ReadFile(IN HANDLE hFile, OUT LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead, IN LPOVERLAPPED lpOverlapped)
push ebx //Key
push ebx //ByteOffset
push [ebp + 0x10] //Length
push [ebp + 0x0c] //Buffer
lea eax, [ebp - 0x28]
push eax //IoStatusBlock
push ebx //ApcContext
push ebx //ApcRoutine
push ebx //Event
push edi //FileHandle
call ds:__imp__NtReadFile
......
retn 14h //5个参数
ntdll:
NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)
mov eax, 0B7h//系统调用号
mov edx, 7FFE0300h
call dword ptr [edx]
retn 24h
ntoskrnl:
NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)
6A 68 push 68h
68 10 A3 41 00 push 0041A310h
E8 18 E3 F6 FF call __SEH_prolog
33 F6 xor esi, esi
......
retn 24h //9个参数
*/
3环:
#include <WINDOWS.H>
#include <STDIO.H>
#define FILENAME "C:\\Program Files\\PETool 1.0.0.5.exe"
#define FUNCNAME ReadFile
#define FILE_SHARE_OTHER 0xffff
int main()
{
//获取3环函数地址
DWORD dwFunc3Addr = (DWORD)FUNCNAME;
printf("函数的地址为:0x%.8x\n\n",dwFunc3Addr);
//CreateFileA
HANDLE hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
{
printf("CreateFileA失败,错误代码:%d\n", GetLastError());
system("pause");
return -1;
}
printf("CreateFileA成功,句柄:0x%x\n",(DWORD)hFile);
//ReadFile
DWORD dwNumber = 0;
DWORD dwLength = 0xffffffff;
LPVOID lpBuffer = malloc(0x100);
printf("\nReadFile,数据地址:0x%.8x\n", lpBuffer);
memset(lpBuffer, 0, 0x100);
BOOL bRet = ReadFile(hFile, lpBuffer, dwLength, &dwNumber, NULL);
/*
if (!bRet)
{
printf("\nReadFile,错误代码:%d\n", GetLastError());
CloseHandle(hFile);
system("pause");
return -1;
}
*/
printf("ReadFile成功,已读取:0x%x个字节,数据地址:0x%.8x\n", dwNumber, lpBuffer);
__asm mov eax,eax;
CloseHandle(hFile);
system("pause");
return 0;
}
三、NtReadFile(HOOK传入、传出参数)
0环:
#include <ntifs.h>
// 系统调用号
// NtReadFile 0xB7
#define SYSCODE 0xB7
#define BUFFERSIZE 0x50
PVOID g_pBgnHookMemAddr;//函数开始处InlineHook跳转地址
PVOID g_pEndHookMemAddr;//函数结尾处InlineHook跳转地址
ULONG g_dwKernelFuncBgnAddr;//内核函数开始处的地址
ULONG g_dwKernelFuncEndAddr;//内核函数结尾处的地址
ULONG g_dwInByte;//HOOK传入参数时修改的字节数
ULONG g_dwOutByte;//HOOK传出参数时修改的字节数
ULONG g_dwFlag;//暗号
ULONG g_Buffer;//3环的缓冲区,用于修改
PUCHAR g_pszProcessName;//3环进程名
// 系统服务表
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG ServiceTableBase; // 函数地址表
PULONG ServiceCounterTableBase; // SSDT 函数被调用的次数
ULONG NumberOfService; // 函数个数
PULONG ParamTableBase; // 函数参数表
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
// SSDT表
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
KSYSTEM_SERVICE_TABLE ntoskrnl; // 内核函数
KSYSTEM_SERVICE_TABLE win32k; // win32k.sys 函数
KSYSTEM_SERVICE_TABLE unUsed1;
KSYSTEM_SERVICE_TABLE unUsed2;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; // 声明全局变量
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
// 开启页保护
VOID PageProtectOn();
// 关闭页保护
VOID PageProtectOff();
// HOOK过程
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwJmpMemAddr, ULONG dwDstFuncAddr, ULONG dwByteSize);
// UN_HOOK
VOID UnHook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr, ULONG dwByteSize);
// 修改传入参数
VOID __stdcall ChangeInPara();
// 修改传出参数
VOID __stdcall ChangeOutPara();
// 查找目标进程CR3
ULONG FindCr3();
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
ULONG dwExecFuncAddr_In;//修改传入参数的函数地址
ULONG dwExecFuncAddr_Out;//修改传出参数的函数地址
g_dwFlag = 0;//暗号初始化:0为未HOOK,1为已HOOK
g_pszProcessName = (PUCHAR)"InlineHook.exe";
DbgPrint("驱动已启动\r\n");
pDriver->DriverUnload = DriverUnload;
//******************************************修改传入参数******************************************
//获取执行函数(ChangeIn)的地址
dwExecFuncAddr_In = (ULONG)ChangeInPara;
//修正地址
if (*(PUCHAR)dwExecFuncAddr_In == 0xe9)
{
DbgPrint("执行函数(ChangeIn)的地址,修正前:0x%.8x\r\n",dwExecFuncAddr_In);
dwExecFuncAddr_In = *(PULONG)(dwExecFuncAddr_In + 1) - (dwExecFuncAddr_In + 5);
DbgPrint("执行函数(ChangeIn)的地址,修正后:0x%.8x\r\n",dwExecFuncAddr_In);
}
else
{
DbgPrint("执行函数(ChangeIn)的地址,无需修正\r\n");
}
//根据系统调用号找到内核函数开始处的地址
g_dwKernelFuncBgnAddr = *(PULONG)((ULONG)(KeServiceDescriptorTable->ntoskrnl.ServiceTableBase) + SYSCODE * 4);
DbgPrint("内核函数开始处地址:0x%.8x\r\n",g_dwKernelFuncBgnAddr);
//申请内存
g_pBgnHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
if (g_pBgnHookMemAddr == NULL)
{
DbgPrint("\r\nExAllocatePool失败\r\n");
return FALSE;
}
DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pBgnHookMemAddr);
RtlFillMemory(g_pBgnHookMemAddr, 0x100, 0x90);
//开始HOOK
/*
6A 68 push 68h
68 10 A3 41 00 push 0041A310h
共7个字节
*/
g_dwInByte = 7;
if (!Hook(g_dwKernelFuncBgnAddr, (ULONG)g_pBgnHookMemAddr, dwExecFuncAddr_In, g_dwInByte))
{
return STATUS_UNSUCCESSFUL;
}
//******************************************修改传出参数******************************************
//获取执行函数(ChangeOut)的地址
dwExecFuncAddr_Out = (ULONG)ChangeOutPara;
//修正地址
if (*(PUCHAR)dwExecFuncAddr_Out == 0xe9)
{
DbgPrint("\r\n执行函数(ChangeOut)的地址,修正前:0x%.8x\r\n",dwExecFuncAddr_Out);
dwExecFuncAddr_Out = *(PULONG)(dwExecFuncAddr_Out + 1) - (dwExecFuncAddr_Out + 5);
DbgPrint("执行函数(ChangeOut)的地址,修正后:0x%.8x\r\n",dwExecFuncAddr_Out);
}
else
{
DbgPrint("\r\n执行函数(ChangeOut)的地址,无需修正\r\n");
}
//申请内存
g_pEndHookMemAddr = ExAllocatePool(NonPagedPool, 0x100);
if (g_pEndHookMemAddr == NULL)
{
DbgPrint("\r\nExAllocatePool失败\r\n");
return FALSE;
}
DbgPrint("\r\nExAllocatePool成功,内存地址:0x%.8x\r\n",(ULONG)g_pEndHookMemAddr);
RtlFillMemory(g_pEndHookMemAddr, 0x100, 0x90);
/*
805727aa 6A 68 push 68h
......
80572d2f C2 24 00 retn 24h
80572d32 cc int 3
80572d33 cc int 3
80572d34 cc int 3
80572d35 cc int 3
80572d36 cc int 3
80572d37 cc int 3
共3个字节,可修改5个字节
*/
g_dwOutByte = 5;
//根据偏移,计算出HOOK传出参数的位置
//80572d2f - 805727aa = 0x585;
g_dwKernelFuncEndAddr = g_dwKernelFuncBgnAddr + 0x585;//不可直接使用IDA的偏移,RVA之故
DbgPrint("内核函数结尾处地址:0x%.8x\r\n",g_dwKernelFuncEndAddr);
//开始HOOK
if (!Hook(g_dwKernelFuncEndAddr, (ULONG)g_pEndHookMemAddr, dwExecFuncAddr_Out, g_dwOutByte))
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
// 关闭页保护
VOID PageProtectOff()
{
__asm
{
cli; // 关闭中断
mov eax, cr0;
and eax, not 0x10000; // WP位置0
mov cr0, eax;
}
}
// 开启页保护
VOID PageProtectOn()
{
__asm
{
mov eax, cr0;
or eax, 0x10000; // WP位置1
mov cr0, eax;
sti; // 恢复中断
}
}
// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
//DbgBreakPoint();
//UN-HOOK
UnHook((ULONG)g_pBgnHookMemAddr, g_dwKernelFuncBgnAddr, g_dwInByte);
UnHook((ULONG)g_pEndHookMemAddr, g_dwKernelFuncEndAddr, g_dwOutByte);
//释放内存
ExFreePool(g_pBgnHookMemAddr);
ExFreePool(g_pEndHookMemAddr);
DbgPrint("驱动已停止\r\n");
}
// HOOK过程
// 将函数自Src处跳转至JmpMem处后Call至Dst函数,ShellCode占ByteSize个字节
BOOLEAN Hook(ULONG dwSrcFuncAddr, ULONG dwJmpMemAddr, ULONG dwDstFuncAddr, ULONG dwByteSize)
{
ULONG i;//for循环的参数
ULONG dwJumpPara;//E9Jmp的参数
ULONG dwCallPara;//E8Call参数
DbgPrint("\r\nHook\r\n");
//DbgBreakPoint();
//pushad pushfd
*((PUCHAR)dwJmpMemAddr + 0) = 0x60;//pushad
*((PUCHAR)dwJmpMemAddr + 1) = 0x9c;//pushfd
//int 3
*((PUCHAR)dwJmpMemAddr + 2) = 0x90;//int 3
//在申请的内存空间偏移+3处编辑ShellCode:call ExecFunc(ChangeInPara)
DbgPrint("\r\n在申请的内存空间偏移+3处编辑ShellCode:Call HookFunc\r\n");
*((PUCHAR)dwJmpMemAddr + 3) = 0xe8;//call
dwCallPara = dwDstFuncAddr - ((ULONG)dwJmpMemAddr + 3 + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)(dwJmpMemAddr + 3 + i) = *(PUCHAR)((ULONG)(&dwCallPara) + i - 1);
}
//popfd popad
*((PUCHAR)dwJmpMemAddr + 8) = 0x9d;//popfd
*((PUCHAR)dwJmpMemAddr + 9) = 0x61;//popad
//DbgBreakPoint();
//保存内核函数前dwByteSize字节的数据到申请的内存区域偏移+10处
DbgPrint("\r\n保存内核函数前dwByteSize字节的数据到申请的内存空间中\r\n");
for (i = 0; i < dwByteSize; i++)
{
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
*((PUCHAR)dwJmpMemAddr + 10 + i) = *(PUCHAR)(dwSrcFuncAddr + i);
DbgPrint("No.%d AllocMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwJmpMemAddr + 10 + i, *((PUCHAR)dwJmpMemAddr + 10 + i));
}
//DbgBreakPoint();
//在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr
DbgPrint("\r\n在申请的内存空间偏移+20处编辑ShellCode:Jump Back To KernelFuncAddr\r\n");
*((PUCHAR)dwJmpMemAddr + 20) = 0xe9;//jmp
dwJumpPara = dwSrcFuncAddr + 5 - (dwJmpMemAddr + 20 + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)(dwJmpMemAddr + 20 + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
}
//DbgBreakPoint();
//修改内核函数前dwByteSize字节进行InlineHook
DbgPrint("\r\n修改内核函数前%d字节\r\n关闭页保护\r\n",dwByteSize);
PageProtectOff();
*(PUCHAR)dwSrcFuncAddr = 0xe9;//jmp
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", 1, dwSrcFuncAddr, *(PUCHAR)dwSrcFuncAddr);
//跳转至申请的内存区域偏移+0处的Jmp参数
dwJumpPara = (ULONG)dwJmpMemAddr - (dwSrcFuncAddr + 5);
for (i = 1; i < 5; i++)
{
*(PUCHAR)(dwSrcFuncAddr + i) = *(PUCHAR)((ULONG)(&dwJumpPara) + i - 1);
DbgPrint("No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwSrcFuncAddr + i, *(PUCHAR)(dwSrcFuncAddr + i));
}
//内核函数多余处填充nop
for (i = 5; i < dwByteSize; i++)
{
*(PUCHAR)(dwSrcFuncAddr + i) = 0x90;//nop
}
DbgPrint("开启页保护\r\n");
PageProtectOn();
//披露重要数据
DbgPrint("\r\nHOOK完成\r\n原函数地址:0x%.8x\r\n跳转区域地址:0x%.8x\r\n执行函数地址:0x%.8x\r\n共修改%d个字节\r\n",dwSrcFuncAddr,dwJmpMemAddr,dwDstFuncAddr,dwByteSize);
return TRUE;
}
// UN_HOOK
// 将SrcAddr区域dwByteSize的数据还原至DstAddr处
VOID UnHook(ULONG dwSrcFuncAddr, ULONG dwDstFuncAddr, ULONG dwByteSize)
{
ULONG i;
DbgPrint("\r\nUnHook\r\n");
//关闭页保护
PageProtectOff();
//将申请的内存区域偏移+10处的前dwByteSize字节的数据还原到内核函数
for (i = 0; i < dwByteSize; i++)
{
DbgPrint("还原前,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwDstFuncAddr + i, *(PUCHAR)(dwDstFuncAddr + i));
*(PUCHAR)(dwDstFuncAddr + i) = *(PUCHAR)(dwSrcFuncAddr + 10 + i);
DbgPrint("还原后,No.%d FuncMemAddr:0x%.8x Value:0x%.2x\r\n", i + 1, dwDstFuncAddr + i, *(PUCHAR)(dwDstFuncAddr + i));
}
//开启页保护
PageProtectOn();
}
// HOOK后的执行函数
/*
NTSTATUS __stdcall NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer, ULONG dwLength, PLARGE_INTEGER ByteOffset, PULONG Key)
KernelFunc(NtReadFile):
此时
{
esp + 0x00 = NtReadFile的返回地址
esp + 0x04 = FileHandle
esp + 0x08 = Event
esp + 0x0c = ApcRoutine
esp + 0x10 = ApcContext
esp + 0x14 = IoStatusBlock
esp + 0x18 = Buffer
esp + 0x1c = dwLength
esp + 0x20 = ByteOffset
esp + 0x24 = Key
}
jmp HookMemory
nop
nop
nop
call __SEH_prolog
......
******************************************
HookMemory:
pushad
pushfd
int 3
此时
{
esp + 0x00 = eflags
esp + 0x04 = edi
esp + 0x08 = esi
esp + 0x0c = ebp
esp + 0x10 = esp
esp + 0x14 = ebx
esp + 0x18 = edx
esp + 0x1c = ecx
esp + 0x20 = eax
esp + 0x24 = NtReadFile的返回地址
esp + 0x28 = FileHandle
esp + 0x2c = Event
esp + 0x30 = ApcRoutine
esp + 0x34 = ApcContext
esp + 0x38 = IoStatusBlock
esp + 0x3c = Buffer
esp + 0x40 = dwLength
esp + 0x44 = ByteOffset
esp + 0x48 = Key
}
call ExecFunc(ChangeInPara)
popfd
popad
push 68h
push 0041A310h
jmp nt!NtReadFile + 0x5(805727af)
******************************************
ExecFunc(ChangeInPara):
此时
{
esp + 0x00 = ExecFunc(ChangeInPara)的返回地址
esp + 0x04 = eflags
esp + 0x08 = edi
esp + 0x0c = esi
esp + 0x10 = ebp
esp + 0x14 = esp
esp + 0x18 = ebx
esp + 0x1c = edx
esp + 0x20 = ecx
esp + 0x24 = eax
esp + 0x28 = NtReadFile的返回地址
esp + 0x2c = FileHandle
esp + 0x30 = Event
esp + 0x34 = ApcRoutine
esp + 0x38 = ApcContext
esp + 0x3c = IoStatusBlock
esp + 0x40 = Buffer
esp + 0x44 = dwLength
esp + 0x48 = ByteOffset
esp + 0x4c = Key
}
push ebp
此时
{
esp + 0x00 = ebp(原)
esp + 0x04 = ExecFunc(ChangeInPara)的返回地址
esp + 0x08 = eflags
esp + 0x0c = edi
esp + 0x10 = esi
esp + 0x14 = ebp
esp + 0x18 = esp
esp + 0x1c = ebx
esp + 0x20 = edx
esp + 0x24 = ecx
esp + 0x28 = eax
esp + 0x2c = NtReadFile的返回地址
esp + 0x30 = FileHandle
esp + 0x34 = Event
esp + 0x38 = ApcRoutine
esp + 0x3c = ApcContext
esp + 0x40 = IoStatusBlock
esp + 0x44 = Buffer
esp + 0x48 = dwLength
esp + 0x4c = ByteOffset
esp + 0x50 = Key
}
mov ebp,esp
此时,esp == ebp
{
ebp + 0x00 = ebp(原)
ebp + 0x04 = ExecFunc(ChangeInPara)的返回地址
ebp + 0x08 = eflags
ebp + 0x0c = edi
ebp + 0x10 = esi
ebp + 0x14 = ebp
ebp + 0x18 = esp
ebp + 0x1c = ebx
ebp + 0x20 = edx
ebp + 0x24 = ecx
ebp + 0x28 = eax
ebp + 0x2c = NtReadFile的返回地址
ebp + 0x30 = FileHandle
ebp + 0x34 = Event
ebp + 0x38 = ApcRoutine
ebp + 0x3c = ApcContext
ebp + 0x40 = IoStatusBlock
ebp + 0x44 = Buffer
ebp + 0x48 = dwLength
ebp + 0x4c = ByteOffset
ebp + 0x50 = Key
}
sub esp,30h
cli
......
*/
// 修改传入参数
VOID __stdcall ChangeInPara()
{
ULONG FileHandle;
ULONG Event;
ULONG ApcRoutine;
ULONG ApcContext;
ULONG IoStatusBlock;
ULONG Buffer;
ULONG dwLength;
ULONG ByteOffset;
ULONG Key;
ULONG dwRetAddr;
__asm
{
cli;
mov eax,[ebp + 0x04];//当前函数的返回地址
mov [dwRetAddr],eax;
mov eax,[ebp + 0x30];//NtReadFile参数01:FileHandle
mov [FileHandle],eax;
mov eax,[ebp + 0x34];//NtReadFile参数02:Event
mov [Event],eax;
mov eax,[ebp + 0x38];//NtReadFile参数03:ApcRoutine
mov [ApcRoutine],eax;
mov eax,[ebp + 0x3c];//NtReadFile参数04:ApcContext
mov [ApcContext],eax;
mov eax,[ebp + 0x40];//NtReadFile参数05:IoStatusBlock
mov [IoStatusBlock],eax;
mov eax,[ebp + 0x44];//NtReadFile参数06:Buffer
mov [Buffer],eax;
mov eax,[ebp + 0x48];//NtReadFile参数07:Length
mov [dwLength],eax;
mov eax,[ebp + 0x4c];//NtReadFile参数08:ByteOffset
mov [ByteOffset],eax;
mov eax,[ebp + 0x50];//NtReadFile参数09:Key
mov [Key],eax;
}
if (dwLength == 0xffffffff)
{
__asm pushfd;
DbgPrint("\r\nChangeInPara\r\n");
DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
//保存目标进程的3环缓冲区,防止后期变更
g_Buffer = Buffer;
DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
__asm popfd;
//修改堆栈中的传入参数:缓冲区大小
dwLength = BUFFERSIZE;
__asm mov eax,[dwLength];
__asm mov [ebp + 0x48],eax;
__asm pushfd;
DbgPrint("已修改参数07:dwLength的值为0x%.8x\r\n",dwLength);
__asm popfd;
//修改暗号为已HOOK
g_dwFlag = 1;
}
/*
//验证堆栈
if (dwRetAddr == ((ULONG)g_pBgnHookMemAddr + 8))
{
__asm pushfd;
DbgPrint("\r\n");
DbgPrint("NtReadFile参数01:FileHandle:0x%.8x\r\n",FileHandle);
DbgPrint("NtReadFile参数02:Event:0x%.8x\r\n",Event);
DbgPrint("NtReadFile参数03:ApcRoutine:0x%.8x\r\n",ApcRoutine);
DbgPrint("NtReadFile参数04:ApcContext:0x%.8x\r\n",ApcContext);
DbgPrint("NtReadFile参数05:IoStatusBlock:0x%.8x\r\n",IoStatusBlock);
DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
DbgPrint("NtReadFile参数08:ByteOffset:0x%.8x\r\n",ByteOffset);
DbgPrint("NtReadFile参数09:Key:0x%.8x\r\n",Key);
DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
__asm popfd;
}
*/
__asm sti;
return;
}
/*
函数调用过程
ReadFilekernel32) ==> NtReadFile(ntdll) ==> NtReadFile(ntoskrnl)
kernel32:
BOOL __stdcall ReadFile(IN HANDLE hFile, OUT LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead, IN LPOVERLAPPED lpOverlapped)
push ebx //Key
push ebx //ByteOffset
push [ebp + 0x10] //Length
push [ebp + 0x0c] //Buffer
lea eax, [ebp - 0x28]
push eax //IoStatusBlock
push ebx //ApcContext
push ebx //ApcRoutine
push ebx //Event
push edi //FileHandle
call ds:__imp__NtReadFile
......
retn 14h //5个参数
ntdll:
NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)
mov eax, 0B7h//系统调用号
mov edx, 7FFE0300h
call dword ptr [edx]
retn 24h
ntoskrnl:
NTSTATUS __stdcall NtReadFile(IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer, IN ULONG dwLength, IN PLARGE_INTEGER ByteOffset, IN PULONG Key)
6A 68 push 68h
68 10 A3 41 00 push 0041A310h
E8 18 E3 F6 FF call __SEH_prolog
33 F6 xor esi, esi
......
retn 24h //9个参数
*/
// HOOK传出参数后的执行函数
VOID __stdcall ChangeOutPara()
{
ULONG i;
ULONG dwRetAddr;
ULONG Buffer;//内核函数传出参数
ULONG dwLength;//内核函数传入参数
PVOID pTempBuffer;//临时缓冲区,用于转存
//当前进程CR3
ULONG dwMyCr3;
//目标进程CR3
ULONG dwTargetCr3;
__asm
{
cli;
mov eax,[ebp + 0x04];//当前函数的返回地址
mov [dwRetAddr],eax;
mov eax,[ebp + 0x44];//NtReadFile参数06:Buffer
mov [Buffer],eax;
mov eax,[ebp + 0x48];//NtReadFile参数07:Length
mov [dwLength],eax;
sti;
}
/*
//当前进程的CR3
__asm cli;
__asm mov eax,cr3;
__asm mov [dwMyCr3],eax;
__asm sti;
//DbgPrint("当前进程的CR3:0x%x\r\n",dwMyCr3);
*/
/*
//验证堆栈
if (dwRetAddr == ((ULONG)g_pEndHookMemAddr + 8))
{
//DbgBreakPoint();
__asm pushfd;
DbgPrint("\r\n");
DbgPrint("NtReadFile参数06:Buffer:0x%.8x\r\n",Buffer);
DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
DbgPrint("当前函数的返回地址:0x%.8x\r\n",dwRetAddr);
__asm popfd;
}
*/
//判断暗号
if (g_dwFlag == 1 && Buffer == g_Buffer)
{
DbgPrint("\r\nChangeOutPara\r\n");
/*
DbgPrint("当前进程的CR3:0x%x\r\n",dwMyCr3);
//目标进程的CR3
dwTargetCr3 = FindCr3();
*/
__asm pushfd;
DbgPrint("\r\nNtReadFile参数06:Buffer:0x%.8x\r\n",g_Buffer);
DbgPrint("NtReadFile参数07:dwLength:0x%.8x\r\n",dwLength);
__asm popfd;
//创建临时缓冲区
pTempBuffer = ExAllocatePool(NonPagedPool, 0x100);
if (pTempBuffer == NULL)
{
__asm pushfd;
DbgPrint("ExAllocatePool失败\r\n");
__asm popfd;
return;
}
__asm pushfd;
DbgPrint("ExAllocatePool成功,高2G缓冲区的内存地址:0x%.8x\r\n",(ULONG)pTempBuffer);
__asm popfd;
//填充数据
for (i = 0; i < 100; i++)
{
*(PUCHAR)((ULONG)pTempBuffer + i) = i;
}
//DbgBreakPoint();
/*
//跨进程写入数据(误,并未跨进程,EIP走到此处,与目标进程为统一进程)
__asm cli;
//1.将当前进程的CR3修改为3环程序的CR3
__asm mov eax,[dwTargetCr3];
__asm mov cr3,eax;
*/
//2.将高2G内存空间的数据转存至低2G空间(3环程序)的缓冲区
RtlCopyMemory((PVOID)g_Buffer, pTempBuffer, BUFFERSIZE);
/*
//3.恢复当前进程的CR3
__asm mov eax,[dwMyCr3];
__asm mov cr3,eax;
__asm sti;
*/
ExFreePool(pTempBuffer);
/*
//修改堆栈中的传出参数:Buffer(无意义)
__asm mov eax,[g_pSpyBuffer];
__asm mov [ebp + 0x44],eax;
*/
__asm pushfd;
DbgPrint("已修改参数06:Buffer的内容\r\n");
__asm popfd;
//恢复初始值
g_dwFlag = 0;
}
//__asm sti;
return;
}
// 查找目标进程CR3
ULONG FindCr3()
{
PEPROCESS pEprocess;
PUCHAR pszProcessName;
PLIST_ENTRY pList;
PLIST_ENTRY pListNext;
ULONG dwCR3;
DbgPrint("\r\nFindCr3\r\n");
//获取当前进程结构体_EPROCESS的地址
__asm
{
pushad;
pushfd;
//CurrentThread: Ptr32 _KTHREAD
mov eax,fs:[0x124];
//ThreadsProcess: Ptr32 _EPROCESS
mov eax,[eax + 0x220];
mov pEprocess,eax;
popfd;
popad;
}
pList = (PLIST_ENTRY)((ULONG)pEprocess + 0x88);
pszProcessName = (PUCHAR)((ULONG)pEprocess + 0x174);
DbgPrint("当前进程名:%s\r\n",pszProcessName);
if (!strcmp(pszProcessName,g_pszProcessName))
{
//_EPROCESS._KPROCESS.DirectoryTableBase : [2] Uint4B
dwCR3 = *(PULONG)((ULONG)pEprocess + 0x18);
DbgPrint("已找到进程%s,CR3:0x%x\r\n",pszProcessName,dwCR3);
return dwCR3;
}
pListNext = pList->Flink;
//遍历所有进程
DbgPrint("\r\n开始遍历进程\r\n");
do
{
pEprocess = (PEPROCESS)(*(PULONG)pListNext - 0x88);
pszProcessName = (PUCHAR)((ULONG)pEprocess + 0x174);
DbgPrint("进程名:%s\r\n",pszProcessName);
if (!strcmp(pszProcessName,g_pszProcessName))
{
//_EPROCESS._KPROCESS.DirectoryTableBase : [2] Uint4B
dwCR3 = *(PULONG)((ULONG)pEprocess + 0x18);
DbgPrint("已找到进程%s,CR3:0x%x\r\n",pszProcessName,dwCR3);
return dwCR3;
}
pListNext = (PLIST_ENTRY)((ULONG)pEprocess + 0x88);
} while (pListNext->Flink != pList);
DbgPrint("进程遍历结束,未找到指定的进程\r\n");
return 0;
}
3环:
#include <WINDOWS.H>
#include <STDIO.H>
#define FILENAME "C:\\Program Files\\PETool.exe"
#define FUNCNAME ReadFile
#define FILE_SHARE_OTHER 0xffff
int main()
{
//获取3环函数地址
DWORD dwFunc3Addr = (DWORD)FUNCNAME;
printf("函数的地址为:0x%.8x\n\n",dwFunc3Addr);
//CreateFileA
HANDLE hFile = CreateFileA(FILENAME, GENERIC_ALL, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
{
printf("CreateFileA失败,错误代码:%d\n", GetLastError());
system("pause");
return -1;
}
printf("CreateFileA成功,句柄:0x%x\n",(DWORD)hFile);
//ReadFile
DWORD dwNumber = 0;
DWORD dwLength = 0xffffffff;
LPVOID lpBuffer = malloc(0x100);
printf("\nReadFile,数据地址:0x%.8x\n", lpBuffer);
memset(lpBuffer, 0, 0x100);
BOOL bRet = ReadFile(hFile, lpBuffer, dwLength, &dwNumber, NULL);
/*
if (!bRet)
{
printf("\nReadFile,错误代码:%d\n", GetLastError());
CloseHandle(hFile);
system("pause");
return -1;
}
*/
//通过查看传出参数dwNumber的值,验证传入参数dwLength是否已被修改
printf("ReadFile成功,已读取:0x%x个字节,数据地址:0x%.8x\n", dwNumber, lpBuffer);
Sleep(1000);
getchar();
//读取缓冲区,验证传出参数的lpBuffer的内容是否被替换
for (int i = 0; i < 0x50; i++)
{
printf("0x%.2x\t",*(PUCHAR)((DWORD)lpBuffer + i));
}
printf("\n");
__asm mov eax,eax;
system("pause");
CloseHandle(hFile);
free(lpBuffer);
return 0;
}
似乎达到了目的,如有错误之处,请留言指出,谢谢!