Maintenant, l'ESP!

April 12, 2026 FCSC 2026 #hardware #wifi

Here is a challenge on ESP-NOW protocol. A quick internet seach tells us it uses existing wifi antennas to send information without using the wifi network. It is a peer-to-peer wifi network of sorts. To identify source and destination MAC addresses are used (as expected as it does not use external infrastructure).

Moreover to be faster than classical wifi can sacrifice handshakes and crypto. In this challenge it will be the case.

This protocol also exclusively uses the Vendor Specific Content of the network packets.

When we open the pcapng in wireshark we see that we have an initial device that is broadcasting something… Followed by exchanges between two devices.

We can extract the data of the exchanges using tshark.

tshark -r capture.pcapng -P -T json | jq '.[]._source.layers."wlan.mgt"."Fixed parameters".data."data.data"' | head
"76:df:23:e6:dd:07:18:fe:34:04:02:01:00"
"f1:a3:9e:de:dd:07:18:fe:34:04:02:01:00"
"cf:0e:e4:f7:dd:07:18:fe:34:04:02:01:00"
"72:4f:1d:22:dd:07:18:fe:34:04:02:01:00"
"30:fd:44:bb:dd:07:18:fe:34:04:02:01:00"
"d9:95:53:0d:dd:07:18:fe:34:04:02:01:00"
"1f:3e:b7:9b:dd:07:18:fe:34:04:02:01:00"

When we scroll through the data we see that

  • the first four bytes vary wildly
  • the 4-11 are always the same
  • the 12th alternates between 03 and 02
  • the last byte is repeated between packets

The last two bytes are 02GG followed by 03GG, so one must be what is sent by the emitter and the reply of the reciever to acknowledge he recieved the packet. Moreover when trying to decode this as hex it gave a telltale ‘FCSC’ string.

I then tried to extract the flag in a oneliner

❯ tshark -r capture.pcapng -P -T json | jq '.[]._source.layers."wlan.mgt"."Fixed parameters".data."data.data"' | grep -Po '(?<=02:02:)\w\w(?=")' | tr -d '\n' | xxd -r -p
FCSC{WfI4cTi0n_Fr4MeS_83f0de591fccea}

and submitted it, but it failed…

When rereading the packets I saw that some packets must have been lost in the exchange, so we needed to make a more resilient program that would check which packet was sent and recieved by who.

using awk we can keep it a oneliner that extracts the whole flag even if the sniffer missed some packages. This one liner relied on the fact that there would be no double letters in which the recieved failed to reply to the sender.

tshark -r capture.pcapng -P -T json | jq '.[]._source.layers."wlan.mgt"."Fixed parameters".data."data.data"' | grep -Po '02:0[23]:\w\w' | awk -F: '{if($2=="02"){printf "%s",$3; e=$3} elseif($2=="03"){if(e==$3){e=""} else{printf "%s",$3; e=""}}}' | xxd -r -p; echo

Anyway this worked so our assumption was correct this time

Another cool challenge to discover a new protocol, I did not go to the original papers for this one but will probably do so when I have more time.

Thanks to the challmakers !