关于64位应用程序上的SystemHandleInformation

时间:2018-07-25 14:27:06

标签: delphi handles

我需要知道在64位应用程序上如何进行精确处理,我在32位上实现了完美处理,但是编译为64位的相同代码仅显示了一些处理。 例如,我已经将变量更改为longword,但没有成功。 我了解到x64上的SystemHandleInformation应该是另一个值,而不是10美元(12月16日),但尝试没有成功。

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Windows,
  Classes,
  PsApi;

const
  SystemHandleInformation       = $10;
  STATUS_SUCCESS                = $00000000;
  STATUS_BUFFER_OVERFLOW        = $80000005;
  STATUS_INFO_LENGTH_MISMATCH   = $C0000004;
  //
  type
  NTSTATUS = Cardinal;
  OBJECT_INFORMATION_CLASS = (ObjectBasicInformation, ObjectNameInformation,
                              ObjectTypeInformation, ObjectAllTypesInformation, ObjectHandleInformation);
  //
  SYSTEM_HANDLE = packed record
    UniqueProcessId       : USHORT;
    CreatorBackTraceIndex : USHORT;
    ObjectTypeIndex       : UCHAR;
    HandleAttributes      : UCHAR;
    HandleValue           : USHORT;
    HObject               : PVOID;
    GrantedAccess         : ULONG;
  end;
  PSYSTEM_HANDLE       = ^SYSTEM_HANDLE;
  SYSTEM_HANDLE_ARRAY  = Array[0..0] of SYSTEM_HANDLE;
  PSYSTEM_HANDLE_ARRAY = ^SYSTEM_HANDLE_ARRAY;
  //
  SYSTEM_HANDLE_INFORMATION = packed record
    uCount   : ULONG;
    Handles  : SYSTEM_HANDLE_ARRAY;
  end;
  PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION;
  //
  TNtQuerySystemInformation  = function (SystemInformationClass:DWORD; SystemInformation:pointer; SystemInformationLength:DWORD;  ReturnLength:PDWORD):THandle; stdcall;
  TNtQueryObject             = function (ObjectHandle:cardinal; ObjectInformationClass:OBJECT_INFORMATION_CLASS; ObjectInformation:pointer; Length:ULONG;ResultLength:PDWORD):THandle;stdcall;

  var
  NTQueryObject             : TNtQueryObject;
  NTQuerySystemInformation  : TNtQuerySystemInformation;

Procedure EnumerateOpenFiles();
const
  HANDLE_BUFFER_INCREASE_CHUNK = 5000 * 1024;
var
  sDummy      : string;
  hProcess    : THandle;
  hObject     : THandle;
  ResultLength: DWORD;
  aBufferSize : DWORD;
  aIndex      : LONG;//Integer;
  pHandleInfo : PSYSTEM_HANDLE_INFORMATION;
  HDummy      : THandle;

  lpszProcess : PWideChar;
begin
  AbufferSize      := HANDLE_BUFFER_INCREASE_CHUNK;
  pHandleInfo      := AllocMem(AbufferSize);
  HDummy           := NTQuerySystemInformation(DWORD(SystemHandleInformation), pHandleInfo, AbufferSize, @ResultLength);  //Get the list of handles

  if(HDummy = STATUS_SUCCESS) then
  begin
    for aIndex:=0 to pHandleInfo^.uCount-1 do
    begin
      hProcess := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, pHandleInfo.Handles[aIndex].UniqueProcessId);  //open the process to get aditional info
      if(hProcess <> INVALID_HANDLE_VALUE) then
      begin
        hObject := 0;

        if DuplicateHandle(hProcess, pHandleInfo.Handles[aIndex].HandleValue, GetCurrentProcess(), @hObject, STANDARD_RIGHTS_REQUIRED, FALSE, 0) then  //Get  a copy of the original handle
        begin
          lpszProcess := AllocMem(MAX_PATH);
          if GetModuleFileNameEx(hProcess, 0,lpszProcess, MAX_PATH) <> 0 then
            sDummy:=lpszProcess
          else
            sDummy:= 'System Process';

            WriteLn(Format('PID [%d] Process [%s]',  [pHandleInfo.Handles[aIndex].UniqueProcessId, sDummy]));

          FreeMem(lpszProcess);
          CloseHandle(hObject);
        end;

        CloseHandle(hProcess);
      end;
    end;
  end;

  WriteLn('Finish');
  FreeMem(pHandleInfo);
end;

begin
  NTQueryObject            := GetProcAddress(GetModuleHandle('NTDLL.DLL'), 'NtQueryObject');
  NTQuerySystemInformation := GetProcAddress(GetModuleHandle('NTDLL.DLL'), 'NtQuerySystemInformation');
  if (@NTQuerySystemInformation <> nil) and (@NTQuerySystemInformation <> nil) then EnumerateOpenFiles() else WriteLn('falhou no inicio');
  ReadLn;
end.

这在x86应用程序上可以完美运行,但是当我更改为x64时,他显示的结果与x86不同,有人知道为什么吗?

1 个答案:

答案 0 :(得分:3)

局部变量名和两个未删除的注释表明,这是RRUZ在2009 here上发布的代码的变体。当时还没有64位的Delphi版本,因此他无法在64位上测试代码。无论如何,我可以在W7x64上使用Xj2使用“ jwanative.pas”对您的样本中缺少的NtQuerySystemInformation进行测试。您还有一个end,您需要删除end之前的FreeMem(lpszProcess);。否则,代码将无法编译-您可能是复制/粘贴错误

错误是SYSTEM_HANDLESYSTEM_HANDLE_INFORMATION记录的 mis-packing ,打包时它们的布局混乱了64位。 Geoff Chappell的This page(必须根据site's terms承认)建议

  

SYSTEM_HANDLE_INFORMATION 是32位的0x14和0x20字节,   分别是64位Windows。

将其解压缩为x64中的32个字节,而不是打包时的28个字节。

类似地,this page建议:

  

SYSTEM_HANDLE_TABLE_ENTRY_INFO 结构为0x10或0x18字节,位于   32位和64位Windows。

解压缩您的记录,在x64上它将是24个字节,而不是打包时的20个字节。尽管成员稍有不同,但您可以看到它的运行与在x32上运行的大致相同。


请注意,该代码可能会或可能不会在更高/将来版本的OS上运行。 Microsoft不仅未完全记录系统信息检索,而且还警告

  

NtQuerySystemInformation 函数及其结构   返回值是操作系统内部的,并且可能会发生变化   从一个Windows版本到另一个版本。