Created
January 24, 2021 01:19
-
-
Save luowei/8028d1e1256a196dce4c53446891c9e5 to your computer and use it in GitHub Desktop.
jurpleConsole - a clone of Apple's purple_console tool, used to connect from your Mac to services on the i-Device (jailbroken or not) via lockdownd using the private MobileDevice.framework.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <CoreFoundation/CoreFoundation.h> | |
// Barebones purple_console clone - constructed with some reverse and forward engineering. | |
// | |
// No copyright or license. Feel free to share. Comments/Feedback welcome @http://newosxbook.com/forum/ | |
// | |
// | |
// To compile: gcc jurpleConsole.c -o jc -framework CoreFoundation -framework MobileDevice | |
// | |
// You will need to make MobileDevice.framework "public" - simplest way is to copy it (-pR) | |
// to Frameworks/ from PrivateFrameworks | |
#ifdef DEBUG | |
#define Dprintf fprintf | |
#else | |
#define Dprintf(...) | |
#endif | |
// These are obviously internal to Apple. The void * is likely some AMDDeviceRef * or something like that | |
// But since it's opaque anyway, just void * it.. | |
extern int AMDeviceConnect (void *device); | |
extern int AMDeviceValidatePairing (void *device); | |
extern int AMDeviceStartSession (void *device); | |
extern int AMDeviceStopSession (void *device); | |
extern int AMDeviceDisconnect (void *device); | |
extern int AMDServiceConnectionReceive(void *device, char *buf,int size, int ); | |
extern int AMDeviceSecureStartService(void *device, | |
CFStringRef serviceName, // One of the services in lockdown's Services.plist | |
int flagsButZeroIsFineAlso, | |
void *handle); | |
extern int AMDeviceNotificationSubscribe(void *, int , int , int, void **); | |
struct AMDeviceNotificationCallbackInformation { | |
void *deviceHandle; | |
uint32_t msgType; | |
} ; | |
#define BUFSIZE 128 // This is used by purpleConsole. So I figure I'll use it too. | |
void doDeviceConnect(void *deviceHandle) | |
{ | |
int rc = AMDeviceConnect(deviceHandle); | |
int fd; | |
char buf[BUFSIZE]; | |
if (rc) { | |
fprintf (stderr, "AMDeviceConnect returned: %d\n", rc); | |
exit(1); | |
} | |
rc = AMDeviceValidatePairing(deviceHandle); | |
if (rc) | |
{ | |
fprintf (stderr, "AMDeviceValidatePairing() returned: %d\n", rc); | |
exit(2); | |
} | |
rc = AMDeviceStartSession(deviceHandle); | |
if (rc) | |
{ | |
fprintf (stderr, "AMStartSession() returned: %d\n", rc); | |
exit(2); | |
} | |
void *f; | |
rc = AMDeviceSecureStartService(deviceHandle, | |
CFSTR("com.apple.syslog_relay"), // Any of the services in lockdown's services.plist | |
0, | |
&f); | |
if (rc != 0) | |
{ | |
fprintf(stderr, "Unable to start service -- Rc %d fd: %p\n", rc, f); | |
exit(4); | |
} | |
rc = AMDeviceStopSession(deviceHandle); | |
if (rc != 0) | |
{ | |
fprintf(stderr, "Unable to disconnect - rc is %d\n",rc); | |
exit(4); | |
} | |
rc = AMDeviceDisconnect(deviceHandle); | |
if (rc != 0) | |
{ | |
fprintf(stderr, "Unable to disconnect - rc is %d\n",rc); | |
exit(5); | |
} | |
memset (buf, '\0', 128); // technically, buf[0] = '\0' is enough | |
while ((rc = AMDServiceConnectionReceive(f, | |
buf, | |
BUFSIZE, 0) > 0)) | |
{ | |
// Messages are read to the buf (Framework uses a socket descriptor) | |
// For syslog_relay, messages are just the raw ASL output (including | |
// kernel.debug), which makes it easy for this sample code. | |
// Other services use bplists, which would call for those nasty | |
// CFDictionary and other APIs.. | |
printf("%s", buf); | |
fflush(NULL); | |
memset (buf, '\0', 128); | |
} | |
} // end doDevice | |
void callback(struct AMDeviceNotificationCallbackInformation *CallbackInfo) | |
{ | |
void *deviceHandle = CallbackInfo->deviceHandle; | |
Dprintf (stderr,"In callback, msgType is %d\n", CallbackInfo->msgType); | |
switch (CallbackInfo->msgType) | |
{ | |
case 1: | |
Dprintf(stderr, "Device %p connected\n", deviceHandle); | |
doDeviceConnect(deviceHandle); | |
break; | |
case 2: | |
Dprintf(stderr, "Device %p disconnected\n", deviceHandle); | |
break; | |
case 3: | |
Dprintf(stderr, "Unsubscribed\n"); | |
break; | |
default: | |
Dprintf(stderr, "Unknown message %d\n", CallbackInfo->msgType); | |
} | |
} | |
int main (int argc, char **argv) | |
{ | |
void *subscribe; | |
int rc = AMDeviceNotificationSubscribe(callback, 0,0,0, &subscribe); | |
if (rc <0) { | |
fprintf(stderr, "Unable to subscribe: AMDeviceNotificationSubscribe returned %d\n", rc); | |
exit(1); | |
} | |
CFRunLoopRun(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment