Files
2023-09-24 12:01:23 +08:00

220 lines
6.9 KiB
PowerShell

#!/usr/bin/env pwsh
#Requires -Version 5.1
#Requires -RunAsAdministrator
# 获取 QQ 安装目录
$Script:QQBase = Get-ChildItem `
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\', `
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\', `
'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' `
| Where-Object Name -Like '*\QQ' `
| Select-Object -Property @(
@{
label = 'Path'
expression = { $_.GetValue('UninstallString') | Split-Path }
}
) `
| Select-Object -ExpandProperty Path
if (!$QQBase) {
throw '未能发现已安装的 NTQQ'
}
function Update-PatchProgress {
[CmdletBinding()]
param (
# Parameter help description
[Parameter(Mandatory)]
[int]
$Progress
)
process {
Write-Progress -Activity '当前修补进度' -Status "$Progress% Complete:" -PercentComplete $Progress
}
}
function Invoke-PatchQQ {
[CmdletBinding()]
param (
# Parameter help description
[Parameter(Mandatory)]
[byte[]]
$OriginalBytes1,
# Parameter help description
[Parameter(Mandatory)]
[byte[]]
$OriginalBytes2,
# Parameter help description
[Parameter(Mandatory)]
[byte[]]
$ReplaceBytes1,
# Parameter help description
[Parameter(Mandatory)]
[byte[]]
$ReplaceBytes2
)
begin {
Write-Host '开始修补...' -ForegroundColor Blue
}
process {
# 要修补的.exe文件路径
$Private:SourceFilePath = "$QQBase\QQ.exe.bak"
$Private:TargetFilePath = "$QQBase\QQ.exe"
# 重命名QQ为.bak
if (-not (Test-Path $SourceFilePath)) {
Rename-Item -Path $TargetFilePath -NewName 'QQ.exe.bak'
}
# 使用二进制文件流打开原始文件和目标文件
$Private:SourceStream = [System.IO.File]::OpenRead($SourceFilePath)
$Private:TargetStream = [System.IO.File]::Create($TargetFilePath)
try {
# 定义缓冲区大小 (4MB)
$Private:BufferSize = 1024 * 1024 * 4
$Private:Buffer = [byte[]]::new($BufferSize)
$Private:FileSize = $SourceStream.Length
$Private:BytesProcessed = 0
$Private:Matched = 0
Update-PatchProgress -Progress 0
# 循环处理文件
while ($true) {
# 从原始文件读取缓冲区数据
$Private:ReadBytes = $SourceStream.Read($Buffer, 0, $BufferSize)
# 如果已经读取到文件末尾,则退出循环
if ($ReadBytes -eq 0) {
break
}
if ($Matched -ne 2) {
# 查找并替换字节序列(写成这样子是为了提高性能)
for ($i = 0; $i -lt $ReadBytes; $i++) {
if (
$Buffer[$i + 0] -eq $OriginalBytes1[0] -and
$Buffer[$i + 1] -eq $OriginalBytes1[1] -and
$Buffer[$i + 2] -eq $OriginalBytes1[2] -and
$Buffer[$i + 3] -eq $OriginalBytes1[3] -and
$Buffer[$i + 4] -eq $OriginalBytes1[4] -and
$Buffer[$i + 5] -eq $OriginalBytes1[5] -and
$Buffer[$i + 6] -eq $OriginalBytes1[6] -and
$Buffer[$i + 7] -eq $OriginalBytes1[7] -and
$Buffer[$i + 8] -eq $OriginalBytes1[8] -and
$Buffer[$i + 9] -eq $OriginalBytes1[9] -and
$Buffer[$i + 10] -eq $OriginalBytes1[10] -and
$Buffer[$i + 11] -eq $OriginalBytes1[11] -and
$Buffer[$i + 12] -eq $OriginalBytes1[12]
) {
$Matched = $Matched + 1
for ($j = 0; $j -lt 13; $j++) {
$Buffer[$i + $j] = $ReplaceBytes1[$j]
}
}
elseif (
$Buffer[$i + 0] -eq $OriginalBytes2[0] -and
$Buffer[$i + 1] -eq $OriginalBytes2[1] -and
$Buffer[$i + 2] -eq $OriginalBytes2[2] -and
$Buffer[$i + 3] -eq $OriginalBytes2[3] -and
$Buffer[$i + 4] -eq $OriginalBytes2[4] -and
$Buffer[$i + 5] -eq $OriginalBytes2[5] -and
$Buffer[$i + 6] -eq $OriginalBytes2[6] -and
$Buffer[$i + 7] -eq $OriginalBytes2[7] -and
$Buffer[$i + 8] -eq $OriginalBytes2[8] -and
$Buffer[$i + 9] -eq $OriginalBytes2[9] -and
$Buffer[$i + 10] -eq $OriginalBytes2[10] -and
$Buffer[$i + 11] -eq $OriginalBytes2[11] -and
$Buffer[$i + 12] -eq $OriginalBytes2[12]
) {
$Matched = $Matched + 1
for ($j = 0; $j -lt 13; $j++) {
$Buffer[$i + $j] = $ReplaceBytes2[$j]
}
}
}
}
# 将缓冲区数据写入目标文件
$TargetStream.Write($Buffer, 0, $ReadBytes)
$BytesProcessed += $ReadBytes
$Private:Progress = [Math]::Truncate(($BytesProcessed / $FileSize) * 100)
Update-PatchProgress -Progress $Progress
}
Update-PatchProgress -Progress 100
}
finally {
# 关闭文件流
$SourceStream.Dispose()
$TargetStream.Dispose()
}
}
end {
Write-Host 'Patch 完成!' -ForegroundColor Blue
}
}
function Invoke-ReplaceInFile {
[CmdletBinding()]
param (
# Parameter help description
[Parameter(Mandatory)]
[string]
$Filename,
# Parameter help description
[Parameter(Mandatory)]
[string]
$OldValue,
# Parameter help description
[Parameter(Mandatory)]
[string]
$NewValue
)
process {
if (Test-Path $Filename) {
(Get-Content $Filename -Raw ) -replace $OldValue, $NewValue | Out-File $Filename
}
}
}
$Private:State = Read-Host -Prompt '您要执行修补吗 [Y/n]'
if (!'y'.Equals($State, [System.StringComparison]::OrdinalIgnoreCase) `
-and ![string]::IsNullOrWhiteSpace($State)) {
exit
}
Write-Host '正在初始化...' -ForegroundColor Blue
[byte[]] $Private:OriginalBytes1 = @(0xAD, 0xA0, 0xB4, 0xAF, 0xA2, 0xA9, 0xA4, 0xB3, 0xEF, 0xAB, 0xB2, 0xAE, 0xAF, 0x00)
[byte[]] $Private:ReplaceBytes1 = @(0xA3, 0xA0, 0xB4, 0xAF, 0xA2, 0xA9, 0xA4, 0xB3, 0xEF, 0xAB, 0xB2, 0xAE, 0xAF, 0x00)
[byte[]] $Private:OriginalBytes2 = @(0xB1, 0xA0, 0xA2, 0xAA, 0xA0, 0xA6, 0xA4, 0xEF, 0xAB, 0xB2, 0xAE, 0xAF, 0x00)
[byte[]] $Private:ReplaceBytes2 = @(0xA3, 0xA0, 0xA2, 0xAA, 0xA0, 0xA6, 0xA4, 0xEF, 0xAB, 0xB2, 0xAE, 0xAF, 0x00)
if (-not (Select-String -Path ("$QQBase\resources\app\package.json") -Pattern 'LiteLoader' -Quiet)) {
Copy-Item -Path ("$QQBase\resources\app\package.json") -Destination ("$QQBase\resources\app\backage.json") -Force
}
Copy-Item -Path ("$QQBase\resources\app\launcher.json") -Destination ("$QQBase\resources\app\bauncher.json") -Force
Invoke-ReplaceInFile `
-FileName "$QQBase\resources\app\bauncher.json" `
-OldValue 'package.json' `
-NewValue 'backage.json'
Invoke-ReplaceInFile `
-FileName "$QQBase\resources\app\package.json" `
-OldValue './app_launcher/index.js' `
-NewValue 'LiteLoader'
Invoke-PatchQQ `
-OriginalBytes1 $OriginalBytes1 `
-ReplaceBytes1 $ReplaceBytes1 `
-OriginalBytes2 $OriginalBytes2 `
-ReplaceBytes2 $ReplaceBytes2 `