nmap / npcap

Nmap Project's Windows packet capture and transmission library
https://npcap.com
Other
2.99k stars 516 forks source link

[Npcap] pcap_snaplen() isn't working well #479

Closed Komosa closed 3 years ago

Komosa commented 8 years ago

Hi all, there is commonly known bug, that pcap_snaplen doesn't work with winpcap, and there is commonly known workaround for this: set empty filter for sniffing after call to activate.

This setting-empty-filter trick stopped to work with npcap. More detailed info: since npcap 0.05 (r1) some packets are snapped, but not all of them; this behavior continues to be observable up to npcap 0.06 (r1) (inclusive).

Since npcap 0.06 r2 behavior is better, way more packets is being snapped (but still not all). This is being observable also for 0.06 r3 and r4. (observable caplens: 134, 276, 342, 1392, 1484, 1486, 1490, 1514).

Since npcap 0.06 r5 (also in r6, I could not test r7) problem is even worse - some packets are not snapped, resulting in ~1500bytes packets, but most of them are snapped at really short level (most commonly 16 (!) bytes).

Scenario: set snaplen to 123. Procedure is: create() set_promisc(0) set_timeout(250) set_snaplen(123) activate() set_nonblock(1) filter("") dispatch() - I will publish examplary tool and comment.

I ran those tests also with libpcap on linux, it works (although snapping at 122).

Komosa commented 8 years ago

https://github.com/Komosa/use-pcap - code for reproduction.

hsluoyz commented 8 years ago

Hi Komosa,

there is commonly known bug, that pcap_snaplen doesn't work with winpcap, and there is commonly known workaround for this: set empty filter for sniffing after call to activate.

I have been reported the pcap_snaplen not working on the outgoing packets issue.

And I also noticed the weird truth that filter has been set (by calling pcap_compile and pcap_setfilter), or even the pcap_snaplen on the incoming packets won't work.

But I don't know this weird behavior originates from WinPcap. I thought it's a bug introduced by Npcap too. However, obviously the Npcap bug is more severe for now.

Below is my analysis about this bug (actually a mail). I'm still working on it. If you have any ideas please inform me too.

I have found a call trace below. I believe this is how snaplen works. It's so complex that I haven't found it for several days.

Here's an example here: https://github.com/hsluoyz/UserBridge/blob/master/UserBridge.c
This application can change snaplen. I believe Wireshark is the same.
We know that the snaplen is the 2nd paramter of pcap_open() call, let's say how it flows into the driver. ----> stands for the the flowing.

1) pcap_open -> pcap_open_live -> pcap_set_snaplen (the snaplen parameter ----> *pcap_t->snapshot)

2) pcap_compile -> pcap_compile_unsafe (*pcap_t->snapshot ----> the BPF filter)

Because in this function there's some code:

    snaplen = pcap_snapshot(p);
    if (snaplen == 0) {
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
             "snaplen of 0 rejects all packets");
        return -1;
    }

    lex_init(xbuf ? xbuf : "");
    init_linktype(p);
    (void)pcap_parse();

    if (n_errors)
        syntax();

    if (root == NULL)
        root = gen_retblk(snaplen);

3.A) pcap_setfilter -> pcap_setfilter_win32_npf -> PacketSetBpf -> DeviceIoControl with BIOCSETF (the BPF filter ----> NewBpfProgram in the Npcap driver)

3.B) NPF_IoControl (NewBpfProgram -> *OPEN_INSTANCE->bpfprogram)

3.C) NPF_SendEx, NPF_TapEx, NPFWrite, NPFBufferedWrite -> NPF_TapExForEachOpen (the packet receive function) -> bpf_filter (*OPEN_INSTANCE->bpfprogram -----> fres)

Finally fres influences the captured packet length in NPF_TapExForEachOpen call.

So we know that Wireshark must have called all the three calls: pcap_open, pcap_compile and pcap_setfilter, otherwise the specified snaplen can't affect the packet length.

So the next question is why the fres variable fails to affect the captured packet length result in NPF_TapExForEachOpen call. But I haven't found out the reason yet.

Do you guys have any ideas?

Since npcap 0.06 r2 behavior is better, way more packets is being snapped (but still not all). This is being observable also for 0.06 r3 and r4. (observable caplens: 134, 276, 342, 1392, 1484, 1486, 1490, 1514).

I checked the commits, actually I didn't change any code part from 0.06 to 0.06 R2 (only some build scripts and installer logic are changed). So it's weird that you can get better result about snaplen in 0.06 R2..

Since npcap 0.06 r5 (also in r6, I could not test r7) problem is even worse - some packets are not snapped, resulting in ~1500bytes packets, but most of them are snapped at really short level (most commonly 16 (!) bytes).

DO NOT USE 0.06 R5, R6 and the original R7. They have a severe bug that causes captured malformed packets. Please use the latest R7.2 for testing.

hsluoyz commented 8 years ago

Hi @Komosa ,

I have fixed the pcap_snaplen() isn't working for outgoing packets issue in Npcap 0.06 R9, please try the lastest installer at: https://github.com/nmap/npcap/releases