⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driver.pas

📁 Delphi开发驱动的一个例子 1.映射ntoskrnl.exe到内存 2.重定位信息... 3.搜索SSDT基址 4.补丁回去
💻 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 + -