PCSC framework spy: broken since Mac OS X Yosemite

In "PCSC API spy, on Mac OS X" I proposed a way to spy on all PC/SC calls of an application.

A few months later Yosemite was available and my spying library does not work any more ☹.

PCSC framework replacement: fails

Example of failure:
$ DYLD_FRAMEWORK_PATH=/tmp pcsc_scan
PC/SC device scanner
V /Users/lroussea/Documents/sc/costa/pcsc-tools (c) 2001-2011, Ludovic Rousseau 
Compiled with PC/SC lite version: 1.4.0
SCardEstablishContext: Service not available.

Spy output (in a second terminal window):
$ ./pcsc-spy
SCardEstablishContext
 i dwScope: SCARD_SCOPE_SYSTEM (0x00000002)
 o hContext: 0x00000000
 => Service not available. (SCARD_E_NO_SERVICE [0x8010001D])  [0.000001109]
SCardReleaseContext
 i hContext: 0x00000000
 => Invalid handle. (SCARD_E_INVALID_HANDLE [0x80100003])  [0.000000006]

Results sorted by total execution time
total time: 0.001138 sec
0.001109 sec (  1 calls) 97.45% SCardEstablishContext
0.000006 sec (  1 calls)  0.53% SCardReleaseContext

If I run pcsc_scan alone, with no PC/SC spy, then the command runs as expected.

Something detects the usage of a new PCSC framework and rejects the first call. I guess the culprit is the original PCSC framework itself and this is a new security feature from Yosemite.

Running the application as root (using sudo) does not help.

SIP: System Integrity Protection

A new change since El Capitan is that the use of DYLD_FRAMEWORK_PATH does not work for programs in protected directories, like /usr/bin/.
$ type pcsctest
pcsctest is hashed (/usr/bin/pcsctest)

$ DYLD_FRAMEWORK_PATH=/tmp pcsctest

MUSCLE PC/SC Lite Test Program

Testing SCardEstablishContext    : Command successful.
Testing SCardGetStatusChange 
Please insert a working reader   : Command successful.
Testing SCardListReaders         : Command successful.
Reader 01: Gemalto PC Twin Reader
Enter the reader number          : ^C

Here the command succeeds but nothing is sent over the spy pipe.

In Yosemite I could use DYLD_FRAMEWORK_PATH=/tmp but with the same results as described above. On El Capitan the dynamic linker dyld just ignores DYLD_FRAMEWORK_PATH.

Another way to check that is to use lldb, the debugger provided with Xcode.

$ lldb pcsctest
(lldb) target create "pcsctest"
Current executable set to 'pcsctest' (x86_64).
(lldb) run
error: process exited with status -1 (cannot attach to process due to System Integrity Protection)
(lldb) quit

Conclusion

I know no way to spy the PC/SC calls done by an application on Mac OS X (with version >= 10.10).

This is problematic because PC/SC is still unstable on El Capitan. See "OS X El Capitan and smart cards: known bugs" for example. In some cases it would really help to know what PC/SC call returns an error to be able to:
  • Report the error to Apple if it is a bug in PC/SC
  • Tell the customer that it is a bug on Apple side
  • Try to find a way to avoid the problem, if possible