Custom Firmware auf dem Router und wie man sie loswird – Fall: Orderbird

Prinzipiell habe ich nichts dagegen, wenn Firmen modifizierte Firmware auf ihre Geräte flashen, um z.B. inkorrekte Bedienung seitens des Kunden zu verhindern oder via Remote Support anbieten zu können. Solange man die Hardware nur mietet, ists voll OK.

Doch im Falle von Orderbird, einem Anbieter für Software im Gastrobereich, wird das etwas anders praktiziert. Man kauft Orderbird die benötigte Hardware ab und ist dann Besitzer der modifizierten Geräte. Konkret geht es um den von Orderbird bereitsgestellten Router TP-LINK AC1750, der mit einer speziellen Firmware versehen ist. Solange der Router im Geschäft aktiv eingesetzt wird, ist alles gut. Braucht man diesen irgendwann mal nicht mehr, dann kann man den Router nicht mehr verkaufen, da sämtliche Funktionen gesperrt, Tastenkombinationen deaktiviert und IP-Adressen verankert sind. Ein Zugriff auf die bekannte Weboberfläche ist nicht möglich, genauso wenig wie ein Hardreset.

Mir lag ein solch modifizierter Router vor. Diesen habe ich wie folgt von seinen Ketten befreit:

Als erstes muss man wissen, dass die meisten TP-Link Router hardwareseitig eine Fallbackoption integriert haben, die es den Entwicklern erlaubt, Daten auf den Router zu pushen. Diese schaut im Fall des AC1750 (hier Version 2.0) so aus: Hält man den WPS/Reset Schalter gedrückt und fährt den Router dann hoch, so fragt der Router nach einer bestimmten IP Adresse und wenn diese übereinstimmt, dann nach einem bestimmten Dateinamen. Also musste ich meinem Fall herausfinden, was sich der Router wünscht, um ihm seinen Wunsch zu erfüllen.

Dazu wurden sämtliche Netzwerkverbindungen getrennt und der Port 1 des Routers direkt am Rechner angeschlossen. Daraufhin habe ich Wireshark – eine Software, die den Datenaustausch über eine bestimmte Schnittstelle protokolliert – installiert (+ Ethernet Adapter ausgewählt), den Router über die Tastenkombo „WPS/Reset + On/off“ gebootet und mir die Aufzeichnungen angeschaut. Aus diesen geht hervor, dass der Router nach folgender IP fragt:

192.168.0.66 > „ARP: Who has 192.168.0.66?“

– Das ist für diese Baureihe typisch und auch im Netz nachzulesen.

Im nächsten Schritt konfiguriere ich meinen LAN Adapter auf die IP (.66) und boote den Router erneuert, um mir im Protokoll ausgeben zu lassen, nach welcher Datei der Router fragt. Der Router erkennt meinen Rechner anhand der IP und wünscht dich eine Datei mit dem Namen:

„ArcherC7v2_tp_recovery.bin“

– Alles klar! Mit einer so benannten Datei muss ich ihn also füttern, damit er einen Update/Recovery-Vorgang initiiert. Gut.

Jetzt hätte ich die Möglichkeit eine modifizierte Firmware einzuspielen oder eben die originale Herstellerfirmware mit den Werkseinstellungen. Zweitere besorge ich mir auf der Webseite des Herstellers und benenne sie in den vom Router gewünschten Dateinamen.

Jetzt fehlt nur noch ein TFTP Client, um den Datentransfer zu bewerkstelligen. An dieser Stelle empfehle ich diese Software, da sie schlank ist und bei mir sofort funktioniert:

http://tftpd32.jounin.net/tftpd32_download.html

Nach der Installation von TFTP wählt man in der Einstellung „Current Directory“ den Speicherort, an dem sich die umbenannten Firmware Datei befindet, aus und unter „Server interfaces“ die Netzwerkkarte mit der vorkonfigurierten IP Adresse „192.168.0.66“.

