|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » PowerShell - Поиск определенного регистра процессора |
|
PowerShell - Поиск определенного регистра процессора
|
Забанен Сообщения: 27 |
Проблема: есть дллка, корректность которой гарантируется за счёт наличия некоторых регистров процессора и которую планируется разворачивать в сети посредством PowerShell. На самом деле таких дллок много, и все они зависят от того или иного регистра процессора, то есть если цпу не имеет этого регистра, будет подобрана нужная в этом случае дллка и установлена (сами дллки написаны на асме лидтимом нашей конторы). Мне ж как админу поручено автоматизировать процесс развёртки. Основная трудность состоит в получении списка поддерживаемых регистров. Возможно ли это сделать средствами PowerShell? Сторонние тулзы в моем случае не вариант, так как в конторе с этим очень строго. Просьба хотя бы указать вектор куда копать.
|
|
Отправлено: 16:05, 20-11-2016 |
Забанен Сообщения: 793
|
Все зависит от конечной цели. Если требуется проверить наличие, скажем, 3DNow, вполне можно обойтись WinAPI функцией IsProcessorFeaturePresent, экспортируемой из kernel32.dll. Правда стоит иметь в виду: из-за, мягко говоря, не совсем удачной реализации, функция может вполне возвращать ложное значение. Поэтому остаются два других варианта: через реестр и вызов cpuid посредством машинных кодов.
Через реестр Сведения о характерных для процессора особенностях хранятся в значении реестра FeatureSet ключа HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\X (где X - номер процессора). Как расшифровывается данное значение Microsoft документировать наотрез отказывается, но ничего сложного там на самом деле нет - смещения да логические операции, - но вот объяснять как именно эти операции проводятся уж очень муторно. Кстати, значение FeatureSet также можно получить с помощью NtQuerySystemInformation, а именно SystemInformationClass = 1 и структуры SYSTEM_PROCESSOR_INFORMATION, имеющей одинаковый размер в x86 и x64 системах и равной 12 байтам. typedef _SYSTEM_PROCESSOR_INFORMATION { USHORT ProcessorArchitecture; USHORT ProcessorLevel; USHORT ProcessorRevision; USHORT Reserved; ULONG ProcessorFeatureBits; } SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; try { $ptr = [Runtime.InteropServices.Marshal]::AllocHGlobal(0xC) if ([Regex].Assembly.GetType( 'Microsoft.Win32.NativeMethods' ).GetMethod( 'NtQuerySystemInformation' ).Invoke($null, @(1, $ptr, 0xC, $null)) -ne 0) { throw New-Object InvalidOperationException( 'Could not get system processor information.' ) } [BitConverter]::ToUInt32( [BitConverter]::GetBytes( [Runtime.InteropServices.Marshal]::ReadInt32($ptr, 8) ), 0 ) } catch { $_ } finally { if ($ptr) { [Runtime.InteropServices.Marshal]::FreeHGlobal($ptr) } } cpuid Крайне непопулярная техника, так как требует специфических навыков и знаний (в частности языка Ассемблера). В системе целочисленных команд процессора есть cpuid, которая получает информацию о текущем процессоре; для получения информации необходимо в регистр EAX поместить параметр (одно из значений 0, 1 или 2). Если EAX = 0, то в регистрах EAX, EBX, EDX и ECX формируется следующая информация: EAX = n, где n - максимально допустимое значение параметра, которое может быть помещено в регистр EAX для задания режима сбора информации; EBX, EDX, ECX - в них будет содержаться строка-идентификатор процессора, наприер, AuthenticAMD. Если EAX = 1, формируется следующая информация: EAX = n - информация о процессоре (SteppingId, Model, Family, Type); EDX = n, ECX = n - собственно, информация о фичах процессора. Ну и к слову, если EAX = 2, в регистрах EAX, EBX, ECX и EDX формируется информация о кэш-памяти первого уровня и TLB-буферах. Если все это перевести в PowerShell, то получим примерно следующее: function Get-CpuId { begin { @( [Runtime.InteropServices.CallingConvention], [Runtime.InteropServices.GCHandle], [Runtime.InteropServices.Marshal], [Reflection.Emit.OpCodes] ) | ForEach-Object { $keys = ($ta = [PSObject].Assembly.GetType( 'System.Management.Automation.TypeAccelerators' ))::Get.Keys $collect = @() }{ if ($keys -notcontains $_.Name) { $ta::Add($_.Name, $_) } $collect += $_.Name } # accelerators function private:Get-ProcAddress { param( [Parameter(Mandatory=$true, Position=0)] [ValidateNotNullOrEmpty()] [String]$Module, [Parameter(Mandatory=$true, Position=1)] [ValidateNotNullOrEmpty()] [String[]]$Function ) begin { [Object].Assembly.GetType( 'Microsoft.Win32.Win32Native' ).GetMethods( [Reflection.BindingFlags]40 ) | Where-Object { $_.Name -cmatch '\AGet(ProcA|ModuleH)' } | ForEach-Object { Set-Variable $_.Name $_ } } process {} end { if (($ptr = $GetModuleHandle.Invoke( $null, @($Module) )) -eq [IntPtr]::Zero) { throw New-Object InvalidOperationException( 'Could not find specified module.' ) } $Function | ForEach-Object {$ret = @{}}{ $ret[$_] = $GetProcAddress.Invoke( $null, @($ptr, [String]$_) ) }{$ret} } } # Get-ProcAddress function private:New-Delegate { param( [Parameter(Mandatory=$true, Position=0)] [ValidateScript({$_ -ne [IntPtr]::Zero})] [IntPtr]$ProcAddress, [Parameter(Mandatory=$true, Position=1)] [ValidateNotNullOrEmpty()] [Type]$Prototype, [Parameter(Position=2)] [ValidateNotNullOrEmpty()] [CallingConvention]$CallingConvention = 'StdCall' ) $method = $Prototype.GetMethod('Invoke') $returntype = $method.ReturnType $paramtypes = $method.GetParameters() | Select-Object -ExpandProperty ParameterType $holder = New-Object Reflection.Emit.DynamicMethod( 'Invoke', $returntype, $( if (!$paramtypes) { $null } else { $paramtypes } ), $Prototype ) $il = $holder.GetILGenerator() if ($paramtypes) { 0..($paramtypes.Length - 1) | ForEach-Object { $il.Emit([OpCodes]::Ldarg, $_) } } switch ([IntPtr]::Size) { 4 { $il.Emit([OpCodes]::Ldc_I4, $ProcAddress.ToInt32()) } 8 { $il.Emit([OpCodes]::Ldc_I8, $ProcAddress.ToInt64()) } } $il.EmitCalli( [OpCodes]::Calli, $CallingConvention, $returntype, $(if (!$paramtypes) { $null } else { $paramtypes }) ) $il.Emit([OpCodes]::Ret) $holder.CreateDelegate($Prototype) } # New-Delegate function private:Get-Blocks { param( [Parameter(Mandatory=$true, Position=0)] [ValidateNotNull()] [Byte[]]$Bytes, [Parameter()] [Switch]$AsInteger, [Parameter()] [Switch]$AsString ) $reg = @{ eax = $Bytes[0..3] ebx = $Bytes[4..7] ecx = $Bytes[8..11] edx = $Bytes[12..15] } if ($AsInteger) { $reg.Keys | ForEach-Object {$num = @{}}{ $num[$_] = [BitConverter]::ToInt32($reg[$_], 0) } $reg = $num } if ($AsString) { $reg.Keys | ForEach-Object {$str = @{}}{ $str[$_] = -join [Char[]]$reg[$_] } $reg = $str } $reg } # Get-Blocks # вспомогательная функция (имитация операторов -shr и -shl для PS v2) function private:Set-Shift { param( [Parameter(Position=0)] [ValidateNotNullOrEmpty()] [ValidateSet('Left', 'Right')] [String]$Direction = 'Right', [Parameter(Position=1)] [ValidateNotNull()] [Object]$Type = [Int32] ) @( 'Ldarg_0' 'Ldarg_1' 'Ldc_I4_S, 31' 'And' $(if ($Direction -eq 'Right') { 'Shr' } else { 'Shl' }) 'Ret' ) | ForEach-Object { $def = New-Object Reflection.Emit.DynamicMethod( $Direction, $Type, @($Type, $Type) ) $il = $def.GetILGenerator() }{ if ($_ -notmatch ',') { $il.Emit([OpCodes]::$_) } else { $il.Emit( [OpCodes]::(($$ = $_.Split(','))[0]), ($$[1].Trim() -as $Type) )} } $def.CreateDelegate(( Invoke-Expression "[Func[$($Type.Name), $($Type.Name), $($Type.Name)]]" )) } # Invoke-Shift $kernel32 = Get-ProcAddress kernel32 ('VirtualAlloc', 'VirtualFree') ($sig = @{ VirtualAlloc = [Func[IntPtr, UIntPtr, UInt32, UInt32, IntPtr]] VirtualFree = [Func[IntPtr, UIntPtr, UInt32, Boolean]] }).Keys | ForEach-Object { Set-Variable $_ (New-Delegate $kernel32.$_ $sig[$_]) } [Byte[]]$bytes = switch ([IntPtr]::Size) { 4 { 0x55, #push ebp 0x8B, 0xEC, #mov ebp, esp 0x53, #push ebx 0x57, #push edi 0x8B, 0x45, 0x08, #mov eax, dword ptr[ebp+8] 0x0F, 0xA2, #cpuid 0x8B, 0x7D, 0x0C, #mov edi, dword ptr[ebp+12] 0x89, 0x07, #mov dword ptr[edi+0], eax 0x89, 0x5F, 0x04, #mov dword ptr[edi+4], ebx 0x89, 0x4F, 0x08, #mov dword ptr[edi+8], ecx 0x89, 0x57, 0x0C, #mov dword ptr[edi+12], edx 0x5F, #pop edi 0x5B, #pop ebx 0x8B, 0xE5, #mov esp, ebp 0x5D, #pop ebp 0xC3 #ret } 8 { 0x53, #push rbx 0x49, 0x89, 0xD0, #mov r8, rdx 0x89, 0xC8, #mov eax, ecx 0x0F, 0xA2, #cpuid 0x41, 0x89, 0x40, 0x00, #mov dword ptr[r8+0], eax 0x41, 0x89, 0x58, 0x04, #mov dword ptr[r8+4], ebx 0x41, 0x89, 0x48, 0x08, #mov dword ptr[r8+8], ecx 0x41, 0x89, 0x50, 0x0C, #mov dword ptr[r8+12], edx 0x5B, #pop rbx 0xC3 #ret } } $features = @{} } process { $func = $ExecutionContext.SessionState.InvokeCommand.GetCommand( 'New-Delegate', [Management.Automation.CommandTypes]::Function ).ScriptBlock $shr = Set-Shift try { $ptr = $VirtualAlloc.Invoke( [IntPtr]::Zero, (New-Object UIntPtr($bytes.Length)), (0x1000 -bor 0x2000), 0x40 ) $cpuid = { param([Int32]$Level, [Byte[]]$Bytes) $func.Invoke( $ptr, [Action[Int32, [Byte[]]]], 'Cdecl' )[0].Invoke($Level, $Bytes) } [Marshal]::Copy($bytes, 0, $ptr, $bytes.Length) [Byte[]]$buf = New-Object Byte[](16) $cpuid.Invoke(0, $buf) $vendor = "$(( # вендор $str = Get-Blocks $buf -AsString ).ebx)$($str.edx)$($str.ecx)" # low leaves $ids = (Get-Blocks $buf -AsInteger).eax $low = @() for ($i = 0; $i -le $ids; $i++) { $cpuid.Invoke($i, $buf) if ($i -eq 1) { $reg = Get-Blocks $buf -AsInteger $stepping = $reg.eax -band 0xF $model = $shr.Invoke($reg.eax, 4) -band 0xF $family = $shr.Invoke($reg.eax, 8) -band 0xF $logiccpu = $shr.Invoke($reg.ebx, 16) -band 0xFF $features['fpu'] = $reg.edx -band 0x00000001 $features['vme'] = $reg.edx -band 0x00000002 $features['de'] = $reg.edx -band 0x00000004 $features['pse'] = $reg.edx -band 0x00000008 $features['tsc'] = $reg.edx -band 0x00000010 $features['msr'] = $reg.edx -band 0x00000020 $features['pae'] = $reg.edx -band 0x00000040 $features['mce'] = $reg.edx -band 0x00000080 $features['cx8'] = $reg.edx -band 0x00000100 $features['apic'] = $reg.edx -band 0x00000200 $features['sep'] = $reg.edx -band 0x00000800 $features['mtrr'] = $reg.edx -band 0x00001000 $features['pge'] = $reg.edx -band 0x00002000 $features['mca'] = $reg.edx -band 0x00004000 $features['cmov'] = $reg.edx -band 0x00008000 $features['pat'] = $reg.edx -band 0x00010000 $features['pse36'] = $reg.edx -band 0x00020000 $features['psn'] = $reg.edx -band 0x00040000 $features['clflush'] = $reg.edx -band 0x00080000 $features['ds'] = $reg.edx -band 0x00200000 $features['acpi'] = $reg.edx -band 0x00400000 $features['mmx'] = $reg.edx -band 0x00800000 $features['fxsr'] = $reg.edx -band 0x01000000 $features['sse'] = $reg.edx -band 0x02000000 $features['sse2'] = $reg.edx -band 0x04000000 $features['ss'] = $reg.edx -band 0x08000000 $features['htt'] = $reg.edx -band 0x10000000 $features['tm'] = $reg.edx -band 0x20000000 $features['ia64'] = $reg.edx -band 0x40000000 $features['pbe'] = $reg.edx -band 0x80000000 $features['sse3'] = $reg.ecx -band 0x00000001 $features['pclmulqdq'] = $reg.ecx -band 0x00000002 $features['dtes64'] = $reg.ecx -band 0x00000004 $features['monitor'] = $reg.ecx -band 0x00000008 $features['ds_cpl'] = $reg.ecx -band 0x00000010 $features['vmx'] = $reg.ecx -band 0x00000020 $features['smx'] = $reg.ecx -band 0x00000040 $features['est'] = $reg.ecx -band 0x00000080 $features['tm2'] = $reg.ecx -band 0x00000100 $features['ssse3'] = $reg.ecx -band 0x00000200 $features['cntx_id'] = $reg.ecx -band 0x00000400 $features['sdbg'] = $reg.ecx -band 0x00000800 $features['fma'] = $reg.ecx -band 0x00001000 $features['cx16'] = $reg.ecx -band 0x00002000 $features['xtpr'] = $reg.ecx -band 0x00004000 $features['pdcm'] = $reg.ecx -band 0x00008000 $features['pcid'] = $reg.ecx -band 0x00020000 $features['dca'] = $reg.ecx -band 0x00040000 $features['sse4_1'] = $reg.ecx -band 0x00080000 $features['sse4_2'] = $reg.ecx -band 0x00100000 $features['x2apic'] = $reg.ecx -band 0x00200000 $features['movbe'] = $reg.ecx -band 0x00400000 $features['popcnt'] = $reg.ecx -band 0x00800000 $features['tsc_deadline'] = $reg.ecx -band 0x01000000 $features['aes'] = $reg.ecx -band 0x02000000 $features['xsave'] = $reg.ecx -band 0x04000000 $features['osxsave'] = $reg.ecx -band 0x08000000 $features['avx'] = $reg.ecx -band 0x10000000 $features['f16c'] = $reg.ecx -band 0x20000000 $features['rdrnd'] = $reg.ecx -band 0x40000000 $features['hypervisor'] = $reg.ecx -band 0x80000000 } $leave = New-Object PSObject -Property (Get-Blocks $buf -AsInteger) $low += $leave } # high leaves $cpuid.Invoke(0x80000000, $buf) $ids = (Get-Blocks $buf -AsInteger).eax $top = @() $name = '' # брэндовая строка for ($i = 0x80000000; $i -le $ids; $i++) { $cpuid.Invoke($i, $buf) if ($i -eq 0x80000001) { $reg = Get-Blocks $buf -AsInteger $features['syscall'] = $reg.edx -band 0x00000800 $features['mp'] = $reg.edx -band 0x00080000 $features['nx'] = $reg.edx -band 0x00100000 $features['mmxext'] = $reg.edx -band 0x00400000 $features['fxsr_opt'] = $reg.edx -band 0x02000000 $features['pdpe1gb'] = $reg.edx -band 0x04000000 $features['rdtscp'] = $reg.edx -band 0x08000000 $features['lm'] = $reg.edx -band 0x20000000 $features['3dnowext'] = $reg.edx -band 0x40000000 $features['3dnow'] = $reg.edx -band 0x80000000 $features['lahf_lm'] = $reg.ecx -band 0x00000001 $features['cmp_legacy'] = $reg.ecx -band 0x00000002 $features['svm'] = $reg.ecx -band 0x00000004 $features['extapic'] = $reg.ecx -band 0x00000008 $features['cr8_legacy'] = $reg.ecx -band 0x00000010 $features['abm'] = $reg.ecx -band 0x00000020 $features['sse4a'] = $reg.ecx -band 0x00000040 $features['misalingsse'] = $reg.ecx -band 0x00000080 $features['3dnowprefetch'] = $reg.ecx -band 0x00000100 $features['osvw'] = $reg.ecx -band 0x00000200 $features['ibs'] = $reg.ecx -band 0x00000400 $features['xop'] = $reg.ecx -band 0x00000800 $features['skinit'] = $reg.ecx -band 0x00001000 $features['wdt'] = $reg.ecx -band 0x00002000 $features['lwp'] = $reg.ecx -band 0x00008000 $features['fma4'] = $reg.ecx -band 0x00010000 $features['tce'] = $reg.ecx -band 0x00020000 $features['nodeid_msr'] = $reg.ecx -band 0x00080000 $features['tbm'] = $reg.ecx -band 0x00200000 $features['topoext'] = $reg.ecx -band 0x00400000 $features['perfctr_core'] = $reg.ecx -band 0x00800000 $features['perfctr_nb'] = $reg.ecx -band 0x01000000 $features['dbx'] = $reg.ecx -band 0x04000000 $features['perftsc'] = $reg.ecx -band 0x08000000 $features['pcx_l2i'] = $reg.ecx -band 0x10000000 } if ($i -eq 0x80000002 -or $i -eq 0x80000003 -or $i -eq 0x80000004) { $name += "$(( $reg = Get-Blocks $buf -AsString ).eax)$($reg.ebx)$($reg.ecx)$($reg.edx)" } $leave = New-Object PSObject -Property (Get-Blocks $buf -AsInteger) $top += $leave } $cpuid = New-Object PSObject -Property @{ Vendor = $vendor Name = $name.Trim() SteppingId = $stepping Model = $model Family = $family LogicalCPUCount = $logiccpu Features = $features.Keys | ForEach-Object { if ($features[$_]) { $_ } } | Sort-Object LowLeaves = $low HighLeaves = $top } | Select-Object ( 'Vendor', 'Name', 'SteppingId', 'Model', 'Family', 'LogicalCPUCount', 'Features', 'LowLeaves', 'HighLeaves' ) } catch { $_ } finally { if ($ptr) { [void]$VirtualFree.Invoke($ptr, [UIntPtr]::Zero, 0x8000) } } } end { $cpuid $collect | ForEach-Object { [void]$ta::Remove($_) } } } Надеюсь это поможет. |
Последний раз редактировалось greg zakharov, 21-11-2016 в 11:09. Отправлено: 10:57, 21-11-2016 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Забанен Сообщения: 27
|
Спасибо! Думаю, вопрос решён.
|
Отправлено: 12:18, 21-11-2016 | #3 |
Новый участник Сообщения: 1
|
Профиль | Отправить PM | Цитировать Доброго времени!
Подскажите пожалуйста такой момент: Я использую в своей проге код на Ассемблере для получения CPUID. Беру только первый отрезок, т.к. остальные там просто нули. Например на моей машине CPUID получается: 0001067А Далее я беру из реестра FeatureSet: 559628286 Складываю CPUID+FeatureSet , Таким образом я получаю уникальный ID для каждой машины. Вопрос: может ли FeatureSet быть одинаковым у похожих процессоров? Могут ли у одинаковых процессоров совпадать FeatureSet ? Другими словами может ли данный прием обеспечить мне уникальность каждой машины ? |
Отправлено: 12:42, 26-04-2017 | #4 |
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
CMD/BAT - [решено] Нахождение совпадения без учета регистра | Mikle_home88 | Скриптовые языки администрирования Windows | 1 | 04-08-2015 15:20 | |
2007 - [решено] Word| Из верхнего регистра в нижний | sashok60 | Microsoft Office (Word, Excel, Outlook и т.д.) | 2 | 05-04-2010 11:24 | |
[решено] Adobe FrameMaker - поиск и применение определенного стиля | Vadikan | AutoIt | 1 | 01-12-2009 15:54 | |
[решено] Поиск обновлений - загрузка процессора 100% | Ser6720 | Microsoft Windows 2000/XP | 14 | 08-06-2007 19:02 | |
Assm - assembler вывод содержимого регистра на экран | Guest | Программирование и базы данных | 1 | 16-07-2004 16:32 |
|