📄 driver.pas
字号:
{
SSDT UnHook By Anskya
Email: Anskya[at]Gmail.com
1.映射ntoskrnl.exe到内存
2.重定位信息...
3.搜索SSDT基址
4.补丁回去
}
unit Driver;
interface
uses
Windows, ntddk; // ---->DDDK.pas
function _DriverEntry(DriverObject: PDriverObject; RegistryPath: PUnicodeString): NTSTATUS; stdcall;
implementation
var
szKernelPath: Array[0..MAX_PATH] Of Char;
// NT_SUCCESS
function NT_SUCCESS(Status: NTSTATUS): Boolean;
begin
Result := Integer(Status) >= 0;
end;
function NtCurrentProcess(): THandle;
begin
Result := THandle(-1);
end;
procedure InitializeObjectAttributes(var p: PObjectAttributes; n: PUnicodeString; a: ULONG; r: THandle; s: PSECURITY_DESCRIPTOR);
begin
p.Length := sizeof(OBJECT_ATTRIBUTES);
p.RootDirectory := r;
p.Attributes := a;
p.ObjectName := n;
p.SecurityDescriptor := s;
p.SecurityQualityOfService := nil;
end;
// 从导入表中获取一个函数的地址
function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall;
begin
Result := PPointer(PPointer(Cardinal(lpImportAddr) + 2)^)^;
end;
function GetModuleBaseAddress(lpszModule: PChar): ULONG;
var
nResult: NTSTATUS;
ulNeededSize, uLoop: ULONG;
pulModuleList: PMODULE_LIST;
lpszModuleName: PChar;
begin
Result := 0;
ZwQuerySystemInformation(SystemModuleInformation, @ulNeededSize, 0, @ulNeededSize);
pulModuleList := ExAllocatePoolWithTag(NonPagedPool, ulNeededSize, PoolWithTag);
nResult := ZwQuerySystemInformation(SystemModuleInformation, pulModuleList, ulNeededSize, nil);
if (NT_SUCCESS(nResult)) then
begin
uLoop := 0;
while (uLoop <= pulModuleList^.dwModules) do
begin
lpszModuleName := @pulModuleList^.Modules[uLoop].ImageName[pulModuleList^.Modules[uLoop].ModuleNameOffset];
//lpszModuleName := ExtractFileName(lpszModuleName);
//DbgPrint('No.%d Module Name: %s; NameOffset: %d', uLoop, lpszModuleName, pulModuleList^.Modules[uLoop].ModuleNameOffset);
if (_stricmp(lpszModuleName, lpszModule) = 0) then
begin
//strcpy(szKernelPath, @pulModuleList^.Modules[uLoop].ImageName);
strcpy(szKernelPath, '\SystemRoot\System32\');
strcat(szKernelPath, lpszModuleName);
{
if (pulModuleList^.Modules[uLoop].ModuleNameOffset = 0) then
begin
strcpy(szKernelPath, '\SystemRoot\System32\');
strcpy(szKernelPath, lpszModuleName);
end else
begin
strcpy(szKernelPath, @pulModuleList^.Modules[uLoop].ImageName);
end;
}
Result := ULONG(pulModuleList^.Modules[uLoop].Base);
Break;
end;
Inc(uLoop, 1);
end;
end else
begin
DbgPrint('ZwQuerySystemInformation failed! ulNeededSize = %ul', ulNeededSize);
end;
ExFreePoolWithTag(pulModuleList, PoolWithTag);
end;
function LoadPeFile(lpszFileName: PChar): PVOID; stdcall;
var
AnsiString: TAnsiString;
uFileName: TUnicodeString;
obj: TObjectAttributes;
ioStatus: IO_STATUS_BLOCK;
Status: NTSTATUS;
hFile: THandle;
Info: FILE_STANDARD_INFORMATION;
lpFileMemory, lpMapPeFile, lpNewSection, lpOldSection: Pointer;
lpNtHeaders, lpNewNtHeaders: PImageNtHeaders;
lpSectionHeader: PImageSectionHeader;
iLoop: Integer;
begin
Result := nil;
RtlInitAnsiString(@AnsiString, lpszFileName);
Status := RtlAnsiStringToUnicodeString(@uFileName, @AnsiString, True);
if Not NT_SUCCESS(Status) then
begin
//DbgPrint('AnsiString To UnicodeString Error!');
Exit;
end;
obj.Length := SizeOf(OBJECT_ATTRIBUTES);
obj.RootDirectory := 0;
obj.Attributes := OBJ_KERNEL_HANDLE or OBJ_CASE_INSENSITIVE;
obj.ObjectName := @uFileName;
obj.SecurityDescriptor := nil;
obj.SecurityQualityOfService := nil;
// 打开文件
lpFileMemory := nil;
Status := ZwCreateFile(@hFile, FILE_EXECUTE or SYNCHRONIZE, @obj, @ioStatus, nil, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ or FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, nil, 0);
if NT_SUCCESS(Status) then
begin
// 获取文件大小,读取到缓冲区内
Status := ZwQueryInformationFile(hFile, @ioStatus, @Info, SizeOf(FILE_STANDARD_INFORMATION), FileStandardInformation);
if (NT_SUCCESS(Status) and (Info.EndOfFile.LowPart > 0) and (Info.EndOfFile.HighPart = 0)) then
begin
lpFileMemory := ExAllocatePool(NonPagedPool, Info.EndOfFile.LowPart);
if (lpFileMemory <> nil) then
begin
Status := ZwReadFile(hFile, 0, nil, nil, @ioStatus, lpFileMemory, Info.EndOfFile.LowPart, nil, nil);
if Not NT_SUCCESS(Status) then
begin
//DbgPrint('File Read Error!');
ExFreePool(lpFileMemory);
lpFileMemory := nil;
end;
end else
begin
//DbgPrint('Get File Memory Error!');
lpFileMemory := nil;
end;
end else
begin
//DbgPrint('Read File Info Error!');
end;
end else
begin
//DbgPrint('Open File Info Error!');
end;
// 关闭文件
ZwClose(hFile);
RtlFreeUnicodeString(@uFileName);
// 判断文件是否读取成功
if (lpFileMemory = nil) then
begin
//DbgPrint('Get File Info Error!.ExitProc!');
Exit;
end;
// 判断文件是是否是PE文件
if (PImageDosHeader(lpFileMemory)^.e_magic <> IMAGE_DOS_SIGNATURE) then
begin
ExFreePool(lpFileMemory);
//DbgPrint('Is File No MZ Header!!!');
Exit;
end;
lpNtHeaders := PImageNtHeaders(DWORD(lpFileMemory) + DWORD(PImageDosHeader(lpFileMemory)^._lfanew));
if (lpNtHeaders^.Signature <> IMAGE_NT_SIGNATURE) then
begin
ExFreePool(lpFileMemory);
//DbgPrint('Is File No PE Header!!!');
Exit;
end;
// 申请装载空间
lpMapPeFile := ExAllocatePool(NonPagedPool, lpNtHeaders^.OptionalHeader.SizeOfImage);
if (lpMapPeFile = nil) then
begin
ExFreePool(lpFileMemory);
//DbgPrint('Get PE Load Memory Error!!!');
Exit;
end;
memcpy(lpMapPeFile, lpFileMemory, lpNtHeaders^.OptionalHeader.SizeOfHeaders);
lpNewNtHeaders := PImageNtHeaders(DWORD(lpMapPeFile) + DWORD(PImageDosHeader(lpMapPeFile)^._lfanew));
// 计算首个段数据
lpSectionHeader := PImageSectionHeader(DWORD(lpNewNtHeaders) + SizeOf(DWORD) + SizeOf(TImageFileHeader) + DWORD(lpNtHeaders^.FileHeader.SizeOfOptionalHeader));
// 填充各段数据与属性
for iLoop := 0 to (lpNtHeaders^.FileHeader.NumberOfSections - 1) do
begin
with lpSectionHeader^ do
begin
lpNewSection := Pointer(VirtualAddress + DWORD(lpMapPeFile));
lpOldSection := Pointer(PointerToRawData + DWORD(lpFileMemory));
{
DbgPrint('Section Name: %s, VirtualAddress: %.8X, PointerToRawData: %X, SizeOfRawData: %.8X, ',
Name, VirtualAddress, PointerToRawData, SizeOfRawData);
DbgPrint('lpNewSection: %X, lpOldSection: %X, SizeOfRawData: %X', lpNewSection, lpOldSection, SizeOfRawData);
}
memcpy(lpNewSection, lpOldSection, SizeOfRawData);
end;
lpSectionHeader := PImageSectionHeader(DWORD(lpSectionHeader) + SizeOf(TImageSectionHeader));
end;
// 释放文件是数据
ExFreePool(lpFileMemory);
Result := lpMapPeFile;
end;
// 查找.SSDT基址
function FindKiServiceTable(hModuleBase: HMODULE; dwKSDT: DWORD): DWORD; stdcall;
const
IMAGE_SIZEOF_BASE_RELOCATION = 8;
IMAGE_REL_BASED_HIGHLOW = 3;
IMAGE_ORDINAL_FLAG32 = DWORD($80000000);
type
PImageBaseRelocation = ^TImageBaseRelocation;
TImageBaseRelocation = packed record
VirtualAddress: cardinal;
SizeOfBlock: cardinal;
end;
var
dwRelocSize, dwRelocCount, dwRelocLoop, dwPointerRva, dwImageBase: DWORD;
lpNtHeaders: PImageNtHeaders;
lpReloc, lpRelocDest: PImageBaseRelocation;
lpRelocInfo: PWORD;
lpPatchAddress: PDWORD;
iRelocType, iRelocOffset: Integer;
begin
Result := 0;
if (PImageDosHeader(hModuleBase)^.e_magic <> IMAGE_DOS_SIGNATURE) then Exit;
lpNtHeaders := PImageNtHeaders(DWORD(PImageDosHeader(hModuleBase)^._lfanew) + hModuleBase);
if (lpNtHeaders^.Signature <> IMAGE_NT_SIGNATURE) then Exit;
dwImageBase := lpNtHeaders^.OptionalHeader.ImageBase;
lpReloc := PImageBaseRelocation(lpNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
dwRelocSize := lpNtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
if ((DWORD(lpReloc) > 0) and (dwRelocSize > 0)) then
begin
lpReloc := PImageBaseRelocation(DWORD(lpReloc) + hModuleBase);
//while ((lpReloc^.VirtualAddress > 0) and (lpReloc^.SizeOfBlock > 0)) do
while (lpReloc^.SizeOfBlock > 0) do
begin
lpRelocDest := PImageBaseRelocation(DWORD(hModuleBase) + lpReloc^.VirtualAddress);
lpRelocInfo := Pointer(DWORD(lpReloc) + SizeOf(TImageBaseRelocation));
dwRelocCount := (((lpReloc^.SizeOfBlock - SizeOf(TImageBaseRelocation)) div 2) - 1);
if (Integer(dwRelocCount) > 0) then
begin
for dwRelocLoop := 0 to dwRelocCount do
begin
iRelocType := (lpRelocInfo^ shr 12);
iRelocOffset := (lpRelocInfo^ and $0FFF);
if (iRelocType = IMAGE_REL_BASED_HIGHLOW) then
begin
lpPatchAddress := Pointer(DWORD(lpRelocDest) + DWORD(iRelocOffset));
dwPointerRva := lpPatchAddress^ - dwImageBase;
if (dwPointerRva = dwKSDT) then
begin
//DbgPrint('dwPointerRva: %.8X = dwKSDT!', dwPointerRva);
if (PWORD(DWORD(lpPatchAddress) - 2)^ = $05C7) then
begin
Result := (PDWORD(DWORD(lpPatchAddress) + 4)^ - dwImageBase) + hModuleBase;
Exit;
end;
end;
lpRelocInfo := PWORD(DWORD(lpRelocInfo) + SizeOf(WORD));
end;
end;
end;
lpReloc := PImageBaseRelocation(DWORD(lpReloc) + lpReloc^.SizeOfBlock);
end;
end;
end;
// 驱动卸载过程
procedure DriverUnload(DriverObject: PDriverObject); stdcall;
begin
//DbgPrint('DriverUnload(-)');
end;
// 驱动入口点
function _DriverEntry(DriverObject: PDriverObject; RegistryPath: PUnicodeString): NTSTATUS; stdcall;
var
uModule, uCount, uSsdtBase, uLoop, uCr0cpu: ULONG;
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
lpModule, lpSsdtBase: PVOID;
dwImageBase, dwSizeOfImage, dwOldSsdtAddress, dwNewSsdtAddress: DWORD;
begin
DriverObject^.DriverUnload := @DriverUnload;
Result := STATUS_SUCCESS;
//DbgPrint('DriverEntry(-):0x%.8X', Result);
// 查找kernel 基址
uModule := GetModuleBaseAddress('ntoskrnl.exe');
if (uModule = 0) then
begin
//DbgPrint('Find Module "ntoskrnl.exe" Error');
uModule := GetModuleBaseAddress('ntkrnlpa.exe');
if (uModule = 0) then
begin
//DbgPrint('Find Module "ntkrnlpa.exe" Error');
Exit;
end else
begin
//DbgPrint('Find Module "ntkrnlpa.exe" Done: 0x%8X', uModule);
end;
end else
begin
//DbgPrint('Find Module "ntoskrnl.exe" Done: 0x%8X', uModule);
end;
lpKeServiceDescriptorTable := GetImportFunAddr(@KeServiceDescriptorTable);
//uCount := lpKeServiceDescriptorTable^.NumberOfServices;
uSsdtBase := ULONG(lpKeServiceDescriptorTable^.ServiceTableBase);
dwImageBase := PImageNtHeaders(DWORD(PImageDosHeader(uModule)^._lfanew) + uModule).OptionalHeader.ImageBase;
dwSizeOfImage := PImageNtHeaders(DWORD(PImageDosHeader(uModule)^._lfanew) + uModule).OptionalHeader.SizeOfImage;
//DbgPrint('ImageBase: 0x%.8X, KeServiceDescriptorTable: 0x%8X, SSDT BaseAddress: 0x%8X, SSDT Count: 0x%X', dwImageBase, lpKeServiceDescriptorTable, uSsdtBase, uCount);
lpModule := LoadPeFile(szKernelPath);
if (lpModule <> nil) then
begin
//DbgPrint('Map %s Demo: %.8X!!!', szKernelPath, lpModule);
lpSsdtBase := Pointer(FindKiServiceTable(DWORD(lpModule), DWORD(lpKeServiceDescriptorTable) - DWORD(uModule)));
if (lpSsdtBase <> nil) then
begin
//DbgPrint('Real Ssdt %.8X', lpSsdtBase);
uLoop := 0;
while (True) do
begin
dwOldSsdtAddress := (PDWORD(DWORD(lpSsdtBase) + (SizeOf(ULONG) * uLoop))^ - dwImageBase) + DWORD(uModule);
// 判断是否到了函数结尾
if ((dwOldSsdtAddress <= DWORD(uModule)) or (dwOldSsdtAddress >= (dwSizeOfImage + DWORD(uModule)))) then
begin
//DbgPrint('No.%d: Break...Now Ssdt %.8X', uLoop, dwOldSsdtAddress);
Break;
end;
dwNewSsdtAddress := PLONG(uSsdtBase + (SizeOf(ULONG) * uLoop))^;
if (dwOldSsdtAddress <> dwNewSsdtAddress) then
begin
//DbgPrint('No.%d: Old: %.8X, New: %.8X', uLoop, dwOldSsdtAddress, dwNewSsdtAddress);
// 关闭写保护
asm
cli
push eax
mov eax, cr0
mov [uCr0cpu], eax
and eax, not 000010000h
mov cr0, eax
pop eax
end;
//PULONG(uSsdtBase + (SizeOf(ULONG) * uLoop))^ := dwOldSsdtAddress;
fast_InterlockedExchange(PLONG(uSsdtBase + (SizeOf(ULONG) * uLoop)), dwOldSsdtAddress);
// 打开写保护
asm
push eax
mov eax, [uCr0cpu]
mov cr0, eax
pop eax
sti
end;
end;
Inc(uLoop, 1);
end;
end else
begin
//DbgPrint('Find Ssdt Base Error!!!');
end;
ExFreePool(lpModule);
end else
begin
//DbgPrint('Map %s Error!!!', szKernelPath);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -