mfontanini / libtins

High-level, multiplatform C++ network packet sniffing and crafting library.
http://libtins.github.io/
BSD 2-Clause "Simplified" License
1.91k stars 377 forks source link

Ocassional duplicate packets seen when decrypting WPA2 #389

Closed stepen closed 4 years ago

stepen commented 4 years ago

I'm running Linux on RaspberryPi4B / 4GB, OS ver 'buster', libtins v/4.3, using a AWUS036ACH antenna. It seems that the library sometimes delivers duplicate packets from sniffing. Packets that are not seen on the wire.

When I run the following simple code (very simple example-code for a WPA2 decryptor) I OCASSIONALLY see duplicates.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>
#include <tins/tins.h>

using namespace Tins;
using namespace std;
using namespace Crypto;

bool wpa2_callback(const PDU &pdu) 
{
    static int decrypted_pktcnt=1;
    try
    {
       const Dot11Data &data = pdu.rfind_pdu<Dot11Data>();
       try 
       {
            const IP &ip = pdu.rfind_pdu<IP>(); 
            cout << to_string(decrypted_pktcnt) << " : msrc:" << data.src_addr() << " mdst:" << data.dst_addr() << " ipsrc:" << ip.src_addr() << " ipdst:" << ip.dst_addr() << " ipid:" << to_string(ip.id()) << " iproto:" << to_string(ip.protocol()) <<endl;
           decrypted_pktcnt++;

       }
       catch (Tins::pdu_not_found &e)
       {
            //cout << "   -->PDU is no IP frame" << endl;;
       }
    }
    catch (Tins::pdu_not_found &e)
    {
        //cout << "  -->PDU is no DATA frame" << endl;;
    }
    return true;
}

int main() 
{

    // Setting the relevant channel for my AP
    std::system("iwconfig wlan1 channel 7");  

    SnifferConfiguration config;
    config.set_promisc_mode(true);
    config.set_rfmon(true);

    // Make a simple WPA2 decryptor
    auto decrypt_proxy = make_wpa2_decrypter_proxy(&wpa2_callback);

    decrypt_proxy.decrypter().add_ap_data("PASSWD", "SSID");   

    Sniffer sniffer("wlan1", config);  // wlan is in monitor mode
    cout << "Starting the proxy decryptor" << endl;
    sniffer.sniff_loop(decrypt_proxy);
}

I have included a sample run, where I am sending 4 pings (ICMP) on a test-net (11.11.11.xx, Ch7, 2.4GhZ) from a PC-client (.101) to a RaspberryPI (.106). The sniffer runs on separate RaspberryPI. Mind you, I have to do this many times before I catch a duplicate-scenario, but it usually happens within 20 tries.

The Ping-command looks like (8 packets. 4 requests and 4 replies):

ping -s 30 -c 4 -i 3 11.11.11.106
PING 11.11.11.106 (11.11.11.106) 30(58) bytes of data.
38 bytes from 11.11.11.106: icmp_seq=1 ttl=64 time=2.67 ms
38 bytes from 11.11.11.106: icmp_seq=2 ttl=64 time=2.52 ms
38 bytes from 11.11.11.106: icmp_seq=3 ttl=64 time=3.32 ms
38 bytes from 11.11.11.106: icmp_seq=4 ttl=64 time=80.0 ms

--- 11.11.11.106 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 9003ms
rtt min/avg/max/mdev = 2.528/22.137/80.024/33.422 ms

The output from the small program above, gives: (MAC addresses have been obscured a little and I've added a REQUEST/REPLY label. Packet # 173 is a duplicate delivered (wrongfully) by the decryptor.

168 : msrc:80:86:... mdst:b8:27:... ipsrc:11.11.11.101 ipdst:11.11.11.106 ipid:26612 iproto:1   REQ  #1
169 : msrc:b8:27:... mdst:80:86:... ipsrc:11.11.11.106 ipdst:11.11.11.101 ipid:18689 iproto:1   RPLY #1
170 : msrc:80:86:... mdst:b8:27:... ipsrc:11.11.11.101 ipdst:11.11.11.106 ipid:26613 iproto:1   REQ  #2
171 : msrc:b8:27:... mdst:80:86:... ipsrc:11.11.11.106 ipdst:11.11.11.101 ipid:18881 iproto:1   RPLY #2
172 : msrc:80:86:... mdst:b8:27:... ipsrc:11.11.11.101 ipdst:11.11.11.106 ipid:26614 iproto:1   REQ  #3
173 : msrc:80:86:... mdst:b8:27:... ipsrc:11.11.11.101 ipdst:11.11.11.106 ipid:26614 iproto:1   REQ  #3 - duplicate NOT on wire
174 : msrc:b8:27:... mdst:80:86:... ipsrc:11.11.11.106 ipdst:11.11.11.101 ipid:19081 iproto:1   RPLY #3
175 : msrc:80:86:... mdst:b8:27:... ipsrc:11.11.11.101 ipdst:11.11.11.106 ipid:26615 iproto:1   REQ  #4
176 : msrc:b8:27:... mdst:80:86:... ipsrc:11.11.11.106 ipdst:11.11.11.101 ipid:19349 iproto:1   RPLY #4

A parallel capture on wireshark (on .101) shows the following - i.e. NO douplicates. (I've added the IP-idents and REQ/REPLY labels):

105 129.640819  11.11.11.101    11.11.11.106    ICMP    72  Echo (ping) request  id=0x0042, seq=1/256, ttl=128 (reply in 106)   [ident:26612] REQ  #1
106 129.643270  11.11.11.106    11.11.11.101    ICMP    72  Echo (ping) reply    id=0x0042, seq=1/256, ttl=64 (request in 105)  [ident:18698] RPLY #1
107 132.641119  11.11.11.101    11.11.11.106    ICMP    72  Echo (ping) request  id=0x0042, seq=2/512, ttl=128 (reply in 108)   [ident:26613] REQ  #2
108 132.643418  11.11.11.106    11.11.11.101    ICMP    72  Echo (ping) reply    id=0x0042, seq=2/512, ttl=64 (request in 107)  [ident:18881] RPLY #2
109 135.642396  11.11.11.101    11.11.11.106    ICMP    72  Echo (ping) request  id=0x0042, seq=3/768, ttl=128 (reply in 110)   [ident:26614] REQ  #3
110 135.645501  11.11.11.106    11.11.11.101    ICMP    72  Echo (ping) reply    id=0x0042, seq=3/768, ttl=64 (request in 109)  [ident:19081] RPLY #3
111 138.644087  11.11.11.101    11.11.11.106    ICMP    72  Echo (ping) request  id=0x0042, seq=4/1024, ttl=128 (reply in 112)  [ident:26615] REQ  #4
112 138.723852  11.11.11.106    11.11.11.101    ICMP    72  Echo (ping) reply    id=0x0042, seq=4/1024, ttl=64 (request in 111) [ident:19349] RPLY #4

I have no idea why this happens with this simple code (maybe I'm overlooking something ?). It perhaps could be a RF (layer 2) re-transmission? Are RF re-transmissions propagated through libtins ? If anyone has any ideas, please share ...

Thanks in advance stepen

stepen commented 4 years ago

The answer is 'yes'... valid packets including re-transmissions are delivered through libtins (as suspected). The network hardware/driver will discard garbled frames/acks, but re-transmissions will be passed through.... as it should come to think about it. This is what I was experiencing. case closed.