关于 64 位应用程序的 SystemHandleInformation
About SystemHandleInformation on 64 bits application
我需要知道 enumarate 是如何处理 64 位应用程序的,我在 32 位上做了它并且工作得很好,但是编译为 64 位的相同代码只显示了一些句柄。
例如,我已经将变量更改为 longword 但没有成功。
我读到有关 x64 上的 SystemHandleInformation 应该是另一个值而不是 10 美元(12 月 16 日)但尝试没有成功。
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Windows,
Classes,
PsApi;
const
SystemHandleInformation = ;
STATUS_SUCCESS = [=10=]000000;
STATUS_BUFFER_OVERFLOW = 000005;
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 相同的结果,有人知道为什么吗?
局部变量名称和两个未删除的注释表明这是 RRUZ 在 2009 年发布的代码的变体 here。当时没有 64 位 Delphi 版本,所以他不可能在 64 位上测试代码。无论如何,我能够使用 "jwanative.pas" 在 W7x64 上使用 XE2 测试您的示例中缺少的 NtQuerySystemInformation
。您还有一个 end
太多了,您需要删除 FreeMem(lpszProcess);
之前的 end
。否则代码将无法编译 - 可能是您的 copy/paste 错误。
错误是 错误打包 SYSTEM_HANDLE
和 SYSTEM_HANDLE_INFORMATION
记录,打包时它们的布局对于 64 位来说是混乱的。 This page by Geoff Chappell (have to acknowledge according to the site's terms) 建议
The SYSTEM_HANDLE_INFORMATION is 0x14 and 0x20 bytes in 32-bit and
64-bit Windows, respectively.
将它解压为 x64 中的 32 个字节,而不是打包时的 28 个字节。
同样,this page建议:
The SYSTEM_HANDLE_TABLE_ENTRY_INFO structure is 0x10 or 0x18 bytes in
32-bit and 64-bit Windows, respectively.
解压缩您的记录,在 x64 上它将是 24 个字节,而不是打包时的 20 个字节。尽管成员略有不同,但您将能够看到它 运行 与 x32 上的大致相同。
请注意,代码在 OS 的 later/future 版本上可能 运行 也可能不 运行。微软不仅没有完整记录系统信息检索,还警告说
The NtQuerySystemInformation function and the structures that it
returns are internal to the operating system and subject to change
from one release of Windows to another.
我需要知道 enumarate 是如何处理 64 位应用程序的,我在 32 位上做了它并且工作得很好,但是编译为 64 位的相同代码只显示了一些句柄。 例如,我已经将变量更改为 longword 但没有成功。 我读到有关 x64 上的 SystemHandleInformation 应该是另一个值而不是 10 美元(12 月 16 日)但尝试没有成功。
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Windows,
Classes,
PsApi;
const
SystemHandleInformation = ;
STATUS_SUCCESS = [=10=]000000;
STATUS_BUFFER_OVERFLOW = 000005;
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 相同的结果,有人知道为什么吗?
局部变量名称和两个未删除的注释表明这是 RRUZ 在 2009 年发布的代码的变体 here。当时没有 64 位 Delphi 版本,所以他不可能在 64 位上测试代码。无论如何,我能够使用 "jwanative.pas" 在 W7x64 上使用 XE2 测试您的示例中缺少的 NtQuerySystemInformation
。您还有一个 end
太多了,您需要删除 FreeMem(lpszProcess);
之前的 end
。否则代码将无法编译 - 可能是您的 copy/paste 错误。
错误是 错误打包 SYSTEM_HANDLE
和 SYSTEM_HANDLE_INFORMATION
记录,打包时它们的布局对于 64 位来说是混乱的。 This page by Geoff Chappell (have to acknowledge according to the site's terms) 建议
The SYSTEM_HANDLE_INFORMATION is 0x14 and 0x20 bytes in 32-bit and 64-bit Windows, respectively.
将它解压为 x64 中的 32 个字节,而不是打包时的 28 个字节。
同样,this page建议:
The SYSTEM_HANDLE_TABLE_ENTRY_INFO structure is 0x10 or 0x18 bytes in 32-bit and 64-bit Windows, respectively.
解压缩您的记录,在 x64 上它将是 24 个字节,而不是打包时的 20 个字节。尽管成员略有不同,但您将能够看到它 运行 与 x32 上的大致相同。
请注意,代码在 OS 的 later/future 版本上可能 运行 也可能不 运行。微软不仅没有完整记录系统信息检索,还警告说
The NtQuerySystemInformation function and the structures that it returns are internal to the operating system and subject to change from one release of Windows to another.