;eax As Save Routine Call Parameter
;Value Of eax Come Stack
;The Is Once Value Copy To Current Stack Top
push eax;
;cr0 Is What
;Value Of cr0 To eax For Save
;Pass Over eax Value
mov eax,cr0;
;uAttr Is ULONG Type Variable
;Value Of eax To uAttr For Save
;The Is Once Value Copy
mov uAttr,eax;
;CR0 16 BIT =ro
;eax=eax&&0fffeffffh
;The Is What
and eax,0FFFEFFFFh;
;Value Of eax To cr0 Save
;The Is Once Value Copy
mov cr0,eax;
;Current Stack Top Value To eax Save
pop eax;
;IF Flag Bit Zero
;The Code Change IF Flag Bit Is Zero
cli
};
//g_uCr0 Is a 全局 Variable
//g_uCr0 Type Is ULONG
//uAttr Is Current Routine Local Variable
//uAttr Type Is ULONG
//g_uCr0 In Current Routine Be Initialize Zero
//uAttr Save Is What
g_uCr0=uAttr;
}
//The Routine Not Return Value
//The Routine Is What
VOID WPON()
{
//Routine Body
//Implant Asm Code
__asm
{
;The Is Asm Code
;The Code 使 If Flag Bit 为 1
;The Is a CUP Control Code
sti
;eax As Save Function Call Parameter
;Value Of eax Come Stack Pass Push
;The Is a Value Copy To Stack Top
push eax;
;g_uCr0 Is 全局 Variable
;g_uCr0 Value To eax Save
mov eax,g_uCr0;
;eax Value To cr0 Save
;cr0 Is What
mov cr0,eax;
;Current Stack Top Value To eax Save
;Pass Current esp
pop eax;
};
}
//In The Routine Complete Irp
//The Routine 直接 Commplete Irp
//然后 Return a STATUS_SUCCESS
NTSTATUS PatchCommonDispatch(
//Irp Send To a DeviceObject
//p == Pointer
//The Is Kernel Structure
PDEVICE_OBJECT DeviceObject,
//Irp Of Current Receive
//Irp == I/O Request Pack
//p == Pointer
PIRP Irp
)
{
//Set Irp Member
Irp->IoStatus.Status=STATUS_SUCCESS; //Set The Irp Complete
Irp->IoStatus.Information=0;
//指定The Irp已经Complete
//已经Complete的Irp将Return To I/O Manager
//也就是说现在要把这个Irp返回到I/O管理器了,所有的处理已经完成了.
//The Routine Not Return Value
IoCompleteRequest(
//The Is Current Irp
//Irp Of 等待被Complete
//The Parameter From Current Caller
Irp,
//Add优先级
IO_NO_INCREMENT
);
return STATUS_SUCCESS; //Return Success To Caller
}
//Get Kernel Function Address Of Function Name
//Current Routine Return a void Type Pointer To Caller
PVOID GetKernelFuncAddr(
//Function Name From Caller
//Find Function Address Of The Parameter
PCHAR func_name
)
{
//Function Body
//String For Ansi Version
//ANSI_STRING Is a Structure
//Source Structure Name 一般都有一个_前缀,表示是一个原始结构被struct声明
//被typedef定义之后一般有2个类型,一个是普通无_前缀版本,另一个是p前缀版本,表示已个Pointer
//ANSI_STRING Member含义与UNICODE_STRING相同
//ANSI_STRING And UNICODE_STRING DataType As Is PCHAR
ANSI_STRING ansi_name;
//The Is UNICODE_STRING Structure
UNICODE_STRING uni_name;
PVOID func_addr; //Function Address be Save In a Pointer
//Initialize String Of Function Name
//func_name From Current Caller
//Finally String To ansi_name
RtlInitString(&ansi_name,func_name);
//AnsiString ConvertTo UnicodeString
//Current Function Receive Parameter Is Function Name Send To uni_name
//第三个参数为true将为uni_name Allocate Memory Space
//uni_name Not Allocate Memory Space
RtlAnsiStringToUnicodeString(&uni_name,&ansi_name,TRUE);
//func_addr Is PVOID Type
//The Kernel Routine Return a Function Pointer Of Function Name
//Function Name From Current Routine Receive Parameter
//The Routine Call 实现了 Current Function的关键功能
//Return Function Address To func_addr
func_addr=MmGetSystemRoutineAddress(&uni_name);
//The Routine Free a Unicode String Of Receive Parameter
RtlFreeUnicodeString(&uni_name);
//Return By The Function Get Address To Caller
return func_addr;
}
//The Routine 对比 func_addr And startbytes 是否相同 Length len
BOOLEAN IfDirty(
//The Is Function Address
//Type Is Void *
//The Parameter From Caller
PVOID func_addr,
//Pointer To Char
//startbytes Is What
CHAR *startbytes,
//The Is Length
int len
)
{
//Current Routine Body
//Current Routine Receive Parameter Save To addr
PCHAR addr=(PCHAR)func_addr;
int i;
//Loop Structure
for(i=0;i<len;++i)
{
//Loop Body
//Function Address Save In addr
//判断addr Array And startbytes Array是否相同
if(addr[i]!=startbytes[i])
return TRUE;
else
continue; //Continue Loop
}
return FALSE;
}
//__declspec(naked) Is What Type
//The Routine Get DeviceObject Pointer
//The Routine Return a __declsped(naked) Type Value To Caller
__declspec(naked) NewStubForIoGetDeviceObjectPointer()
{
//Routine Body
//Pointer To Unicode String Structure
//The Is Object Name
//UNICODE_STRING Is a Kernel Structure
PUNICODE_STRING ObjectName;
//DbgPrint 被 Convert 为 DWORD Type And Save In edi
//DbgPrint Is What
_asm mov edi,DWORD PTR DbgPrint
//
_asm mov MyDbgPrint,edi
//MyDbgPrint("object name %ws\n", ObjectName->Buffer);
//_asm add esp, 8
//Compare UnicodeString
//RtlCompareUnicodeString Routine Return 0 Value 表示相等
//UNICODE_STRING Is a Kernel Structure
if(RtlCompareUnicodeString((PUNICODE_STRING)ObjectName,&ObjPtrName,TRUE)==0)
{
_asm
{
mov esp,ebp
pop ebp
mov eax,0xC000000D
ret 10h
}
}
__asm
{
mov esp,ebp
pop ebp
//must declare this tag for insert orginal function's starting bytes here
_emit 0xaa
_emit 0xaa
_emit 0xaa
_emit 0xaa
}
}
//The Routine Is What
//The Routine Return int To Caller
//The Routine Get Length To Caller
//Get Routine Length Pass Function Address And
int GetPatchLength(
//Pointer Char
//Function Start Address
//The Parameter Is IoGetDeviceObjectPointer
PCHAR func_start,
//Maximum Length
//The Parameter Is Number 7
int max_need_len
)
{
//Routine Body
//op == opcode
//opcode Length
int one_oplen=0;
int actual_oplen=0;
//The Structure Is Kernel Structure
//The Structure No Is By User Define
//The Is What Structure
struct disasm_struct dis;
//Loop Structure
//actual_oplen By Current Routine Define
//max_need_len From Caller
//Current Parameter max_need_len Is Number 7
//Loop 从0到6
while(actual_oplen<max_need_len)
{
//Loop Body
//ade32_disasm Function From ade32.h
one_oplen=ade32_disasm(func_start,&dis);
func_start+=one_oplen;
actual_oplen+=one_oplen;
}
return actual_oplen; //Return opcode Length To Caller
}
//PPATCH_INFO Is Pointer To patch_into Structure
//The Routine Return a BOOLEAN Type Value To Caller
BOOLEAN UnpatchX(PPATCH_INFO pach)
{
//Routine Body
//The Is What
if(pach->patch_len&&pach->org_func_addr)
{
//Copy Memory Black By The Kernel Routine
//From patch_info Structure
RtlCopyMemory(pach->org_func_addr,pach->org_bytes,pach->patch_len);
return TRUE;
}
return FALSE;
}
//typedef unsigned short int BOOOLEAN
BOOLEAN PatchX(
//PCHAR == Pointer To Char
//The Parameter Is Function Name
PCHAR func_name,
//PVOID == void*
//The Parameter Is New Function
PVOID new_func,
//The Parameter Is New Function Length
int new_func_len,
//The Parameter Is UserDefine Structure
//Pointer To patch_info Structure
PPATCH_INFO pach
)
{
//Routine Body
int i;
BOOLEAN bFoundTag=FALSE; //BOOLEAN Type 可以表示2个值 true or false
WPOFF(); //Call The Function
//get original function address In GetKernelFuncAddr Routine Return Value
//Parameter Is Current Receive Function Name
//Return Value Save In pach_info Structure
//Of Function Name Return a Function Address
pach->org_func_addr=GetKernelFuncAddr(func_name);
//判断Get Address 是否 Success
//Kernel Function Address Pass MmGetSystemRoutineAddress Get
if(pach->org_func_addr)
{
//Call The User Define Routine Get Length To pach->patch_len
//Of pach->org_func_addr And Number 7 Get Thr Routine Return Value
pach->patch_len=GetPatchLength(pach->org_func_addr,7);
//Return a Pool Memory To pach->new_func_addr
//The Routine Return Type Is PVOID
pach->new_func_addr=(PVOID)ExAllocatePoolWithTag(
NonPagedPool,
new_func_len,
'kdD'
);
if(pach->new_func_addr)
{
//In The Hook ?
RtlCopyMemory(pach->new_func_addr,new_func,new_func_len);
//找到啦
if(bFoundTag)
{
//save original function's starting bytes for later Unpatch
RtlCopyMemory(pach->org_bytes,pach->org_func_addr,pach->patch_len);
//modify new_func to jmp to original function
RtlCopyMemory((BYTE *)pach->new_func_addr+i,pach->org_func_addr,pach->patch_len);
((BYTE *)pach->new_func_addr+i+pach->patch_len)[0]=0xea;
*(ULONG *)((BYTE *)pach->new_func_addr+i+pach->patch_len+1)=(ULONG)pach->org_func_addr+pach->patch_len;
*(USHORT *)((BYTE *)pach->new_func_addr+i+pach->patch_len+5)=KERNEL_SEG;
//modify original function to jmp to new_func first
((BYTE *)pach->org_func_addr)[0]=0xea;
*(ULONG *)((BYTE *)pach->org_func_addr+1)=(ULONG)pach->new_func_addr;
*(USHORT *)((BYTE *)pach->org_func_addr+5)=KERNEL_SEG;
return TRUE;
}
else
{
ExFreePool(pach->new_func_addr);
pach->new_func_addr=NULL;
}
}
}
WPON(); //Call The Function
return FALSE;
}
//PatchDeviceControl Routine处理Irp
//The tPatchDeviceControl Routine Is What
//NTSTATUS Is a 32Bit Value
//By FinallyCode And ErrorCode 组成
//FinallyCode And ErrorCode各占32Bit的部分
//IO_ERR_XXX 为ErrorCode
//STATUS_XXX 为FinallyStatus
NTSTATUS
tPatchDeviceControl(
//Parameter About Current Routine
PDEVICE_OBJECT DeviceObject, //DeviceObject Of Irp Send
PIRP Irp //Irp Of Current Routine Receiver
)
{
//Routine Body
//Get Current Irp In Stack Location
PIO_STACK_LOCATION irpSp=IoGetCurrentIrpStackLocation(Irp);
WCHAR *DeviceName=L"\\Device\\Harddisk0\\DR0"; //The Is Harddisk Device
UNICODE_STRING uni_name; //UNICODE_STRING Is a Structure
PDEVICE_OBJECT TempDeviceObject; //The Is DeviceObject
//FILE_OBJECT Is a KernelMode DataStructure
//FILE_OBJECT 代表一个已经打开的文件或目录
//Pass FILE_OBJECT Can Get DEVICE_OBJECT
PFILE_OBJECT TempFileObject;
NTSTATUS status; //NTSTATUS Is a 32Bit Int
PATCH_INFO pach; //PATCH_INFO Is a User-Defined Structure
//多分支选择
//WinDbg应该可以看到内核结构,可惜现在我还不会用...
//我猜测一下PIO_STACK_LOCATION...
//irpSp Is PIO_STACK_LOCATION Type
switch(irpSp->Parameters.DeviceIoControl.IoControlCode) //判断Irp的ControlCode
{
case 1:
//Pass 0 Fill Memory Block
//Fill PATCH_INFO Structure
RtlZeroMemory(
&pach, //Start Fill Address
sizeof(PATCH_INFO) //Fill Length
);
//Call The Routine
PatchX("IoGetDeviceObjectPointer",NewStubForIoGetDeviceObjectPointer,256,&pach);
//Initialize UnicodeString To uni_name Of DeviceName
//From WCHAR To UnicodeString
RtlInitUnicodeString(&uni_name,DeviceName);
//Return DeviceObject Pointer To status
//
status=IoGetDeviceObjectPointer(
//Device Is Harddisk
//DeviceObject Name
//Type Is UNICODE_STRING
&uni_name,
//DeviceObject Pointer In The Out Parameter
//DeviceObject Pointer
&TempDeviceObject
);
//Un(&pach);
//status=IoGetDeviceObjectPointer(&uni_name,FILE_READ_DATA,&TempFileObject,&TempDeviceObject);
break;
}
return PatchCommonDispatch(DeviceObject,Irp); //ReturnValue From The Routine
}
//The Function Unload Current Driver
//The Routine Not Return Value
//The Routine Return a Void Value To Caller
//The Routine In Current Be Unload Time Call
void PatchUnload(
//The Parameter Is Pointer DRIVER_OBJECT Structure
//DriverObject 代表 Current Driver Program
PDRIVER_OBJECT DriverObject
)
{
//Routine Body
//UNICODE_STRING Is a Kernel Structure
//The Is a Symbolic Link
UNICODE_STRING uni_symbolic;
//The Routine Call Remove Current DeviceObject
//The Routine Not Return Value
//DriverObject->DeviceObject For Delete
//DeviceObject In DriverObject Get
IoDeleteDevice(DriverObject->DeviceObject);
//Initialize a Unicode String Pass The Routine Call
//Set Symbolic Link Pass The Routine Call
RtlInitUnicodeString(
//Pointer To a Memory Buffer For Initialize Unicode String
//The Paramter Is Local Variable
//Save Symbolic Link
&uni_symbolic,
//Source Unicode String
//The Is Symbolic Link
//Pointer To Zero End String For Initialize
L"\\DosDevices\\doptr"
);
//Remove a Symbolic Link Pass The Routine Call
//The Routine Return a NTSTATUS Type Value To Caller
IoDeleteSymbolicLink(&uni_symbolic);
}
//Driver EntryPoint
//Driver Load之后First Call Function
//The Function负责Initialize Current Driver
NTSTATUS //The Type Is 32Bit int,被typedef,表示ErrorCode Or FinallyState
DriverEntry(
//The Parameter By Caller提供,Is a Driver_Object Structure Pointer
//Driver_Object代表Current Driver
//Driver_Object Is a DriverImage
//Driver_Object 的 Poiner被作为InputParameter传递到DriverEntry,为First Parameter
//Initialize Driver By a Driver_Object来完成
PDRIVER_OBJECT DriverObject, //Type的前缀P代表是Poiner,之后是用处的描述
//The UnicodeString表示Current Driver的Path
//P代表Poiner,可以被理解为Poiner To UnicodeString
PUNICODE_STRING RegistryPath
)
{
//Function Body
//DEVICE_OBJECT代表一个设备
//Input/Output Request将Send To The DEVICE_OBJECT
//每个Driver Must Create a DEVICE_OBJECT
//通过DEVICE_OBJECT可以Get DRIVER_OBJECT,也可以通过DRIVER_OBJECT Get DEVICE_OBJECT
//通过DEVICE_OBJECT可以Get Current PIRP
PDEVICE_OBJECT DeviceObject; //Pointer To a DEVICE_OBJECT Structure
//W==WideChar
//L前缀表示后面的String Is a UnicodeString
WCHAR *DeviceName=L"\\Device\\doptr"; //Set The Device Name,doptr Is What Device
WCHAR *SymbolicName=L"\\DosDevices\\doptr"; //Set The Device SymbolicName
//UNICODE_STRING Is a Structure
//Source Structure:
//struct _UNICODE_STRING{
// Length //Current String Length
// MaximumLength //Buffer Length
// Buffer}
UNICODE_STRING uni_name,uni_symbolic; //声明Name And Symbolic
NTSTATUS status; //The 表示 Current Driver Run State
int i;
//Initialize a Unicode String
//The Function Not Return Value
//Parameter1: Pointer To a Buffer For Save UnicodeString
//Parameter2: Pointer To a Zero End String
RtlInitUnicodeString(
&ObjPtrName, //The Is 全局变量 Length Member 被赋值为0
L"\\Device\\Harddisk0\\DR0" //The Is Default Harddisk Device Path
);
RtlInitUnicodeString(&uni_name,DeviceName); //Initialize DeviceName To uni_name Buffer
//Loop Body
//IRP_MJ_MAXIMUM_FUNCTION 表示irp的最大数量
//Loop And Find 每一个Irp
for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;++i)
DriverObject->MajorFunction[i]=PatchCommonDispatch; //All Irp By The Routine 处理
//MajorFunction Array Save Pointer To DispatchFunction
//Irp==InputOutput Request Pack
//Driver 中的 Device_Object将Receive特定Type的Request
//IOCTL == InputOutput Control Code
//Driver Pass Request Control Device
//Driver是否能够处理Request,要看所绑定的Device Type
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=PatchDeviceControl; //Set Dispatch Function
DriverObject->DriverUnload=PatchUnload; //Set Driver Unload Function
//Create And Initialize Device Object
//status Is NTSTATUS Type
//Allocate Memory For a Device_Object And Initialize The Device_Object
status=IoCreateDevice(
0
//Pointer To DriverObject Structure By DriverEntry Routine Get,In System Call Current Driver
DriverObject,
//The Parameter 指定Byte Number Of Device的扩展Size
0,
//a Pointer To UnicodeString Is The DeviceName
&uni_name,
//The Is DeviceType,The Parameter By SystemDefine Constant指定
0,
//To The Device Add More Info
0,
//The Device 是否是HighLevel的
FALSE,
//If The Function Call Success 将 Return DeviceObject To The Parameter
&DeviceObject
);
//判断Device是否被Success Create
if(NT_SUCCESS(status))
{
//To Kernel Send a String
//DbgPrint Return a ULONG Value
//First Parameter Is a Format String
//可以In DbgPrint Function中使用printf Function的FormatString
//第二个Parameter Is 被Print的String
//DbgPrint Routine Call Success Return STATUS_SUCCESS,否则Return ErrorCode
DbgPrint("%ws\n",SymbolicName); //Output Device Symbolic Name
//Initialize UnicodeString Of SymbolicName To uni_symbolic
RtlInitUnicodeString(&uni_symbolic,SymbolicName);
//For The Device Create a SymbolicLink
//The Routine Call Success Return NTSTATUS_SUCCESS
status=IoCreateSymbolicLink(
&uni_symbolic, //The Is Symbolic Name
&uni_name //Current Create 的 DeviceObject的Name
);
}
//If Current Function Success则Return STATUS_SUCCESS
//否则Return a 相关的ErrorStatus,ErrorStatus被Define In ntstatus.h
return status; //最后一次To status 赋值Is In IoCreateSymbolicLink Routine
}