#include <ntddk.h>
/*
x64 inline hook ZwCreateSection.
为啥不x64 ssdt hook?,原因有:
1.ssdt 里面的函数少.
2.微软官方声明,这样会patchguard检测到并蓝屏.
3.ssdt 没有导出,需要自己获得.
made by correy
made at 2013.09.06
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
*/
/*
本代码测试环境为:windows server 2008 R2 X64
测试对象为:ZwCreateSection
0: kd> vertarget
Windows 7 Kernel Version 7601 (Service Pack 1) MP (2 procs) Free x64
Product: Server, suite: Enterprise TerminalServer SingleUserTS
Built by: 7601.18205.amd64fre.win7sp1_gdr.130708-1532
Machine Name:
Kernel base = 0xfffff800`01617000 PsLoadedModuleList = 0xfffff800`0185a6d0
Debug session time: Thu Sep 5 20:21:57.396 2013 (UTC + 8:00)
System Uptime: 0 days 0:11:39.021
0: kd> u nt!ZwCreateSection
nt!ZwCreateSection:
fffff800`016c3a60 488bc4 mov rax,rsp
fffff800`016c3a63 fa cli
fffff800`016c3a64 4883ec10 sub rsp,10h
fffff800`016c3a68 50 push rax
fffff800`016c3a69 9c pushfq
fffff800`016c3a6a 6a10 push 10h
fffff800`016c3a6c 488d055d290000 lea rax,[nt!KiServiceLinkage (fffff800`016c63d0)]
fffff800`016c3a73 50 push rax
*/
/*
经过编译,搜索,发现如下机器码.提示,用push 0x9999999999 是不行的.只能一个字节.
48b89999999909000000 mov rax,999999999h
50 push rax
c3 retn
retn 应该没啥影响,实验吧!
这个12字节,正好对应ZwCreateSection的前几个指令.
如果不对应,后面可以加NOP.
*/
#pragma pack(1) //这一行必不可少.
typedef struct _opcode {
unsigned short int mov_rax;
unsigned __int64 my_fn;
unsigned char push_rax;
unsigned char retn;
} opcode, *popcode;
opcode g_op;
unsigned char g_original[sizeof(opcode)];//保存函数的前几个字节.
PVOID g_pfn = 0;
NTSTATUS SuperRtlCopyMemory(IN VOID UNALIGNED *Destination, IN CONST VOID UNALIGNED *Source, IN SIZE_T Length)
{
NTSTATUS status = STATUS_SUCCESS;//STATUS_UNSUCCESSFUL
PMDL g_pmdl;
unsigned int * Mapped;
KIRQL kirql;
//改变内存属性。
g_pmdl = IoAllocateMdl(Destination, sizeof(opcode), 0, 0, NULL);
if(!g_pmdl) {
return status;
}
MmBuildMdlForNonPagedPool(g_pmdl);
Mapped = (unsigned int *)MmMapLockedPages(g_pmdl, KernelMode); //建议使用MmMapLockedPagesSpecifyCache。
if (Mapped == NULL) {
return status;
}
kirql = KeRaiseIrqlToDpcLevel();
RtlCopyMemory(Mapped,/*&*/Source,Length);//运行此行前后可以用u nt!ZwOpenProcess看看达到效果没有.
KeLowerIrql(kirql);
//恢复内存属性.
if(g_pmdl) {
MmUnmapLockedPages((PVOID)Mapped, g_pmdl);
IoFreeMdl(g_pmdl);
}
return status;
}
NTSTATUS
MyZwCreateSection(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
//也可以通过bu nt!ZwOpenProcess,看看在那里是否跳转到这里.
KdBreakPoint();//DbgBreakPoint()
//这是一个示例:打印一个消息,然后原路返回,没有过滤.
KdPrint(("i am in MyZwCreateSection!\n"));
SuperRtlCopyMemory(g_pfn,g_original,sizeof(opcode));
//疑问是在两个SuperRtlCopyMemory函数的调用之间,再发生ZwCreateSection调用,估计是拦截不到的.
status = ZwCreateSection(SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, SectionPageProtection, AllocationAttributes, FileHandle);
SuperRtlCopyMemory(g_pfn,&g_op,sizeof(opcode));
//if (0) //如果拒绝
//{
// //直接返回即可,不必进行下一行的复杂操作.注意,这没有测试.
// //设置ZwOpenProcess的sizeof(opcode)+1 = 0xc3,让主函数返回.
//}
//else
//{
// //恢复设置,(加DPC及内存读写),包括:ZwOpenProcess的sizeof(opcode)+1 = 0xc3的恢复.
// //调用原来的函数.//不准别的在调用.这时功能已经完成了.
// //设置hook.(加DPC及内存读写)
//}
return status;
}
NTSTATUS hook(wchar_t * pfn,unsigned __int64 p_my_fn)
{
NTSTATUS status = STATUS_SUCCESS;//STATUS_UNSUCCESSFUL
UNICODE_STRING usfn;
RtlInitUnicodeString( &usfn, pfn);
g_pfn = MmGetSystemRoutineAddress(&usfn);
if (g_pfn == NULL) {
return status;
}
g_op.mov_rax = 0xb848;
g_op.my_fn = MyZwCreateSection;
g_op.push_rax = 0x50;
g_op.retn = 0xc3;//此时可以用 u g_op看看效果.
RtlCopyMemory(g_original,g_pfn,sizeof(opcode));
return SuperRtlCopyMemory(g_pfn,&g_op,sizeof(opcode));
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
SuperRtlCopyMemory(g_pfn,g_original,sizeof(opcode));
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
KdBreakPoint();//DbgBreakPoint()
DriverObject->DriverUnload = DriverUnload;
return hook(L"ZwCreateSection",MyZwCreateSection);
}
/*一下是验证效果.
0: kd> u nt!ZwCreateSection
nt!ZwCreateSection:
fffff800`016c3a60 488bc4 mov rax,rsp
fffff800`016c3a63 fa cli
fffff800`016c3a64 4883ec10 sub rsp,10h
fffff800`016c3a68 50 push rax
fffff800`016c3a69 9c pushfq
fffff800`016c3a6a 6a10 push 10h
fffff800`016c3a6c 488d055d290000 lea rax,[nt!KiServiceLinkage (fffff800`016c63d0)]
fffff800`016c3a73 50 push rax
0: kd> p
test!write_memory+0x8d:
fffff880`049a029d 0fb64c2430 movzx ecx,byte ptr [rsp+30h]
0: kd> u nt!ZwCreateSection
nt!ZwCreateSection:
fffff800`016c3a60 48b840019a0480f8ffff mov rax,offset test!MyZwCreateSection (fffff880`049a0140)
fffff800`016c3a6a 50 push rax
fffff800`016c3a6b c3 ret
fffff800`016c3a6c 488d055d290000 lea rax,[nt!KiServiceLinkage (fffff800`016c63d0)]
fffff800`016c3a73 50 push rax
fffff800`016c3a74 b847000000 mov eax,47h
fffff800`016c3a79 e982600000 jmp nt!KiServiceInternal (fffff800`016c9b00)
fffff800`016c3a7e 6690 xchg ax,ax
依旧出现:
BugCheck 109
Fatal System Error: 0x00000109
nt!FsRtlPrivateInsertSharedLock
*/
没有评论:
发表评论