Last active
May 17, 2018 13:27
-
-
Save HoShiMin/9cafccafcf4b6b179b06 to your computer and use it in GitHub Desktop.
Многофункциональный API для работы с процессами
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unit ProcessAPI; | |
interface | |
//{$DEFINE DEBUG_PRIVILEGE} | |
uses | |
Windows, TlHelp32, CodepageAPI; | |
// Результат функции GetProcessList - массив процессов: | |
type | |
// Информация о процессе (TlHelp32): | |
PROCESSENTRY32A = record | |
Size : DWORD; | |
Usage : DWORD; | |
ProcessID : DWORD; | |
DefaultHeapID : ULONG_PTR; | |
ModuleID : DWORD; | |
ThreadsCount : DWORD; | |
ParentProcessID : DWORD; | |
Priority : Longint; | |
Flags : DWORD; | |
ExeFile : array [0 .. MAX_PATH - 1] of AnsiChar; | |
end; | |
TProcessEntry32A = PROCESSENTRY32A; | |
// Информация о потоке (TlHelp32): | |
THREADENTRY32 = record | |
Size : DWORD; | |
Usage : DWORD; | |
ThreadID : DWORD; | |
OwnerProcessID : DWORD; | |
Priority : Longint; | |
DeltaPriority : Longint; | |
Flags : DWORD; | |
end; | |
TThreadEntry32 = THREADENTRY32; | |
TProcessInfo = TProcessEntry32A; | |
TProcessList = array of TProcessInfo; | |
// Информация о загруженноых модулях: | |
TModuleInfo = record | |
FullPath : AnsiString; // Полный путь к модулю | |
ModuleName : AnsiString; // Имя модуля | |
BaseAddress : UInt64; // Базовый адрес загрузки (начало распакованного файла в ОЗУ) | |
EntryAddress : UInt64; // Точка входа | |
SizeOfImage : Cardinal; // Размер образа в байтах | |
end; | |
// Базовая информация о процессе: | |
TProcessBasicInfo = record | |
ExitStatus : LongWord; | |
AffinityMask : UInt64; | |
BasePriority : LongWord; | |
UniqueProcessId : UInt64; | |
InheritedFromUniqueProcessId : UInt64; | |
end; | |
TModulesList = record | |
Length: Cardinal; // Всего загруженных модулей | |
Modules: array of TModuleInfo; // Массив из информации о каждом модуле | |
end; | |
// Структура результата функции GetProcessInfo: | |
PROCESS_INFO = record | |
// Идентификаторы: | |
Handle : LongWord; // Хэндл процесса при получении информации | |
ID : UInt64; // Идентификатор процесса | |
InheritedFromID : UInt64; // Идентификатор процесса-родителя | |
SessionID : LongWord; // Идентификатор сессии | |
// Свойства процесса: | |
Priority : UInt64; // Приоритет процесса | |
AffinityMask : UInt64; // Маска соответствия процесса ядрам (число надо перевести в двоичный вид) | |
// Разное: | |
IsDebugged : Boolean; // Отлаживается ли процесс | |
ExitStatus : LongWord; // Код выхода | |
ThreadsCount : LongWord; // Количество потоков | |
HandlesCount : LongWord; // Количество открытых хэндлов | |
ReservedMemory : LongWord; // Зарезервированная память в байтах | |
// Адреса: | |
ImageBaseAddress : UInt64; // Адрес загрузки образа в оперативной памяти | |
LdrAddress : UInt64; // Адрес загрузочной информации | |
PEBAddress : UInt64; // Адрес блока окружения процесса (структура PEB) | |
// Хэндлы ввода-вывода: | |
ConsoleHandle : UInt64; // Хэндл консоли | |
StdInputHandle : UInt64; // Стандартный хэндл ввода | |
StdOutputHandle : UInt64; // Стандартный хэндл вывода | |
StdErrorHandle : UInt64; // Стандартный хэндл вывода ошибок | |
// Строковые параметры: | |
ProcessName : AnsiString; // Имя процесса | |
CurrentDirectoryPath : AnsiString; // Текущая папка | |
ImagePathName : AnsiString; // Имя образа процесса | |
CommandLine : AnsiString; // Командная строка | |
// Список загруженных модулей: | |
ModulesList: TModulesList; | |
// Глобальные системные свойства: | |
Is64BitProcess: BOOL; // 64х-битный ли процесс | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
// Преобразование ProcessID в Handle: | |
function ProcessIDToHandle(ProcessID: LongWord; AccessRights: LongWord = PROCESS_VM_READ or PROCESS_QUERY_INFORMATION): THandle; | |
// Преобразование Handle в ProcessID: | |
function HandleToProcessID(ProcessHandle: THandle): LongWord; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
// 64х-битная ли ОС: | |
function Is64BitWindows: BOOL; | |
// Получение подробной информации о процессе по его ID: | |
function GetProcessInfo(ProcessID: LongWord; out ProcessInfo: PROCESS_INFO; Process32_64CompatibleMode: Boolean = false): Boolean; | |
// Получение базовой информации о процессе по его ID: | |
function GetProcessBasicInfo(ProcessID: LongWord; out ProcessBasicInfo: TProcessBasicInfo): Boolean; | |
// 64х-битный ли процесс: | |
function Is64BitProcess(ProcessID: LongWord): LongBool; | |
// Запущен ли процесс (по имени процесса): | |
function IsProcessLaunched(ProcessName: AnsiString): Boolean; overload; | |
// Запущен ли процесс (по ID процесса): | |
function IsProcessLaunched(ProcessID: LongWord): Boolean; overload; | |
// Есть ли библиотека в процессе: | |
function IsLibInProcess(LibName: AnsiString; ProcessID: LongWord): Boolean; | |
// Получить список запущенных процессов с краткой информацией: | |
procedure GetProcessList(out ProcessList: TProcessList); | |
// Получить информацию из TlHelp32 по ID процесса: | |
function GetTlHelp32ProcessInfo(ProcessID: LongWord): TProcessInfo; overload; | |
// Получить информацию из TlHelp32 по имени процесса: | |
function GetTlHelp32ProcessInfo(ProcessName: AnsiString): TProcessInfo; overload; | |
// Запуск процесса: | |
procedure StartProcess(const CommandLine: string; out ProcessHandle: THandle; out ProcessID: LongWord); | |
// Ожидание завершения процесса: | |
procedure WaitProcess(ProcessID: LongWord); | |
// Убить процесс по ID: | |
procedure KillProcess(ProcessID: LongWord); overload; | |
// Убить процесс по имени: | |
procedure KillProcess(ProcessName: AnsiString; CanKillSelf: Boolean = False); overload; | |
// Получить загрузку ЦП данным процессом (Delay ставить в пределах от 25 до 500, меньше - неточно, больше - ни к чему): | |
function GetProcessCPULoading(ProcessID: LongWord; Delay: Cardinal): Single; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
type | |
Pointer64 = UInt64; | |
Pointer32 = UInt; | |
// Структура для получения данных о процессе под Win32 | |
PROCESS_BASIC_INFORMATION = record | |
ExitStatus: LongWord; | |
PebBaseAddress: Pointer; | |
AffinityMask: Cardinal; | |
BasePriority: Integer; | |
UniqueProcessId: LongWord; | |
InheritedFromUniqueProcessId: LongWord; | |
end; | |
PROCESS_BASIC_INFORMATION64 = record | |
ExitStatus: LongWord; | |
Reserved0: LongWord; | |
PebBaseAddress: UInt64; | |
AffinityMask: UInt64; | |
BasePriority: LongWord; | |
Reserved1: LongWord; | |
UniqueProcessId: UInt64; | |
InheritedFromUniqueProcessId: UInt64; | |
end; | |
PROCESS_BASIC_INFORMATION_WOW64 = record | |
Wow64PebAddress: UInt64; | |
end; | |
UCHAR = AnsiChar; | |
// Юникодная строка в Win32 | |
UNICODE_STRING = record | |
Length: Word; | |
MaximumLength: Word; | |
Buffer: Pointer; | |
end; | |
UNICODE_STRING_WOW64 = record | |
Length: Word; | |
MaximumLength: Word; | |
Buffer: Pointer32; | |
end; | |
UNICODE_STRING64 = record | |
Length: Word; | |
MaximumLength: Word; | |
Fill: LongWord; | |
Buffer: UInt64; | |
end; | |
PLDR_MODULE = Pointer; | |
TModuleListEntry = record | |
ForwardLDRModule: PLDR_MODULE; | |
BackwardLDRModule: PLDR_MODULE; | |
end; | |
LDR_MODULE = record | |
InLoadModuleOrderList: TModuleListEntry; | |
InMemoryModuleOrderList: TModuleListEntry; | |
InInitializationModuleOrderList: TModuleListEntry; | |
BaseAddress: Pointer; | |
EntryPoint: Pointer; | |
SizeOfImage: UInt; | |
FullDLLName: UNICODE_STRING; | |
BaseDLLName: UNICODE_STRING; | |
Flags: ULONG; | |
LoadCount: Short; | |
TlsIndex: Short; | |
TimeDateStamp: ULONG; | |
end; | |
PEB_LDR_DATA = record | |
Size: ULong; | |
Initialized: Boolean; | |
SsHandle: Pointer; | |
InLoadModuleOrderList: TModuleListEntry; | |
InMemoryModuleOrderList: TModuleListEntry; | |
InInitializationModuleOrderList: TModuleListEntry; | |
end; | |
PPEB_LDR_DATA = ^PEB_LDR_DATA; | |
// LDR WOW64: | |
PLDR_MODULE_WOW64 = Pointer32; | |
TModuleListEntryWow64 = record | |
ForwardLDRModule: PLDR_MODULE_WOW64; | |
BackwardLDRModule: PLDR_MODULE_WOW64; | |
end; | |
LDR_MODULE_WOW64 = record | |
InLoadModuleOrderList: TModuleListEntryWow64; | |
InMemoryModuleOrderList: TModuleListEntryWow64; | |
InInitializationModuleOrderList: TModuleListEntryWow64; | |
BaseAddress: Pointer32; | |
EntryPoint: Pointer32; | |
SizeOfImage: UInt; | |
FullDLLName: UNICODE_STRING_WOW64; | |
BaseDLLName: UNICODE_STRING_WOW64; | |
Flags: ULONG; | |
LoadCount: Short; | |
TlsIndex: Short; | |
TimeDateStamp: ULONG; | |
end; | |
PEB_LDR_DATA_WOW64 = record | |
Size: ULong; | |
Initialized: Boolean; | |
SsHandle: Pointer32; | |
InLoadModuleOrderList: TModuleListEntryWow64; | |
InMemoryModuleOrderList: TModuleListEntryWow64; | |
InInitializationModuleOrderList: TModuleListEntryWow64; | |
end; | |
PPEB_LDR_DATA_WOW64 = Pointer32; | |
// LDR x64: | |
PLDR_MODULE64 = UInt64; | |
TModuleListEntry64 = record | |
ForwardLDRModule: PLDR_MODULE64; | |
BackwardLDRModule: PLDR_MODULE64; | |
end; | |
LDR_MODULE64 = record | |
InLoadModuleOrderList: TModuleListEntry64; | |
InMemoryModuleOrderList: TModuleListEntry64; | |
InInitializationModuleOrderList: TModuleListEntry64; | |
BaseAddress: Pointer64; | |
EntryPoint: Pointer64; | |
SizeOfImage: ULong; | |
FullDLLName: UNICODE_STRING64; | |
BaseDLLName: UNICODE_STRING64; | |
Flags: ULONG; | |
LoadCount: Short; | |
TlsIndex: Short; | |
TimeDateStamp: ULONG; | |
end; | |
PEB_LDR_DATA64 = record | |
Size: UInt; | |
Initialized: Boolean; | |
SsHandle: UInt64; | |
InLoadModuleOrderList: TModuleListEntry64; | |
InMemoryModuleOrderList: TModuleListEntry64; | |
InInitializationModuleOrderList: TModuleListEntry64; | |
end; | |
PEB = record | |
InheritedAddressSpace: UCHAR; | |
ReadImageFileExecOptions: UCHAR; | |
BeingDebugged: Boolean; | |
BitField: UChar; | |
Mutant: Pointer; | |
ImageBaseAddress: Pointer; | |
Ldr: PPEB_LDR_DATA; | |
ProcessParameters: Pointer; | |
Reserved0: array [0..103] of Byte; | |
Reserved1: array [0..51] of Pointer; | |
PostProcessInitRoutine: Pointer; | |
Reserved2: array [0..127] of Byte; | |
Reserved3: Pointer; | |
SessionID: LongWord; | |
end; | |
PEB_WOW64 = record | |
InheritedAddressSpace: UCHAR; | |
ReadImageFileExecOptions: UCHAR; | |
BeingDebugged: Boolean; | |
BitField: UChar; | |
Mutant: Pointer32; | |
ImageBaseAddress: Pointer32; | |
Ldr: PPEB_LDR_DATA_WOW64; | |
ProcessParameters: Pointer32; | |
Reserved0: array [0..103] of Byte; | |
Reserved1: array [0..51] of Pointer32; | |
PostProcessInitRoutine: Pointer32; | |
Reserved2: array [0..127] of Byte; | |
Reserved3: Pointer32; | |
SessionID: LongWord; | |
end; | |
PEB64 = record | |
InheritedAddressSpace: Byte; | |
ReadImageFileExecOptions: Byte; | |
BeingDebugged: Boolean; | |
BitField: Byte; | |
Reserved0: LongWord; | |
Mutant: UInt64; | |
ImageBaseAddress: UInt64; | |
Ldr: UInt64; | |
ProcessParameters: UInt64; | |
Reserved1: array [0..519] of Byte; | |
PostProcessInitRoutine: UInt64; | |
Reserved2: array [0..135] of Byte; | |
SessionID: LongWord; | |
end; | |
// Структура RTL_USER_PROCESS_PARAMETERS под Win32 | |
RTL_USER_PROCESS_PARAMETERS = record | |
MaximumLength: LongWord; | |
Length: LongWord; | |
Flags: LongWord; | |
DebugFlags: LongWord; | |
ConsoleHandle: THandle; | |
ConsoleFlags: LongWord; | |
StdInputHandle: THandle; | |
StdOutputHandle: THandle; | |
StdErrorHandle: THandle; | |
CurrentDirectoryPath: UNICODE_STRING; | |
CurrentDirectoryHandle: THandle; | |
DllPath: UNICODE_STRING; | |
ImagePathName: UNICODE_STRING; | |
CommandLine: UNICODE_STRING; | |
end; | |
RTL_USER_PROCESS_PARAMETERS_WOW64 = record | |
MaximumLength: LongWord; | |
Length: LongWord; | |
Flags: LongWord; | |
DebugFlags: LongWord; | |
ConsoleHandle: LongWord; | |
ConsoleFlags: LongWord; | |
StdInputHandle: LongWord; | |
StdOutputHandle: LongWord; | |
StdErrorHandle: LongWord; | |
CurrentDirectoryPath: UNICODE_STRING_WOW64; | |
CurrentDirectoryHandle: LongWord; | |
DllPath: UNICODE_STRING_WOW64; | |
ImagePathName: UNICODE_STRING_WOW64; | |
CommandLine: UNICODE_STRING_WOW64; | |
end; | |
RTL_USER_PROCESS_PARAMETERS64 = record | |
MaximumLength: LongWord; | |
Length: LongWord; | |
Flags: LongWord; | |
DebugFlags: LongWord; | |
ConsoleHandle: UInt64; | |
ConsoleFlags: LongWord; | |
Reserved: LongWord; | |
StdInputHandle: UInt64; | |
StdOutputHandle: UInt64; | |
StdErrorHandle: UInt64; | |
CurrentDirectoryPath: UNICODE_STRING64; | |
CurrentDirectoryHandle: UInt64; | |
DllPath: UNICODE_STRING64; | |
ImagePathName: UNICODE_STRING64; | |
CommandLine: UNICODE_STRING64; | |
end; | |
VM_COUNTERS = record | |
PeakVirtualSize: LongWord; | |
VirtualSize: LongWord; | |
PageFaultCount: LongWord; | |
PeakWorkingSetSize: LongWord; | |
WorkingSetSize: LongWord; | |
QuotaPeakPagedPoolUsage: LongWord; | |
QuotaPagedPoolUsage: LongWord; | |
QuotaPeakNonPagedPoolUsage: LongWord; | |
QuotaNonPagedPoolUsage: LongWord; | |
PagefileUsage: LongWord; | |
PeakPagefileUsage: LongWord; | |
end; | |
PROCESSINFOCLASS = ( | |
ProcessBasicInformation, | |
ProcessQuotaLimits, | |
ProcessIoCounters, | |
ProcessVmCounters, | |
ProcessTimes, | |
ProcessBasePriority, | |
ProcessRaisePriority, | |
ProcessDebugPort, | |
ProcessExceptionPort, | |
ProcessAccessToken, | |
ProcessLdtInformation, | |
ProcessLdtSize, | |
ProcessDefaultHardErrorMode, | |
ProcessIoPortHandlers, // Note: this is kernel mode only | |
ProcessPooledUsageAndLimits, | |
ProcessWorkingSetWatch, | |
ProcessUserModeIOPL, | |
ProcessEnableAlignmentFaultFixup, | |
ProcessPriorityClass, | |
ProcessWx86Information, | |
ProcessHandleCount, | |
ProcessAffinityMask, | |
ProcessPriorityBoost, | |
ProcessDeviceMap, | |
ProcessSessionInformation, | |
ProcessForegroundInformation, | |
ProcessWow64Information, | |
ProcessImageFileName, | |
ProcessLUIDDeviceMapsEnabled, | |
ProcessBreakOnTermination, | |
ProcessDebugObjectHandle, | |
ProcessDebugFlags, | |
ProcessHandleTracing, | |
ProcessIoPriority, | |
ProcessExecuteFlags, | |
ProcessTlsInformation, | |
ProcessCookie, | |
ProcessImageInformation, | |
ProcessCycleTime, | |
ProcessPagePriority, | |
ProcessInstrumentationCallback, | |
ProcessThreadStackAllocation, | |
ProcessWorkingSetWatchEx, | |
ProcessImageFileNameWin32, | |
ProcessImageFileMapping, | |
ProcessAffinityUpdateMode, | |
ProcessMemoryAllocationMode, | |
ProcessGroupInformation, | |
ProcessTokenVirtualizationEnabled, | |
ProcessOwnerInformation, | |
ProcessWindowInformation, | |
ProcessHandleInformation, | |
ProcessMitigationPolicy, | |
ProcessDynamicFunctionTableInformation, | |
ProcessHandleCheckingMode, | |
ProcessKeepAliveCount, | |
ProcessRevokeFileHandles, | |
ProcessWorkingSetControl, | |
ProcessHandleTable, | |
ProcessCheckStackExtentsMode, | |
ProcessCommandLineInformation, | |
ProcessProtectionInformation, | |
MaxProcessInfoClass | |
); | |
SYSTEMINFOCLASS = ( | |
SystemBasicInformation, | |
Unknown, | |
SystemPerformanceInformation, | |
SystemInformationClassMax | |
); | |
NTStatus = LongWord; | |
SIZE_T = Cardinal; | |
_PROCESS_MEMORY_COUNTERS_EX = record | |
cb: LongWord; | |
PageFaultCount: LongWord; | |
PeakWorkingSetSize: SIZE_T; | |
WorkingSetSize: SIZE_T; | |
QuotaPeakPagedPoolUsage: SIZE_T; | |
QuotaPagedPoolUsage: SIZE_T; | |
QuotaPeakNonPagedPoolUsage: SIZE_T; | |
QuotaNonPagedPoolUsage: SIZE_T; | |
PagefileUsage: SIZE_T; | |
PeakPagefileUsage: SIZE_T; | |
PrivateUsage: SIZE_T; | |
end; | |
function NtQueryInformationProcess( | |
ProcessHandle: THandle; | |
ProcessInformationClass: PROCESSINFOCLASS; | |
ProcessInformation: Pointer; | |
ProcessInformationLength: LongWord; | |
out ReturnLength: LongWord | |
): NTStatus; stdcall; external 'ntdll.dll'; | |
function NtReadVirtualMemory( | |
ProcessHandle: THandle; | |
BaseAddress: Pointer; | |
Buffer: Pointer; | |
BufferLength: LongWord; | |
out ReturnLength: LongWord | |
): BOOL; stdcall; external 'ntdll.dll'; | |
function NtQuerySystemInformation( | |
SystemInformationClass: SYSTEMINFOCLASS; | |
SystemInformation: Pointer; | |
SystemInformationLength: ULONG; | |
ReturnLength: PDWORD | |
): NTStatus; stdcall; external 'ntdll.dll'; | |
// 64х-битные аналоги: | |
var | |
NtWow64QueryInformationProcess64: function( | |
ProcessHandle: THandle; | |
ProcessInformationClass: PROCESSINFOCLASS; | |
ProcessInformation: Pointer; | |
ProcessInformationLength: LongWord; | |
out ReturnLength: UInt64 | |
): NTStatus; stdcall; | |
NtWow64ReadVirtualMemory64: function( | |
ProcessHandle: THandle; | |
BaseAddress: UInt64; | |
Buffer: Pointer; | |
BufferLength: UInt64; | |
out ReturnLength: UInt64 | |
): BOOL; stdcall; | |
IsWow64Process: function(ProcessHandle: THandle; out Wow64Process: BOOL): BOOL; stdcall; | |
procedure GetProcessMemoryInfo(ProcessHandle: THandle; out ProcessMemoryCounters: _PROCESS_MEMORY_COUNTERS_EX; ProcessMemoryCountersSize: LongWord); stdcall; external 'psapi.dll'; | |
function GetProcessHandleCount(ProcessHandle: THandle; CounterPtr: Pointer): LongBool; stdcall; external 'kernel32.dll'; | |
function GetProcessId(Handle: THandle): LongWord; stdcall; external 'kernel32.dll'; | |
function Process32FirstA(hSnapshot: THandle; var lppe: TProcessEntry32A): BOOL; stdcall; external 'kernel32.dll' name 'Process32First'; | |
function Process32NextA(hSnapshot: THandle; var lppe: TProcessEntry32A): BOOL; stdcall; external 'kernel32.dll' name 'Process32Next'; | |
implementation | |
type | |
{$IFDEF CPUX64} | |
NativeUInt = UInt64; | |
{$ELSE} | |
NativeUInt = LongWord; | |
{$ENDIF} | |
var | |
_Is64BitWindows: BOOL = FALSE; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
function ProcessIDToHandle(ProcessID: LongWord; AccessRights: LongWord): THandle; | |
begin | |
Result := OpenProcess( | |
AccessRights, | |
FALSE, | |
ProcessID | |
); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function HandleToProcessID(ProcessHandle: THandle): LongWord; | |
begin | |
Result := GetProcessID(ProcessHandle); | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
{$IFDEF DEBUG_PRIVILEGE} | |
const | |
SE_DEBUG_NAME = 'SeDebugPrivilege'; | |
// Установка привилегий | |
function NTSetPrivilege(sPrivilege: AnsiString; bEnabled: Boolean): Boolean; | |
var | |
hToken: THandle; | |
TokenPriv: TOKEN_PRIVILEGES; | |
PrevTokenPriv: TOKEN_PRIVILEGES; | |
ReturnLength: Cardinal; | |
begin | |
if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then | |
begin | |
if LookupPrivilegeValueA(nil, PAnsiChar(sPrivilege), TokenPriv.Privileges[0].Luid) then | |
begin | |
TokenPriv.PrivilegeCount := 1; | |
case bEnabled of | |
True: TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; | |
False: TokenPriv.Privileges[0].Attributes := 0; | |
end; | |
ReturnLength := 0; | |
PrevTokenPriv := TokenPriv; | |
AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv), | |
PrevTokenPriv, ReturnLength); | |
end; | |
CloseHandle(hToken); | |
end; | |
Result := GetLastError = ERROR_SUCCESS; | |
end; | |
{$ENDIF} | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
function Is64BitWindows: BOOL; | |
{$IFNDEF CPUX64} | |
var | |
Wow64Process: Bool; | |
{$ENDIF} | |
begin | |
IsWow64Process := GetProcAddress(GetModuleHandle(kernel32), 'IsWow64Process'); | |
{$IFDEF CPUX64} | |
Result := True; | |
{$ELSE} | |
Wow64Process := false; | |
if Assigned(IsWow64Process) then Wow64Process := IsWow64Process(GetCurrentProcess, Wow64Process) and Wow64Process; | |
Result := Wow64Process; | |
{$ENDIF} | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
procedure _InitFunctions; | |
var | |
NtdllHandle: THandle; | |
begin | |
_Is64BitWindows := Is64BitWindows; | |
if _Is64BitWindows then | |
begin | |
// Ищем адреса 64х-битных функций: | |
NtdllHandle := GetModuleHandleA('ntdll.dll'); | |
{$IFDEF CPUX64} | |
NtWow64QueryInformationProcess64 := GetProcAddress(NtdllHandle, 'NtQueryInformationProcess'); | |
NtWow64ReadVirtualMemory64 := GetProcAddress(NtdllHandle, 'NtReadVirtualMemory'); | |
{$ELSE} | |
NtWow64QueryInformationProcess64 := GetProcAddress(NtdllHandle, 'NtWow64QueryInformationProcess64'); | |
NtWow64ReadVirtualMemory64 := GetProcAddress(NtdllHandle, 'NtWow64ReadVirtualMemory64'); | |
{$ENDIF} | |
end | |
else | |
begin | |
_Is64BitWindows := false; | |
end; | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
procedure _GetModulesList32(ProcessHandle: THandle; LDRAddress: Pointer; out Modules: TModulesList); | |
var | |
LdrInfo: PEB_LDR_DATA; | |
ModuleInfo: LDR_MODULE; | |
StringBuffer: Pointer; | |
StringPointer: Pointer; | |
StringLength: Word; | |
BytesRead: LongWord; | |
begin | |
// Читаем PEB_LDR_DATA: | |
NtReadVirtualMemory(ProcessHandle, LDRAddress, @LdrInfo, SizeOf(LdrInfo), BytesRead); | |
// Читаем LDR_MODULE_INFO: | |
NtReadVirtualMemory(ProcessHandle, LdrInfo.InLoadModuleOrderList.ForwardLDRModule, @ModuleInfo, SizeOf(ModuleInfo), BytesRead); | |
FillChar(Modules, SizeOf(Modules), #0); | |
while (LdrInfo.InLoadModuleOrderList.ForwardLDRModule <> nil) and (BytesRead <> 0) and (ModuleInfo.BaseAddress <> nil) do | |
begin | |
Inc(Modules.Length); | |
SetLength(Modules.Modules, Modules.Length); | |
// Получаем численную информацию: | |
with Modules do | |
begin | |
Modules[Length - 1].BaseAddress := UInt64(ModuleInfo.BaseAddress); | |
Modules[Length - 1].EntryAddress := UInt64(ModuleInfo.EntryPoint); | |
Modules[Length - 1].SizeOfImage := UInt64(ModuleInfo.SizeOfImage); | |
end; | |
// Читаем полный путь: | |
StringPointer := ModuleInfo.FullDLLName.Buffer; | |
StringLength := ModuleInfo.FullDLLName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtReadVirtualMemory(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
Modules.Modules[Modules.Length - 1].FullPath := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Читаем имя библиотеки: | |
StringPointer := ModuleInfo.BaseDLLName.Buffer; | |
StringLength := ModuleInfo.BaseDLLName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtReadVirtualMemory(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
Modules.Modules[Modules.Length - 1].ModuleName := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Читаем следующий в списке LDR_MODULE_INFO: | |
NtReadVirtualMemory(ProcessHandle, ModuleInfo.InLoadModuleOrderList.ForwardLDRModule, @ModuleInfo, SizeOf(ModuleInfo), BytesRead); | |
end; | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure _GetProcessInfo32(ProcessID: LongWord; out ProcessInfo: PROCESS_INFO); | |
var | |
ProcessHandle: THandle; | |
ProcessBasicInfo: PROCESS_BASIC_INFORMATION; | |
PEBInfo: PEB; | |
UserParameters: RTL_USER_PROCESS_PARAMETERS; | |
BytesRead: UInt; | |
ReturnLength: UInt; | |
//ReturnStatus: LongWord; | |
_Is64BitProcess: BOOL; | |
CurrentDirectory: AnsiString; | |
ImageName: AnsiString; | |
CmdLine: AnsiString; | |
StringBuffer: Pointer; | |
StringPointer: Pointer; | |
StringLength: Word; | |
TlHelp32Info: TProcessInfo; | |
LocalHandlesCount: LongWord; | |
MemoryCounters: _PROCESS_MEMORY_COUNTERS_EX; | |
begin | |
FillChar(ProcessBasicInfo, SizeOf(ProcessBasicInfo), #0); | |
FillChar(PEBInfo, SizeOf(PEBInfo), #0); | |
FillChar(UserParameters, SizeOf(UserParameters), #0); | |
FillChar(ProcessInfo, SizeOf(ProcessInfo), #0); | |
ProcessHandle := ProcessIDToHandle(ProcessID); | |
// Получаем разрядность процесса: | |
_Is64BitProcess := FALSE; // Процессы заведомо 32х-битные | |
// Заполняем PROCESS_BASIC_INFORMATION: | |
NtQueryInformationProcess(ProcessHandle, ProcessBasicInformation, @ProcessBasicInfo, SizeOf(ProcessBasicInfo), ReturnLength); | |
// Читаем PEB: | |
NtReadVirtualMemory(ProcessHandle, ProcessBasicInfo.PebBaseAddress, @PEBInfo, SizeOf(PEBInfo), BytesRead); | |
// Читаем RTL_USER_PROCESS_PARAMETERS: | |
NtReadVirtualMemory(ProcessHandle, PEBInfo.ProcessParameters, @UserParameters, SizeOf(UserParameters), BytesRead); | |
// Получаем список загруженных модулей: | |
_GetModulesList32(ProcessHandle, PEBInfo.Ldr, ProcessInfo.ModulesList); | |
// Читаем строки: | |
// CommandLine: | |
StringPointer := UserParameters.CommandLine.Buffer; | |
StringLength := UserParameters.CommandLine.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtReadVirtualMemory(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
CmdLine := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// ImageFilePath: | |
StringPointer := UserParameters.ImagePathName.Buffer; | |
StringLength := UserParameters.ImagePathName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtReadVirtualMemory(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
ImageName := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
//CurrentDirectoryPath: | |
StringPointer := UserParameters.CurrentDirectoryPath.Buffer; | |
StringLength := UserParameters.CurrentDirectoryPath.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtReadVirtualMemory(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
CurrentDirectory := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Получаем информацию о памяти процесса: | |
FillChar(MemoryCounters, SizeOf(MemoryCounters), #0); | |
GetProcessMemoryInfo(ProcessHandle, MemoryCounters, SizeOf(MemoryCounters)); | |
// Получаем информацию из TlHelp32: | |
FillChar(TlHelp32Info, SizeOf(TlHelp32Info), #0); | |
TlHelp32Info := GetTlHelp32ProcessInfo(ProcessID); | |
// Получаем количество открытых хэндлов: | |
GetProcessHandleCount(ProcessHandle, @LocalHandlesCount); | |
// Возвращаем результат: | |
with ProcessInfo do | |
begin | |
Handle := ProcessHandle; | |
ID := ProcessBasicInfo.UniqueProcessId; | |
InheritedFromID := ProcessBasicInfo.InheritedFromUniqueProcessId; | |
SessionID := PEBInfo.SessionID; | |
Priority := ProcessBasicInfo.BasePriority; | |
AffinityMask := ProcessBasicInfo.AffinityMask; | |
IsDebugged := PEBInfo.BeingDebugged; | |
ExitStatus := ProcessBasicInfo.ExitStatus; | |
ThreadsCount := TlHelp32Info.ThreadsCount; | |
HandlesCount := LocalHandlesCount; | |
ReservedMemory := MemoryCounters.PrivateUsage; | |
ImageBaseAddress := UInt64(PEBInfo.ImageBaseAddress); | |
LdrAddress := UInt64(PEBInfo.Ldr); | |
PEBAddress := UInt64(ProcessBasicInfo.PebBaseAddress); | |
ConsoleHandle := UserParameters.ConsoleHandle; | |
StdInputHandle := UserParameters.StdInputHandle; | |
StdOutputHandle := UserParameters.StdOutputHandle; | |
StdErrorHandle := UserParameters.StdErrorHandle; | |
ProcessName := TlHelp32Info.ExeFile; | |
CurrentDirectoryPath := CurrentDirectory; | |
ImagePathName := ImageName; | |
CommandLine := CmdLine; | |
Is64BitProcess := _Is64BitProcess; | |
end; | |
CloseHandle(ProcessHandle); | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
procedure _GetModulesList64(ProcessHandle: THandle; LDRAddress: UInt64; out Modules: TModulesList); | |
var | |
LdrInfo: PEB_LDR_DATA64; | |
ModuleInfo: LDR_MODULE64; | |
StringBuffer: Pointer; | |
StringPointer: UInt64; | |
StringLength: Word; | |
BytesRead: UInt64; | |
begin | |
// Читаем PEB_LDR_DATA: | |
NtWow64ReadVirtualMemory64(ProcessHandle, LDRAddress, @LdrInfo, SizeOf(LdrInfo), BytesRead); | |
// Читаем LDR_MODULE_INFO: | |
NtWow64ReadVirtualMemory64(ProcessHandle, UInt64(LdrInfo.InLoadModuleOrderList.ForwardLDRModule), @ModuleInfo, SizeOf(ModuleInfo), BytesRead); | |
FillChar(Modules, SizeOf(Modules), #0); | |
while (LdrInfo.InLoadModuleOrderList.ForwardLDRModule <> 0) and (BytesRead <> 0) and (ModuleInfo.BaseAddress <> 0) do | |
begin | |
Inc(Modules.Length); | |
SetLength(Modules.Modules, Modules.Length); | |
// Получаем численную информацию: | |
with Modules do | |
begin | |
Modules[Length - 1].BaseAddress := ModuleInfo.BaseAddress; | |
Modules[Length - 1].EntryAddress := ModuleInfo.EntryPoint; | |
Modules[Length - 1].SizeOfImage := ModuleInfo.SizeOfImage; | |
end; | |
// Читаем полный путь: | |
StringPointer := ModuleInfo.FullDLLName.Buffer; | |
StringLength := ModuleInfo.FullDLLName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
Modules.Modules[Modules.Length - 1].FullPath := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Читаем имя библиотеки: | |
StringPointer := ModuleInfo.BaseDLLName.Buffer; | |
StringLength := ModuleInfo.BaseDLLName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
Modules.Modules[Modules.Length - 1].ModuleName := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Читаем следующий в списке LDR_MODULE_INFO: | |
NtWow64ReadVirtualMemory64(ProcessHandle, ModuleInfo.InLoadModuleOrderList.ForwardLDRModule, @ModuleInfo, SizeOf(ModuleInfo), BytesRead); | |
end; | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure _GetProcessInfo64(ProcessID: LongWord; out ProcessInfo: PROCESS_INFO); | |
var | |
ProcessHandle: THandle; | |
ProcessBasicInfo: PROCESS_BASIC_INFORMATION64; | |
PEBInfo: PEB64; | |
UserParameters: RTL_USER_PROCESS_PARAMETERS64; | |
BytesRead: UInt64; | |
ReturnLength: UInt64; | |
//ReturnStatus: LongWord; | |
_Is64BitProcess: BOOL; | |
CurrentDirectory: AnsiString; | |
ImageName: AnsiString; | |
CmdLine: AnsiString; | |
StringBuffer: Pointer; | |
StringPointer: UInt64; | |
StringLength: Word; | |
TlHelp32Info: TProcessInfo; | |
LocalHandlesCount: LongWord; | |
MemoryCounters: _PROCESS_MEMORY_COUNTERS_EX; | |
begin | |
FillChar(ProcessBasicInfo, SizeOf(ProcessBasicInfo), #0); | |
FillChar(PEBInfo, SizeOf(PEBInfo), #0); | |
FillChar(UserParameters, SizeOf(UserParameters), #0); | |
FillChar(ProcessInfo, SizeOf(ProcessInfo), #0); | |
ProcessHandle := ProcessIDToHandle(ProcessID); | |
// Получаем разрядность процесса: | |
IsWow64Process(ProcessHandle, _Is64BitProcess); | |
_Is64BitProcess := not _Is64BitProcess; | |
// Заполняем PROCESS_BASIC_INFORMATION: | |
NtWow64QueryInformationProcess64(ProcessHandle, ProcessBasicInformation, @ProcessBasicInfo, SizeOf(ProcessBasicInfo), ReturnLength); | |
// Читаем PEB: | |
NtWow64ReadVirtualMemory64(ProcessHandle, ProcessBasicInfo.PebBaseAddress, @PEBInfo, SizeOf(PEBInfo), BytesRead); | |
// Читаем RTL_USER_PROCESS_PARAMETERS: | |
NtWow64ReadVirtualMemory64(ProcessHandle, PEBInfo.ProcessParameters, @UserParameters, SizeOf(UserParameters), BytesRead); | |
// Получаем список загруженных модулей: | |
_GetModulesList64(ProcessHandle, PEBInfo.Ldr, ProcessInfo.ModulesList); | |
// Читаем строки: | |
// CommandLine: | |
StringPointer := UserParameters.CommandLine.Buffer; | |
StringLength := UserParameters.CommandLine.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
CmdLine := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// ImageFilePath: | |
StringPointer := UserParameters.ImagePathName.Buffer; | |
StringLength := UserParameters.ImagePathName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
ImageName := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
//CurrentDirectoryPath: | |
StringPointer := UserParameters.CurrentDirectoryPath.Buffer; | |
StringLength := UserParameters.CurrentDirectoryPath.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
CurrentDirectory := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Получаем информацию о памяти процесса: | |
FillChar(MemoryCounters, SizeOf(MemoryCounters), #0); | |
GetProcessMemoryInfo(ProcessHandle, MemoryCounters, SizeOf(MemoryCounters)); | |
// Получаем информацию из TlHelp32: | |
FillChar(TlHelp32Info, SizeOf(TlHelp32Info), #0); | |
TlHelp32Info := GetTlHelp32ProcessInfo(ProcessID); | |
// Получаем количество открытых хэндлов: | |
GetProcessHandleCount(ProcessHandle, @LocalHandlesCount); | |
// Возвращаем результат: | |
with ProcessInfo do | |
begin | |
Handle := ProcessHandle; | |
ID := ProcessBasicInfo.UniqueProcessId; | |
InheritedFromID := ProcessBasicInfo.InheritedFromUniqueProcessId; | |
SessionID := PEBInfo.SessionID; | |
Priority := ProcessBasicInfo.BasePriority; | |
AffinityMask := ProcessBasicInfo.AffinityMask; | |
IsDebugged := PEBInfo.BeingDebugged; | |
ExitStatus := ProcessBasicInfo.ExitStatus; | |
ThreadsCount := TlHelp32Info.ThreadsCount; | |
handlesCount := LocalHandlesCount; | |
ReservedMemory := MemoryCounters.PrivateUsage; | |
ImageBaseAddress := PEBInfo.ImageBaseAddress; | |
LdrAddress := PEBInfo.Ldr; | |
PEBAddress := ProcessBasicInfo.PebBaseAddress; | |
ConsoleHandle := UserParameters.ConsoleHandle; | |
StdInputHandle := UserParameters.StdInputHandle; | |
StdOutputHandle := UserParameters.StdOutputHandle; | |
StdErrorHandle := UserParameters.StdErrorHandle; | |
ProcessName := TlHelp32Info.ExeFile; | |
CurrentDirectoryPath := CurrentDirectory; | |
ImagePathName := ImageName; | |
CommandLine := CmdLine; | |
Is64BitProcess := _Is64BitProcess; | |
end; | |
CloseHandle(ProcessHandle); | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
procedure _GetModulesListWow64(ProcessHandle: THandle; LDRAddress: Pointer32; out Modules: TModulesList); | |
var | |
LdrInfo: PEB_LDR_DATA_WOW64; | |
ModuleInfo: LDR_MODULE_WOW64; | |
StringBuffer: Pointer; | |
StringPointer: UInt64; | |
StringLength: Word; | |
BytesRead: UInt64; | |
begin | |
// Читаем PEB_LDR_DATA: | |
NtWow64ReadVirtualMemory64(ProcessHandle, UInt64(LDRAddress), @LdrInfo, SizeOf(LdrInfo), BytesRead); | |
// Читаем LDR_MODULE_INFO: | |
NtWow64ReadVirtualMemory64(ProcessHandle, UInt64(LdrInfo.InLoadModuleOrderList.ForwardLDRModule), @ModuleInfo, SizeOf(ModuleInfo), BytesRead); | |
FillChar(Modules, SizeOf(Modules), #0); | |
while (LdrInfo.InLoadModuleOrderList.ForwardLDRModule <> 0) and (BytesRead <> 0) and (ModuleInfo.BaseAddress <> 0) do | |
begin | |
Inc(Modules.Length); | |
SetLength(Modules.Modules, Modules.Length); | |
// Получаем численную информацию: | |
with Modules do | |
begin | |
Modules[Length - 1].BaseAddress := ModuleInfo.BaseAddress; | |
Modules[Length - 1].EntryAddress := ModuleInfo.EntryPoint; | |
Modules[Length - 1].SizeOfImage := ModuleInfo.SizeOfImage; | |
end; | |
// Читаем полный путь: | |
StringPointer := ModuleInfo.FullDLLName.Buffer; | |
StringLength := ModuleInfo.FullDLLName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
Modules.Modules[Modules.Length - 1].FullPath := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Читаем имя библиотеки: | |
StringPointer := ModuleInfo.BaseDLLName.Buffer; | |
StringLength := ModuleInfo.BaseDLLName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
Modules.Modules[Modules.Length - 1].ModuleName := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Читаем следующий в списке LDR_MODULE_INFO: | |
NtWow64ReadVirtualMemory64(ProcessHandle, ModuleInfo.InLoadModuleOrderList.ForwardLDRModule, @ModuleInfo, SizeOf(ModuleInfo), BytesRead); | |
end; | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure _GetProcessInfoWow64(ProcessID: LongWord; out ProcessInfo: PROCESS_INFO); | |
var | |
ProcessHandle: THandle; | |
ProcessBasicInfo: PROCESS_BASIC_INFORMATION64; | |
ProcessBasicInfoWow64: PROCESS_BASIC_INFORMATION_WOW64; | |
PEBInfo: PEB_WOW64; | |
UserParameters: RTL_USER_PROCESS_PARAMETERS_WOW64; | |
BytesRead: UInt64; | |
ReturnLength: UInt64; | |
//ReturnStatus: LongWord; | |
_Is64BitProcess: BOOL; | |
CurrentDirectory: AnsiString; | |
ImageName: AnsiString; | |
CmdLine: AnsiString; | |
StringBuffer: Pointer; | |
StringPointer: UInt64; | |
StringLength: Word; | |
TlHelp32Info: TProcessInfo; | |
LocalHandlesCount: LongWord; | |
MemoryCounters: _PROCESS_MEMORY_COUNTERS_EX; | |
begin | |
FillChar(ProcessBasicInfo, SizeOf(ProcessBasicInfo), #0); | |
FillChar(PEBInfo, SizeOf(PEBInfo), #0); | |
FillChar(UserParameters, SizeOf(UserParameters), #0); | |
FillChar(ProcessInfo, SizeOf(ProcessInfo), #0); | |
ProcessHandle := ProcessIDToHandle(ProcessID); | |
// Получаем разрядность процесса: | |
IsWow64Process(ProcessHandle, _Is64BitProcess); | |
_Is64BitProcess := not _Is64BitProcess; | |
// Заполняем PROCESS_BASIC_INFORMATION: | |
NtWow64QueryInformationProcess64(ProcessHandle, ProcessBasicInformation, @ProcessBasicInfo, SizeOf(ProcessBasicInfo), ReturnLength); | |
// Получаем адрес 32х-битного PEB: | |
NtWow64QueryInformationProcess64(ProcessHandle, ProcessWow64Information, @ProcessBasicInfoWow64, SizeOf(ProcessBasicInfoWow64), ReturnLength); | |
// Читаем PEB: | |
//NtWow64ReadVirtualMemory64(ProcessHandle, ProcessBasicInfo.PebBaseAddress, @PEBInfo, SizeOf(PEBInfo), BytesRead); | |
NtWow64ReadVirtualMemory64(ProcessHandle, ProcessBasicInfoWow64.Wow64PebAddress, @PEBInfo, SizeOf(PEBInfo), BytesRead); | |
// Читаем RTL_USER_PROCESS_PARAMETERS: | |
NtWow64ReadVirtualMemory64(ProcessHandle, UInt64(PEBInfo.ProcessParameters), @UserParameters, SizeOf(UserParameters), BytesRead); | |
// Получаем список загруженных модулей: | |
_GetModulesListWow64(ProcessHandle, UInt64(PEBInfo.Ldr), ProcessInfo.ModulesList); | |
// Читаем строки: | |
// CommandLine: | |
StringPointer := UserParameters.CommandLine.Buffer; | |
StringLength := UserParameters.CommandLine.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
CmdLine := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// ImageFilePath: | |
StringPointer := UserParameters.ImagePathName.Buffer; | |
StringLength := UserParameters.ImagePathName.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
ImageName := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
//CurrentDirectoryPath: | |
StringPointer := UserParameters.CurrentDirectoryPath.Buffer; | |
StringLength := UserParameters.CurrentDirectoryPath.Length; | |
GetMem(StringBuffer, StringLength + 2); | |
FillChar(StringBuffer^, StringLength + 2, #0); | |
NtWow64ReadVirtualMemory64(ProcessHandle, StringPointer, StringBuffer, StringLength, BytesRead); | |
CurrentDirectory := WideToAnsi(PWideChar(StringBuffer)); | |
FreeMem(StringBuffer); | |
// Получаем информацию о памяти процесса: | |
FillChar(MemoryCounters, SizeOf(MemoryCounters), #0); | |
GetProcessMemoryInfo(ProcessHandle, MemoryCounters, SizeOf(MemoryCounters)); | |
// Получаем информацию из TlHelp32: | |
FillChar(TlHelp32Info, SizeOf(TlHelp32Info), #0); | |
TlHelp32Info := GetTlHelp32ProcessInfo(ProcessID); | |
// Получаем количество открытых хэндлов: | |
GetProcessHandleCount(ProcessHandle, @LocalHandlesCount); | |
// Возвращаем результат: | |
with ProcessInfo do | |
begin | |
Handle := ProcessHandle; | |
ID := ProcessBasicInfo.UniqueProcessId; | |
InheritedFromID := ProcessBasicInfo.InheritedFromUniqueProcessId; | |
SessionID := PEBInfo.SessionID; | |
Priority := ProcessBasicInfo.BasePriority; | |
AffinityMask := ProcessBasicInfo.AffinityMask; | |
IsDebugged := PEBInfo.BeingDebugged; | |
ExitStatus := ProcessBasicInfo.ExitStatus; | |
ThreadsCount := TlHelp32Info.ThreadsCount; | |
HandlesCount := LocalHandlesCount; | |
ReservedMemory := MemoryCounters.PrivateUsage; | |
ImageBaseAddress := UInt64(PEBInfo.ImageBaseAddress); | |
LdrAddress := UInt64(PEBInfo.Ldr); | |
PEBAddress := ProcessBasicInfo.PebBaseAddress; | |
ConsoleHandle := UserParameters.ConsoleHandle; | |
StdInputHandle := UserParameters.StdInputHandle; | |
StdOutputHandle := UserParameters.StdOutputHandle; | |
StdErrorHandle := UserParameters.StdErrorHandle; | |
ProcessName := TlHelp32Info.ExeFile; | |
CurrentDirectoryPath := CurrentDirectory; | |
ImagePathName := ImageName; | |
CommandLine := CmdLine; | |
Is64BitProcess := _Is64BitProcess; | |
end; | |
CloseHandle(ProcessHandle); | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
function GetProcessInfo(ProcessID: LongWord; out ProcessInfo: PROCESS_INFO; Process32_64CompatibleMode: Boolean = false): Boolean; | |
var | |
IsTarget64Bit: LongBool; | |
TargetHandle: THandle; | |
begin | |
FillChar(ProcessInfo, SizeOf(ProcessInfo), #0); | |
TargetHandle := ProcessIDToHandle(ProcessID); | |
Result := (TargetHandle <> INVALID_HANDLE_VALUE) or (TargetHandle <> 0); | |
if not Result then Exit; | |
IsWow64Process(TargetHandle, IsTarget64Bit); | |
IsTarget64Bit := not IsTarget64Bit; | |
CloseHandle(TargetHandle); | |
{$IFDEF CPUX64} | |
if IsTarget64Bit then | |
_GetProcessInfo64(ProcessID, ProcessInfo) | |
else | |
if Process32_64CompatibleMode then | |
_GetProcessInfo64(ProcessID, ProcessInfo) | |
else | |
_GetProcessInfoWow64(ProcessID, ProcessInfo); | |
{$ELSE} | |
if _Is64BitWindows then | |
if IsTarget64Bit then | |
_GetProcessInfo64(ProcessID, ProcessInfo) | |
else | |
if Process32_64CompatibleMode then | |
_GetProcessInfo64(ProcessID, ProcessInfo) | |
else | |
_GetProcessInfo32(ProcessID, ProcessInfo) | |
else | |
_GetProcessInfo32(ProcessID, ProcessInfo); | |
{$ENDIF} | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function GetProcessBasicInfo(ProcessID: LongWord; out ProcessBasicInfo: TProcessBasicInfo): Boolean; | |
var | |
ProcessBasicInfo32: {$IFDEF CPUX64}PROCESS_BASIC_INFORMATION64{$ELSE}PROCESS_BASIC_INFORMATION{$ENDIF}; | |
ProcessBasicInfo64: PROCESS_BASIC_INFORMATION64; | |
ProcessHandle: THandle; | |
ReturnLength32: LongWord; | |
ReturnLength64: UInt64; | |
begin | |
ProcessHandle := ProcessIDtoHandle(ProcessID); | |
Result := (ProcessHandle <> INVALID_HANDLE_VALUE) or (ProcessHandle <> 0); | |
if not Result then Exit; | |
if Is64BitProcess(ProcessID) then | |
begin | |
NtWow64QueryInformationProcess64(ProcessHandle, ProcessBasicInformation, @ProcessBasicInfo64, SizeOf(ProcessBasicInfo64), ReturnLength64); | |
ProcessBasicInfo.ExitStatus := ProcessBasicInfo64.ExitStatus; | |
ProcessBasicInfo.AffinityMask := ProcessBasicInfo64.AffinityMask; | |
ProcessBasicInfo.BasePriority := ProcessBasicInfo64.BasePriority; | |
ProcessBasicInfo.UniqueProcessId := ProcessBasicInfo64.UniqueProcessId; | |
ProcessBasicInfo.InheritedFromUniqueProcessId := ProcessBasicInfo64.InheritedFromUniqueProcessId; | |
end | |
else | |
begin | |
NtQueryInformationProcess(ProcessHandle, ProcessBasicInformation, @ProcessBasicInfo32, SizeOf(ProcessBasicInfo32), ReturnLength32); | |
ProcessBasicInfo.ExitStatus := ProcessBasicInfo32.ExitStatus; | |
ProcessBasicInfo.AffinityMask := ProcessBasicInfo32.AffinityMask; | |
ProcessBasicInfo.BasePriority := ProcessBasicInfo32.BasePriority; | |
ProcessBasicInfo.UniqueProcessId := ProcessBasicInfo32.UniqueProcessId; | |
ProcessBasicInfo.InheritedFromUniqueProcessId := ProcessBasicInfo32.InheritedFromUniqueProcessId; | |
end; | |
CloseHandle(ProcessHandle); | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
function Is64BitProcess(ProcessID: LongWord): LongBool; | |
var | |
ProcessHandle: NativeUInt; | |
begin | |
ProcessHandle := ProcessIDtoHandle(ProcessID); | |
if _Is64BitWindows then | |
begin | |
IsWow64Process(ProcessHandle, Result); | |
Result := not Result; | |
end | |
else | |
begin | |
Result := False; | |
end; | |
CloseHandle(ProcessHandle); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function IsProcessLaunched(ProcessName: AnsiString): Boolean; | |
var | |
hSnapshot: THandle; | |
ProcessInfo: TProcessInfo; | |
begin | |
Result := false; | |
ProcessInfo.Size := SizeOf(ProcessInfo); | |
hSnapshot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
if Process32FirstA(hSnapshot, ProcessInfo) then | |
begin | |
if ProcessInfo.ExeFile = ProcessName then | |
begin | |
Result := true; | |
end | |
else | |
begin | |
while Process32NextA(hSnapshot, ProcessInfo) do | |
begin | |
if ProcessInfo.ExeFile = ProcessName then | |
begin | |
Result := true; | |
Break; | |
end; | |
end; | |
end; | |
end; | |
CloseHandle(hSnapshot); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function IsProcessLaunched(ProcessID: LongWord): Boolean; | |
var | |
ProcessHandle: THandle; | |
begin | |
ProcessHandle := OpenProcess(PROCESS_VM_READ, FALSE, ProcessID); | |
Result := ProcessHandle <> 0; | |
if Result then CloseHandle(ProcessHandle); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function IsLibInProcess(LibName: AnsiString; ProcessID: LongWord): Boolean; | |
var | |
ProcessInfo: PROCESS_INFO; | |
I: LongWord; | |
begin | |
Result := False; | |
GetProcessInfo(ProcessID, ProcessInfo); | |
if ProcessInfo.ModulesList.Length > 0 then | |
for I := 0 to ProcessInfo.ModulesList.Length - 1 do | |
if ProcessInfo.ModulesList.Modules[I].ModuleName = LibName then | |
begin | |
Result := True; | |
Exit; | |
end; | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function GetProcessIdFromThreadID(ThreadID: LongWord): LongWord; | |
var | |
TlHelpHandle: LongWord; | |
ThreadEntry32: TThreadEntry32; | |
begin | |
Result := 0; | |
TlHelpHandle := CreateToolHelp32Snapshot(TH32CS_SNAPTHREAD, 0); | |
if TlHelpHandle <> INVALID_HANDLE_VALUE then | |
begin | |
ThreadEntry32.Size := SizeOf(TThreadEntry32); | |
if Thread32First(TlHelpHandle, tagTHREADENTRY32(ThreadEntry32)) then | |
repeat | |
if ThreadEntry32.ThreadID = ThreadID then | |
Result := ThreadEntry32.OwnerProcessID; | |
until not Thread32Next(TlHelpHandle, tagTHREADENTRY32(ThreadEntry32)); | |
CloseHandle(TlHelpHandle); | |
end; | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure GetProcessList(out ProcessList: TProcessList); | |
var | |
hSnapshot: THandle; | |
ProcessInfo: TProcessInfo; | |
Size: LongWord; | |
begin | |
Size := 0; | |
SetLength(ProcessList, Size); | |
ProcessInfo.Size := SizeOf(ProcessInfo); | |
hSnapshot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
if Process32FirstA(hSnapshot, ProcessInfo) then | |
begin | |
Inc(Size); | |
SetLength(ProcessList, Size); | |
ProcessList[Size - 1] := ProcessInfo; | |
while Process32NextA(hSnapshot, ProcessInfo) do | |
begin | |
Inc(Size); | |
SetLength(ProcessList, Size); | |
ProcessList[Size - 1] := ProcessInfo; | |
end; | |
end; | |
CloseHandle(hSnapshot); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function GetTlHelp32ProcessInfo(ProcessID: LongWord): TProcessInfo; overload; | |
var | |
hSnapshot: THandle; | |
ProcessInfo: TProcessInfo; | |
begin | |
FillChar(Result, SizeOf(Result), #0); | |
ProcessInfo.Size := SizeOf(ProcessInfo); | |
hSnapshot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
if Process32FirstA(hSnapshot, ProcessInfo) then | |
begin | |
if ProcessInfo.ProcessID = ProcessID then | |
begin | |
Result := ProcessInfo; | |
end | |
else | |
begin | |
while Process32NextA(hSnapshot, ProcessInfo) do | |
begin | |
if ProcessInfo.ProcessID = ProcessID then | |
begin | |
Result := ProcessInfo; | |
Break; | |
end; | |
end; | |
end; | |
end; | |
CloseHandle(hSnapshot); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function GetTlHelp32ProcessInfo(ProcessName: AnsiString): TProcessInfo; overload; | |
var | |
hSnapshot: THandle; | |
ProcessInfo: TProcessInfo; | |
begin | |
FillChar(Result, SizeOf(Result), #0); | |
ProcessInfo.Size := SizeOf(ProcessInfo); | |
hSnapshot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
if Process32FirstA(hSnapshot, ProcessInfo) then | |
begin | |
if ProcessInfo.ExeFile = ProcessName then | |
begin | |
Result := ProcessInfo; | |
end | |
else | |
begin | |
while Process32NextA(hSnapshot, ProcessInfo) do | |
begin | |
if ProcessInfo.ExeFile = ProcessName then | |
begin | |
Result := ProcessInfo; | |
Break; | |
end; | |
end; | |
end; | |
end; | |
CloseHandle(hSnapshot); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure StartProcess(const CommandLine: string; out ProcessHandle: THandle; out ProcessID: LongWord); | |
var | |
ProcessInfo: _PROCESS_INFORMATION; | |
StartupInfo: _STARTUPINFO; | |
begin | |
FillChar(StartupInfo, SizeOf(StartupInfo), #0); | |
FillChar(ProcessInfo, SizeOf(ProcessInfo), #0); | |
StartupInfo.wShowWindow := SW_SHOWNORMAL; | |
CreateProcess( | |
nil, | |
PChar(CommandLine), | |
nil, | |
nil, | |
FALSE, | |
0, | |
nil, | |
nil, | |
StartupInfo, | |
ProcessInfo | |
); | |
CloseHandle(ProcessInfo.hThread); | |
ProcessHandle := ProcessInfo.hProcess; | |
ProcessID := ProcessInfo.dwProcessId; | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure WaitProcess(ProcessID: LongWord); inline; | |
var | |
ProcessHandle: THandle; | |
begin | |
ProcessHandle := OpenProcess(SYNCHRONIZE, FALSE, ProcessID); | |
if ProcessHandle = 0 then Exit; | |
WaitForSingleObject(ProcessHandle, INFINITE); | |
CloseHandle(ProcessHandle); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure KillProcess(ProcessID: LongWord); overload; | |
var | |
ProcessHandle: THandle; | |
begin | |
ProcessHandle := ProcessIDToHandle(ProcessID, PROCESS_TERMINATE); | |
TerminateProcess(ProcessHandle, 0); | |
CloseHandle(ProcessHandle); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
procedure KillProcess(ProcessName: AnsiString; CanKillSelf: Boolean = False); overload; | |
var | |
ProcessList: TProcessList; | |
ProcessListCount: Integer; | |
I: Integer; | |
CurrentID: LongWord; | |
NeedToKillSelf: Boolean; | |
begin | |
GetProcessList(ProcessList); | |
CurrentID := GetCurrentProcessID; | |
ProcessListCount := Length(ProcessList); | |
if ProcessListCount = 0 then Exit; | |
NeedToKillSelf := False; | |
for I := 0 to ProcessListCount - 1 do | |
begin | |
if ProcessList[I].ExeFile = ProcessName then | |
if ProcessList[I].ProcessID = CurrentID then | |
NeedToKillSelf := True | |
else | |
KillProcess(ProcessList[I].ProcessID); | |
end; | |
if CanKillSelf and NeedToKillSelf then ExitProcess(0); | |
end; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
function GetProcessCPULoading(ProcessID: LongWord; Delay: Cardinal): Single; | |
var | |
SystemInfo: SYSTEM_INFO; | |
ProcessorsCount: Byte; | |
lpCreationTime, lpExitTime, | |
lpKernelTime, lpUserTime: TFileTime; | |
WorkingTime: Int64; | |
WorkingInterval, LifeInterval: Single; | |
FirstUpdateTime, SecondUpdateTime: Cardinal; | |
FirstWorkingTime: Int64; | |
ProcessHandle: THandle; | |
begin | |
ProcessHandle := ProcessIDtoHandle(ProcessID); | |
// Получаем количество ядер: | |
GetSystemInfo(SystemInfo); | |
ProcessorsCount := SystemInfo.dwNumberOfProcessors; | |
// Получаем времена процесса: | |
GetProcessTimes(ProcessHandle, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime); | |
FirstUpdateTime := GetTickCount; | |
// Рабочее время в начале интервала: | |
FirstWorkingTime := Int64(lpKernelTime) + Int64(lpUserTime); | |
Sleep(Delay); | |
// Получаем времена процесса через интервал: | |
GetProcessTimes(ProcessHandle, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime); | |
SecondUpdateTime := GetTickCount; | |
// Интервал, во время которого будем измерять нагрузку: | |
LifeInterval := SecondUpdateTime - FirstUpdateTime; | |
if LifeInterval <= 0 then LifeInterval := 0.01; | |
// Рабочее время в конце интервала: | |
WorkingTime := Int64(lpKernelTime) + Int64(lpUserTime); | |
// Разность между рабочими временами в конце и начале интервала: | |
WorkingInterval := WorkingTime - FirstWorkingTime; | |
// Выводим результат: | |
Result := WorkingInterval / (LifeInterval * 100 * ProcessorsCount); | |
CloseHandle(ProcessHandle); | |
end; | |
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH | |
initialization | |
{$IFDEF DEBUG_PRIVILEGE} | |
NTSetPrivilege(SE_DEBUG_NAME, True); | |
{$ENDIF} | |
_InitFunctions; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ну и нахуя я это прочитал