/*
感谢QQ群:《windbg调试,dump分析》 里面的 虾米在养虾 提供的思路。
虽然有硬编码,但是我觉得通用。
其实我也想过这个办法,觉得麻烦,其实做起来挺简单的。
其实我追求更好,其实只要能完成功能就可以了。
先思路,再手动实现,最后编码实现,计算机的运行速度还是挺快的。
made by correy
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
#ifdef _X86_
int modify_driver_32(PVOID ImageBase) //她奶奶的,不能用bool和true.
{
//此时驱动已经加载,但还没有运行。
//做法是在驱动的入口填写c20800即ret 8。注释不是:retn的机器码c3.
//不必要再写mov eax,STATUS_UNSUCCESSFUL的机器码了。#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
//wdk编译的驱动入口是添加的,非真正的入口,汇编写的驱动入口才是真正的入口,这里的入口是pe文件的入口和DriverEntry的关系。
//B8 01 00 00 C0 mov eax, 0C0000001h
//c20800 ret 8
unsigned char opcode[] = {0xB8,0x01,0x00,0x00,0xC0,0xc2,0x08,0x00};
int pe;//pe的偏移。
int oep;
unsigned int x;
pe = *(unsigned int *)((unsigned int)ImageBase + 0x3c);
oep = *(unsigned int *)((unsigned int)ImageBase + pe + 4 + 20 + 16);
x = oep;
x += (unsigned int)ImageBase;//奶奶的,必须加这两行,直接用好像不行。
RtlCopyMemory((unsigned int *)x,opcode,8);
return 1;
}
#endif
#if defined(_AMD64_) || defined(_IA64_) //defined(_WIN64_)
int modify_driver_64(PVOID ImageBase)
{
//做法是在驱动的入口填写retn的机器码c3.
//B8 01 00 00 C0 mov eax, 0C0000001h
//c3 retn
unsigned char opcode[] = {0xB8,0x01,0x00,0x00,0xC0,0xc3};
int pe;//pe的偏移。
int oep;
ULONG64 x;
pe = *(int *)((ULONG64)ImageBase + 0x3c);
oep = *(int *)((ULONG64)ImageBase + pe + 4 + 20 + 16);
//x = (ULONG64 *)ImageBase + oep;//这一行总会把oep*8,所以用下面的两行替换。
x = oep;
x += (ULONG64)ImageBase;
RtlCopyMemory((ULONG64 *)x,opcode,6);//其实直接赋值也可以。
return 1;//true
}
#endif
VOID MY_PLOAD_IMAGE_NOTIFY_ROUTINE(__in_opt PUNICODE_STRING FullImageName, __in HANDLE ProcessId, __in PIMAGE_INFO ImageInfo)
{
NTSTATUS r;
int n,len;
wchar_t sysname[] = L"sys.sys";
UNICODE_STRING u1,u2;
int b = 0;
HANDLE hcp;
hcp = PsGetCurrentProcessId();//如果是驱动模块,ProcessId总为0,这可能是错误的。
//其实这里也可以把进程给结束了。
len = wcslen(sysname) * sizeof(wchar_t);
n = (FullImageName->Length - len)/sizeof(wchar_t);
//如果加载的驱动是:sys.sys,就调用ZwUnmapViewOfSection
RtlInitUnicodeString(&u1,sysname);
RtlInitUnicodeString(&u2,&FullImageName->Buffer[n]);
b = RtlEqualUnicodeString(&u1,&u2,1);
if (b) //判断条件不一定准确。其实也可以写一个函数。
{
#ifdef _X86_
modify_driver_32(ImageInfo->ImageBase);
#endif
#if defined(_AMD64_) || defined(_IA64_) //defined(_WIN64_)
modify_driver_64(ImageInfo->ImageBase);
#endif
}
}
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
PsRemoveLoadImageNotifyRoutine(MY_PLOAD_IMAGE_NOTIFY_ROUTINE);
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
//KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = Unload;
status = PsSetLoadImageNotifyRoutine(MY_PLOAD_IMAGE_NOTIFY_ROUTINE);
return status;
}
//made 2013.02.17
//一下有改进,但是没有测试。
#include <ntddk.h>
#ifdef _X86_
int modify_driver_32(PVOID ImageBase) //她奶奶的,不能用bool和true.
{
//此时驱动已经加载,但还没有运行。
//做法是在驱动的入口填写c20800即ret 8。注释不是:retn的机器码c3.
//不必要再写mov eax,STATUS_UNSUCCESSFUL的机器码了。#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
//wdk编译的驱动入口是添加的,非真正的入口,汇编写的驱动入口才是真正的入口,这里的入口是pe文件的入口和DriverEntry的关系。
//B8 01 00 00 C0 mov eax, 0C0000001h
//c20800 ret 8
unsigned char opcode[] = {0xB8,0x01,0x00,0x00,0xC0,0xc2,0x08,0x00};
int pe;//pe的偏移。
int oep;
unsigned int x;
pe = *(unsigned int *)((unsigned int)ImageBase + 0x3c);
oep = *(unsigned int *)((unsigned int)ImageBase + pe + 4 + 20 + 16);
x = oep;
x += (unsigned int)ImageBase;//奶奶的,必须加这两行,直接用好像不行。
RtlCopyMemory((unsigned int *)x,opcode,8);
return 1;
}
#endif
#if defined(_AMD64_) || defined(_IA64_) //defined(_WIN64_)
int modify_driver_64(PVOID ImageBase)
{
//做法是在驱动的入口填写retn的机器码c3.
//B8 01 00 00 C0 mov eax, 0C0000001h
//c3 retn
unsigned char opcode[] = {0xB8,0x01,0x00,0x00,0xC0,0xc3};
int pe;//pe的偏移。
int oep;
ULONG64 x;
pe = *(int *)((ULONG64)ImageBase + 0x3c);
oep = *(int *)((ULONG64)ImageBase + pe + 4 + 20 + 16);
//x = (ULONG64 *)ImageBase + oep;//这一行总会把oep*8,所以用下面的两行替换。
x = oep;
x += (ULONG64)ImageBase;
RtlCopyMemory((ULONG64 *)x,opcode,6);//其实直接赋值也可以。
return 1;//true
}
#endif
int IsMyfilter(__in_opt PUNICODE_STRING FullImageName)
{
NTSTATUS r;
int n,len;
wchar_t sysname[] = L"sys.sys";
UNICODE_STRING u1,u2;
int b = 0;
HANDLE hcp;
hcp = PsGetCurrentProcessId();//如果是驱动模块,这个值大多为system的pid.
len = wcslen(sysname) * sizeof(wchar_t);
n = (FullImageName->Length - len)/sizeof(wchar_t);
RtlInitUnicodeString(&u1,sysname);
RtlInitUnicodeString(&u2,&FullImageName->Buffer[n]);
return RtlEqualUnicodeString(&u1,&u2,1);
}
VOID MY_PLOAD_IMAGE_NOTIFY_ROUTINE(__in_opt PUNICODE_STRING FullImageName, __in HANDLE ProcessId, __in PIMAGE_INFO ImageInfo)
{
int b = 0;
if (ProcessId == 0) //如果监控的是驱动,加上这一句,计算机会运行快一些,因为自己发现:如果是驱动模块,ProcessId总为0
{
b = IsMyfilter(FullImageName);
if (b) //判断条件不一定准确。其实也可以写一个函数。
{
#ifdef _X86_
modify_driver_32(ImageInfo->ImageBase);
#endif
#if defined(_AMD64_) || defined(_IA64_) //defined(_WIN64_)
modify_driver_64(ImageInfo->ImageBase);
#endif
}
}
}
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
PsRemoveLoadImageNotifyRoutine(MY_PLOAD_IMAGE_NOTIFY_ROUTINE);
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
//KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = Unload;
status = PsSetLoadImageNotifyRoutine(MY_PLOAD_IMAGE_NOTIFY_ROUTINE);
return status;
}
2013年2月17日星期日
PsSetLoadImageNotifyRoutine2.c
2013年2月7日星期四
PsSetLoadImageNotifyRoutine.C
#include <ntddk.h>
VOID MY_PLOAD_IMAGE_NOTIFY_ROUTINE(__in_opt PUNICODE_STRING FullImageName, __in HANDLE ProcessId, __in PIMAGE_INFO ImageInfo)
{
NTSTATUS r;
int n,len;
wchar_t sysname[] = L"sys.sys";
UNICODE_STRING u1,u2;
int b = 0;
HANDLE hcp;
hcp = PsGetCurrentProcessId();//如果是驱动模块,ProcessId总为0,这可能是错误的。
//其实这里也可以把进程给结束了。
len = wcslen(sysname) * sizeof(wchar_t);
n = (FullImageName->Length - len)/sizeof(wchar_t);
//如果加载的驱动是:sys.sys,就调用ZwUnmapViewOfSection
RtlInitUnicodeString(&u1,sysname);
RtlInitUnicodeString(&u2,&FullImageName->Buffer[n]);
b = RtlEqualUnicodeString(&u1,&u2,1);
if (b)
{
//Note If the call to this function occurs in user mode, you should use the name "NtUnmapViewOfSection" instead of "ZwUnmapViewOfSection".
r = ZwUnmapViewOfSection(ProcessId,ImageInfo->ImageBase); //得到的结论是不能卸载驱动,断言只能卸载dll.
if (r == STATUS_ACCESS_DENIED )
{
DbgPrint("The caller does not have access rights to the process object or to the base virtual address of the view.");
}
//RtlZeroMemory(ImageInfo->ImageBase,ImageInfo->ImageSize);//这个蓝屏,难道要锁定内存。
//更深入的函数有:IopDeleteDriver等。
}
//如果阻止驱动加载呢?难道必须用hook?
}
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
PsRemoveLoadImageNotifyRoutine(MY_PLOAD_IMAGE_NOTIFY_ROUTINE);
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = Unload;
status = PsSetLoadImageNotifyRoutine(MY_PLOAD_IMAGE_NOTIFY_ROUTINE);
return status;
}
//made 2013.02.07
订阅:
博文 (Atom)