Das Programm ist nun im Standbymodus und wartet auf eine Anfrage nach der entsprechenden Datei über die entsprechende Adresse. Nun bootet man den Router ein weiteres Mal mit der „WPS/Reset + On/off“-Kombination, hält den WPS/Reset-Button solange gedrückt, bis der TFTP Client eine Fortschrittsanzeige anzeigt.

Ist der Vorgang mit 100% markiert, bedeutet es, dass der Router nun die neue Firmware „aufgesaugt“ hat und den Recoveryvorgang initiiert. Intern entpackt er die Datei, checkt die Prüfsumme und die Versionierung und flasht die neue Firmware.

Die modifizierte Firmware ist nun überschrieben und die originale Firmware ist auf dem Router drauf. Nun lässt sich der Router mit den Standardoptionen (Adresse: 192.168.0.1 + admin/admin) ansteuern und die Weboberfläche kann zur Konfiguration genutzt werden. In diesem Zustand entspricht der Router einem neu erworbenen Gerät und kann nun an Interessenten verkauft werden.

Läuft.

8 Kommentare. Hinterlasse eine Antwort

  • vielen Dank! Du bist mein Hero!!
    idk ob das 2026 noch jmd braucht, ich habe basierend auf dieser Beschreibung ein Script (UTF-8) erstellt und die eben die originale Herstellerfirmware auf meinen Archer eingespielt. Script lädt Firmware für EU automatisch herunter und nach der Erfolgsmeldung kann man IP wieder zurücksetzen.

    Datei: ArcherC7_Recovery_GUI.ps1
    Versuche es hier hinzuzufügen:

    # ============================================================
    # Archer C7 V2 Recovery Tool – GUI
    # Version 1.4 – TFTP mit ACK-Unterstützung
    # Speichern als: ArcherC7_Recovery_GUI.ps1
    # Starten: powershell.exe -STA -ExecutionPolicy Bypass -File „.\ArcherC7_Recovery_GUI.ps1“
    # ============================================================

    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    [System.Windows.Forms.Application]::EnableVisualStyles()

    # ——————– Hauptfenster ——————–
    $form = New-Object System.Windows.Forms.Form
    $form.Text = „Orderbird Router Recovery – Archer C7 V2 (v1.4 ACK)“
    $form.Size = New-Object System.Drawing.Size(760, 780)
    $form.StartPosition = „CenterScreen“
    $form.FormBorderStyle = „FixedSingle“
    $form.MaximizeBox = $false
    $form.BackColor = [System.Drawing.Color]::FromArgb(28, 28, 28)
    $form.ForeColor = [System.Drawing.Color]::White

    $title = New-Object System.Windows.Forms.Label
    $title.Text = „TP-Link Archer C7 V2 Recovery Tool“
    $title.Font = New-Object System.Drawing.Font(„Segoe UI“, 16, [System.Drawing.FontStyle]::Bold)
    $title.Location = New-Object System.Drawing.Point(20, 12)
    $title.Size = New-Object System.Drawing.Size(720, 32)
    $form.Controls.Add($title)

    $subtitle = New-Object System.Windows.Forms.Label
    $subtitle.Text = „Entfernt Orderbird Custom Firmware • TFTP mit ACK-Unterstützung“
    $subtitle.Location = New-Object System.Drawing.Point(20, 46)
    $subtitle.Size = New-Object System.Drawing.Size(720, 20)
    $subtitle.ForeColor = [System.Drawing.Color]::LightGray
    $form.Controls.Add($subtitle)

    $logBox = New-Object System.Windows.Forms.TextBox
    $logBox.Multiline = $true
    $logBox.ScrollBars = „Vertical“
    $logBox.Location = New-Object System.Drawing.Point(20, 80)
    $logBox.Size = New-Object System.Drawing.Size(700, 260)
    $logBox.BackColor = [System.Drawing.Color]::FromArgb(18, 18, 18)
    $logBox.ForeColor = [System.Drawing.Color]::Lime
    $logBox.Font = New-Object System.Drawing.Font(„Consolas“, 9)
    $logBox.ReadOnly = $true
    $form.Controls.Add($logBox)

    $progressBar = New-Object System.Windows.Forms.ProgressBar
    $progressBar.Location = New-Object System.Drawing.Point(20, 350)
    $progressBar.Size = New-Object System.Drawing.Size(700, 22)
    $progressBar.Minimum = 0
    $progressBar.Maximum = 100
    $progressBar.Value = 0
    $form.Controls.Add($progressBar)

    $lblProgress = New-Object System.Windows.Forms.Label
    $lblProgress.Text = „Bereit“
    $lblProgress.Location = New-Object System.Drawing.Point(20, 375)
    $lblProgress.Size = New-Object System.Drawing.Size(700, 18)
    $lblProgress.ForeColor = [System.Drawing.Color]::LightGray
    $form.Controls.Add($lblProgress)

    $lblFolder = New-Object System.Windows.Forms.Label
    $lblFolder.Text = „Firmware-Ordner:“
    $lblFolder.Location = New-Object System.Drawing.Point(20, 410)
    $lblFolder.Size = New-Object System.Drawing.Size(120, 20)
    $form.Controls.Add($lblFolder)

    $txtFolder = New-Object System.Windows.Forms.TextBox
    $txtFolder.Text = „$env:USERPROFILE\Desktop\ArcherC7_Recovery“
    $txtFolder.Location = New-Object System.Drawing.Point(140, 407)
    $txtFolder.Size = New-Object System.Drawing.Size(490, 25)
    $txtFolder.BackColor = [System.Drawing.Color]::FromArgb(40, 40, 40)
    $txtFolder.ForeColor = [System.Drawing.Color]::White
    $form.Controls.Add($txtFolder)

    $btnBrowse = New-Object System.Windows.Forms.Button
    $btnBrowse.Text = „Ordner…“
    $btnBrowse.Location = New-Object System.Drawing.Point(640, 405)
    $btnBrowse.Size = New-Object System.Drawing.Size(80, 28)
    $form.Controls.Add($btnBrowse)

    $btnDownload = New-Object System.Windows.Forms.Button
    $btnDownload.Text = „EU-Firmware herunterladen“
    $btnDownload.Location = New-Object System.Drawing.Point(20, 455)
    $btnDownload.Size = New-Object System.Drawing.Size(220, 40)
    $btnDownload.BackColor = [System.Drawing.Color]::FromArgb(0, 100, 180)
    $btnDownload.ForeColor = [System.Drawing.Color]::White
    $btnDownload.FlatStyle = „Flat“
    $form.Controls.Add($btnDownload)

    $btnIP = New-Object System.Windows.Forms.Button
    $btnIP.Text = „IP 192.168.0.66 setzen“
    $btnIP.Location = New-Object System.Drawing.Point(260, 455)
    $btnIP.Size = New-Object System.Drawing.Size(220, 40)
    $btnIP.BackColor = [System.Drawing.Color]::FromArgb(0, 90, 160)
    $btnIP.ForeColor = [System.Drawing.Color]::White
    $btnIP.FlatStyle = „Flat“
    $form.Controls.Add($btnIP)

    $btnStart = New-Object System.Windows.Forms.Button
    $btnStart.Text = „TFTP-Server STARTEN“
    $btnStart.Location = New-Object System.Drawing.Point(500, 455)
    $btnStart.Size = New-Object System.Drawing.Size(220, 40)
    $btnStart.BackColor = [System.Drawing.Color]::FromArgb(0, 120, 40)
    $btnStart.ForeColor = [System.Drawing.Color]::White
    $btnStart.FlatStyle = „Flat“
    $form.Controls.Add($btnStart)

    $btnResetIP = New-Object System.Windows.Forms.Button
    $btnResetIP.Text = „IP zurücksetzen (DHCP)“
    $btnResetIP.Location = New-Object System.Drawing.Point(20, 510)
    $btnResetIP.Size = New-Object System.Drawing.Size(220, 40)
    $btnResetIP.BackColor = [System.Drawing.Color]::FromArgb(100, 60, 0)
    $btnResetIP.ForeColor = [System.Drawing.Color]::White
    $btnResetIP.FlatStyle = „Flat“
    $form.Controls.Add($btnResetIP)

    $btnDiag = New-Object System.Windows.Forms.Button
    $btnDiag.Text = „Adapter anzeigen“
    $btnDiag.Location = New-Object System.Drawing.Point(260, 510)
    $btnDiag.Size = New-Object System.Drawing.Size(220, 40)
    $btnDiag.BackColor = [System.Drawing.Color]::FromArgb(70, 70, 70)
    $btnDiag.ForeColor = [System.Drawing.Color]::White
    $btnDiag.FlatStyle = „Flat“
    $form.Controls.Add($btnDiag)

    $btnStop = New-Object System.Windows.Forms.Button
    $btnStop.Text = „Server STOPPEN“
    $btnStop.Location = New-Object System.Drawing.Point(500, 510)
    $btnStop.Size = New-Object System.Drawing.Size(220, 40)
    $btnStop.BackColor = [System.Drawing.Color]::FromArgb(140, 30, 30)
    $btnStop.ForeColor = [System.Drawing.Color]::White
    $btnStop.FlatStyle = „Flat“
    $btnStop.Enabled = $false
    $form.Controls.Add($btnStop)

    $btnLog = New-Object System.Windows.Forms.Button
    $btnLog.Text = „Log-Datei öffnen“
    $btnLog.Location = New-Object System.Drawing.Point(20, 565)
    $btnLog.Size = New-Object System.Drawing.Size(220, 40)
    $btnLog.BackColor = [System.Drawing.Color]::FromArgb(50, 50, 90)
    $btnLog.ForeColor = [System.Drawing.Color]::White
    $btnLog.FlatStyle = „Flat“
    $form.Controls.Add($btnLog)

    $footer = New-Object System.Windows.Forms.Label
    $footer.Text = „1. EU-Firmware laden → 2. IP setzen → 3. Server starten → 4. Router mit WPS/Reset + Power booten → 5. IP zurücksetzen“
    $footer.Location = New-Object System.Drawing.Point(20, 630)
    $footer.Size = New-Object System.Drawing.Size(700, 40)
    $footer.ForeColor = [System.Drawing.Color]::Gray
    $form.Controls.Add($footer)

    # ——————– Globale Variablen ——————–
    $script:running = $false
    $script:tftpPowerShell = $null
    $script:progressValue = 0
    $script:progressText = „Bereit“
    $script:logFile = Join-Path $env:USERPROFILE „Desktop\ArcherC7_Recovery\Recovery_Log.txt“

    $firmwareUrl = „https://static.tp-link.com/upload/firmware/2024/202411/20241108/Archer%20C7(EU)_V2_241108.zip“

    function Log {
    param([string]$msg)
    $line = „$(Get-Date -Format ‚HH:mm:ss‘) $msg“
    $logBox.AppendText(„$line`r`n“)
    $logBox.ScrollToCaret()
    try {
    $dir = Split-Path $script:logFile
    if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
    Add-Content -Path $script:logFile -Value $line -ErrorAction SilentlyContinue
    } catch {}
    }

    function Update-Progress {
    param([int]$value, [string]$text)
    $script:progressValue = $value
    $script:progressText = $text
    }

    $timer = New-Object System.Windows.Forms.Timer
    $timer.Interval = 250
    $timer.Add_Tick({
    $progressBar.Value = [Math]::Min(100, [Math]::Max(0, $script:progressValue))
    $lblProgress.Text = $script:progressText
    })
    $timer.Start()

    # ——————– Events ——————–
    $btnBrowse.Add_Click({
    try {
    $dlg = New-Object System.Windows.Forms.FolderBrowserDialog
    $dlg.Description = „Firmware-Ordner auswählen“
    $dlg.SelectedPath = $txtFolder.Text
    $dlg.ShowNewFolderButton = $true
    if ($dlg.ShowDialog($form) -eq [System.Windows.Forms.DialogResult]::OK) {
    $txtFolder.Text = $dlg.SelectedPath
    Log „Ordner gesetzt: $($dlg.SelectedPath)“
    }
    } catch { Log „Fehler: $($_.Exception.Message)“ }
    })

    $btnDownload.Add_Click({
    $btnDownload.Enabled = $false
    Update-Progress 0 „Download läuft…“
    Log „Starte Download der offiziellen EU-Firmware…“
    try {
    $folder = $txtFolder.Text
    if (-not (Test-Path $folder)) { New-Item -ItemType Directory -Path $folder -Force | Out-Null }
    $zipPath = Join-Path $folder „ArcherC7_EU_Firmware.zip“
    $targetBin = Join-Path $folder „ArcherC7v2_tp_recovery.bin“

    Invoke-WebRequest -Uri $firmwareUrl -OutFile $zipPath -UseBasicParsing
    Update-Progress 50 „Entpacke…“
    Expand-Archive -Path $zipPath -DestinationPath $folder -Force

    $binFile = Get-ChildItem -Path $folder -Filter „*.bin“ -Recurse | Where-Object { $_.Length -gt 5MB } | Select-Object -First 1
    if ($binFile) {
    Copy-Item $binFile.FullName $targetBin -Force
    Log „✅ Firmware bereit: $targetBin ($([math]::Round($binFile.Length/1MB,2)) MB)“
    Update-Progress 100 „Firmware bereit“
    } else {
    Log „❌ Keine .bin gefunden“
    Update-Progress 0 „Fehler“
    }
    Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
    } catch {
    Log „❌ Download fehlgeschlagen: $($_.Exception.Message)“
    Update-Progress 0 „Fehler“
    } finally {
    $btnDownload.Enabled = $true
    }
    })

    $btnIP.Add_Click({
    try {
    $adapters = Get-NetAdapter | Where-Object {
    $_.HardwareInterface -eq $true -and
    $_.InterfaceDescription -notmatch „Virtual|VMware|Hyper-V|TAP|VPN|Wi-Fi|Wireless|Bluetooth|Pseudo“
    } | Sort-Object Status -Descending
    if (-not $adapters) { $adapters = Get-NetAdapter | Where-Object { $_.Status -eq ‚Up‘ } }
    if (-not $adapters) {
    Log „❌ Kein Adapter gefunden!“
    return
    }
    $adapter = $adapters | Where-Object { $_.Status -eq ‚Up‘ } | Select-Object -First 1
    if (-not $adapter) { $adapter = $adapters | Select-Object -First 1 }

    Log „Adapter: $($adapter.Name) ($($adapter.InterfaceDescription))“
    Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
    Remove-NetIPAddress -Confirm:$false -ErrorAction SilentlyContinue
    New-NetIPAddress -InterfaceIndex $adapter.ifIndex -IPAddress „192.168.0.66“ -PrefixLength 24 -ErrorAction Stop | Out-Null
    Set-NetIPInterface -InterfaceIndex $adapter.ifIndex -Dhcp Disabled -ErrorAction SilentlyContinue
    Log „✅ IP 192.168.0.66 gesetzt“
    } catch {
    Log „Fehler: $($_.Exception.Message)“
    }
    })

    $btnResetIP.Add_Click({
    try {
    $adapters = Get-NetAdapter | Where-Object {
    $_.HardwareInterface -eq $true -and
    $_.InterfaceDescription -notmatch „Virtual|VMware|Hyper-V|TAP|VPN|Wi-Fi|Wireless|Bluetooth|Pseudo“
    }
    if (-not $adapters) { $adapters = Get-NetAdapter | Where-Object { $_.Status -eq ‚Up‘ } }
    foreach ($adapter in $adapters) {
    Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
    Remove-NetIPAddress -Confirm:$false -ErrorAction SilentlyContinue
    Set-NetIPInterface -InterfaceIndex $adapter.ifIndex -Dhcp Enabled -ErrorAction SilentlyContinue
    Log „DHCP aktiviert: $($adapter.Name)“
    }
    ipconfig /renew | Out-Null
    Log „✅ IP zurückgesetzt (DHCP)“
    [System.Windows.Forms.MessageBox]::Show(„IP-Adressen auf DHCP zurückgesetzt.“, „Fertig“, „OK“, „Information“)
    } catch {
    Log „Fehler: $($_.Exception.Message)“
    }
    })

    $btnDiag.Add_Click({
    $all = Get-NetAdapter | Select-Object Name, Status, InterfaceDescription, ifIndex
    $list = ($all | Format-Table -AutoSize | Out-String)
    Log „=== Adapter ===`r`n$list“
    [System.Windows.Forms.MessageBox]::Show($list, „Adapter-Liste“, „OK“, „Information“)
    })

    $btnLog.Add_Click({
    if (Test-Path $script:logFile) {
    Start-Process notepad.exe -ArgumentList $script:logFile
    } else {
    [System.Windows.Forms.MessageBox]::Show(„Log-Datei noch nicht vorhanden.`nPfad: $script:logFile“, „Hinweis“, „OK“, „Information“)
    }
    })

    # ———- TFTP mit ACK ———-
    $btnStart.Add_Click({
    $firmwareFile = Join-Path $txtFolder.Text „ArcherC7v2_tp_recovery.bin“
    if (-not (Test-Path $firmwareFile)) {
    [System.Windows.Forms.MessageBox]::Show(„Firmware-Datei nicht gefunden!“, „Fehler“, „OK“, „Error“)
    return
    }

    try {
    New-NetFirewallRule -DisplayName „ArcherC7 TFTP“ -Direction Inbound -Protocol UDP -LocalPort 69 -Action Allow -ErrorAction SilentlyContinue | Out-Null
    } catch {}

    $btnStart.Enabled = $false
    $btnStop.Enabled = $true
    Update-Progress 0 „Warte auf Router…“
    Log „🚀 TFTP-Server (mit ACK) gestartet auf Port 69“
    Log „Halte jetzt am Router WPS/Reset + Power gedrückt…“

    $script:running = $true

    $runspace = [runspacefactory]::CreateRunspace()
    $runspace.ApartmentState = „STA“
    $runspace.Open()
    $ps = [powershell]::Create()
    $ps.Runspace = $runspace

    $null = $ps.AddScript({
    param($folderPath, $logAction, $progressAction)

    $udp = New-Object System.Net.Sockets.UdpClient
    $udp.Client.ReceiveTimeout = 3000 # 3 Sekunden Timeout für ACK
    $endpoint = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 69)
    $udp.Client.Bind($endpoint)

    while ($true) {
    try {
    $remoteEP = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
    $req = $udp.Receive([ref]$remoteEP)

    if ($req.Length -ge 2 -and $req[1] -eq 1) { # RRQ
    $name = [System.Text.Encoding]::ASCII.GetString($req, 2, $req.Length – 2).Split([char]0)[0]
    & $logAction „Anfrage: $name von $($remoteEP.Address)“
    & $progressAction 1 „Übertragung startet…“

    $filePath = Join-Path $folderPath „ArcherC7v2_tp_recovery.bin“
    if (-not (Test-Path $filePath)) { $filePath = Join-Path $folderPath $name }

    if (-not (Test-Path $filePath)) {
    & $logAction „❌ Datei nicht gefunden“
    continue
    }

    $fileBytes = [System.IO.File]::ReadAllBytes($filePath)
    $total = $fileBytes.Length
    & $logAction „Sende $total Bytes (mit ACK)…“

    $block = 1
    $offset = 0
    $maxRetries = 5
    $success = $true

    while ($offset -lt $total) {
    $chunkSize = [Math]::Min(512, $total – $offset)
    $chunk = New-Object byte[] $chunkSize
    [Array]::Copy($fileBytes, $offset, $chunk, 0, $chunkSize)

    $packet = New-Object byte[] (4 + $chunkSize)
    $packet[0] = 0
    $packet[1] = 3 # DATA
    $packet[2] = [byte](($block -shr 8) -band 0xFF)
    $packet[3] = [byte]($block -band 0xFF)
    [Array]::Copy($chunk, 0, $packet, 4, $chunkSize)

    $acked = $false
    for ($retry = 0; $retry -lt $maxRetries; $retry++) {
    $udp.Send($packet, $packet.Length, $remoteEP) | Out-Null

    try {
    $ackEP = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0)
    $ack = $udp.Receive([ref]$ackEP)

    # ACK prüfen (Opcode 4 + richtige Blocknummer)
    if ($ack.Length -ge 4 -and $ack[1] -eq 4) {
    $ackBlock = ($ack[2] -shl 8) -bor $ack[3]
    if ($ackBlock -eq $block) {
    $acked = $true
    break
    }
    }
    }
    catch {
    # Timeout → erneut senden
    }
    }

    if (-not $acked) {
    & $logAction „❌ Timeout bei Block $block – Übertragung abgebrochen“
    & $progressAction 0 „Timeout / Fehler“
    $success = $false
    break
    }

    $offset += $chunkSize
    $block++

    $percent = [int](($offset / $total) * 100)
    if ($percent % 2 -eq 0 -or $percent -eq 100) {
    & $progressAction $percent „Sende… $percent % (Block $block)“
    }
    }

    if ($success) {
    & $progressAction 100 „Fertig – Router flasht jetzt (2–5 Min.)“
    & $logAction „✅ Firmware erfolgreich übertragen (mit ACK)!“
    & $logAction „Warte 2–5 Minuten, dann 192.168.0.1 öffnen (admin/admin).“
    }
    }
    }
    catch {
    break
    }
    }
    $udp.Close()
    }).AddArgument($txtFolder.Text).AddArgument(${function:Log}).AddArgument(${function:Update-Progress})

    $script:tftpPowerShell = $ps
    $null = $ps.BeginInvoke()
    })

    $btnStop.Add_Click({
    $script:running = $false
    try {
    if ($script:tftpPowerShell) {
    $script:tftpPowerShell.Stop()
    $script:tftpPowerShell.Dispose()
    }
    } catch {}
    $btnStart.Enabled = $true
    $btnStop.Enabled = $false
    Update-Progress 0 „Gestoppt“
    Log „⛔ Server gestoppt.“
    })

    # ——————– Start ——————–
    Log „GUI gestartet (Version 1.4 – TFTP mit ACK).“
    Log „Log-Datei: $script:logFile“
    Log „“
    Log „Empfohlene Reihenfolge:“
    Log „1. EU-Firmware herunterladen“
    Log „2. IP 192.168.0.66 setzen“
    Log „3. TFTP-Server STARTEN“
    Log „4. Router mit WPS/Reset + Power booten“
    Log „5. Nach Erfolg → IP zurücksetzen (DHCP)“

    [System.Windows.Forms.Application]::Run($form)
    $timer.Stop()

    Antworten
  • Exzellente Beschreibung, soeben mit Erfolg einen Wdr3600 entfesselt! Herzlichen Dank!!

    Antworten
  • Hallo,
    vielen Dank für die Antwort. Es scheint wirklich nur an der Firewall gelegen zu haben. Hat also jetzt beim WDR3600 auch wunderbar geklappt!

    Viele Grüße und weiter so!

    Antworten
  • Hallo
    das ist eine sehr schöne Anleitung.
    Ich versuche das ganze gerade mit einem WDR3600. Ich bin auch bis zum letzten Schritt gekommen. Aber der Router holt sich die Firmware nicht vom Laptop. Kann bei WireShark auch keine Fehlermeldungen finden.
    Haben Sie vielleicht eine Idee an was es liegen könnte?

    Viele Grüße

    Antworten
    • Moin, danke. Eine Ferndiagnose ist kaum möglich. Ich vermute, es scheitert an dem TFTP Client? Ist dieser korrekt konfiguriert, sprich Netzwerkadapter ist korrekt ausgewählt sowie die Datei? Gibts ggf. vergessene Portrestriktionen? Viel Erfolg!

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.

 

Mehr?