param( [Parameter(Mandatory = $true)] [string]$patchFile, [Parameter(Mandatory = $true)] [string]$targetFile, [switch]$fixOffset ) # Function to check if the script is running as administrator function Test-IsAdmin { $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($currentUser) return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } # Function to restart the script as administrator function Restart-Elevated { $scriptPath = $myInvocation.MyCommand.Definition $arguments = "-File `"$scriptPath`" -patchFile `"$patchFile`" -targetFile `"$targetFile`"" if ($fixOffset) { $arguments += " -fixOffset" } Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments -WorkingDirectory (Get-Location).Path exit } # Check if running as administrator if (-not (Test-IsAdmin)) { Write-Host "This script must be run as an administrator. Please re-run this script with administrator privileges." -ForegroundColor Red timeout /T -1 exit } function Unlock-DLL { param ( [string]$filePath ) # Check if the file exists if (-Not (Test-Path -Path $filePath)) { Write-Host "The specified file does not exist." -ForegroundColor Red exit } Write-Host "Unlocking file: $filePath" -ForegroundColor Yellow # Get the file security object $fileSecurity = Get-Acl -Path $filePath # Set the owner to "Administrators" $administrators = [System.Security.Principal.NTAccount]"Administrators" $fileSecurity.SetOwner($administrators) # Apply the new owner to the file Set-Acl -Path $filePath -AclObject $fileSecurity # Define a new access rule for "Administrators" with full control $administratorsRights = [System.Security.AccessControl.FileSystemRights]::FullControl $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($administrators, $administratorsRights, [System.Security.AccessControl.InheritanceFlags]::None, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow) # Add the new access rule to the file security object $fileSecurity.AddAccessRule($accessRule) # Apply the updated security settings to the file Set-Acl -Path $filePath -AclObject $fileSecurity Write-Host "Owner changed to 'Administrators' and full control permissions granted to 'Administrators' for file: $filePath" -ForegroundColor Green } function Remove-Certificate { param( [string]$filePath ) $signature = @" [DllImport("imagehlp.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool ImageRemoveCertificate(IntPtr handle, int index); "@ $type = Add-Type -MemberDefinition $signature -Name "Win32RemoveCertificate" -Namespace "Win32Functions" -PassThru Write-Host "Opening file stream for $filePath to remove certificate." -ForegroundColor Yellow $fs = New-Object System.IO.FileStream($filePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite) $handle = $fs.SafeFileHandle.DangerousGetHandle() Write-Host "Removing certificate from $filePath." -ForegroundColor Yellow $result = $type::ImageRemoveCertificate($handle, 0) $fs.Close() Write-Host "Certificate removal result: $result." -ForegroundColor Green return $result } function Update-CheckSum { param( [string]$filePath ) $signature = @" [DllImport("imagehlp.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern uint MapFileAndCheckSum(string Filename, out uint HeaderSum, out uint CheckSum); "@ $type = Add-Type -MemberDefinition $signature -Name "Win32CheckSum" -Namespace "Win32Functions" -PassThru $headerSum = 0 $calculatedSum = 0 Write-Host "Calculating checksum for $filePath." -ForegroundColor Yellow $returnCode = $type::MapFileAndCheckSum($filePath, [ref]$headerSum, [ref]$calculatedSum) if ($returnCode -eq 0) { Write-Host "Checksum calculation successful. Updating file checksum." -ForegroundColor Yellow $fileStream = [System.IO.File]::Open($filePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite) $br = New-Object System.IO.BinaryReader($fileStream) $bw = New-Object System.IO.BinaryWriter($fileStream) $data = $br.ReadBytes($br.BaseStream.Length) $peHeaderOffset = [System.BitConverter]::ToInt32($data, 0x3C) $optionalHeaderOffset = $peHeaderOffset + 24 $checksumOffset = $optionalHeaderOffset + 64 $bw.BaseStream.Position = $checksumOffset $bw.Write($calculatedSum) $bw.Close() $br.Close() $fileStream.Close() Write-Host "Checksum updated successfully." -ForegroundColor Green } else { Write-Host "Checksum calculation failed with return code $returnCode." -ForegroundColor Red } return $returnCode } function Apply-Patch { param( [string]$exePath, [string]$patchPath, [switch]$fixOffset ) $baseOffset = 0xC00 # Adjust this base offset as necessary $dateTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" if (-not (Test-Path $exePath)) { Write-Host "Target executable file does not exist." -ForegroundColor Red return } if (-not (Test-Path $patchPath)) { Write-Host "Patch file does not exist." -ForegroundColor Red return } Write-Host "Reading patch instructions from $patchPath." -ForegroundColor Yellow $patchInstructions = Get-Content $patchPath if ($patchInstructions[0] -notmatch "^>nvencodeapi(?:64)?\.dll$") { Write-Host "Invalid patch file format. The first line should be '>nvencodeapi64.dll' atau '>nvencodeapi.dll'." -ForegroundColor Red return } $fileVersionInfo = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($exePath) $version = $fileVersionInfo.FileVersion.Replace(".", "_") $backupFilePath = "$($exePath -replace '\.dll$', '').dll.$version.$dateTime.bak" Write-Host "Starting patching process..." -ForegroundColor Cyan Write-Host "Target executable: $exePath" -ForegroundColor Cyan Write-Host "Patch file: $patchPath" -ForegroundColor Cyan Write-Host "Fix offset: $fixOffset" -ForegroundColor Cyan $exeData = [System.IO.File]::ReadAllBytes($exePath) $allOffsetsFound = $true Write-Host "Validating patch instructions..." -ForegroundColor Yellow foreach ($instruction in $patchInstructions[1..($patchInstructions.Length - 1)]) { if ($instruction -match "^(.*?):(.*?)\->(.*?)$") { $offset = [Convert]::ToInt32($matches[1], 16) $originalByte = [Convert]::ToByte($matches[2], 16) if ($fixOffset) { $offset -= $baseOffset } if ($exeData[$offset] -ne $originalByte) { Write-Host "Mismatch or offset not found at 0x$($offset.ToString('X')). Expected: 0x$($originalByte.ToString('X')), Found: 0x$($exeData[$offset].ToString('X'))" -ForegroundColor Red $allOffsetsFound = $false break } else { Write-Host "Offset 0x$($offset.ToString('X')) validated successfully. Found byte: 0x$($exeData[$offset].ToString('X'))" -ForegroundColor Green } } else { Write-Host "Invalid instruction format: $instruction" -ForegroundColor Red $allOffsetsFound = $false break } } if ($allOffsetsFound) { Write-Host "All offsets validated successfully." -ForegroundColor Green # Unlock the DLL file before patching Unlock-DLL -filePath $exePath # Create a backup before patching if all offsets are correct if (-not (Test-Path $backupFilePath)) { Write-Host "Creating a backup of the original file at $backupFilePath." -ForegroundColor Yellow Copy-Item -Path $exePath -Destination $backupFilePath Write-Host "Backup created successfully." -ForegroundColor Cyan } # Re-check and apply the patches Write-Host "Applying patches..." -ForegroundColor Yellow foreach ($instruction in $patchInstructions[1..($patchInstructions.Length - 1)]) { if ($instruction -match "^(.*?):(.*?)\->(.*?)$") { $offset = [Convert]::ToInt32($matches[1], 16) $newByte = [Convert]::ToByte($matches[3], 16) if ($fixOffset) { $offset -= $baseOffset } $originalByte = $exeData[$offset] $exeData[$offset] = $newByte Write-Host "Patched offset 0x$($offset.ToString('X')). Original byte: 0x$($originalByte.ToString('X')), New byte: 0x$($newByte.ToString('X'))." -ForegroundColor Green } } Write-Host "Writing patched data to $exePath." -ForegroundColor Yellow [System.IO.File]::WriteAllBytes($exePath, $exeData) Write-Host "Removing digital certificate from patched file." -ForegroundColor Yellow Remove-Certificate -filePath $exePath | Out-Null Write-Host "Updating checksum of patched file." -ForegroundColor Yellow Update-CheckSum -filePath $exePath | Out-Null Write-Host "All patches applied successfully." -ForegroundColor Green } else { Write-Host "Patching aborted. No changes were made to the target file." -ForegroundColor Red } } # Execute the patch function with required parameters Apply-Patch -exePath $targetFile -patchPath $patchFile -fixOffset:$fixOffset # Wait for user input before closing timeout /T -1