227 lines
6.0 KiB
PowerShell
227 lines
6.0 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Calculate hash for Set-Association function
|
|
|
|
.VERSION
|
|
7.1.4
|
|
|
|
.DATE
|
|
24.02.2026
|
|
|
|
.COPYRIGHT
|
|
(c) 2014—2026 Team Sophia
|
|
|
|
.LINK
|
|
https://github.com/farag2/Sophia-Script-for-Windows
|
|
#>
|
|
function Get-Hash
|
|
{
|
|
[CmdletBinding()]
|
|
[OutputType([string])]
|
|
Param
|
|
(
|
|
[Parameter(
|
|
Mandatory = $true,
|
|
Position = 0
|
|
)]
|
|
[string]
|
|
$ProgId,
|
|
|
|
[Parameter(
|
|
Mandatory = $true,
|
|
Position = 1
|
|
)]
|
|
[string]
|
|
$Extension,
|
|
|
|
[Parameter(
|
|
Mandatory = $true,
|
|
Position = 2
|
|
)]
|
|
[string]
|
|
$SubKey
|
|
)
|
|
|
|
$Signature = @{
|
|
Namespace = "WinAPI"
|
|
Name = "PatentHash"
|
|
Language = "CSharp"
|
|
CompilerParameters = $CompilerParameters
|
|
MemberDefinition = @"
|
|
public static uint[] WordSwap(byte[] a, int sz, byte[] md5)
|
|
{
|
|
if (sz < 2 || (sz & 1) == 1)
|
|
{
|
|
throw new ArgumentException(String.Format("Invalid input size: {0}", sz), "sz");
|
|
}
|
|
|
|
unchecked
|
|
{
|
|
uint o1 = 0;
|
|
uint o2 = 0;
|
|
int ta = 0;
|
|
int ts = sz;
|
|
int ti = ((sz - 2) >> 1) + 1;
|
|
|
|
uint c0 = (BitConverter.ToUInt32(md5, 0) | 1) + 0x69FB0000;
|
|
uint c1 = (BitConverter.ToUInt32(md5, 4) | 1) + 0x13DB0000;
|
|
|
|
for (uint i = (uint)ti; i > 0; i--)
|
|
{
|
|
uint n = BitConverter.ToUInt32(a, ta) + o1;
|
|
ta += 8;
|
|
ts -= 2;
|
|
|
|
uint v1 = 0x79F8A395 * (n * c0 - 0x10FA9605 * (n >> 16)) + 0x689B6B9F * ((n * c0 - 0x10FA9605 * (n >> 16)) >> 16);
|
|
uint v2 = 0xEA970001 * v1 - 0x3C101569 * (v1 >> 16);
|
|
uint v3 = BitConverter.ToUInt32(a, ta - 4) + v2;
|
|
uint v4 = v3 * c1 - 0x3CE8EC25 * (v3 >> 16);
|
|
uint v5 = 0x59C3AF2D * v4 - 0x2232E0F1 * (v4 >> 16);
|
|
|
|
o1 = 0x1EC90001 * v5 + 0x35BD1EC9 * (v5 >> 16);
|
|
o2 += o1 + v2;
|
|
}
|
|
|
|
if (ts == 1)
|
|
{
|
|
uint n = BitConverter.ToUInt32(a, ta) + o1;
|
|
|
|
uint v1 = n * c0 - 0x10FA9605 * (n >> 16);
|
|
uint v2 = 0xEA970001 * (0x79F8A395 * v1 + 0x689B6B9F * (v1 >> 16)) - 0x3C101569 * ((0x79F8A395 * v1 + 0x689B6B9F * (v1 >> 16)) >> 16);
|
|
uint v3 = v2 * c1 - 0x3CE8EC25 * (v2 >> 16);
|
|
|
|
o1 = 0x1EC90001 * (0x59C3AF2D * v3 - 0x2232E0F1 * (v3 >> 16)) + 0x35BD1EC9 * ((0x59C3AF2D * v3 - 0x2232E0F1 * (v3 >> 16)) >> 16);
|
|
o2 += o1 + v2;
|
|
}
|
|
|
|
uint[] ret = new uint[2];
|
|
ret[0] = o1;
|
|
ret[1] = o2;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
public static uint[] Reversible(byte[] a, int sz, byte[] md5)
|
|
{
|
|
if (sz < 2 || (sz & 1) == 1)
|
|
{
|
|
throw new ArgumentException(String.Format("Invalid input size: {0}", sz), "sz");
|
|
}
|
|
|
|
unchecked
|
|
{
|
|
uint o1 = 0;
|
|
uint o2 = 0;
|
|
int ta = 0;
|
|
int ts = sz;
|
|
int ti = ((sz - 2) >> 1) + 1;
|
|
|
|
uint c0 = BitConverter.ToUInt32(md5, 0) | 1;
|
|
uint c1 = BitConverter.ToUInt32(md5, 4) | 1;
|
|
|
|
for (uint i = (uint)ti; i > 0; i--)
|
|
{
|
|
uint n = (BitConverter.ToUInt32(a, ta) + o1) * c0;
|
|
n = 0xB1110000 * n - 0x30674EEF * (n >> 16);
|
|
ta += 8;
|
|
ts -= 2;
|
|
|
|
uint v1 = 0x5B9F0000 * n - 0x78F7A461 * (n >> 16);
|
|
uint v2 = 0x1D830000 * (0x12CEB96D * (v1 >> 16) - 0x46930000 * v1) + 0x257E1D83 * ((0x12CEB96D * (v1 >> 16) - 0x46930000 * v1) >> 16);
|
|
uint v3 = BitConverter.ToUInt32(a, ta - 4) + v2;
|
|
|
|
uint v4 = 0x16F50000 * c1 * v3 - 0x5D8BE90B * (c1 * v3 >> 16);
|
|
uint v5 = 0x2B890000 * (0x96FF0000 * v4 - 0x2C7C6901 * (v4 >> 16)) + 0x7C932B89 * ((0x96FF0000 * v4 - 0x2C7C6901 * (v4 >> 16)) >> 16);
|
|
|
|
o1 = 0x9F690000 * v5 - 0x405B6097 * (v5 >> 16);
|
|
o2 += o1 + v2;
|
|
}
|
|
|
|
if (ts == 1)
|
|
{
|
|
uint n = BitConverter.ToUInt32(a, ta) + o1;
|
|
|
|
uint v1 = 0xB1110000 * c0 * n - 0x30674EEF * ((c0 * n) >> 16);
|
|
uint v2 = 0x5B9F0000 * v1 - 0x78F7A461 * (v1 >> 16);
|
|
uint v3 = 0x1D830000 * (0x12CEB96D * (v2 >> 16) - 0x46930000 * v2) + 0x257E1D83 * ((0x12CEB96D * (v2 >> 16) - 0x46930000 * v2) >> 16);
|
|
uint v4 = 0x16F50000 * c1 * v3 - 0x5D8BE90B * ((c1 * v3) >> 16);
|
|
uint v5 = 0x96FF0000 * v4 - 0x2C7C6901 * (v4 >> 16);
|
|
o1 = 0x9F690000 * (0x2B890000 * v5 + 0x7C932B89 * (v5 >> 16)) - 0x405B6097 * ((0x2B890000 * v5 + 0x7C932B89 * (v5 >> 16)) >> 16);
|
|
o2 += o1 + v2;
|
|
}
|
|
|
|
uint[] ret = new uint[2];
|
|
ret[0] = o1;
|
|
ret[1] = o2;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
public static long MakeLong(uint left, uint right)
|
|
{
|
|
return (long)left << 32 | (long)right;
|
|
}
|
|
"@
|
|
}
|
|
|
|
if (-not ("WinAPI.PatentHash" -as [type]))
|
|
{
|
|
Add-Type @Signature
|
|
}
|
|
|
|
function Get-KeyLastWriteTime ($SubKey)
|
|
{
|
|
$LastModified = [WinAPI.Action]::GetLastModified([Microsoft.Win32.RegistryHive]::CurrentUser,$SubKey)
|
|
$FileTime = ([DateTime]::New($LastModified.Year, $LastModified.Month, $LastModified.Day, $LastModified.Hour, $LastModified.Minute, 0, $LastModified.Kind)).ToFileTime()
|
|
|
|
return [string]::Format("{0:x8}{1:x8}", $FileTime -shr 32, $FileTime -band [uint32]::MaxValue)
|
|
}
|
|
|
|
function Get-DataArray
|
|
{
|
|
[OutputType([array])]
|
|
|
|
# Secret static string stored in %SystemRoot%\SysWOW64\%SystemRoot%\System32\shell32.dll
|
|
$userExperience = "User Choice set via Windows User Experience {D18B6DD5-6124-4341-9318-804003BAFA0B}"
|
|
# Get user SID
|
|
$userSID = (Get-CimInstance -ClassName Win32_UserAccount | Where-Object -FilterScript {$_.Name -eq $env:USERNAME}).SID
|
|
$KeyLastWriteTime = Get-KeyLastWriteTime -SubKey $SubKey
|
|
$baseInfo = ("{0}{1}{2}{3}{4}" -f $Extension, $userSID, $ProgId, $KeyLastWriteTime, $userExperience).ToLowerInvariant()
|
|
$StringToUTF16LEArray = [System.Collections.ArrayList]@([System.Text.Encoding]::Unicode.GetBytes($baseInfo))
|
|
$StringToUTF16LEArray += (0,0)
|
|
|
|
return $StringToUTF16LEArray
|
|
}
|
|
|
|
function Get-PatentHash
|
|
{
|
|
[OutputType([string])]
|
|
param
|
|
(
|
|
[Parameter(Mandatory = $true)]
|
|
[byte[]]
|
|
$Array,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[byte[]]
|
|
$MD5
|
|
)
|
|
|
|
$Size = $Array.Count
|
|
$ShiftedSize = ($Size -shr 2) - ($Size -shr 2 -band 1) * 1
|
|
|
|
[uint32[]]$Array1 = [WinAPI.PatentHash]::WordSwap($Array, [int]$ShiftedSize, $MD5)
|
|
[uint32[]]$Array2 = [WinAPI.PatentHash]::Reversible($Array, [int]$ShiftedSize, $MD5)
|
|
|
|
$Ret = [WinAPI.PatentHash]::MakeLong($Array1[1] -bxor $Array2[1], $Array1[0] -bxor $Array2[0])
|
|
|
|
return [System.Convert]::ToBase64String([System.BitConverter]::GetBytes([Int64]$Ret))
|
|
}
|
|
|
|
$DataArray = Get-DataArray
|
|
$DataMD5 = [System.Security.Cryptography.HashAlgorithm]::Create("MD5").ComputeHash($DataArray)
|
|
$Hash = Get-PatentHash -Array $DataArray -MD5 $DataMD5
|
|
|
|
return $Hash
|
|
}
|