我需要知道在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不同,有人知道为什么吗?
答案 0 :(得分:3)
局部变量名和两个未删除的注释表明,这是RRUZ在2009 here上发布的代码的变体。当时还没有64位的Delphi版本,因此他无法在64位上测试代码。无论如何,我可以在W7x64上使用Xj2使用“ jwanative.pas”对您的样本中缺少的NtQuerySystemInformation
进行测试。您还有一个end
,您需要删除end
之前的FreeMem(lpszProcess);
。否则,代码将无法编译-您可能是复制/粘贴错误。
错误是SYSTEM_HANDLE
和SYSTEM_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版本到另一个版本。