Anthor:shdaianita
The project is simpler and refer to master-hand's code to practise oneself.While that is simpler,Novice is be suggest practice much.
The code:
NTSTATUS
DriverEntry(
PDRIVER_OBJECT pDriverObj,
PUNICODE_STRING pRegistryString
)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING ustrLinkName;
UNICODE_STRING ustrDevName;
PDEVICE_OBJECT pDevObj;
//HardCode For Searching……
ULONG Addr_KiInsertQueueApc=0;
CHAR FindCode[1][5]={
{0xe8,0x4b,0x2b,0x00,0x00}
};
KdPrint(("==>DriverEntry\n"));
pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
pDriverObj->DriverUnload = DriverUnload;
RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
status = IoCreateDevice(pDriverObj,
0,
&ustrDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&pDevObj);
if(!NT_SUCCESS(status)) {
return status;
}
RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
if(!NT_SUCCESS(status)) {
IoDeleteDevice(pDevObj);
return status;
}
//
// 添加执行代码
//
KdPrint(("Search ……\n"));
OrigfnAddr.KiInsertQueueApc=GetTargetFnAddrFromExportedFn(FindCode[0],L"KeInsertQueueApc",100,0x2b4b);
if (OrigfnAddr.KiInsertQueueApc!=0)
{
KdPrint(("We find it!Address of KiInsertQueueApc: 0x%08x\n",OrigfnAddr.KiInsertQueueApc));
}
else
{
KdPrint(("Not Find~ \n"));
return STATUS_UNSUCCESSFUL;
}
status=InlineHook(OrigfnAddr.KiInsertQueueApc,(ULONG)fake_KiInsertQueueApc,(ULONG)Proxy_KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc); //进行inlineHook
if (!NT_SUCCESS(status))
{
return status;
}
KdPrint(("<==DriverEntry\n"));
return status;
}
VOID
DriverUnload(
PDRIVER_OBJECT pDriverObj
)
{
UNICODE_STRING strLink;
NTSTATUS status;
RtlInitUnicodeString(&strLink, LINK_NAME);
//
// add unload's code
//
status=UnHook(OrigfnAddr.KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc);
if (!NT_SUCCESS(status))
{
KdPrint(("DriverUnload!UnHook Failre~"));
}
IoDeleteSymbolicLink(&strLink);
IoDeleteDevice(pDriverObj->DeviceObject);
KdPrint(("==>DriverUnload\n"));
}
DriverEntry(
PDRIVER_OBJECT pDriverObj,
PUNICODE_STRING pRegistryString
)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING ustrLinkName;
UNICODE_STRING ustrDevName;
PDEVICE_OBJECT pDevObj;
//HardCode For Searching……
ULONG Addr_KiInsertQueueApc=0;
CHAR FindCode[1][5]={
{0xe8,0x4b,0x2b,0x00,0x00}
};
KdPrint(("==>DriverEntry\n"));
pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
pDriverObj->DriverUnload = DriverUnload;
RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
status = IoCreateDevice(pDriverObj,
0,
&ustrDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&pDevObj);
if(!NT_SUCCESS(status)) {
return status;
}
RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
if(!NT_SUCCESS(status)) {
IoDeleteDevice(pDevObj);
return status;
}
//
// 添加执行代码
//
KdPrint(("Search ……\n"));
OrigfnAddr.KiInsertQueueApc=GetTargetFnAddrFromExportedFn(FindCode[0],L"KeInsertQueueApc",100,0x2b4b);
if (OrigfnAddr.KiInsertQueueApc!=0)
{
KdPrint(("We find it!Address of KiInsertQueueApc: 0x%08x\n",OrigfnAddr.KiInsertQueueApc));
}
else
{
KdPrint(("Not Find~ \n"));
return STATUS_UNSUCCESSFUL;
}
status=InlineHook(OrigfnAddr.KiInsertQueueApc,(ULONG)fake_KiInsertQueueApc,(ULONG)Proxy_KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc); //进行inlineHook
if (!NT_SUCCESS(status))
{
return status;
}
KdPrint(("<==DriverEntry\n"));
return status;
}
VOID
DriverUnload(
PDRIVER_OBJECT pDriverObj
)
{
UNICODE_STRING strLink;
NTSTATUS status;
RtlInitUnicodeString(&strLink, LINK_NAME);
//
// add unload's code
//
status=UnHook(OrigfnAddr.KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc);
if (!NT_SUCCESS(status))
{
KdPrint(("DriverUnload!UnHook Failre~"));
}
IoDeleteSymbolicLink(&strLink);
IoDeleteDevice(pDriverObj->DeviceObject);
KdPrint(("==>DriverUnload\n"));
}
Next codes realize hooking:
//WriteProtect OFF/ON By MDL!
PVOID WPOFFByMdl(PVOID VirtualAddr,ULONG uLen,PMDL pMDL)
{
PVOID MVA=NULL; //system-base VA maps physical pages that MDL describes
pMDL=IoAllocateMdl(VirtualAddr,uLen,FALSE,FALSE,NULL);
if (pMDL==NULL)
{
KdPrint(("WPOFF!IoAllocateMdl FAILURE pMdl==NULL\n"));
return NULL;
}
MmBuildMdlForNonPagedPool(pMDL);
_try
{
MmProbeAndLockPages(pMDL,KernelMode,IoModifyAccess);
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
return NULL;
}
pMDL->MdlFlags|=MDL_MAPPED_TO_SYSTEM_VA;
MVA=MmGetSystemAddressForMdlSafe(pMDL,NormalPagePriority);
if (MVA)
{
KdPrint(("MVA : %x",MVA));
}
KdPrint(("WPOFFByMdl Successful"));
return MVA;
}
VOID WPONByMdl(PMDL pMdl)
{
if (pMdl==NULL)
{
return ;
}
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
}
//Write Protect OFF/ON By CR0!
VOID WPOFFByCR0()
{
ULONG uAttr;
_asm
{
push eax;
mov eax, cr0;
mov uAttr, eax;
and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
mov cr0, eax;
pop eax;
cli
};
g_uCr0 = uAttr; //Keep original CRO
}
VOID WPONByCR0()
{
_asm
{
sti
push eax;
mov eax, g_uCr0; //恢原有 CR0 性
mov cr0, eax;
pop eax;
};
}
///////////////////////////////////////////////////////////////////////
//Get the exported function's address
ULONG GetFunctionAddr(PCWSTR FunctionName)
{
UNICODE_STRING uFnName;
RtlInitUnicodeString(&uFnName,FunctionName);
return (ULONG)MmGetSystemRoutineAddress(&uFnName);
}
//Find address of the function that we want to hook
//
//Description:Through known function to find us target function
//
//ARGUMENTs:
//
//FindCode:find target function(want to hook functiong),use hard code
//ExportedFnName:Known function's name
//SearchLen:at Known functions search length
//Offset:relatively jump value
//
ULONG GetTargetFnAddrFromExportedFn(CHAR* FindCode,PCWSTR ExportedFnName,ULONG SearchLen,ULONG Offset)
{
ULONG i=0,j=0;
CHAR * Addr_ExportedFn=NULL;
ULONG TargetFnAddr=0;
Addr_ExportedFn=(CHAR*)GetFunctionAddr(ExportedFnName);
if (Addr_ExportedFn==NULL)
{
KdPrint(("GetTargetFnAddrFromExportedFn!GetFunctionAddr FAILURE\n"));
return 0;
}
for (i=0;i<SearchLen;i++) //搜索用户指定长度的函数字节
{
if (Addr_ExportedFn[i]==FindCode[0])
{
for (j=1;j<sizeof(FindCode);j++)
{
if (Addr_ExportedFn[i+j]==FindCode[j])
{
continue;
}
else
{
break;
}
}
if (j==sizeof(FindCode))
{
TargetFnAddr=(ULONG)&Addr_ExportedFn[i]+Offset+5; //由相对jmp的dword值得到
break;
}
}
}
return TargetFnAddr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//Hook Function
//
NTSTATUS InlineHook(ULONG OrigFnAddr,ULONG FakeFnAddr,ULONG ProxyFnAddr,PVOID OrigHeadCode)
{
KIRQL oldIrql;
BYTE HookCode[5]={0xe9,0x00,0x00,0x00,0x00};
BYTE jmpCode[7]={0xEA,0x00,0x00,0x00,0x00,0x08,0x00};
PVOID MVA=NULL;
if (!OrigFnAddr||!FakeFnAddr||!ProxyFnAddr||!OrigHeadCode)
{
return STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(OrigHeadCode,(BYTE*)OrigFnAddr,5);
*(ULONG*)(HookCode+1)=(ULONG)FakeFnAddr-(ULONG)OrigFnAddr-5;
*(ULONG*)(jmpCode+1)=(ULONG)((BYTE*)OrigFnAddr+0x05);// 不需要相对跳转,这里是长转移
RtlCopyMemory((BYTE*)ProxyFnAddr,(BYTE*)OrigHeadCode,5);
RtlCopyMemory((BYTE*)ProxyFnAddr+5,(BYTE*)jmpCode,7);
/*WPOFFByCR0();*/ //这里是去掉内存写保护,两种方法,我们选择MDL的方法
MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
if (!MVA)
{
KdPrint(("WPOFFByMdl FAILURE~"));
return STATUS_UNSUCCESSFUL;
}
oldIrql=KeRaiseIrqlToDpcLevel();
/*RtlCopyMemory((BYTE*)OrigFnAddr,(BYTE*)HookCode,5);*/ //将要HOOK的函数的函数头前5个字节改写 跳到我们的fake函数里面
RtlCopyMemory((BYTE*)MVA,(BYTE*)HookCode,5);
KeLowerIrql(oldIrql);
/*WPONByCR0();*/
WPONByMdl(MDLs.KiInsertQueueApc); //Recover write-protect
return STATUS_SUCCESS;
}
//
// Stop inline hook
//
NTSTATUS UnHook(ULONG OrigFnAddr,PVOID OrigHeadCode)
{
KIRQL oldIrql;
PVOID MVA=NULL;
if (!OrigFnAddr||!OrigHeadCode)
{
return STATUS_UNSUCCESSFUL;
}
/*WPOFFByCR0();*/
MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
if (!MVA)
{
KdPrint(("WPOFFByMdl FAILURE~"));
return STATUS_UNSUCCESSFUL;
}
oldIrql = KeRaiseIrqlToDpcLevel();
RtlCopyMemory ( (BYTE*)OrigFnAddr, OrigHeadCode, 5 );
KeLowerIrql(oldIrql);
/*WPONByCR0();*/
WPONByMdl(MDLs.KiInsertQueueApc);
return STATUS_SUCCESS;
}
//WriteProtect OFF/ON By MDL!
PVOID WPOFFByMdl(PVOID VirtualAddr,ULONG uLen,PMDL pMDL)
{
PVOID MVA=NULL; //system-base VA maps physical pages that MDL describes
pMDL=IoAllocateMdl(VirtualAddr,uLen,FALSE,FALSE,NULL);
if (pMDL==NULL)
{
KdPrint(("WPOFF!IoAllocateMdl FAILURE pMdl==NULL\n"));
return NULL;
}
MmBuildMdlForNonPagedPool(pMDL);
_try
{
MmProbeAndLockPages(pMDL,KernelMode,IoModifyAccess);
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
return NULL;
}
pMDL->MdlFlags|=MDL_MAPPED_TO_SYSTEM_VA;
MVA=MmGetSystemAddressForMdlSafe(pMDL,NormalPagePriority);
if (MVA)
{
KdPrint(("MVA : %x",MVA));
}
KdPrint(("WPOFFByMdl Successful"));
return MVA;
}
VOID WPONByMdl(PMDL pMdl)
{
if (pMdl==NULL)
{
return ;
}
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
}
//Write Protect OFF/ON By CR0!
VOID WPOFFByCR0()
{
ULONG uAttr;
_asm
{
push eax;
mov eax, cr0;
mov uAttr, eax;
and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
mov cr0, eax;
pop eax;
cli
};
g_uCr0 = uAttr; //Keep original CRO
}
VOID WPONByCR0()
{
_asm
{
sti
push eax;
mov eax, g_uCr0; //恢原有 CR0 性
mov cr0, eax;
pop eax;
};
}
///////////////////////////////////////////////////////////////////////
//Get the exported function's address
ULONG GetFunctionAddr(PCWSTR FunctionName)
{
UNICODE_STRING uFnName;
RtlInitUnicodeString(&uFnName,FunctionName);
return (ULONG)MmGetSystemRoutineAddress(&uFnName);
}
//Find address of the function that we want to hook
//
//Description:Through known function to find us target function
//
//ARGUMENTs:
//
//FindCode:find target function(want to hook functiong),use hard code
//ExportedFnName:Known function's name
//SearchLen:at Known functions search length
//Offset:relatively jump value
//
ULONG GetTargetFnAddrFromExportedFn(CHAR* FindCode,PCWSTR ExportedFnName,ULONG SearchLen,ULONG Offset)
{
ULONG i=0,j=0;
CHAR * Addr_ExportedFn=NULL;
ULONG TargetFnAddr=0;
Addr_ExportedFn=(CHAR*)GetFunctionAddr(ExportedFnName);
if (Addr_ExportedFn==NULL)
{
KdPrint(("GetTargetFnAddrFromExportedFn!GetFunctionAddr FAILURE\n"));
return 0;
}
for (i=0;i<SearchLen;i++) //搜索用户指定长度的函数字节
{
if (Addr_ExportedFn[i]==FindCode[0])
{
for (j=1;j<sizeof(FindCode);j++)
{
if (Addr_ExportedFn[i+j]==FindCode[j])
{
continue;
}
else
{
break;
}
}
if (j==sizeof(FindCode))
{
TargetFnAddr=(ULONG)&Addr_ExportedFn[i]+Offset+5; //由相对jmp的dword值得到
break;
}
}
}
return TargetFnAddr;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//Hook Function
//
NTSTATUS InlineHook(ULONG OrigFnAddr,ULONG FakeFnAddr,ULONG ProxyFnAddr,PVOID OrigHeadCode)
{
KIRQL oldIrql;
BYTE HookCode[5]={0xe9,0x00,0x00,0x00,0x00};
BYTE jmpCode[7]={0xEA,0x00,0x00,0x00,0x00,0x08,0x00};
PVOID MVA=NULL;
if (!OrigFnAddr||!FakeFnAddr||!ProxyFnAddr||!OrigHeadCode)
{
return STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(OrigHeadCode,(BYTE*)OrigFnAddr,5);
*(ULONG*)(HookCode+1)=(ULONG)FakeFnAddr-(ULONG)OrigFnAddr-5;
*(ULONG*)(jmpCode+1)=(ULONG)((BYTE*)OrigFnAddr+0x05);// 不需要相对跳转,这里是长转移
RtlCopyMemory((BYTE*)ProxyFnAddr,(BYTE*)OrigHeadCode,5);
RtlCopyMemory((BYTE*)ProxyFnAddr+5,(BYTE*)jmpCode,7);
/*WPOFFByCR0();*/ //这里是去掉内存写保护,两种方法,我们选择MDL的方法
MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
if (!MVA)
{
KdPrint(("WPOFFByMdl FAILURE~"));
return STATUS_UNSUCCESSFUL;
}
oldIrql=KeRaiseIrqlToDpcLevel();
/*RtlCopyMemory((BYTE*)OrigFnAddr,(BYTE*)HookCode,5);*/ //将要HOOK的函数的函数头前5个字节改写 跳到我们的fake函数里面
RtlCopyMemory((BYTE*)MVA,(BYTE*)HookCode,5);
KeLowerIrql(oldIrql);
/*WPONByCR0();*/
WPONByMdl(MDLs.KiInsertQueueApc); //Recover write-protect
return STATUS_SUCCESS;
}
//
// Stop inline hook
//
NTSTATUS UnHook(ULONG OrigFnAddr,PVOID OrigHeadCode)
{
KIRQL oldIrql;
PVOID MVA=NULL;
if (!OrigFnAddr||!OrigHeadCode)
{
return STATUS_UNSUCCESSFUL;
}
/*WPOFFByCR0();*/
MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
if (!MVA)
{
KdPrint(("WPOFFByMdl FAILURE~"));
return STATUS_UNSUCCESSFUL;
}
oldIrql = KeRaiseIrqlToDpcLevel();
RtlCopyMemory ( (BYTE*)OrigFnAddr, OrigHeadCode, 5 );
KeLowerIrql(oldIrql);
/*WPONByCR0();*/
WPONByMdl(MDLs.KiInsertQueueApc);
return STATUS_SUCCESS;
}
No comments:
Post a Comment