this code should be alternative 1-1 code, to decode binary data, productKey from registry (Off 52/808) Found in --> LicensingDiagSpp.dll, LicensingWinRT.dll, SppComApi.dll, SppWinOb.dll under this name __int64 __fastcall CProductKeyUtilsT<CEmptyType>::BinaryDecode(__m128i *a1, __int64 a2, unsigned __int16 **a3) it similer to origional vbs janek code, but, it more like the origional version (c/c+ based) i even kept the origonal name, v? whatever, was a fun project for today. can use using this example. Code: $pKeyBytes = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name "DigitalProductId" -ErrorAction Stop | Select-Object -ExpandProperty DigitalProductId $pKey = Get-DigitalProductKey -bCDKeyArray $pKeyBytes[52..66] $pKeyBytes = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name "DigitalProductId4" -ErrorAction Stop | Select-Object -ExpandProperty DigitalProductId4 $pKey = Get-DigitalProductKey -bCDKeyArray $pKeyBytes[808..822] Ps1 `1-1` Same Code. [v3] Code: function Get-DigitalProductKey { param ( [Parameter(Mandatory=$true)] [byte[]]$bCDKeyArray, [switch]$Log ) # Clone input to v21 (like C++ __m128i copy) $v21 = $bCDKeyArray.Clone() # Character set for base-24 decoding $v22 = "BCDFGHJKMPQRTVWXY2346789" # Validate input length if ($v21.Length -lt 15 -or $v21.Length -gt 16) { throw "Input data must be a 15 or 16 byte array." } # OEM key check if (($v21[14] -band 0xF0) -ne 0) { throw "Failed to decode" } # N-flag $v7 = ($v21[14] -band 0x08) -ne 0 # Adjust v21[14] like C++ XOR operation $v21[14] = ($v21[14] -bxor (($v21[14] -bxor (4 * [int]$v7)) -band 8)) # Only first 15 bytes are used $v21 = $v21[0..14].Clone() $Src = New-Object char[] 25 # Base-24 decoding loop for ($v6 = 24; $v6 -ge 0; $v6--) { $v8 = 0 for ($j = 14; $j -ge 0; $j--) { $v10 = $v21[$j] + ($v8 -shl 8) $v21[$j] = [math]::Floor($v10 / 0x18) $v8 = $v10 % 0x18 } $Src[$v6] = $v22[$v8] } if ($v21[0] -ne 0) { throw "Invalid product key data" } # Handle N-flag if ($Log) { $Output = (0..4 | % { -join $Src[(5*$_)..((5*$_)+4)] }) -join '-' Write-Warning "Before, $Output" } if ($v7 -and ($v8 -le 0)) { $Src[0] = [Char]78 } elseif ($v7 -and ($v8 -gt 0)) { $N, $Src1, $Src2 = @([Char]78), ($Src[1..$v8]), ($Src[($v8+1)..24]) $Src = @($Src1 + $N + $Src2) } # Dynamically format 5x5 with dashes $Output = (0..4 | % { -join $Src[(5*$_)..((5*$_)+4)] }) -join '-' if ($Log) { Write-Warning "After, $Output" } return $Output } Original Disassembly Code Code: __int64 __fastcall CProductKeyUtilsT<CEmptyType>::BinaryDecode(__m128i *a1, __int64 a2, unsigned __int16 **a3) { unsigned __int16 *v3; // rbx unsigned int v5; // edi __int64 v6; // r9 BOOL v7; // r10d __int64 v8; // r8 __int64 i; // rcx unsigned int v10; // r8d __int64 v11; // rbx int v12; // eax unsigned __int16 *v13; // r9 __int16 *v14; // r10 int j; // r8d unsigned __int16 v16; // ax __int64 v17; // rcx HANDLE ProcessHeap; // rax unsigned __int16 *v20; // [rsp+28h] [rbp-51h] BYREF __m128i v21; // [rsp+30h] [rbp-49h] __int128 v22[3]; // [rsp+40h] [rbp-39h] wchar_t v23; // [rsp+70h] [rbp-9h] __int16 v24; // [rsp+78h] [rbp-1h] BYREF char Src[54]; // [rsp+7Ah] [rbp+1h] BYREF v3 = 0i64; v23 = aBcdfghjkmpqrtv[24]; v22[0] = *(_OWORD *)L"BCDFGHJKMPQRTVWXY2346789"; v20 = 0i64; v22[1] = *(_OWORD *)L"MPQRTVWXY2346789"; v22[2] = *(_OWORD *)L"Y2346789"; v21 = *a1; if ( (_mm_srli_si128(v21, 8).m128i_u64[0] & 0xF0000000000000i64) != 0 ) goto LABEL_2; v6 = 24i64; v7 = (v21.m128i_i8[14] & 8) != 0; v21.m128i_i8[14] ^= (v21.m128i_i8[14] ^ (4 * ((v21.m128i_i8[14] & 8) != 0))) & 8; do { LODWORD(v8) = 0; for ( i = 14i64; i >= 0; --i ) { v10 = v21.m128i_u8[i] + ((_DWORD)v8 << 8); v21.m128i_i8[i] = v10 / 0x18; v8 = v10 % 0x18; } *(_WORD *)&Src[2 * v6-- - 2] = *((_WORD *)v22 + v8); } while ( v6 >= 0 ); if ( v21.m128i_i8[0] ) { LABEL_2: v5 = -2147024883; CBreakOnFailureT<CEmptyType>::CheckToBreakOnFailure(2147942413i64); } else { if ( v7 ) { v11 = 2 * v8; memmove_0(&v24, Src, 2 * v8); *(_WORD *)&Src[v11 - 2] = 78; } v12 = STRAPI_CreateCchBufferN(0x2Du, 0x1Eui64, &v20); v5 = v12; if ( v12 >= 0 ) { v13 = v20; v14 = &v24; for ( j = 0; j < 25; ++j ) { v16 = *v14++; v17 = j + j / 5; v13[v17] = v16; } v3 = 0i64; *a3 = v13; } else { CBreakOnFailureT<CEmptyType>::CheckToBreakOnFailure((unsigned int)v12); v3 = v20; } } CChkMacroETWLoggerT<CEmptyType>::LogHResultEvent(v5); if ( v3 ) { ProcessHeap = GetProcessHeap(); HeapFree(ProcessHeap, 0, v3 - 2); CChkMacroETWLoggerT<CEmptyType>::LogHResultEvent(0i64); } return v5; }
So, darky decide to play so, N Pos, depend >13 or less will be shifted manual Left or right for the fun. so, instead of create new array, i use same array, 0 to 24, +2 more, to able shift right without fail So, now, $Src = New-Object char[] 27 instead 25, able handle n=25 Code: Clear-Host Write-Host function Get-DigitalProductKey { param ( [Parameter(Mandatory=$true)] [byte[]]$bCDKeyArray, [Parameter(Mandatory=$false)] [switch]$Log ) # Clone input to v21 (like C++ __m128i copy) $keyData = $bCDKeyArray.Clone() # +2 for N` Logic Shift right [else fail] $Src = New-Object char[] 27 # Character set for base-24 decoding $charset = "BCDFGHJKMPQRTVWXY2346789" # Validate input length if ($keyData.Length -lt 15 -or $keyData.Length -gt 16) { throw "Input data must be a 15 or 16 byte array." } # Win.8 key check if (($keyData[14] -band 0xF0) -ne 0) { throw "Failed to decode.!" } # N-flag $T, $flag = 0, (($keyData[14] -band 0x08) -ne 0) # Adjust v21[14] like C++ XOR operation $keyData[14] = ($keyData[14] -bxor (($keyData[14] -bxor (4 * [int]$flag)) -band 8)) # Base-24 decoding loop for ($idx = 24; $idx -ge 0; $idx--) { $last = 0 for ($j = 14; $j -ge 0; $j--) { $val = $keyData[$j] + ($last -shl 8) $keyData[$j] = [math]::Floor($val / 0x18) $last = $val % 0x18 } $Src[$idx] = $charset[$last] } if ($keyData[0] -ne 0) { throw "Invalid product key data" } # Handle N-flag $rev = $last -gt 13 $pos = if ($rev) {25} else {-1} if ($Log) { $Output = (0..4 | % { -join $Src[(5*$_)..((5*$_)+4)] }) -join '-' Write-Warning "Before, $Output" } # Shift Left, Insert N, At position 0 >> $Src[0]=`N` if ($flag -and ($last -le 0)) { $Src[0] = [Char]78 } # Shift right, Insert N, Count 1-25 [27 Base,0-24 & 2` Spacer's] elseif ($flag -and $rev) { while ($pos-- -gt $last){$Src[$pos + 1]=$Src[$pos]} $T, $Src[$last+1] = 1, [char]78 } # Shift left, Insert N, elseif ($flag -and !$rev) { while (++$pos -lt $last){$Src[$pos] = $Src[$pos + 1]} $Src[$last] = [char]78 } # Dynamically format 5x5 with dashes $Output = (0..4 | % { -join $Src[((5*$_)+$T)..((5*$_)+4+$T)] }) -join '-' if ($Log) { Write-Warning "After, $Output" } return $Output } $pKeyBytes = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name "DigitalProductId" -ErrorAction Stop | Select-Object -ExpandProperty DigitalProductId $pKey = Get-DigitalProductKey -bCDKeyArray $pKeyBytes[52..67] -Log SL-InstallProductKey -Keys $pKey