Что нового

Разные структуры для 32- и 64-разрядных процессов

madmasles

Модератор
Глобальный модератор
Сообщения
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 системе, проверьте и поправьте, пожалуйста, код.
Код:
#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
Содержание проверочного Temp.au3 (его надо скомпилировать):
Код:
#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')
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
temp.exe - x64
launcher - x86
(если я верно понял вашу задумку)

Результат:
64ea163dbe.png
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
firex,
Похоже, что у Вас в консоли написано Error, значит надо менять структуру. Я внесу изменения в код функции, а Вы, если Вам не трудно, проверьте, пожалуйста, на 64 системе следующие варианты: temp.exe - x64 и launcher - x64, temp.exe - x86 launcher - x86, temp.exe - x86 launcher - x64.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
madmasles
Так или иначе прочитать память x64 разрядного процесса из x86 разрядного невозможно, в свое время сам убедился. А вот если наоборот - то пожалуйста. ( перепроверил ваш код - эффект тот же )

Я в сам код не вникал, но полагаю, что будет проблема с типами ака ptr. Будет правильнее определять разрядность процесса и уже исходя из этой информации использовать int / int64. Это имеет смысл для x64 систем.

Уверен, что это одна из причин неработоспособности вашего кода.
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
firex,
Вы не могли бы проверить этот вариант функции (не уверен, что правильный) в разных вариантах разрядности.
Код:
Func _WinAPI_GetProcessEnvVars($i_PID = 0)
	Local $a_Res, $h_Process, $i_Error = 1

	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')
;~ 		================================= изменено, но не проверено
		If @OSArch = 'X64' Then
			$a_Res = DllCall('kernel32.dll', 'int', 'IsWow64Process', 'ptr', $h_Process, 'int*', 0)
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			If $a_Res[2] Then
				$t_MBI = DllStructCreate('align 16;uint64 BaseAddress;uint64 AllocationBase;dword AllocationProtect;uint64 RegionSize;dword State;dword Protect;dword Type')
			Else
				If @AutoItX64 Then
					$t_MBI = DllStructCreate('align 16;uint64 BaseAddress;uint64 AllocationBase;dword AllocationProtect;uint64 RegionSize;dword State;dword Protect;dword Type')
				Else
					$t_MBI = DllStructCreate('ptr BaseAddress;ptr AllocationBase;dword AllocationProtect;ulong_ptr RegionSize;dword State;dword Protect;dword Type')
				EndIf
			EndIf
		Else
;~ 			это работает
			$t_MBI = DllStructCreate('ptr BaseAddress;ptr AllocationBase;dword AllocationProtect;ulong_ptr RegionSize;dword State;dword Protect;dword Type')
		EndIf
;~ 		=================================
		$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
Функция не работает в 64-х системах.

PS
Вроде видел где-то, что архитектура @OSArch = 'IA64' - 32-разрядная система, это так или нет?
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
madmasles
Результат отрицательный. Даже с вариантом x86 - x86

