# encoding: ascii
# api: powershell
# title: Get-CPUID (with asm)
# description: Original post was found at https://github.com/gregzakh/alt-ps/blob/master/Get-CPUID.ps1 (author gregzakh)
# version: 0.1
# type: function
# author: Jakub Jares
# license: CC0
# function: Get-CPUID
# x-poshcode-id: 6405
# x-archived: 2016-06-29T04:04:09
# x-published: 2016-06-24T19:26:00
#
#
function Get-CPUID {
<#
.SYNOPSIS
Queries the CPU for information about its type.
#>
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
}
}
Add-Type -AssemblyName System.ServiceModel
([AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object {
$_.ManifestModule.ScopeName.Equals(
'System.ServiceModel.dll'
)
}).GetType(
'System.ServiceModel.Channels.UnsafeNativeMethods'
).GetMethods([Reflection.BindingFlags]40) |
Where-Object {
$_.Name -cmatch '\AVirtual(Alloc|Free)'
} | ForEach-Object { Set-Variable $_.Name $_ }
[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
}
}
}
process {
try {
$ptr = $VirtualAlloc.Invoke($null, @(
[IntPtr]::Zero, [UIntPtr](New-Object UIntPtr($bytes.Length)),
[UInt32](0x1000 -bor 0x2000), [UInt32]0x40
))
[Marshal]::Copy($bytes, 0, $ptr, $bytes.Length)
$proto = [Action[Int32, [Byte[]]]]
$method = $proto.GetMethod('Invoke')
$returntype = $method.ReturnType
$paramtypes = $method.GetParameters() |
Select-Object -ExpandProperty ParameterType
$holder = New-Object Reflection.Emit.DynamicMethod(
'Invoke', $returntype, $paramtypes, $proto
)
$il = $holder.GetILGenerator()
0..($paramtypes.Length - 1) | ForEach-Object {
$il.Emit([OpCodes]::Ldarg, $_)
}
switch ([IntPtr]::Size) {
4 { $il.Emit([OpCodes]::Ldc_I4, $ptr.ToInt32()) }
8 { $il.Emit([OpCodes]::Ldc_I8, $ptr.ToInt64()) }
}
$il.EmitCalli(
[OpCodes]::Calli, [CallingConvention]::Cdecl, $returntype, $paramtypes
)
$il.Emit([OpCodes]::Ret)
$cpuid = $holder.CreateDelegate($proto)
[Byte[]]$buf = New-Object Byte[] 16
$gch = [GCHandle]::Alloc($buf, 'Pinned')
$cpuid.Invoke(0, $buf)
$gch.Free()
"$(-join [Char[]]$buf[4..7])$(
-join [Char[]]$buf[12..15]
)$(-join [Char[]]$buf[8..11])"
}
catch { $_.Exception }
finally {
if ($ptr) {
[void]$VirtualFree.Invoke($null, @($ptr, [UIntPtr]::Zero, [UInt32]0x8000))
}
}
}
end {
$collect | ForEach-Object { [void]$ta::Remove($_) }
}
}