My fight with PTPCamera or a fascinating story about reversing for the smallest
- Tutorial
Gphoto currently supports 1598 camera models and the list is constantly growing. The project is built for all UNIX-like operating systems, including Linux and Mac OS X. Filming can be controlled both using the command line utility and from your own program using the libgphoto library. Bindings are available for different language platforms, including node.js .
In modern operating systems, there are built-in tools for working with digital cameras - as a rule, “work” means only uploading photos from the camera. These built-in mechanisms hinder the operation of gphoto, as they capture the USB device in exclusive mode. Especially interesting things are in this regard in Mac OS X - the OS does not provide any regular options for disabling, but the support system for digital cameras is easily amenable to reverse engineering.
Scripts to block the launch of PTPCamera on github.
PTPCamera
The Internet advises to execute the commandkillall -9 PTPCamera(kill the PTPCamera process) after connecting the camera for normal gphoto operation. This really helps, but every time you connect the camera, you have to repeat the procedure again. Of course, the PTPCamera program can simply be removed, but I wanted to get by with a less radical solution. In general, it was necessary to understand the mechanism for starting PTPCamera, and to disable this function as correctly as possible.
About capturing images in Mac OS X
According to available sources [ 1 , 2 ], the image capture infrastructure in Mac OS X is organized as follows.
At the top of the stack are applications that the user interacts directly with (ex: iPhoto).
At the very bottom are applications for managing devices, the latter include PTPCamera. Applications for control devices (
MassStorageCamera.app, PTPCamera.app, TWAINBridge.appetc.) Live system folders /System/Library/Image Capture/Devicesand /Library/Image Capture/Devices. In the middle is a communication layer that organizes the connection between the upper and lower levels. It is curious that several user applications can share the same device, and transparent work with devices on the local network is also possible.
Who launches PTPCamera?
Let's try to determine the mechanism for starting PTPCamera, and first we define the parent process.$ pgrep PTPCamera
29045
$ ps -O ppid -p 29045
PID PPID TT STAT TIME COMMAND
29045 202 ?? S 0:00.10 /System/Library/Image Capture/Devices/PTPCamer
$ ps -p 202
PID TTY TIME CMD
202 ?? 0:16.75 /sbin/launchd
So, we see that PTPCamera is launched by the launchd process. On Mac OS X, launchd is a universal launcher for system and user daemons. The system runs an instance of launchd for each active user. The root launchd performs the same functions as init on traditional UNIX systems.
$ ps -A -O user | grep /sbin/launchd
1 root ?? Ss 3:06.80 /sbin/launchd
172 _windowserver ?? Ss 0:00.06 /sbin/launchd
202 nickz ?? Ss 0:16.76 /sbin/launchd
206 _spotlight ?? Ss 0:00.27 /sbin/launchd
28919 _cvmsroot ?? Ss 0:00.01 /sbin/launchd
28937 _securityagent ?? Ss 0:00.01 /sbin/launchdIn addition to daemons, laucnhd also launches graphical applications on the command of other programs. PTPCamera is just the last case, as you can see from the task ID in launchd, the [prefix] tells us this.
$ launchctl list | grep PTPCamera
29045 - [0x0-0x457457].com.apple.PTPCameraSo, we know that PTPCamera was launched by the launchd process, at the command of a certain application X.
Turn on launchd (
launchctl log level debug) logging , and provoke the restart of PTPCamera. By default, a quota of 500 log entries per second is allocated for each process in the system. Messages that are not within the limit are discarded. Set up a separate assembly of debug messages to bypass the limit.
Add a
/etc/syslog.confline to the file*.debug /var/log/debug.logand inform the daemon
syslogdabout the need to re-read the settingssudo killall -HUP syslogdWe analyze the resulting file
debug.log. We find the desired:([0x0-0x2d92d9].com.apple.PTPCamera[24472]): Spawned by PID 240: com.apple.SystemUIServer.agentWe request
launchdinformation about com.apple.SystemUIServer.agent:$ launchctl list com.apple.SystemUIServer.agent
{
"Program" = "/System/Library/CoreServices/SystemUIServer.app/Contents/MacOS/SystemUIServer";
};Now we know that the “culprit” of the launch
PTPCamerais SystemUIServer, no less.Poking SystemUIServer
There is a suspicion that the desired functionality is not in itselfSystemUIServer, but in one of the linked frameworks:$ otool -L /System/Library/CoreServices/SystemUIServer.app/Contents/MacOS/SystemUIServer
/System/Library/CoreServices/SystemUIServer.app/Contents/MacOS/SystemUIServer:
/System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI
/System/Library/PrivateFrameworks/Admin.framework/Versions/A/Admin
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon
/System/Library/PrivateFrameworks/SystemUIPlugin.framework/Versions/A/SystemUIPlugin
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
/System/Library/Frameworks/Security.framework/Versions/A/Security
/System/Library/PrivateFrameworks/ICANotifications.framework/Versions/A/ICANotifications
/System/Library/PrivateFrameworks/iPod.framework/Versions/A/iPod
...
The main suspect on this list is
ICANotifications.framework. ICA- This is an abbreviation for image capture , the same acronym is used in public frameworks for image capture.Learning ICANotifications.framework
Lyrical digression. The executable file consists of code and immutable static data (different constants, tables, etc.) String constants are of particular interest. You can retrieve them using the commandstrings. We launch
strings /System/Library/PrivateFrameworks/ICANotifications.framework/Versions/A/ICANotifications, and enjoy the results:...
/Library/Caches/com.apple.ImageCaptureNotifications.DeviceDiscoveryDatabase.%d
...
CREATE TABLE DBVersion (ID integer primary key not null, typeID integer, value integer)
CREATE TABLE SourceFile (ID integer primary key not null, typeID integer, bundleID varchar(256), bundleVersion integer, bundlePath varchar(256), deviceDiscoveryPath varchar(256), deviceDiscoveryModDate varchar(20), readDate varchar(20), iTWAINDS integer)
CREATE TABLE IOUSBDevice (ID integer primary key not null, typeID integer, idVendor integer, idProduct integer)
CREATE TABLE IOUSBInterface (ID integer primary key not null, typeID integer, bInterfaceClass integer, bInterfaceSubClass integer, bInterfaceProtocol integer)
...
So this is SQL!
So, the working hypothesis is that the library works with a SQLite database, most likely it is a file
com.apple.ImageCaptureNotifications.DeviceDiscoveryDatabasein /Library/Caches.$ ls /Library/Caches/com.apple.ImageCaptureNotifications.DeviceDiscoveryDatabase.*
/Library/Caches/com.apple.ImageCaptureNotifications.DeviceDiscoveryDatabase.501
$ sqlite3 /Library/Caches/com.apple.ImageCaptureNotifications.DeviceDiscoveryDatabase.501
sqlite> .schema
CREATE TABLE DBVersion (ID integer primary key not null, typeID integer, value integer);
CREATE TABLE IOUSBDevice (ID integer primary key not null, typeID integer, idVendor integer, idProduct integer);
CREATE TABLE IOUSBInterface (ID integer primary key not null, typeID integer, bInterfaceClass integer, bInterfaceSubClass integer, bInterfaceProtocol integer);
...And there is!
It can be seen that the
com.apple.ImageCaptureNotifications.DeviceDiscoveryDatabase.501user ID is appended to the end of the name ( ), each user has its own file. From the contents it is clear that the base sets the list of correspondences of the device class and the control program that must be run when the device is detected. I edit the database, we turn off the launch
PTPCamerafor any selected user, this is a definite success ! If necessary, return everything back, roll back the changes, or simply delete the db file (the name of the folder
/Library/Cachestells us that the OS can regenerate the contents if necessary). Further is a matter of technology.