[?]
Вроде видел где-то, что архитектура @OSArch = 'IA64' - 32-разрядная система, это так или нет?
64-х разрядная. Про нее, как я полагаю, уже давно забыли.
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
firex [?]
Результат отрицательный.
Значит эта функция только для 32-разрядных систем, я не знаю, как ее поправить. :(
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
madmasles
С вашим примером я не мог добраться до указателя на переменные окружения. Вероятно вы ошиблись в структурах.

Код:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <FMemory64.au3>

#cs
typedef struct _PROCESS_BASIC_INFORMATION {
    PVOID Reserved1;
    PPEB PebBaseAddress;
    PVOID Reserved2[2];
    ULONG_PTR UniqueProcessId;
    PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;

typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged;
  BYTE                          Reserved2[1];
  PVOID                         Reserved3[2];
  PPEB_LDR_DATA                 Ldr;
  PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  BYTE                          Reserved4[104];
  PVOID                         Reserved5[52];
  PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  BYTE                          Reserved6[128];
  PVOID                         Reserved7[1];
  ULONG                         SessionId;
} PEB, *PPEB;

typedef struct _RTL_USER_PROCESS_PARAMETERS {
  BYTE           Reserved1[16];
  PVOID          Reserved2[10];
  UNICODE_STRING ImagePathName;
  UNICODE_STRING CommandLine;

  <<< NEXT TED STRUCTURE ( MAIN THREAD )

} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
#ce

Global $tPBI = DllStructCreate( 'ptr; ptr PebBaseAddress; ptr[2]; ulong_ptr UniqueProcessId; ptr;' )
Global $tagPEB = 'byte[4]; ptr[3]; ptr ProcessParameters; byte[104]; ptr[52]; ptr; byte[128]; ptr; ulong;'
Global $tagUPP = 'ulong[4]; ptr; ulong; ptr[3]; dword; ptr; handle; dword; ptr; dword; ptr; word len1; word len2; ptr; ptr EnvironmentBlock;'

_WinAPI_GetProcessEnvVars( ProcessExists( "explorer.exe" ) )
Func _WinAPI_GetProcessEnvVars( $iPid = 0 )
	Local $aRes, $iError = 1, _
		$tPEB, $tUPP
	; ---
	If Not $iPid Then _
		$iPid = @AutoItPID

	_FMem_Open( $iPid )
	Do
		$aRes = DllCall( 'ntdll.dll', 'int', 'NtQueryInformationProcess', 'handle', $FMem_hMem, 'dword', 0, 'ptr', DllStructGetPtr( $tPBI ), 'ulong', DllStructGetSize( $tPBI ), 'ulong*', 0)
		If @Error Or $aRes[0] Then _ ;$aRes[0] NTSTATUS, 0=STATUS_SUCCESS
			ExitLoop

		$tPEB = _FMem_Read2( $tPBI.PebBaseAddress, $tagPEB, 0 )
		If Not IsDllStruct( $tPEB ) Then _
			ExitLoop

		$tUPP = _FMem_Read2( $tPEB.ProcessParameters, $tagUPP, 0 )
		If Not IsDllStruct( $tPEB ) Then _
			ExitLoop

		ConsoleWrite( $tUPP.EnvironmentBlock & @CRLF)
	Until True
	_FMem_Close()
EndFunc

FMemory64: http://pastebin.com/fMPPDzwc

12b3ddf021.png

Как видите - я успешно добрался но переменных окружения explorer.exe, лаунчер - x64;

Так что все возможно :smile:
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
firex [?]
Вероятно вы ошиблись в структурах.
Структуры $t_PBI, $t_PEB и $t_UPP в моем примере взяты из функции _WinAPI_GetProcessCommandLine() из WinAPIEx.au3 (WinAPIProc.au3) Yashied`а, я их не менял. Вам не сложно будет проверить _WinAPI_GetProcessCommandLine() в 64 системе с вариантами?
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
madmasles
Работает. Самому стало интересно изучить этот вопрос, сейчас переоформлю и допишу мою реализацию этой функции ( GetEnvVars ).


Добавлено:
Сообщение автоматически объединено:

У вас ошибка, вообще не понимаю как оно могло работать.

Код:
$i_Size = DllStructGetData($t_MBI, 'RegionSize') - $p_Env - DllStructGetData($t_MBI, 'BaseAddress')

Нужно:
Код:
$i_Size = DllStructGetData($t_MBI, 'RegionSize') - ( $p_Env - DllStructGetData($t_MBI, 'BaseAddress') )


Честно говоря - лень допилить, однако в целом все готово ( должно работать на всех версиях ):
*Обратите внимание в коде на константный размер UPP ( 0x80 для x64 и 0x46 для x86 )
Код:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <FMemory64.au3>

#cs
typedef struct _PROCESS_BASIC_INFORMATION {
    PVOID Reserved1;
    PPEB PebBaseAddress;
    PVOID Reserved2[2];
    ULONG_PTR UniqueProcessId;
    PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;

typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged;
  BYTE                          Reserved2[1];
  PVOID                         Reserved3[2];
  PPEB_LDR_DATA                 Ldr;
  PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  BYTE                          Reserved4[104];
  PVOID                         Reserved5[52];
  PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  BYTE                          Reserved6[128];
  PVOID                         Reserved7[1];
  ULONG                         SessionId;
} PEB, *PPEB;

typedef struct _RTL_USER_PROCESS_PARAMETERS {
  BYTE           Reserved1[16];
  PVOID          Reserved2[10];
  UNICODE_STRING ImagePathName;
  UNICODE_STRING CommandLine;

  <<< NEXT TED STRUCTURE ( MAIN THREAD )

} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

typedef struct _MEMORY_BASIC_INFORMATION {
  PVOID  BaseAddress;
  PVOID  AllocationBase;
  DWORD  AllocationProtect;
  SIZE_T RegionSize;
  DWORD  State;
  DWORD  Protect;
  DWORD  Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
#ce

$tRet = _WinAPI_GetProcessEnvVars( ProcessExists( "explorer.exe" ) )
ClipPut( StringTrimLeft( DllStructGetData( $tRet, 1 ), 2 ) )

Func _WinAPI_GetProcessEnvVars( $iPid = 0 )
    Local $aRes, $iEnvSize, _
		$tPBI = DllStructCreate( 'ptr Reserved1; ptr PebBaseAddress; ptr Reserved2[2]; ulong_ptr UniqueProcessId; ptr Reserved3;' ), _
		$tMBI = DllStructCreate( 'ptr BaseAddress; ptr AllocationBase; dword AllocationProtect; ulong_ptr RegionSize; dword State; dword Protect; dword Type;' ), _
        $tPEB, $tUPP, $tBuffer
    ; ---
    If Not $iPid Then _
        $iPid = @AutoItPID

    _FMem_Open( $iPid )
    Do
        $aRes = DllCall( 'ntdll.dll', 'int', 'NtQueryInformationProcess', 'handle', $FMem_hMem, 'dword', 0, 'ptr', DllStructGetPtr( $tPBI ), 'ulong', DllStructGetSize( $tPBI ), 'ulong*', 0)
        If @Error Or $aRes[0] Then _
            ExitLoop

        $tPEB = _FMem_Read2( $tPBI.PebBaseAddress, 'byte[4]; ptr[3]; ptr ProcessParameters;', 0 )
        If Not IsDllStruct( $tPEB ) Then _
            ExitLoop

        $tUPP = _FMem_Read2( $tPEB.ProcessParameters + 0x80, "ptr EnvironmentBlock;", 0 ) ;Sizeof _RTL_USER_PROCESS_PARAMETERS ( X64 )( X86 = 0x46 ) > TED STRUCTURE
        If Not IsDllStruct( $tPEB ) Then _
            ExitLoop

		$aRes = DllCall( $FMem_hDll, 'ulong_ptr', 'VirtualQueryEx', 'handle', $FMem_hMem, 'ptr', $tUPP.EnvironmentBlock, 'ptr', DllStructGetPtr( $tMBI ), 'ulong_ptr', DllStructGetSize($tMBI) )
		If @Error Or Not $aRes[0] Then _
			ExitLoop

		$iEnvSize = $tMBI.RegionSize - ( $tUPP.EnvironmentBlock - $tMBI.BaseAddress )
		; -
		$tBuffer = _FMem_Read2( $tUPP.EnvironmentBlock, 'byte[' & $iEnvSize & '];', 0 )
		;Буфер с переменными окружения, ваш код обрабатывающий его полагаю вполне сгодится
    Until True
    _FMem_Close()

	Return $tBuffer
EndFunc
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Ввиду некоторых планов решил привести функцию в подобающе-рабочий вид:

Код:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <WinAPI.au3>
#Include <Array.au3>

$aEnvVars = _WinAPI_GetProcessEnvVars( ProcessExists( "explorer.exe" ) )
_ArrayDisplay( $aEnvVars )

Func _WinAPI_GetProcessEnvVars( $iPid = 0 )
	If Not $iPid Then _
        $iPid = @AutoItPID

	Local $hProc, $vRes, $iBytes, $tVar, $aVar, $aVar_sz, $aRet[1][2] = [[0]], _
		$pRTL_UPP_sz, $tEnvBuf, $pEnvBuf, $iEnvBuf_sz, _
		$tPBI = DllStructCreate( 'ptr Reserved1; ptr PebBaseAddress; ptr Reserved2[2]; ulong_ptr UniqueProcessId; ptr Reserved3;' ), _
		$tMBI = DllStructCreate( 'ptr BaseAddress; ptr AllocationBase; dword AllocationProtect; ulong_ptr RegionSize; dword State; dword Protect; dword Type;' ), _
		$tPEB = DllStructCreate( 'byte[4]; ptr[3]; ptr ProcessParameters' ), _ ;Stripped
		$tUPP = DllStructCreate( 'ptr EnvironmentBlock' ) ;Stripped, UPP of main thread
	; *
	If @AutoItX64 Then
		$pRTL_UPP_sz = 0x80
	Else
		$pRTL_UPP_sz = 0x48
	EndIf
    ; ---
	$hProc = _WinAPI_OpenProcess( 0x1F0FFF, 1, $iPid )
    Do
        $vRes = DllCall( 'ntdll.dll', 'int', 'NtQueryInformationProcess', 'handle', $hProc, 'dword', 0, 'struct*', $tPBI, 'ulong', DllStructGetSize( $tPBI ), 'ulong*', 0)
        If @Error Or $vRes[0] Then _
            ExitLoop

		$vRes = _WinAPI_ReadProcessMemory( $hProc, $tPBI.PebBaseAddress, DllStructGetPtr( $tPEB ), DllStructGetSize( $tPEB ), $iBytes )
		If Not $vRes Then _
			ExitLoop

		$vRes = _WinAPI_ReadProcessMemory( $hProc, $tPEB.ProcessParameters + $pRTL_UPP_sz, DllStructGetPtr( $tUPP ), DllStructGetSize( $tUPP ), $iBytes )
		If Not $vRes Then _
			ExitLoop

		$vRes = DllCall( 'kernel32.dll', 'ulong_ptr', 'VirtualQueryEx', 'handle', $hProc, 'ptr', $tUPP.EnvironmentBlock, 'struct*', $tMBI, 'ulong_ptr', DllStructGetSize( $tMBI ) )
		If @Error Or Not $vRes[0] Then _
			ExitLoop
		; < ---
		$iEnvBuf_sz = $tMBI.RegionSize - ( $tUPP.EnvironmentBlock - $tMBI.BaseAddress )
		$tEnvBuf = DllStructCreate( 'byte[' & $iEnvBuf_sz & ']' )
		$pEnvBuf = DllStructGetPtr( $tEnvBuf )

		$vRes = _WinAPI_ReadProcessMemory( $hProc, $tUPP.EnvironmentBlock, DllStructGetPtr( $tEnvBuf ), DllStructGetSize( $tEnvBuf ), $iBytes )
		If Not $vRes Then _
			ExitLoop

		While 1
			$aVar_sz = DllCall("kernel32.dll", "int", "lstrlenW", "ptr", $pEnvBuf)
			If @Error Or Not $aVar_sz[0] Then _
				ExitLoop

			$tVar = DllStructCreate( "wchar Var[" & $aVar_sz[0] + 1 & "]", $pEnvBuf )
			$aVar = StringSplit( $tVar.Var, "=" )
			If UBound( $aVar ) = 3 Then
				$aRet[0][0] += 1
				; -
				ReDim $aRet[$aRet[0][0]+1][2]
				$aRet[$aRet[0][0]][0] = $aVar[1]
				$aRet[$aRet[0][0]][1] = $aVar[2]
			EndIf
			; -
			$pEnvBuf += DllStructGetSize( $tVar )
			$tVar = 0
		WEnd
    Until True
    _WinAPI_CloseHandle( $hProc )

	Return $aRet
EndFunc
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
firex,
Так чуть быстрее будет.
Код:
#include <WinAPI.au3>
#include <Array.au3>

Opt('MustDeclareVars', 1)

Global $iRand = Random(100, 200, 1), $aEnv[$iRand + 1][2] = [[$iRand]], $iTimer, $aEnvVars, $iPid = 0;ProcessExists("explorer.exe")

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
$iTimer = TimerInit()
$aEnvVars = _WinAPI_GetProcessEnvVars($iPid)
If @error Then Exit 13
ConsoleWrite(TimerDiff($iTimer) & @CRLF)
_ArrayDisplay($aEnvVars)

Func _WinAPI_GetProcessEnvVars($iPid = 0)
Local $hProc, $vRes, $iBytes, $tVar, $aVar, $aVar_sz, $aRet[101][2] = [[0, 100]], _
			$pRTL_UPP_sz, $tEnvBuf, $pEnvBuf, $iEnvBuf_sz, $iErr = 1, _
			$tPBI = DllStructCreate('ptr Reserved1; ptr PebBaseAddress; ptr Reserved2[2]; ulong_ptr UniqueProcessId; ptr Reserved3;'), _
			$tMBI = DllStructCreate('ptr BaseAddress; ptr AllocationBase; dword AllocationProtect; ulong_ptr RegionSize; dword State; dword Protect; dword Type;'), _
			$tPEB = DllStructCreate('byte[4]; ptr[3]; ptr ProcessParameters'), _ ;Stripped
			$tUPP = DllStructCreate('ptr EnvironmentBlock') ;Stripped, UPP of main thread
	; *
	If @AutoItX64 Then
		$pRTL_UPP_sz = 0x80
	Else
		$pRTL_UPP_sz = 0x48
	EndIf
	If $iPid Then
		$hProc = _WinAPI_OpenProcess(0x00000410, 1, $iPid); BitOR($PROCESS_VM_READ, $PROCESS_QUERY_INFORMATION)
	Else
		$hProc = _WinAPI_GetCurrentProcess()
	EndIf
	If Not $hProc Then Return SetError(1, 0, 0)
	Do
		$vRes = DllCall('ntdll.dll', 'int', 'NtQueryInformationProcess', 'handle', $hProc, 'dword', 0, 'struct*', $tPBI, 'ulong', DllStructGetSize($tPBI), 'ulong*', 0)
		If @error Or $vRes[0] Then ExitLoop
		$vRes = _WinAPI_ReadProcessMemory($hProc, $tPBI.PebBaseAddress, DllStructGetPtr($tPEB), DllStructGetSize($tPEB), $iBytes)
		If Not $vRes Then ExitLoop
		$vRes = _WinAPI_ReadProcessMemory($hProc, $tPEB.ProcessParameters + $pRTL_UPP_sz, DllStructGetPtr($tUPP), DllStructGetSize($tUPP), $iBytes)
		If Not $vRes Then ExitLoop
		$vRes = DllCall('kernel32.dll', 'ulong_ptr', 'VirtualQueryEx', 'handle', $hProc, 'ptr', $tUPP.EnvironmentBlock, 'struct*', $tMBI, 'ulong_ptr', DllStructGetSize($tMBI))
		If (@error) Or (Not $vRes[0]) Then ExitLoop
		; < ---
		$iEnvBuf_sz = $tMBI.RegionSize - ($tUPP.EnvironmentBlock - $tMBI.BaseAddress)
		$tEnvBuf = DllStructCreate('byte[' & $iEnvBuf_sz & ']')
		$pEnvBuf = DllStructGetPtr($tEnvBuf)

		$vRes = _WinAPI_ReadProcessMemory($hProc, $tUPP.EnvironmentBlock, DllStructGetPtr($tEnvBuf), DllStructGetSize($tEnvBuf), $iBytes)
		If Not $vRes Then ExitLoop

		While 1
			$iEnvBuf_sz =  _WinAPI_StringLenW($pEnvBuf) + 1
			If @error Then ExitLoop 2
			If $iEnvBuf_sz = 1 Then ExitLoop
			$tVar = DllStructCreate("wchar Var[" & $iEnvBuf_sz & "]", $pEnvBuf)
			$aVar = StringSplit($tVar.Var, "=")
			If $aVar[0] = 2 Then
				$aRet[0][0] += 1
				If $aRet[0][0] = $aRet[0][1] Then
					$aRet[0][1] += 100
					ReDim $aRet[$aRet[0][1] + 1][2]
				EndIf
				$aRet[$aRet[0][0]][0] = $aVar[1]
				$aRet[$aRet[0][0]][1] = $aVar[2]
			EndIf
			; -
			$pEnvBuf += $iEnvBuf_sz * 2
		WEnd
		$iErr = 0
	Until True
	If $iPid Then _WinAPI_CloseHandle($hProc)
	If $iErr Then Return SetError(2, 0, 0)
	If $aRet[0][0] <> $aRet[0][1] Then ReDim $aRet[$aRet[0][0] + 1][2]
	$aRet[0][1] = ''
	Return $aRet
EndFunc   ;==>_WinAPI_GetProcessEnvVars
 
Верх