- Сообщения
- 7,790
- Репутация
- 2,322
На основании этого примера и функции _WinAPI_GetProcessCommandLine() из WinAPIEx.au3 (WinAPIProc.au3) Yashied`а попробовал сделать функцию для получения переменной среды чужого процесса. В функции используется MEMORY_BASIC_INFORMATION structure ($t_MBI), про которую на MSDN пишут, что она должна быть разной для 32- и 64-разрядных процессов, как я понял, в 64 системе. Не имею возможности проверить работу этих структур в 64 системе. Функция (написана на AutoIt 3.3.8.1) у меня работает на WinXP 32 без проблем. Если у кого-нибудь есть доступ к 64 системе, проверьте и поправьте, пожалуйста, код.
Содержание проверочного Temp.au3 (его надо скомпилировать):
Код:
#RequireAdmin
#include <APIConstants.au3>
#include <Array.au3>
#include <WinAPIEx.au3>
Opt('MustDeclareVars', 1)
Global $hToken, $aAdjust, $iPID, $aEnvVars, $iErr
$iPID = Run('"' & @ScriptDir & '\Temp.exe"')
If Not $iPID Then Exit 1
If Not WinWait('[Title:MyTempEnv; Class:AutoIt v3 GUI]', '', 3) Then Exit 2
$hToken = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY))
_WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)
$aEnvVars = _WinAPI_GetProcessEnvVars($iPID)
$iErr = @error
_WinAPI_AdjustTokenPrivileges($hToken, $aAdjust, 0, $aAdjust)
_WinAPI_CloseHandle($hToken)
If $iErr Then
ConsoleWrite('Error' & @LF)
Else
_ArrayDisplay($aEnvVars, '_WinAPI_GetProcessEnvVars')
EndIf
;~ работает только в 32-разрядных системах, в 64 вернет @error = -1
Func _WinAPI_GetProcessEnvVars($i_PID = 0)
Local $a_Res, $h_Process, $i_Error = 1
If StringInStr(@OSArch, '64') Then Return SetError(-1, 0, 0)
If Not $i_PID Then $i_PID = @AutoItPID
$a_Res = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'dword', __Iif($__WINVER < 0x0600, 0x00000410, 0x00001010), 'int', 0, 'dword', $i_PID)
If (@error) Or (Not $a_Res[0]) Then Return SetError(1, 0, 0)
$h_Process = $a_Res[0]
Local $t_EnvStr, $p_Env, $i_Size, $p_EnvStr, $i_Offset, $t_Tmp, $a_Tmp, $a_EnvVars[101][2] = [[0, 100]]
Local $t_PBI = DllStructCreate('ulong_ptr ExitStatus;ptr PebBaseAddress;ulong_ptr AffinityMask;ulong_ptr BasePriority;ulong_ptr UniqueProcessId;ulong_ptr InheritedFromUniqueProcessId')
Local $t_PEB = DllStructCreate('byte InheritedAddressSpace;byte ReadImageFileExecOptions;byte BeingDebugged;byte Spare;ptr Mutant;ptr ImageBaseAddress;ptr LoaderData;ptr ProcessParameters;ptr SubSystemData;ptr ProcessHeap;ptr FastPebLock;ptr FastPebLockRoutine;ptr FastPebUnlockRoutine;ulong EnvironmentUpdateCount;ptr KernelCallbackTable;ptr EventLogSection;ptr EventLog;ptr FreeList;ulong TlsExpansionCounter;ptr TlsBitmap;ulong TlsBitmapBits[2];ptr ReadOnlySharedMemoryBase;ptr ReadOnlySharedMemoryHeap;ptr ReadOnlyStaticServerData;ptr AnsiCodePageData;ptr OemCodePageData;ptr UnicodeCaseTableData;ulong NumberOfProcessors;ulong NtGlobalFlag;byte Spare2[4];int64 CriticalSectionTimeout;ulong HeapSegmentReserve;ulong HeapSegmentCommit;ulong HeapDeCommitTotalFreeThreshold;ulong HeapDeCommitFreeBlockThreshold;ulong NumberOfHeaps;ulong MaximumNumberOfHeaps;ptr ProcessHeaps;ptr GdiSharedHandleTable;ptr ProcessStarterHelper;ptr GdiDCAttributeList;ptr LoaderLock;ulong OSMajorVersion;ulong OSMinorVersion;ulong OSBuildNumber;ulong OSPlatformId;ulong ImageSubSystem;ulong ImageSubSystemMajorVersion;ulong ImageSubSystemMinorVersion;ulong GdiHandleBuffer[34];ulong PostProcessInitRoutine;ulong TlsExpansionBitmap;byte TlsExpansionBitmapBits[128];ulong SessionId')
Local $t_UPP = DllStructCreate('ulong AllocationSize;ulong ActualSize;ulong Flags;ulong Unknown1;ushort LengthUnknown2;ushort MaxLengthUnknown2;ptr Unknown2;ptr InputHandle;ptr OutputHandle;ptr ErrorHandle;ushort LengthCurrentDirectory;ushort MaxLengthCurrentDirectory;ptr CurrentDirectory;ptr CurrentDirectoryHandle;ushort LengthSearchPaths;ushort MaxLengthSearchPaths;ptr SearchPaths;ushort LengthApplicationName;ushort MaxLengthApplicationName;ptr ApplicationName;ushort LengthCommandLine;ushort MaxLengthCommandLine;ptr CommandLine;ptr EnvironmentBlock;ulong Unknown[9];ushort LengthUnknown3;ushort MaxLengthUnknown3;ptr Unknown3;ushort LengthUnknown4;ushort MaxLengthUnknown4;ptr Unknown4;ushort LengthUnknown5;ushort MaxLengthUnknown5;ptr Unknown5')
Local $t_MBI = DllStructCreate('ptr BaseAddress;ptr AllocationBase;dword AllocationProtect;ulong_ptr RegionSize;dword State;dword Protect;dword Type')
Do
$a_Res = DllCall('ntdll.dll', 'int', 'NtQueryInformationProcess', 'ptr', $h_Process, 'ulong', 0, 'struct*', $t_PBI, 'ulong', DllStructGetSize($t_PBI), 'ulong*', 0)
If (@error) Or ($a_Res[0]) Then ExitLoop
$a_Res = DllCall('kernel32.dll', 'int', 'ReadProcessMemory', 'ptr', $h_Process, 'ptr', DllStructGetData($t_PBI, 'PebBaseAddress'), 'struct*', $t_PEB, 'ulong_ptr', DllStructGetSize($t_PEB), 'ulong_ptr*', 0)
If (@error) Or (Not $a_Res[0]) Or (Not $a_Res[5]) Then ExitLoop
$a_Res = DllCall('kernel32.dll', 'int', 'ReadProcessMemory', 'ptr', $h_Process, 'ptr', DllStructGetData($t_PEB, 'ProcessParameters'), 'struct*', $t_UPP, 'ulong_ptr', DllStructGetSize($t_UPP), 'ulong_ptr*', 0)
If (@error) Or (Not $a_Res[0]) Or (Not $a_Res[5]) Then ExitLoop
$p_Env = DllStructGetData($t_UPP, 'EnvironmentBlock')
$a_Res = DllCall('kernel32.dll', 'ulong_ptr', 'VirtualQueryEx', 'ptr', $h_Process, 'ptr', $p_Env, 'struct*', $t_MBI, 'ulong_ptr', DllStructGetSize($t_MBI))
If (@error) Or (Not $a_Res[0]) Then ExitLoop
$i_Size = DllStructGetData($t_MBI, 'RegionSize') - $p_Env - DllStructGetData($t_MBI, 'BaseAddress')
If $i_Size <= 0 Then ExitLoop
$t_EnvStr = DllStructCreate('byte[' & $i_Size & ']')
$a_Res = DllCall('kernel32.dll', 'int', 'ReadProcessMemory', 'ptr', $h_Process, 'ptr', $p_Env, 'struct*', $t_EnvStr, 'ulong_ptr', DllStructGetSize($t_EnvStr), 'ulong_ptr*', 0)
If (@error) Or (Not $a_Res[0]) Or (Not $a_Res[5]) Then ExitLoop
_WinAPI_CloseHandle($h_Process)
$h_Process = 0
$p_EnvStr = DllStructGetPtr($t_EnvStr)
Do
$a_Res = DllCall('kernel32.dll', 'int', 'lstrlenW', 'ptr', $p_EnvStr + $i_Offset)
If @error Then ExitLoop 2
If Not $a_Res[0] Then ExitLoop
$a_Res[0] += 1
$t_Tmp = DllStructCreate('wchar[' & $a_Res[0] & ']', $p_EnvStr + $i_Offset)
$a_Tmp = StringSplit(DllStructGetData($t_Tmp, 1), '=')
If $a_Tmp[0] = 2 Then
$a_EnvVars[0][0] += 1
If $a_EnvVars[0][0] = $a_EnvVars[0][1] Then
$a_EnvVars[0][1] *= 2
ReDim $a_EnvVars[$a_EnvVars[0][1] + 1][2]
EndIf
For $j = 1 To 2
$a_EnvVars[$a_EnvVars[0][0]][$j - 1] = $a_Tmp[$j]
Next
EndIf
$i_Offset += $a_Res[0] * 2
Until $i_Offset >= $i_Size
$i_Error = 0
Until 1
If $h_Process Then _WinAPI_CloseHandle($h_Process)
If ($i_Error) Or (Not $a_EnvVars[0][0]) Then Return SetError(1, 0, '')
ReDim $a_EnvVars[$a_EnvVars[0][0] + 1][2]
$a_EnvVars[0][1] = ''
Return $a_EnvVars
EndFunc ;==>_WinAPI_GetProcessEnvVars
Код:
#include <Array.au3>
Global $iRand = Random(10, 20, 1), $aEnv[$iRand + 1][2] = [[$iRand]]
For $i = 1 To $aEnv[0][0]
EnvSet('MyTempEnv_' & $i, @ScriptFullPath & '_MyTestString_' & $i)
$aEnv[$i][0] = '%MyTempEnv_' & $i & '%'
$aEnv[$i][1] = EnvGet('MyTempEnv_' & $i)
Next
_ArrayDisplay($aEnv, 'MyTempEnv')