# Skript um die Sicherungsdatei aus der Fritzbox 7270 per SSL herunterzuladen.
# Benutzer nach Fritzbox-Passwort fragen. –asSecureString versteckt die Eingabe, aber macht die folgenden beiden Befehle nötig,
# um das verschlüsselte Passwort wieder in Klartext zu verwandeln.
$passwort = Read-Host -Prompt "Bitte Fritzbox-Passwort eingeben" –asSecureString
$passwort = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($passwort)
$passwort = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($passwort)
# Erstmal einen WebClient erzeugen, der später mit der Box spricht
$w=New-Object System.Net.WebClient
# Das Encoding sollte immer UTF8 sein.
$w.Encoding=[System.Text.Encoding]::UTF8
#TEIL1 SSL-port aus der Fritzbox auslesen
# Eine erste Abfrage ohne SSL
# Auch im http-Header muss stehen, dass die Kommunikation per UTF-8 kodiert ist
$w.Headers.Set("Content-Type", 'text/xml; charset="utf-8"')
# Der Funktionsaufruf kommt in den Header SOAPACTION
$w.Headers.Set("SOAPACTION", 'urn:dslforum-org:service:DeviceInfo:1#GetSecurityPort')
# Der SOAP-Aufruf wird in XML verpackt, und zwar...
# ... beginnt er mit einem immer gleichen Header.
$query='<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body> ' +
# Dann kommt nochmal der Aufruf, diesmal steht der Funktionsname vorne
'<u:GetSecurityPort xmlns:u="urn:dslforum-org:service:DeviceInfo:1">
</u:GetSecurityPort>' +
# Und das Ende ist auch immer gleich
'</s:Body>
</s:Envelope>'
# Diese XML-Abfrage schickt der Web-Client mit der Funktion UploadString an die Box.
# Der genaue URL gehört zum Service (siehe Artikel c't 6-2015)
# Die Typ-Umwandlung im XML macht aus der Antwort gleich eine Baumstruktur, ...
$r = [xml]$w.UploadString("http://fritz.box:49000/upnp/control/deviceinfo",$query)
# ... in der sich die gesuchte Information über ihren Namen ansprechen lässt.
# In diesem Falle ist das der Port, auf dem die Box einen SSL-gesicherten Zugang für SOAP bietet.
$port=$r.Envelope.Body.GetSecurityPortResponse.NewSecurityPort
#TEIL2 Config-Datei aus der Fritzbox herunterladen über eine verschlüsselte Verbindung
# Der WebClient enthält die Antowrt-Header aus der vorigen Abfrage. Daher diese neu setzen:
$w.Headers.Set("Content-Type", 'text/xml; charset="utf-8"')
# Der Funktionsaufruf kommt in den Header SOAPACTION Name der Funktion laut http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/deviceconfigSCPD.pdf
$w.Headers.Set("SOAPACTION", 'urn:dslforum-org:service:DeviceConfig:1#X_AVM-DE_GetConfigFile')
# Der SOAP-Aufruf wird in XML verpackt, und zwar...
# ... beginnt er mit einem immer gleichen Header.
$query='<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body> ' +
# Dann kommt nochmal der Aufruf, diesmal steht der Funktionsname vorne
# Der mitgegebene Parameter steht innerhalb des Funktions-Tags
# Hier wird mit NewX_AVM-DE_Password das Passwort der Fritzbox eingetragen
'<u:X_AVM-DE_GetConfigFile xmlns:u="urn:dslforum-org:service:DeviceConfig:1">
<NewX_AVM-DE_Password>$passwort</NewX_AVM-DE_Password>
</u:X_AVM-DE_GetConfigFile>' +
# Und das Ende ist auch immer gleich
'</s:Body>
</s:Envelope>'
# Der WebClient braucht nur die Zugangsdaten, dann wickelt er das Login ganz allein ab.
# dslf-config ist der im TR-64-Standard definierte Name.
$w.Credentials=New-Object System.Net.NetworkCredential("dslf-config",$passwort)
# Das SSL-Zertifikat der Box ist nicht so signiert, dass es der sehr genauen Prüfung im WebClient standhält.
# Daher würde keine Verbindung zu Stande kommen, wenn man nicht die
# SSL-Zertifikatprüfung für diesen Prozess ausschaltet.
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
# Query abschicken. Diesmal sind drei Dinge anders:
# - https statt http
# - Der eben ermittelte Port statt 49000
# - Der URL zum Service (siehe Artikel)
$r = [xml]$w.UploadString("https://fritz.box:"+$port+"/upnp/control/deviceconfig",$query)
# ... in der sich die gesuchte Information über ihren Namen ansprechen lässt.
# In diesem Falle ist das der URL, unter der die Box die Sicherungdatei zum Download anbietet.
# Die Anführungszeichen bei X_AVM... sind nötig, weil sonst die Bindestriche als Operatoren interpretiert werden
$url=$r.Envelope.Body.'X_AVM-DE_GetConfigFileResponse'.'NewX_AVM-DE_ConfigFileUrl'
# Am Besten funktioniert der Download, wenn im WebClient keine Header gesetzt sind.
$w.Headers.Clear()
# Pfad des Skripts bestimmen; die Datei wird dann im gleichen Pfad gespeichert.
$Skriptpfad = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
# Herunterladen:
$w.DownloadFile( $url, $Skriptpfad+"\Fritzbox_7270_Sicherung.export")