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:
774C8202200057134704340000172834D21122011676600000671F5F2002202F5F3401019F100706011103A000
009F2608A4933D887F0065CE9F2701809F3602004E9F6C023E009F6E04207000009000
While Part 5 shows a different packet with an expiry date as well starting with 70:
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:
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:
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:
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}