#!/usr/bin/env python3 """Поймать загрузчик модуля (HKLFBOOT) — ТАЙТОВЫЙ спам Connect (как DMR Upgrade Tool). DMR Upgrade Tool: жмёшь Upgrade (спам Connect=01 E0 FC 01 00), затем MENU+включение — загрузчик ловит connect в окне до старта приложения. Наш powershell-цикл со Start-Sleep был слишком медленный и промахивался. Здесь — спам БЕЗ пауз (тысячи/сек), ловит короткое окно. Процедура: запусти тул, затем зажми MENU и включи рацию. Успех = ответ загрузчика на link-check (04 0E 05 ...) и приложение (0x68 06 02) НЕ стартует. Только connect — ни erase, ни write. """ import argparse, subprocess PS = r''' $p = New-Object System.IO.Ports.SerialPort "{port}",115200,"None",8,"one" $p.ReadTimeout=1; $p.WriteTimeout=50; $p.ReadBufferSize=8192 try {{ $p.Open() }} catch {{ Write-Output "ERR:$($_.Exception.Message)"; exit }} $lc=[byte[]]@(1,224,252,1,0) $sw=[Diagnostics.Stopwatch]::StartNew() $acc=New-Object System.Collections.Generic.List[byte] $caught=$false while($sw.Elapsed.TotalSeconds -lt {sec}){{ if(-not $caught){{ try {{ $p.Write($lc,0,$lc.Length) }} catch {{}} }} $n=$p.BytesToRead if($n -gt 0){{ $b=New-Object byte[] $n; $p.Read($b,0,$n)|Out-Null foreach($x in $b){{ $acc.Add($x) }} $hex=($b|ForEach-Object{{"{{0:x2}}"-f $_}}) -join "" Write-Output ("t"+[int]$sw.Elapsed.TotalSeconds+"|"+$hex) # ответ загрузчика на link-check: 04 0e 05 ... if($hex -match "040e05"){{ Write-Output "CAUGHT"; $caught=$true }} }} }} $p.Close(); Write-Output "END" ''' def main(): ap=argparse.ArgumentParser() ap.add_argument("--port", default="COM4"); ap.add_argument("--sec", type=int, default=30) a=ap.parse_args() print(f"[ТАЙТОВЫЙ спам 01 e0 fc 01 00 на {a.port}, {a.sec}с]") print(">>> ЗАЖМИ MENU и включи рацию СЕЙЧАС (как при прошивке модуля) <<<\n") r=subprocess.run(["powershell.exe","-NoProfile","-Command",PS.format(port=a.port,sec=a.sec)], capture_output=True, text=True) banner=app=caught=False; n=0 for line in r.stdout.replace("\r","").split("\n"): line=line.strip() if line.startswith("ERR:"): print(line); return if line=="CAUGHT": caught=True; continue if "|" not in line: continue t,hexs=line.split("|",1); n+=1 try: asc=bytes.fromhex(hexs).decode("latin1") except: asc="" asc="".join(c if 32<=ord(c)<127 else "." for c in asc) print(f" {t}: {asc[:48]} [{hexs[:40]}]") if "HKLF" in asc: banner=True if "680602" in hexs: app=True print() if caught: print("✅✅✅ ЗАГРУЗЧИК ПОЙМАН (ответ 04 0e 05)! Держим сессию — можно читать флеш.") elif banner and app: print("⚠️ Баннер+приложение стартовало. Окно ещё промахнули — повтори (спам уже без пауз).") elif banner: print("✅ Баннер был, приложение не стартовало — возможно, поймали. Проверю ответ.") elif not n: print("Тишина — не попал во включение? Порт COM4? Повтори.") else: print("Данные без баннера — перезагрузка вне окна. Повтори.") if __name__=="__main__": main()