О SystemHandleInformation для 64-битного приложения
Мне нужно знать, как enumarate обрабатывает 64-битные приложения, я сделал это на 32-битных и работает отлично, но тот же код, скомпилированный как 64-битные, показывает только некоторые дескрипторы. Я уже изменил переменные на длинное слово, например, но безуспешно. я читал о SystemHandleInformation на x64 должен быть другое значение вместо $10 (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 ответ
Имена локальных переменных и два не удаленных комментария позволяют предположить, что это вариант кода, размещенного RRUZ в 2009 году здесь. В то время не было 64-битной версии Delphi, поэтому он не мог протестировать код на 64-битной версии. Во всяком случае, я смог проверить это с XE2 на W7x64, используя "jwanative.pas" для пропавших без вести NtQuerySystemInformation
из вашего образца. У вас также есть один end
слишком много, вам нужно удалить end
что приходит раньше FreeMem(lpszProcess);
, В противном случае код не скомпилируется - возможно, ошибка копирования / вставки с вашей стороны.
Ошибка - неправильная упаковка SYSTEM_HANDLE
а также SYSTEM_HANDLE_INFORMATION
записи, их макеты перепутаны на 64 бит при упаковке. Эта страница Джеффа Чаппелла (должна быть подтверждена в соответствии с условиями сайта) предполагает, что
SYSTEM_HANDLE_INFORMATION составляет 0x14 и 0x20 байтов в 32-битной и 64-битной Windows, соответственно.
Распакуйте его, чтобы иметь 32 байта в x64 вместо 28 во время упаковки.
Точно так же эта страница предлагает:
Структура SYSTEM_HANDLE_TABLE_ENTRY_INFO составляет 0x10 или 0x18 байтов в 32-битной и 64-битной Windows соответственно.
Распакуйте свою запись, и она будет 24 байта на x64 вместо 20 во время упаковки. Хотя члены немного отличаются, вы сможете увидеть, что он работает примерно так же, как на x32.
Обратите внимание, что код может запускаться или не запускаться в более поздних / будущих версиях ОС. Microsoft не только полностью документирует поиск информации о системе, но и предупреждает, что
Функция NtQuerySystemInformation и возвращаемые ей структуры являются внутренними для операционной системы и могут изменяться от одного выпуска Windows к другому.