Skip to content

Instantly share code, notes, and snippets.

@pp5x
Last active January 28, 2025 10:23
Show Gist options
  • Select an option

  • Save pp5x/98eef4bf958b7cf7fef74fc818905bf6 to your computer and use it in GitHub Desktop.

Select an option

Save pp5x/98eef4bf958b7cf7fef74fc818905bf6 to your computer and use it in GitHub Desktop.
Send a file in chunk to a specific window process
# Requires: Install-Module -Name BaseEncoder -Scope CurrentUse
param (
[string] $path,
[int] $start = 0
)
[Object] $path = Get-Item $path
function Show-Window {
param(
[Parameter(Mandatory)]
[string] $ProcessName
)
# As a courtesy, strip '.exe' from the name, if present.
$ProcessName = $ProcessName -replace '\.exe$'
# Get the ID of the first instance of a process with the given name
# that has a non-empty window title.
# NOTE: If multiple instances have visible windows, it is undefined
# which one is returned.
$procId = (Get-Process -ErrorAction Ignore $ProcessName).Where({ $_.MainWindowTitle }, 'First').Id
if (-not $procId) { Throw "No $ProcessName process with a non-empty window title found." }
# Note:
# * This can still fail, because the window could have been closed since
# the title was obtained.
# * If the target window is currently minimized, it gets the *focus*, but is
# *not restored*.
# * The return value is $true only if the window still existed and was *not
# minimized*; this means that returning $false can mean EITHER that the
# window doesn't exist OR that it just happened to be minimized.
$null = (New-Object -ComObject WScript.Shell).AppActivate($procId)
}
add-type -AssemblyName System.Windows.Forms
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create('sha256')
function SendChunksToProcess {
param (
[int]$ChunkSize = 1 -shl 20
)
$bytes = $input | ForEach-Object { $_ }
if (-not $bytes) {
Write-Error "No input received."
exit 1
}
$bytes.Length
$nbChunks = [Math]::Ceiling(($bytes.Length / $ChunkSize))
[string[]]$chunks = foreach ($i in (0 .. ($nbChunks - 1))) {
$end = [math]::min((($i + 1) * $ChunkSize) - 1, $bytes.Length - 1)
-join $bytes[($i * $ChunkSize) .. $end ]
}
$name = $path.Name
if ($nbChunks -ne $chunks.Length) {
Write-Warning ("{0} != {1}" -f $nbChunks,$chunks.Length)
}
Write-Host "Number of chunks to send = $nbChunks. Press key to continue."
Read-Host
Get-FileHash $path | Format-List
$timeout = 300
$mean = 1000
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
for ($i = $start; $i -lt $chunks.Length; $i++) {
$stopWatch.Restart()
$chunk = $chunks[$i]
$chunk | Set-Clipboard
Show-Window 'nxplayer.bin'
start-sleep -Milliseconds $timeout
if ($i -eq $start) {
[System.Windows.Forms.SendKeys]::SendWait("^{c}^{u}clear{ENTER}")
start-sleep -Milliseconds $timeout
[System.Windows.Forms.SendKeys]::SendWait('unset HISTFILE{ENTER}')
start-sleep -Milliseconds $timeout
[System.Windows.Forms.SendKeys]::SendWait("alias xb='xsel -b'{ENTER}")
start-sleep -Milliseconds $timeout
[System.Windows.Forms.SendKeys]::SendWait("alias x=xsel{ENTER}")
start-sleep -Milliseconds $timeout
[System.Windows.Forms.SendKeys]::SendWait("alias s=sha256sum{ENTER}")
start-sleep -Milliseconds $timeout
[System.Windows.Forms.SendKeys]::SendWait("PROMPT={ENTER}")
start-sleep -Milliseconds $timeout
[System.Windows.Forms.SendKeys]::SendWait("^{c}^{u}clear{ENTER}xb > $name-$i{ENTER}")
} else {
[System.Windows.Forms.SendKeys]::SendWait("^{p}^{p}^{w}$i{ENTER}")
}
start-sleep -Milliseconds $timeout
if ($i -eq $start) {
[System.Windows.Forms.SendKeys]::SendWait("^{u}s $name-$i|x{ENTER}")
} else {
[System.Windows.Forms.SendKeys]::SendWait("^{p}^{p}^{w}^{w}$i|x{ENTER}")
}
start-sleep -Milliseconds $timeout
Show-Window WindowsTerminal.exe
start-sleep -Milliseconds $timeout
$hash = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($chunk.Trim()))
$hashString = [System.BitConverter]::ToString($hash)
$hashString = $hashString.Replace('-', '')
$hashString = "$hashString $name-$i".toLower()
#$hashString | Tee-Object -FilePath "$name-hashes.txt"
$hashString | Out-File -FilePath "$name-hashes.txt" -Append -Encoding utf8
$nxHash = Get-Clipboard -Raw
$nxHash = $nxHash.Replace('\n', '').toLower()
$escaped = $stopwatch.Elapsed.TotalMilliseconds + $timeout
$mean = $mean + ($escaped - $mean) / ($i + 1)
$estimated = $mean * ($nbChunks - $i)
$est = $estimated | Select-Object @{N="Duration"; E={"{0:hh}:{0:mm}:{0:ss}" -f [timespan]::frommilliseconds($_)}}
Write-Host -NoNewLine "`r" ("[{0}%][$i/$nbChunks] {1} {2} {3}" -f ([Math]::Ceiling(($i / $nbChunks) * 100),$mean,$est,$timeout))
if ($nxHash.Trim() -ne $hashString.Trim()) {
#Write-Warning "hash mismatch: former timeout $timeout"
$successiveFailures += 1
$timeout = $timeout * 1.10
#$chunks.Length
if ($i -ge ($chunks.Length - 1)) {
# Issue with hash on last chunk.
#Write-Warning "$hashString != $nxHash"
break
} else {
$i--
}
if ($successiveFailures -gt 5) {
$start = $i + 1
}
} else {
$timeout = $timeout * 0.98
$successiveFailures = 0
}
}
Write-Host
Show-Window 'nxplayer.bin'
start-sleep -Milliseconds 1000
[System.Windows.Forms.SendKeys]::SendWait("ls -1 $name-* | sort -V -u | xargs cat > $name.base64{ENTER}")
start-sleep -Milliseconds 500
[System.Windows.Forms.SendKeys]::SendWait("ascii85 -n -d $name.base64 > $name{ENTER}")
start-sleep -Milliseconds 500
[System.Windows.Forms.SendKeys]::SendWait("s $name | x{ENTER}")
start-sleep -Milliseconds 5000
Show-Window WindowsTerminal.exe
$finalHash = Get-Clipboard -Raw
Write-Host "final hash: $finalHash"
Write-Host ("file hash: {0}" -f (Get-FileHash $path).Hash)
Write-Host "All chunks processed." -foregroundColor Green
}
$data = ConvertTo-Ascii85 -Raw -Unformatted -File $path
#$data = [Convert]::ToBase64String([IO.File]::ReadAllBytes($path))
#$data = [IO.File]::ReadAllBytes($path)
$data | SendChunksToProcess
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment