Decode Binary Alternative 1-1 PS Code

Discussion in 'Scripting' started by Dark Vador, Aug 28, 2025 at 19:36.

  1. Dark Vador

    Dark Vador X Æ A-12

    Feb 2, 2011
    4,773
    7,040
    150
    #1 Dark Vador, Aug 28, 2025 at 19:36
    Last edited: Aug 29, 2025 at 11:37
    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;
    }
    
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  2. Dark Vador

    Dark Vador X Æ A-12

    Feb 2, 2011
    4,773
    7,040
    150
    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
    
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...