This esoteric challenge was something I had almost no prior experience with, decoding USB packets with Wireshark. We will learn the protocol for smart cards to recover the card number and expiration date from the traffic capture.

The Challenge

We get a short description of our task in the challenge itself:

I have a very bad habit: I store my credit card in my PC's smart card reader. An attacker is stealing its information. Can you recover the number and expiration date on the front of my credit card? Flag format: GCC{1234123412341234|MM/YY}

With this comes a usb.pcapng file for Wireshark with a lot of USB URB packets:

Decoding the traffic

From the description, we can assume this is somehow a traffic capture of a smart card that we have to reverse engineer. Searching online for things like "Wireshark smart card" we quickly see other people asking similar questions, mentioning "ISO 7816", the standard for smart cards communication. Searching now for "Wireshark ISO 7816" specifically results in a blog post explaining how they decoded raw USB packets into CCID packets and then ISO 7816 commands:

ISO 7816-4 spy using Wireshark

The post explains how you can decode the packets as USBCCID and then select the payload ISO 7816 in Wireshark. By also adding the iso7816 filter we see only the packets we need:

While we have a lot of useful packets now, there still aren't any obvious strings related to a card number or date. Only some strings like "MASTERCARD" and "1PAY.SYS.DFF01". These are likely encoded in some binary format that we need to find from a specification.

Extracting a card number and date

Doing some more googling, we can use the "1PAY.SYS.DFF01" string because it might be related to the internals of this protocol. This shows a few explanations of the first parts of the protocol, but nothing yet about the card number or expiration date. If we search for "1PAY.SYS.DFF01 expire date" we find a Part 4 and Part 5 of a highly detailed article explaining the protocol in hex, and what all the different parts of the payload mean. This is perfect!

Part 4 shows the expiry date in a packet starting with 77:

Hex

774C8202200057134704340000172834D21122011676600000671F5F2002202F5F3401019F100706011103A000
009F2608A4933D887F0065CE9F2701809F3602004E9F6C023E009F6E04207000009000

While Part 5 shows a different packet with an expiry date as well starting with 70:

Hex

70818C9F420206435F25031603015F24032011305A0855702956266780855F3401029F0702FF008C219F02069F
03069F1A0295055F2A029A039C019F37049F35019F45029F4C089F34038D0C910A8A0295059F37049F4C088E14
000000000000000042014403410342031E031F039F0D05BC50BC88009F0E0500000800009F0F05BC70BC98005F
280206439F4A01829000

Now that we know what to look for, we can quickly find similar packets in the Wireshark capture that start with 70 and have a similar length. These are marked as "Malformed Packets" by the decoder for some reason, but we can still get their raw data. One of the first sizable packets (#3278) has a large payload starting with 70, this might be it. We can copy the data by right-clicking the hex dump and choosing Copy as Hex Stream. This copies the whole packet instead of what is selected, so cut off the first part until 70 and you should get something like this:

Hex

7081a857135132630040615951d23022016950876900000f5a0851326300406159515f24032302285f25032002
015f280202505f3401018c279f02069f03069f1a0295055f2a029a039c019f37049f35019f45029f4c089f3403
9f21039f7c148d12910a8a0295059f37049f4c089f02069f03068e0a00000000000000001f039f0702ff009f08
0200039f0d05b4606080009f0e0500100000009f0f05b4606098009f420209

That is very similar to the example from the article (Part 5), and it might contain the card number and expiry date. The article explains that the expiry date can be found with a tag of 5F24 and the data after it is prefixed with the byte length. We can find this byte sequence in our capture too:

Hex

7081a857135132630040615951d23022016950876900000f5a0851326300406159515f24032302285f25032002
                                                                    ^^^^03       = length
                                                                          230228 = date

A date like 201230 is turned into "2020, December (12th month), 30th day", so our 230228 should be "2023, February (2nd month), 28th day". It fits in the date format so it would make sense. That's one objective completed.

Now the card number is not much different. Its tag is 5A and after it comes the complete card number itself, no decoding necessary:

Hex

7081a857135132630040615951d23022016950876900000f5a0851326300406159515f24032302285f25032002
                                                ^^08                 = length
                                                    5132630040615951 = card number

"5132630040615951" is then the card number! Combining these into the flag format we get the correct flag:

GCC{5132630040615951|02/23}