PowerShell protip 0076
in 𝕏

& "C:\Program Files\Wireshark shark.exe" -i Wi-Fi -l -T fields -e data "icmp[0]=8" | % { -join ($_ -split "(.{2})" -match "." | % { [char][byte]"0x$_"}) } - wyświetl payload pakietów ICMP

tty1 · powershell
PS> & "C:\Program Files\Wireshark shark.exe" -i Wi-Fi -l -T fields -e data "icmp[0]=8" | % { -join ($_ -split "(.{2})" -match "." | % { [char][byte]"0x$_"}) }
#Powershell#Admin#BlueTeam#Magic

tshark to konsolowy brat znanego i lubianego sniffera pakietów - Wiresharka. Powyższy oneliner będzie nasłuchiwał na interfejsie o nazwie Wi-Fi pakietów ICMP Echo Request (pakiety ICMP o typie 8), czyli na popularne pingi. Następnie, będzie wyświetlał ładunek takich pakietów w wersji tekstowej. Co ciekawe, analizując domyślny ładunek takich pingów, możemy stwierdzić z jakiego systemu operacyjnego został wysłany.

W celu wygodniejszej pracy w konsoli z tsharkiem, moglibyśmy dodać katalog Wiresharka do zmiennej środowiskowej $env:PATH, co zostało omówione w /pl/0075:

[Environment]::SetEnvironmentVariable('Path', [Environment]::GetEnvironmentVariable('Path','Machine')+';C:\Program Files\Wireshark', 'Machine')

Moglibyśmy wtedy po prostu użyć:

tshark -i Wi-Fi -l -T fields -e data "icmp[0]=8" | % { -join ($_ -split "(.{2})" -match "." | % { [char][byte]"0x$_"}) }

Idąc szerzej

W powyższym przykładzie nie mamy informacji o adresie pakietu - wyłącznie payload. Dlatego, zamiast -T fields -e data możemy poprosić tsharka o zwracanie danych w postaci JSON - możemy do tego wykorzystać -T ek, co spowoduje wyświetlanie pakietów jako jednolinijkowe stringo JSON (ek oznacza format przeznaczony do importu przez Elasticsearch). Co ciekawe, naturalnym mogłoby się tutaj wydawać -T json, jednak nie nada to się do naszych celów, bo tak generowany JSON jest wyświetlany w wielu linijkach, z wcięciami, co utrudnia parsowanie (ale ładnie wygląda;). A dlaczego potrzebujemy każdy pakiet jako jednolijkowy JSON? Ponieważ wykorzystując cmdlet ConvertFrom-Json, z łatwością przekonwertujemy pakiety zwracane przez tsharka do PowerShellowych obiektów:

& "C:\Program Files\Wireshark\tshark.exe" -i Wi-Fi -l -T ek  "icmp[0]=8"|% {
    $pkt = ($_|ConvertFrom-Json)
    if ($pkt.layers.icmp.data.data_data_data) {
        $data = -join ($pkt.layers.icmp.data.data_data_data -split ":"|%{[char][byte]"0x$_"})
        $pkt.layers.ip.ip_ip_src + ":" + $data
    }
}

Zwróćcie uwagę na to, że tym razem payload pakietu ICMP jest przedstawiony również jako dwuznakowe, szesnastkowe bajty, ale tym razem są rozdzielone dwukropkami, co nieco upraszcza całość.

Żeby poznać z jakimi właściwościami pakietu mamy do czynienia, moglibyśmy na przykład jako ćwieczenie skonwertowany ze stringa obiekt przekonwertować ponownie na JSON, czyli:

& "C:\Program Files\Wireshark\tshark.exe" -i Wi-Fi -l -T ek  "icmp[0]=8"|% {
    $pkt = ($_|ConvertFrom-Json)
    $pkt | ConvertTo-Json
}

Bonus - niespodzianka zagadka

Przeanalizujcie poniższy skrypt i zobaczcie co się wydarzy, kiedy do hosta, na którym ten skrypt jest uruchomiony ktoś wyśle pakiet ICMP Echo request z payloadem nosiemasiema (np. wykorzystując klasę Net.NetworkInformation.Ping którą już wcześniej wykorzystywaliśmy: 0072).

$cmds = @{
    "nosiemasiema" = { 
        $rule = New-NetFirewallRule -DisplayName "8080 - icmp knocking, src=$($args.ip)" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8080 -RemoteAddress $args.ip
        Write-Host "Witamy witamy, regula dla $($args.ip) dodana ($($rule.Name))"; 
    }
}

& 'C:\Program Files\Wireshark\tshark.exe' -i Wi-Fi -l -T ek  "icmp[0]=8" | ForEach-Object { 
    $json = ConvertFrom-Json -InputObject $_
    $ip = $json.layers.ip.ip_ip_src
    if ($json.layers.icmp.data.data_data_data) {
        $data = -join ($json.layers.icmp.data.data_data_data -split ":" | ForEach-Object { [char][Convert]::ToInt16($_, 16) })
        if ($cmds.Contains($data)) {
            Invoke-Command -ScriptBlock $cmds.$data -ArgumentList @{ip=$ip}
        }
    }
}

A na koniec wiecie, PowerShell działa również świetnie na Linuksach czy MacOS-ach.

Jak to działa — krok po kroku

Rozłóżmy onelinera na czynniki pierwsze:

& "C:\Program Files\Wireshark\tshark.exe

uruchamiamy aplikację tshark.exe wykorzystując operator wywołania &, który pozwala uruchomić aplikację, skrypt bądź blok skryptu,

-i Wi-Fi

wskazujemy interfejs, na którym chcemy sniffować pakiety, w naszym wypadku jest to interfejs Wi-Fi; by zobaczyć dostępne interfejsy sieciowe, możemy wykorzystać tshark a z parametrem -D, czyli: & "C:\Program Files\Wireshark\tshark.exe" -D lub jeśli Wireshark jest w zmiennej $env:PATH, po prostu: tshark -D,

-l

wyświetlaj natychmiast każdy przechwycony pakiet,

-T fields -e data

wskazujemy, że interesuje nas jedynie pole data pakietu, które w przypadku pakietów ICMP Echo request będzie zawierało payload pinga,

"icmp[0]=8"

definiujemy filtr, przekazując, że interesują nas jedynie pakiety ICMP o typie 8 (ICMP Echo request),

| % { ... }

każdy przechwycony pakiet wysyłamy do dalszego przetwarzania wykorzystując cmdlet ForEach-Object posiadający alias %,

-join ($_ -split "(.{2})" -match "." | % { [char][byte]"0x$_" })

jako, że tshark w polu danych zwróci strumień bajtów w postaci szesnastkowej, dzielimy cały string na dwuznakowe łańcuchy (wykorzystując trick z operatorem -split omówiony już w protipie aptm.in/protip/0072), następnie każdy taki szesnastkowy dwuliterowiec rzutujemy na bajt, a następnie na znak; operator -join na początku wyrażenia, składa nam tak wygenerowaną tablicę znaków w jeden string.

Przydatne linki

www.wireshark.org/ strona domowa Wiresharka web ↗ www.wireshark.org/docs/man-pages/tshark.html manual do tsharka web ↗
← poprzedni protip 0075 ••• Wszystkie protipy następny → protip 0077
// subskrybuj

Nowe protipy prosto na maila.

Mięsiste jednolinijkowce i triki z prawdziwych zleceń. Zero spamu, zero teorii. Wypisujesz się jednym kliknięciem.

wersja newslettera: