Closed liamhays closed 9 months ago
Hi, ensure that you pn532 works propperly. There are useful tools included in libnfc
. Try something like nfc-pool
or nfc-scan-device
with you card first
My board is definitely working, because running nfc-poll
finds the board and the card and identifies it as an ISO 14443A target, then reads the ATQA, UID, and SAK fields. The UID changes on every read.
Don't know how to reproduce it. Any advices are welcomed, also feel free to open PR if you could fix that issue
I can get this to segfault with my Apple Watch. I'm mostly a C programmer so I'm a bit stuck but I'll keep checking.
Edit: Of course after compiling with -g and running the program in gdb, no crash.
Edit2: More info from my end. I'm running this with an SCL3711 on a Raspberry Pi. Reading my VISA card, a proper read gives the sections:
[Info] Response from SELECT PPSE [Info] Response from SELECT APP [Info] Response from GET PROCESSING OPTIONS [Info] Response from READ RECORD from SFI2 record2 [Info] Response from READ RECORD from SFI2 record3 [Info] Response from READ RECORD from SFI2 record4
Messing around with various readers gave me another segfault with the sections:
[Info] Response from SELECT PPSE [Info] Response from SELECT APP [Info] Response from GET PROCESSING OPTIONS
and then 4779 bytes of data until the segmentation fault.
I got things to work again by unplugging and replugging in the SCL3711.
I'm going to see if I can enable core dumps and get it to fail again.
Core was generated by `./nfc-frog full'. Program terminated with signal SIGSEGV, Segmentation fault.
name=0x559e329380 "READ RECORD from SFI1 record60") at device_nfc.cpp:90
90 std::cout << HEX(ret.data[i]) << " "; (gdb) bt
name=0x559e329380 "READ RECORD from SFI1 record60") at device_nfc.cpp:90
HEX()
is defined in headers/tools.h
as
// Macro to print unsigned chars in hexadecimal
#define HEX(c) \
std::hex << std::uppercase << std::setw(2) << std::setfill('0') \
<< (unsigned int)c << std::dec
The line
std::cout << HEX(ret.data[i]) << " ";
references the local variable ret
, which is of type struct APDU
. That struct is:
struct APDU {
size_t size;
byte_t data[MAX_FRAME_LEN];
};
MAX_FRAME_LEN
is 300. As I suspected, it is in fact a buffer overflow.
Increasing MAX_FRAME_LEN
to larger values makes no difference. The maximum I tried was 1000000 (one million bytes), and it still segfaulted. I suspect the card is looping over all its data or generating new data at certain intervals.
nfc-frog
is actually segfaulting for me with a different backtrace than @htodd's backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x0000555555557e0d in DeviceNFC::execute_command (this=0x7fffffffdce0, command=0x7fffffffdbf0 "@\001", size=22, name=0x55555555d400 "SELECT PPSE") at device_nfc.cpp:90
90 std::cout << HEX(ret.data[i]) << " ";
(gdb) bt
#0 0x0000555555557e0d in DeviceNFC::execute_command (this=0x7fffffffdce0, command=0x7fffffffdbf0 "@\001", size=22,
name=0x55555555d400 "SELECT PPSE") at device_nfc.cpp:90
#1 0x0000555555558541 in DeviceNFC::load_applications_list (this=0x7fffffffdce0) at device_nfc.cpp:176
#2 0x0000555555556c22 in main (argc=2, argv=0x7fffffffdf48) at main.cpp:106
load_applications_list()
runs a SELECT PPSE command on the card, then parses the data. That SELECT PPSE command is the one returning the huge amount of data.
This might be helpful: https://github.com/cuamckuu/nfc-frog/issues/11 there were Application level error
too
I can reproduce (also using a Raspberry Pi). Here's the output with catchsegv of a read of an EMV test card. output.txt
This method assigns the result of a call to pn53x_transceive
to a variable of type size_t
: https://github.com/cuamckuu/nfc-frog/blob/9a4699d0c6fa39da01674406002af8d7ebbae61f/device_nfc.cpp#L78-L80.
pn53x_transceive
can return -1 in the case when it encounters an error:
https://github.com/nfc-tools/libnfc/blob/3df7f25f11499fa788e40c41ee7b45582262c566/libnfc/drivers/pn532_uart.c#L409,L496.
So, the reason for the segfault is that a -1 is being interpreted as a max unsigned size_t
.
The NFC Frog code should be changed to handle this error instead of segfaulting.
Now, why are we getting an application error, I'm not quite sure. It's generated here: https://github.com/nfc-tools/libnfc/blob/3df7f25f11499fa788e40c41ee7b45582262c566/libnfc/drivers/pn532_uart.c#L405-L410.
The PN532 manual states
c) Error at application level When the PN532 detects an error at the application level, it sends back the specific “Syntax Error frame” to the host controller (see §6.2.1.5, p: 31). An application level error may be due to one of the following reasons: • Unknown Command Code sent by the host controller in the command frame, • Unexpected frame length, • Incorrect parameters in the command frame.
I ran nfc-frog with LIBNFC_LOG_LEVEL=3
and saw:
debug libnfc.chip.pn53x InDataExchange
debug libnfc.chip.pn53x No timeout
debug libnfc.bus.uart TX: 00 00 ff 17 e9 d4 40 01 00 a4 04 00 0e 32 50 41 59 2e 53 59 53 2e 44 44 46 30 31 00 8f 00
debug libnfc.bus.uart RX: 00 00 ff 00 ff 00
debug libnfc.chip.pn53x PN53x ACKed
debug libnfc.bus.uart RX: 00 00 ff 01 ff
debug libnfc.bus.uart RX: 7f 81 00
error libnfc.driver.pn532_uart Application level error detected
I assume the PN532 is unhappy with something in the command
00 00 ff 17 e9 d4 40 01 00 a4 04 00 0e 32 50 41 59 2e 53 59 53 2e 44 44 46 30 31 00 8f 00
which I cannot really parse by hand, as I'm not an expert in this chip; I was hoping to just use the library 🙂.
I'd be very happy if anyone can take this debugging further.
Thanks @ipopov, great work! If you want, feel free to make pull request with fix to be listed in contributors
I need a programmer, to do track2 nfc simulation of payment in card machine contact me
I am attempting to use nfc-frog to read my own Visa card, and nfc-frog always segfaults no matter what mode it's in:
I trimmed and line-wrapped the SELECT PPSE data, as it's about 9500 bytes (counted with
str.split()
in Python). It's also not all zeros, but it starts out with a large zero block. Given the large amount of data, which is different from the handful of bytes that the example video shows, I suspect that some buffer is overflowing and causing the segfault.It is reading the same data on every attempt, so I think communication with the card is functional. I don't know why the "application level error" is getting printed.