-
-
Save Dantee296/e084c6a57e6d80a9bde5e6b09c78f9c9 to your computer and use it in GitHub Desktop.
jurpleConsole from newosxbook.com with an adjusted buffer size to work
This file contains hidden or 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 <dlfcn.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 -framework MobileDevice -F /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/System/Library/Frameworks/ | |
// | |
// You will need to make MobileDevice.framework "public" - simplest way is to copy it (-pR) | |
// to Frameworks/ from PrivateFrameworks | |
// | |
// /Library/Apple/System/Library/PrivateFrameworks/MobileDevice.framework | |
// to | |
// /Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/System/Library/Frameworks | |
#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 1024 // This used to be 128, but that needed to be adjusted. According to Jonathan Levin, the reason for this was that the real purple_console also | |
// used a buffer size of 128, although it wasn't nearly enough to support any readable data within the stream of logs. I was recently able to | |
// take a look at the original purple_console program, and regardless of it being built in 2020, it still uses a buffer size of 128 and spits out | |
// the same unreadable data. Regardless of usability, Jonathan Levin's original code posted years ago is still an identical clone to the most | |
// recently built version of the internal-only tool. | |
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', 1024); // 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', 1024); | |
} | |
} // 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