最近看见论坛很多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;