Ich habe hier versucht, dies mit AutoHotkey nachzubilden.
Um den Kontakt mit der Fritzbox herzustellen reicht es nicht, diese Webseite aufzurufen.
Der Login erfolgt über das Challenge-Response-Verfahren. Auf der Heiseseite https://www.heise.de/select/ct/2016/7/1459414791794586 im Kasten "Frage-Antwort-Spiel" kann man den Vorgang sehr schön nachvollziehen.
Hat man im Challenge-Response-Verfahren eine SID erhalten, kann man damit Abfragen an die Fritzbox richten.
Mit meinem Skript nehme ich den Internetverkehr in wiederkehrenden Zeitabständen auf. So kann man bei Bedarf längere Zeit in kleinen Häppchen speichern. Den Speicherort konnte ich Fritzboxseitig nicht beeinflussen, daher habe ich mich hier mit verschieben der Datei in den Skriptordner beholfen.
Eine Analyse der erzeugten Dateien ist z.B. mit Wireshark möglich. Da ALLES was über die Fritzbox läuft aufgezeichnet wird, sollte man sich der datenschutzrechtlichen Problematik bewusst sein.
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
SetTitleMatchMode, 2
SetTitleMatchMode, slow
debugging :=0
if (debugging)
startDebugview()
FileCreateDir, saved
global headers
ADSliste:="maxfiles,CTimeInMin,autostart,fehlerlog"
maxfiles:=3
savethis:=0
running:=0
fehlerlog:=0
pwd:="xxx" ;Fritzbox-Passwort
username:="xxx"
;"Anmeldung mit dem FRITZ!Box-Kennwort" username:="".
;"Anmeldung mit FRITZ!Box-Benutzernamen und Kennwort" username:="xxx"
Menu, Tray, NoStandard
Menu, Tray, Add, Fritzbox Capture,leer
Menu, Tray, Add
Menu, Tray, add, Show Gui,showgui
Menu, Tray, Add
Menu, Tray, Add, Start,start
Menu, Tray, Default, Start
Menu, Tray, Add, Stop,stop
Menu, Tray, Disable, Stop
Menu, Tray, Add
Menu, Tray, Add, Datei sichern,saveThisFile
Menu, Tray, Disable, Datei sichern
Menu, Tray, Add
Menu, Tray, Add, Aufnahme verlängern, extendRecordingTime
Menu, Tray, Disable, Aufnahme verlängern
Menu, Tray, Add
Menu, Tray, Tip,
Menu, Tray, add, Hilfe
Menu, Tray, Add, Beenden,GuiEscape
Gui Add, Button, x10 y20 w150 h50 gStart vbcaprec, Capture
GuiControlGet, bcaprec,, bcaprec
Gui Add, Button, x200 y20 w150 h50 gstop vbstoprec, Stop
GuiControlGet, bstoprec,, bstoprec
Gui, Add, DropDownList, x390 y20 w50 vmaxfiles, 1|2|3|4||5|15|30|60|120|
Gui Add, text, x443 y25 , neueste Aufnahmen
Gui, Add, DropDownList, x390 y48 w50 gChangeCT vCTimeInMin, 5|10|15||30|60|120|
Gui, Add, CheckBox, x390 y72 w200 glog vautoStart, beim nächsten Start sofort aufnehmen
Gui, Add, CheckBox, x390 y102 w200 glog vfehlerlog, Bei Fehler Neustart und Logging
Gui Add, text, x443 y53 , min/Aufnahme
Gui Add, text, x170 y80 w150 vtremtime, %remtime%
Gui Add, text, x120 y80 , Restzeit:
GuiControlGet, tremtime,, tremtime
Gui Add, Button, x10 y100 w150 h50 gextendRecordingTime vbextrec, Aufnahmezeit verlängern
GuiControlGet, bextrec,, bextrec
Gui Add, Button, x200 y100 w150 h50 gsaveThisFile vbsaverec, diese Aufnahme sichern
Gui Add, Button, x390 y120 w150 h30 gshowgui , Hide Gui
GuiControlGet, bsaverec,, bsaverec
GuiControl, Disable, bstoprec
GuiControl, Disable, bextrec
GuiControl, Disable, bsaverec
Gui Show, hide, Fritzbox Capture
gosub, settings
gosub, changeCT
if(autoStart)
gosub Start
Return
settings:
Gui, Submit , NoHide
gosub, ADSread
Optionct=5|10|15|30|60|120|
Option1 := StrReplace(Optionct, CTimeInMin . "|", CTimeInMin . "||",,1)
Optionmf=1|2|3|4|5|15|30|60|120|
Option2 := StrReplace(Optionmf, maxfiles . "|", maxfiles . "||",,1)
GuiControl, , CTimeInMin, |%Option1%
GuiControl, , maxfiles, |%Option2%
GuiControl,,autoStart,%autoStart%
GuiControl,,fehlerlog,%fehlerlog%
return
GuiEscape:
GuiClose:
Gui, Submit , NoHide
ADSwrite(ADSliste)
;gosub stoprecording
if (debugging)
stopDebugview()
ExitApp
showgui:
Gui, Submit , NoHide
showhide:=!showhide ? 1:0
if (showhide)
{
Gui Show,
Menu, Tray, Rename, Show Gui,Hide Gui
}
else
{
Gui Show, hide
Menu, Tray, Rename, Hide Gui, Show Gui
}
return
LoopCapture:
Gui, Submit, NoHide
gosub, stoprecording
sleep, 10000
gosub, recording
return
Statusoperation:
Gui, Submit, NoHide
switch Status
{
case "Firstrun": gosub, recording
case "Stop": gosub, stoprecording
case "Next": gosub, LoopCapture
case "Loop":
}
;status=
return
Start:
Gui, Submit , NoHide
GuiControl, Disable, bcaprec
GuiControl, Enable, bstoprec
GuiControl, Enable, bextrec
GuiControl, Enable, bsaverec
captureTime := CTimeInMin*60000
ts:=ts(captureTime)
gosub, mnuRunning
Status=firstrun
gosub, Statusoperation
return
ChangeCT:
Gui, Submit, NoHide
captureTime := CTimeInMin*60000
ts:=ts(captureTime)
remtime:=ts
gosub, traytip
GuiControl, Text, tremtime , %ts%
gosub, log
return
Stop:
Gui, Submit, NoHide
GuiControl, Enable, bcaprec
GuiControl, Disable, bstoprec
GuiControl, Disable, bextrec
GuiControl, Disable, bsaverec
gosub, mnuStart
Status=Stop
return
ExtendRecordingTime:
Gui, Submit , NoHide
gosub, resettimer
return
log:
Gui, Submit, NoHide
if (fehlerlog)
{
guicontrol,,autostart,1
guicontrol,Disable,autostart
}
else if !(fehlerlog) and !(autostart)
{
guicontrol,,autostart,0
guicontrol,Enable,autostart
}
else if !(fehlerlog)
guicontrol,Enable,autostart
return
saveThisFile:
Gui, Submit, NoHide
GuiControl, Text, sa , die Aufnahme wird gesichert
GuiControl, Disable, bsaverec
Menu, Tray, Disable, Datei sichern
savethis:=1
return
resettimer:
Gui, Submit , NoHide
ts:=ts(captureTime)
GuiControl, Text, tremtime , %ts%
gosub, traytip
StartTime:=A_TickCount
SetTimer, countdowntimer,1000
return
countdowntimer:
Gui, Submit, NoHide
RemainingTime := StartTime + captureTime - A_TickCount
if (RemainingTime<=0)
status=Next
gosub onError
ts:=ts(RemainingTime)
GuiControl, Text, tremtime , %ts%
gosub, traytip
gosub, Statusoperation
return
recording:
Gui, Submit, NoHide
status=Loop ;nichts machen
ch:= getChallenge(whr)
rsp:= ch . "-" . getResponse(ch,pwd)
sid:= getSID(whr,rsp)
gosub resettimer
running:=1
startCapture(whr,sid)
return
stoprecording:
Gui, Submit, NoHide
gosub, resettimer
SetTimer, countdowntimer,Off
;sichern
MoveFileFromIECacheToScriptDir(savethis,maxfiles)
savethis:=0
running:=0
gosub, traytip
stopCapture(whr,sid)
return
traytip:
Gui, Submit, NoHide
as:= autostart ? "an" : "aus"
an:= running ? "an" : "aus"
fl:= fehlerlog ? "an" : "aus"
Menu, Tray, Tip, Aufnahmen: %maxfiles% `nDauer (min): %CTimeInMin%`nAutostart: %as%`nLog: %fl%`n==========`nRestzeit: %ts%`nAufnahme: %an%
return
hilfe:
Gui, Submit, NoHide
Hilfe =
(
Das Programm nimmt mit Hilfe der Fritzbox den Internetverkehr auf.
Dabei werden Dateien für die Analyse mit Wireguard angelegt
(ala fritzbox-vcc0_31.10.19_1545[1].eth).
Diese Dateien speichert die Fritzbox im IE Cache in
C:\Users\<username>\AppData\Local\Microsoft\Windows\INetCache\IE\<XXX>
Alle z.B. %remtime% min werden neue Dateien gespeichert und in den Skriptordner verschoben.
Die verbleibende Aufnahmezeit kann auf z.B. %remtime% min verlängert werden.
Die Aufnahme kann jederzeit gestoppt und damit gespeichert werden.
Es werden nur die letzten %maxfiles% gespeichert.
Eine laufende Aufnahme kann zur Sicherung markiert werden.
Sie wird in den Odner saved verschoben.
)
Msgbox, %Hilfe%
return
;OutputDebug DBGVIEWCLEAR
mnuStart:
Gui, Submit, NoHide
Menu, Tray, Disable, Datei sichern
Menu, Tray, Enable, Start
Menu, Tray, Default, Start
Menu, Tray, Disable, Stop
Menu, Tray, Disable, Aufnahme verlängern
return
mnuRunning:
Gui, Submit, NoHide
Menu, Tray, Enable, Stop
Menu, Tray, Disable, Start
Menu, Tray, Default, Aufnahme verlängern
Menu, Tray, Enable, Aufnahme verlängern
Menu, Tray, Enable, Datei sichern
return
onError:
Gui, Submit, NoHide
; alle 60 sec wird geprüft ob im Status Loop eine Datei im IE Cache existiert. Wenn nicht ist dies ein Fehler, dann wird das Programm neugestartet
if ((status="Loop") and !(mod(Round(RemainingTime, -3)//1000, 60))) and fehlerlog
if !(ethFilesInIeCacheExists())
{
MoveFileFromIECacheToScriptDir(savethis,maxfiles)
autostart:=1
ADSwrite(ADSliste)
FileAppend,% a_now " keine *.eth im IE Cache`n", fehlerlog.txt
sleep, 1000
reload
}
return
;===============================
; Challenge response authorization
;===============================
getChallenge(ByRef whr){
whr := ComObjCreate("Msxml2.XMLHTTP")
whr.Open("GET", "http://fritz.box/login_sid.lua", false)
whr.Send()
Array := StrSplit(whr.ResponseText , ["<Challenge>","</Challenge>"])
OutputDebug, % "challenge Status: " Array[2] "`n"
return Array[2]
}
getResponse(challenge,pwd){
ch:=challenge . "-" . pwd
len:=strpututf16raw(ch,string)
return MD5FromAddr(&string,len)
}
getSID(ByRef whr,rstr){
global username
whr.Open("GET", "http://fritz.box/login_sid.lua?username=" . username . "&response=" . rstr, false)
whr.Send()
Array := StrSplit(whr.ResponseText , ["<SID>","</SID>"])
OutputDebug, % "getSID Status: " Array[2] "`n"
return Array[2]
}
;===============================
;===============================
startCapture(ByRef whr,sid){
url:="http://fritz.box/cgi-bin/capture_notimeout?sid=" . sid . "&capture=Start&snaplen=1600&ifaceorminor=2-1"
whr.Open("GET", url, true) ; true false
;For header, value in headers
; whr.SetRequestHeader(header,value)
whr.Send()
return
}
stopCapture(ByRef whr,sid){
;url := "http://fritz.box/cgi-bin/capture_notimeout?iface=stopall&capture=Stop&sid=" . sid
url := "http://fritz.box/cgi-bin/capture_notimeout?iface=internet,voip&minor=1&type=2&capture=Stop&sid=" . sid . "&useajax=1&xhr=1&"
whr.Open("GET", url, false)
whr.Send()
while whr.readyState != 4
sleep 100
sleep 200
return
}
ethFilesInIeCacheExists(){
iecachePath := "C:\Users\" . a_username . "\AppData\Local\Microsoft\Windows\INetCache\IE"
b := 0
Loop, Files, %iecachePath%\*.eth ,FR
b += A_Index
return b
}
MoveFileFromIECacheToScriptDir(savethis=0,maxfiles=3){
OutputDebug, % "savethis: " savethis "`n"
iecachePath := "C:\Users\" . a_username . "\AppData\Local\Microsoft\Windows\INetCache\IE"
FileList := ""
Loop, Files, %iecachePath%\*.eth ,FR
FileList .= A_LoopFilePath . "`n"
If (savethis)
Loop, Parse, FileList, `n
FileMove, %A_LoopField%, %A_ScriptDir%\saved
else
Loop, Parse, FileList, `n
FileMove, %A_LoopField%, %A_ScriptDir%
;===============================
; maxfiles neueste dateien behalten, den Rest löschen
;===============================
FileList := ""
count:=0
Loop, Files, %A_ScriptDir%\*.eth ,F
{
FileGetTime, fileCreationTime, %A_LoopFilePath%, C
FileList .= fileCreationTime . "-" . A_LoopFilePath . "`n"
count++
}
Sort, FileList, F StringSort
count:=0
loop,parse,FileList,"`n"," `t`n`r"
{
sarray:=StrSplit(a_loopfield,"-",,2)
count++
if (count>maxfiles)
FileDelete, % sarray[2]
}
return
}
StringSort(a2, a1)
{
return a1 > a2 ? 1 : a1 < a2 ? -1 : 0 ; Sorts alphabetically based on the setting of StringCaseSense.
}
;===============================
;===============================
StrPutUTF16RAW(Str,byref Var,zeroterminated=1)
{ ;https://autohotkey.com/board/topic/90962-wie-erzeuge-ich-eine-bytefolge-der-utf-16le-codierung/ ;nnnik
zeroterminated:=zeroterminated?2:0
VarSetCapacity(Var,(var2:=(strlen(str)-1)*2)+zeroterminated,0)
loop,% var2
{
NumPut(Asc(str),Var,(A_Index-1)*2,"UShort")
StringTrimLeft,str,str,1
}
return var2+zeroterminated
}
MD5FromAddr(addr, len)
{
return HashFromAddr(addr, len, 0x8003)
}
HashFromAddr(pData, len, algid, key=0)
{ ;https://autohotkey.com/board/topic/90962-wie-erzeuge-ich-eine-bytefolge-der-utf-16le-codierung/ ;nnnik
ptr := (A_PtrSize) ? "ptr" : "uint"
aw := (A_IsUnicode) ? "W" : "A"
if (DllCall("advapi32\CryptAcquireContext" aw, ptr "*", hProv, ptr, 0, ptr, 0, "uint", 1, "uint", 0xF0000000))
{
if (DllCall("advapi32\CryptCreateHash", ptr, hProv, "uint", algid, "uint", key, "uint", 0, ptr "*", hHash))
{
if (DllCall("advapi32\CryptHashData", ptr, hHash, ptr, pData, "uint", len, "uint", 0))
{
if (DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, 0, "uint*", size, "uint", 0))
{
VarSetCapacity(bhash, size, 0)
DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, &bhash, "uint*", size, "uint", 0)
}
}
DllCall("advapi32\CryptDestroyHash", ptr, hHash)
}
DllCall("advapi32\CryptReleaseContext", ptr, hProv, "uint", 0)
}
int := A_FormatInteger
SetFormat, Integer, h
Loop, % size
{
v := substr(NumGet(bhash, A_Index-1, "uchar") "", 3)
while (strlen(v)<2)
v := "0" v
hash .= v
}
SetFormat, Integer, % int
return hash
}
stopDebugview(){
If (WinExist("DebugView++"))
{
WinActivate
send,{Alt down}fx{Alt up}
}
return
}
startDebugview(){
if FileExist("DebugView++.exe")
if !(WinExist("DebugView++"))
run DebugView++
else
WinActivate
return
}
ts(NumberOfMilliSeconds) ; Convert the specified number of seconds to hh:mm:ss format.
{
NumberOfMilliSeconds:=Round(NumberOfMilliSeconds, -3)//1000
time := 19990101 ; *Midnight* of an arbitrary date.
time += NumberOfMilliSeconds, seconds
FormatTime, mmss, %time%, mm:ss
return NumberOfMilliSeconds//3600 ":" mmss
/*
; Unlike the method used above, this would not support more than 24 hours worth of seconds:
FormatTime, hmmss, %time%, h:mm:ss
return hmmss
*/
}
Xts(n, r = 1000) {
;https://autohotkey.com/board/topic/12395-format-number-of-seconds-to-days-hours-minutes-seconds/page-3 ;polyethene
s -= ((m := s := n) //= i := 60 * r) * i
Return, m . ":" . SubStr(0 . s /= r, 1 + (s > 9), 2 + 4 * (s > s // 1))
}
leer:
return
ADSwrite(ADSliste){
stream_1:=A_ScriptFullPath ":sfdata"
VarArray :={}
VarArray := StrSplit(ADSliste, ",", " `r`t`n")
For index, var in VarArray
{
Transform, OutputVar, Deref, % "%" . var . "%"
ADSstr.= (index<>1) ? "," . var . "=" . trim(OutputVar) : var . "=" . trim(OutputVar)
}
filedelete,%stream_1%
fileappend, %ADSstr%, %stream_1%
return ADSstr
}
ADSread:
stream_1:=A_ScriptFullPath ":sfdata"
fileread, ADSstr, %stream_1%
if (ADSstr="")
ADSstr:="maxfiles=4,CTimeInMin=15,autoStart=0,fehlerlog=0" ;anpassen
loop, Parse, ADSstr, `,
{
t=
t:=StrSplit(a_loopfield,"=",,2)
switch t[1]
{
case "maxfiles": maxfiles :=t[2] ;anpassen
case "CTimeInMin": CTimeInMin :=t[2] ;anpassen
case "autoStart": autoStart :=t[2] ;anpassen
case "fehlerlog": fehlerlog :=t[2] ;anpassen
}
}
return
Mein System:
Windows 10, v1903 (Build 18362.449), x64
FRITZ!Box 7490
FRITZ!OS: 07.12
Funktioniert nicht mit:
FRITZ!Box 6490 Cable
Kann sein, dass der Provider diese Option abgeschaltet hat.
Ob das Skript funktionieren sollte, kann man testen, indem man die http://fritz.box/html/capture.html aufruft, und versucht in der Rubrik "Internet" eine Aufnahme der "1. Internetverbindung" zu starten. Dabei muß dann ein Angebot kommen eine Datei zu speichern oder in Wireshark zu öffnen.