PCSC API spy, update
10 years ago I documented in "PCSC API spy, third try" a way to generate PC/SC API traces when using pcsc-lite.
Since then the ecosystem has changed. This article is an update of the previous blog article with more up-to-date information.
Changes
- The pcsc-spy.py command has been renamed pcsc-spy (in 2012)
- The libpcscspy.so library has been moved from /usr/lib/ to /usr/lib/x86_64-linux-gnu/ (for Intel 64-bits CPU systems)
-
opensc-tool can't be used with
LD_PRELOAD=
any more
Demo
As before we have two cases for the use of libpcsclite.so.1.Applications linked with libpcsclite.so.1
This is the case of the pcsc_scan command for example.
You can use the ldd
command to know what library has been dynamically linked
at build time:
$ ldd /usr/bin/pcsc_scan
linux-vdso.so.1 (0x00007fffac11b000)
libpcsclite.so.1 => /lib/x86_64-linux-gnu/libpcsclite.so.1 (0x00007f85a5f24000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f85a5f03000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f85a5d2a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f85a5f4f000)
You can use the LD_PRELOAD solution by doing:
In on terminal you run the pcsc-spy
program. In another terminal you run:
$ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libpcscspy.so.0 pcsc_scan -r libpcsclite_nospy.so.1: cannot open shared object file: No such file or directory No reader found.
In the first terminal you get the trace:
$ pcsc-spy SCardEstablishContext i dwScope: SCARD_SCOPE_SYSTEM (0x00000002) o hContext: 0x0E4C693B => Command successful. (SCARD_S_SUCCESS [0x00000000]) [0.002456] SCardGetStatusChange i hContext: 0x0E4C693B i dwTimeout: 0x00000000 (0) i cReaders: 1 i szReader: \\?PnP?\Notification i dwCurrentState: (0x00000000) i dwEventState: SCARD_STATE_IGNORE, SCARD_STATE_UNKNOWN, SCARD_STATE_UNAVAILABLE, SCARD_STATE_EMPTY, SCARD_STATE_INUSE, SCARD_STATE_MUTE (0x55EDE352031D) i Atr length: 0x55EDE352032C (94480209412908) i Atr: NULL o szReader: \\?PnP?\Notification o dwCurrentState: (0x00000000) o dwEventState: (0x00000000) o Atr length: 0x55EDE352032C (94480209412908) o Atr: NULL => Command timeout. (SCARD_E_TIMEOUT [0x8010000A]) [0.007774] SCardListReaders i hContext: 0x0E4C693B i mszGroups: (null) o pcchReaders: 0x00000001 o mszReaders: NULL => Cannot find a smart card reader. (SCARD_E_NO_READERS_AVAILABLE [0x8010002E]) [0.000908] SCardListReaders i hContext: 0x0E4C693B i mszGroups: (null) o pcchReaders: 0x00000001 o mszReaders: NULL => Cannot find a smart card reader. (SCARD_E_NO_READERS_AVAILABLE [0x8010002E]) [0.000531] Thread 1/1 Results sorted by total execution time total time: 0.011769 sec 0.007774 sec ( 1 calls) 66.06% SCardGetStatusChange 0.002456 sec ( 1 calls) 20.87% SCardEstablishContext 0.001439 sec ( 2 calls) 12.23% SCardListReaders
Application loading libpcsclite.so.1
In this case you need to modify the system configuration to replace the
libpcsclite.so.1 library. This is done by the
install_spy.sh
script. You only need to run the script once.
$ sudo bash /usr/share/doc/libpcsclite-dev/install_spy.sh Using directory: /lib/x86_64-linux-gnu Spying library is: /lib/x86_64-linux-gnu/libpcscspy.so.0
On Debian (and derivatives like Ubuntu) and with pcsc-lite version 1.9.8 and
more the script is provided by the libpcsclite-dev package.
In on terminal you run the pcsc-spy program. In another terminal you run the program you want to spy. For example:
$ opensc-tool -a No smart card readers found. Failed to connect to reader: No readers found
In the first terminal you get the trace:
SCardEstablishContext i dwScope: SCARD_SCOPE_USER (0x00000000) o hContext: 0x2667F6DA => Command successful. (SCARD_S_SUCCESS [0x00000000]) [0.005316] SCardListReaders i hContext: 0x2667F6DA i mszGroups: (null) o pcchReaders: 0x00000001 o mszReaders: NULL => Cannot find a smart card reader. (SCARD_E_NO_READERS_AVAILABLE [0x8010002E]) [0.000079] SCardReleaseContext i hContext: 0x2667F6DA => Command successful. (SCARD_S_SUCCESS [0x00000000]) [0.000074] Thread 1/1 Results sorted by total execution time total time: 0.007195 sec 0.005316 sec ( 1 calls) 73.88% SCardEstablishContext 0.000079 sec ( 1 calls) 1.10% SCardListReaders 0.000074 sec ( 1 calls) 1.03% SCardReleaseContext
Do not forget to restore the system configuration using the
uninstall_spy.sh
script.
$ sudo bash /usr/share/doc/libpcsclite-dev/uninstall_spy.sh Using directory: /lib/x86_64-linux-gnu
Redirection in a file
It is still possible to redirect the traces in a file. Instead of running
pcsc-spy
you do:
$ mkfifo ~/pcsc-spy $ cat ~/pcsc-spy > logfile
And in another terminal you start the application as indicated above (i.e.
using LD_PRELOAD=
or after running install_spy.sh
)
You can then analyse the logs later using:
$ pcsc-spy logfile
Remarks
Bugs found
I note that SCardReleaseContext()
is not always called by
pcsc_scan
before exit. I just fixed this problem in
pcsc-tools.
Install/uninstall
It is important to run the uninstall_spy.sh
script to undo the
changes made by the install_spy.sh
script.
It is important you undo the changes before any execution of the ldconfig (configure dynamic linker run-time bindings) administration command. ldconfig is used, for example, during the installation of a package.
If you run uninstall_spy.sh
after an execution of
ldconfig you may get a broken libpcsclite installation with an
error like:
$ pcsc_scan
pcsc_scan: error while loading shared libraries: libpcsclite.so.1: cannot open shared object file: No such file or directory
To fix te problem you can force reinstall the libpcsclite1 (or equivalent) package.
Order of execution
It is important to start pcsc-spy
before the application
you want to spy. If you start pcsc-spy after the application you have 2
cases:
- if the fifo file ~/pcsc-spy does not yet exist then pcsc-spy will display nothing
-
if the fifo file ~/pcsc-spy already exists then
libpcscspy.so will use it to send logs and will be blocked
until something reads the file (
pcsc-spy
or thecat
command to redirect the content)
Conclusion
I hope this update is useful.
if you have ideas to improve the logs please contact me.