最近看见论坛很多DELPHI写驱动的教程,小弟学习之余,把自己的学习成果展示出来 与大家一起分享
代码:
unit Driver; interface uses nt_status,ntoskrnl,ntutils; const DeviceName = '\Device\360safeBoxA'; DosDeviceName = '\DosDevices\360safeBoxA'; IOCTL_HOOK_START = $0022E000; IOCTL_HOOK_STOP = $0022E004; IOCTL_PROTECT_PROCESS = $0022E200; IOCTL_PROTECT_HWND = $0022E201; IOCTL_PROTECT_OTHER = $0022E204; var DosDevName: TUnicodeString; TempSafeId:Handle=0; TempSafehandle:Handle=0; function _DriverEntry(pDriverObject: PDriverObject; RegistryPath: PUnicodeString) : NTSTATUS; stdcall; implementation uses hooking; function hookCreate(ADeviceObject: PDeviceObject; AIrp: PIrp): NTSTATUS; stdcall; begin Result := STATUS_SUCCESS; AIrp^.IoStatus.Status := Result; IoCompleteRequest(AIrp, IO_NO_INCREMENT); end; function hookClose(ADeviceObject: PDeviceObject; AIrp: PIrp): NTSTATUS; stdcall; begin Result := STATUS_SUCCESS; AIrp^.IoStatus.Status := Result; IoCompleteRequest(AIrp, IO_NO_INCREMENT); end; function hookDeviceControl(ADeviceObject: PDeviceObject; AIrp:PIrp): NTSTATUS; stdcall; var LStack: PIO_STACK_LOCATION; pIOBuffer: Pointer; LBufInLen, LBufOutLen, LCode, LRet,OutByteCount: ULONG; begin LStack := IoGetCurrentIrpStackLocation(AIrp); Result := STATUS_SUCCESS; AIrp^.IoStatus.Information := 0; LCode := LStack^.Parameters.DeviceIoControl.IoControlCode; pIOBuffer := AIrp^.AssociatedIrp.SystemBuffer; LBufInLen := LStack^.Parameters.DeviceIoControl.InputBufferLength; LBufOutLen := LStack^.Parameters.DeviceIoControl.OutputBufferLength; OutByteCount:=0; case LCode of IOCTL_HOOK_START: begin LRet := HookingHook; OutByteCount:=4; LONG(pIOBuffer^):=LRet; end; IOCTL_HOOK_STOP: begin LRet := HookingUnhook; OutByteCount:=4; LONG(pIOBuffer^):=LRet; end; IOCTL_PROTECT_PROCESS: begin TempSafeId:=Handle(pIOBuffer^); SetSafeId(TempSafeId); OutByteCount:=4; LONG(pIOBuffer^):=Integer(True); end; IOCTL_PROTECT_HWND:begin TempSafehandle:=Handle(pIOBuffer^); SetSafehandle(TempSafehandle); OutByteCount:=4; LONG(pIOBuffer^):=Integer(True); end; IOCTL_PROTECT_OTHER: begin DoPub; OutByteCount:=4; LONG(pIOBuffer^):=Integer(True); end; else Result := STATUS_INVALID_DEVICE_REQUEST; AIrp^.IoStatus.Information := 0; end; AIrp^.IoStatus.Status := Result; AIrp^.IoStatus.Information := OutByteCount; IoCompleteRequest(AIrp, IO_NO_INCREMENT); end; procedure DriverUnload(pDriverObject: PDriverObject); stdcall; begin HookingUnhook; IoDeleteSymbolicLink(@DosDevName); IoDeleteDevice(pDriverObject^.DeviceObject); end; function _DriverEntry(pDriverObject: PDriverObject; RegistryPath: PUnicodeString) : NTSTATUS; stdcall; var LDevName: TUnicodeString; LDevObj: PDeviceObject; begin RtlInitUnicodeString(LDevName, DeviceName); RtlInitUnicodeString(DosDevName, DosDeviceName); Result := IoCreateDevice(pDriverObject,0, @LDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, LDevObj); if NT_SUCCESS(Result) then begin pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @hookCreate; pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @hookClose; pDriverObject^.MajorFunction[IRP_MJ_DEVICE_CONTROL] := @hookDeviceControl; pDriverObject^.DriverUnload := @DriverUnload; Result := IoCreateSymbolicLink(@DosDevName, @LDevName); if not NT_SUCCESS(Result) then begin IoDeleteDevice(pDriverObject^.DeviceObject); end; end; end; end.
代码:
unit hooking; interface uses nt_status,ntoskrnl,ntutils,ssdthook; type TZwOpenProcess = function(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId):NTSTATUS; stdcall; TNtUserFindWindowEx= Function (hwndParent,hwndChild:Handle; pstrClassName,pstrWindowName:PUnicodeString; dwType:LONG):NTSTATUS;stdcall; var HookActive: Boolean=False; OldZwOpenProcess:LONG=0; OldNtUserFindWindowEx:LONG=0; SafeId:Handle=0; SafeHandle:Handle=0; procedure SetSafeId(value:Handle); procedure SetSafeHandle(value:Handle); function HookingHook: Integer; stdcall; function HookingUnhook: Integer; stdcall; procedure DoPub; implementation procedure SetSafeId(value:Handle); begin SafeId:=value; end; procedure SetSafeHandle(value:Handle); begin SafeHandle:=value; end; function ZwOpenProcessAddr:Pointer; begin Result:=GetImportFunAddr(@ZwOpenProcess); end; function NewNtUserFindWindowEx(hwndParent,hwndChild:Handle;pstrClassName,pstrWindowName:PUnicodeString;dwType:LONG):NTSTATUS;stdcall; begin Result:=TNtUserFindWindowEx(pointer(OldNtUserFindWindowEx))(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType); if Result=SafeHandle then Result:=0; end; function NewZwOpenProcess(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId):NTSTATUS; stdcall; var Temp:Handle; begin Temp:=ProcessHandle^; if Temp=SafeId then Result:=0 else Result:=TZwOpenProcess(pointer(OldZwOpenProcess))(ProcessHandle,DesiredAccess,ObjectAttributes, ClientId); end; function HookingHook: Integer; stdcall; var uCr0cpu:dword; begin if HookActive then begin Result:=Integer(False); Exit; end; //关闭写保护 asm cli push eax mov eax, cr0 mov [uCr0cpu], eax and eax, not 000010000h mov cr0, eax pop eax end; OldZwOpenProcess:=InterlockedExchange(SystemServiceName(ZwOpenProcessAddr),LONG(@NewZwOpenProcess)); OldNtUserFindWindowEx:=InterlockedExchange(ShadowSystemServiceOrd($17a),LONG(@NewNtUserFindWindowEx)); // 打开写保护 asm push eax mov eax, [uCr0cpu] mov cr0, eax pop eax sti end; HookActive := True; Result := Integer(True); end; function HookingUnhook: Integer; stdcall; var uCr0cpu:dword; begin if not HookActive then begin Result:=Integer(False); Exit; end; //关闭写保护 asm cli push eax mov eax, cr0 mov [uCr0cpu], eax and eax, not 000010000h mov cr0, eax pop eax end; InterlockedExchange(SystemServiceName(ZwOpenProcessAddr),OldZwOpenProcess); InterlockedExchange(ShadowSystemServiceOrd($17a),OldNtUserFindWindowEx); // 打开写保护 asm push eax mov eax, [uCr0cpu] mov cr0, eax pop eax sti end; HookActive := False; Result := Integer(True); end; procedure DoPub; begin DbgPrint('%08x',ShadowSystemServiceOrd(0)); DbgPrint('%08x',ShadowSystemServiceOrd(0)^); end; end.
代码:
// 从导入表中获取一个函数的地址 function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall; begin Result := PPointer(PPointer(Cardinal(lpImportAddr) + 2)^)^; end; // KeServiceDescriptorTable+函数名计算SSDT函数偏移 function SystemServiceName(AFunc: Pointer): PLONG; stdcall; var lpKeServiceDescriptorTable: PServiceDescriptorEntry; begin lpKeServiceDescriptorTable := GetImportFunAddr(@KeServiceDescriptorTable); Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * PULONG(ULONG(AFunc) + 1)^)); end; // KeServiceDescriptorTable+序号名计算SSDT函数偏移 function SystemServiceOrd(iOrd: ULONG): PLONG; stdcall; var lpKeServiceDescriptorTable: PServiceDescriptorEntry; begin lpKeServiceDescriptorTable := GetImportFunAddr(@KeServiceDescriptorTable); Result := PLONG(PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * iOrd))); end; function FindShadowTable:Pointer; //XP版本 var lpKeServiceDescriptorTable:ULONG; begin lpKeServiceDescriptorTable := ULONG(GetImportFunAddr(@KeServiceDescriptorTable)); Result:=Pointer(lpKeServiceDescriptorTable-$40); end; function FindShadowTable2:Pointer; var cPtr, pOpcode:ULONG; I:ULONG; begin Result:=nil; cPtr:=ULONG(GetImportFunAddr(@KeAddSystemServiceTable)); I:=cPtr; While (I<(cPtr+$1000)) Do begin if MmIsAddressValid(Pointer(I)) then begin if word(pointer(I)^)=$888d then begin Result:=PPointer(I+2)^; break end; end; I:=I+1; end; end; //序号名计算Shadow SSDT函数偏移 function ShadowSystemServiceOrd(iOrd: ULONG): PLONG; stdcall; var lpKeServiceDescriptorTable:PShadowSrvDescriptorEntry; begin lpKeServiceDescriptorTable :=FindShadowTable2; Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.win32kTable.ServiceTableBase) + (SizeOf(ULONG) * iOrd)); end;