├── cmd_gg.h ├── cmd_mg.h ├── cmd_install.h ├── cmd_syscfg.h ├── cmd_syslog.h ├── cmd_tunnel.h ├── cmd_bytetest.h ├── service_sysmon.h ├── service_notifications.h ├── cmd_list.h ├── MobileDevice.framework ├── cmd_ioreg.h ├── .gitignore ├── uuid.h ├── service_testmanager.h ├── cmd_listapps.h ├── cmd_img.h ├── archiver ├── plist_read.h ├── nsutil.h ├── byteswap.h ├── Makefile ├── plist.h ├── unarchiver.h ├── ptrarr.h ├── byteswap.c ├── out.c ├── in.c ├── ptrarr.c ├── nsutil.m ├── types.h ├── archiver.h ├── unarchiver.c └── plist.c ├── cmd_file.h ├── cmd_info.h ├── service_deviceinfo.h ├── mobdev_err.h ├── services.h ├── Makefile ├── cmd_process.h ├── dtxmsg.h ├── cmd_dtxdump.h ├── dtxmsg.c ├── cmd_gg.c ├── ujsonin ├── ujsonin.h ├── string-tree.h ├── red_black_tree.h ├── string-tree.c └── red_black_tree.c ├── service_notifications.c ├── cmd_list.c ├── bytearr.h ├── cfutil.h ├── uclop.h ├── cmd_install.c ├── uuid.c ├── services.c ├── sandbird └── sandbird.h ├── cmd_listapps.c ├── service_sysmon.c ├── service.h ├── cmd_mg.c ├── cmd_info.c ├── dump.pl ├── cmd_bytetest.c ├── README.md ├── mobiledevice.h ├── cmd_ioreg.c ├── cmd_file.c ├── cmd_process.c ├── main.c ├── cmd_tunnel.c ├── uclop.c ├── cmd_image.c ├── cmd_syslog.c ├── bytearr.c ├── cmd_syscfg.c ├── LICENSE ├── service_deviceinfo.c └── cmd_dtxdump.c /cmd_gg.h: -------------------------------------------------------------------------------- 1 | void run_gg( ucmd *cmd ); -------------------------------------------------------------------------------- /cmd_mg.h: -------------------------------------------------------------------------------- 1 | void run_mg( ucmd *cmd ); -------------------------------------------------------------------------------- /cmd_install.h: -------------------------------------------------------------------------------- 1 | void run_install( ucmd *cmd ); -------------------------------------------------------------------------------- /cmd_syscfg.h: -------------------------------------------------------------------------------- 1 | void run_syscfg( ucmd *cmd ); -------------------------------------------------------------------------------- /cmd_syslog.h: -------------------------------------------------------------------------------- 1 | void run_syslog( ucmd *cmd ); -------------------------------------------------------------------------------- /cmd_tunnel.h: -------------------------------------------------------------------------------- 1 | void run_tunnel( ucmd *cmd ); -------------------------------------------------------------------------------- /cmd_bytetest.h: -------------------------------------------------------------------------------- 1 | void run_bytetest( ucmd *cmd ); -------------------------------------------------------------------------------- /service_sysmon.h: -------------------------------------------------------------------------------- 1 | void run_sysmon( ucmd *cmd ); -------------------------------------------------------------------------------- /service_notifications.h: -------------------------------------------------------------------------------- 1 | void run_notices( ucmd *cmd ); -------------------------------------------------------------------------------- /cmd_list.h: -------------------------------------------------------------------------------- 1 | void run_list( ucmd *cmd ); 2 | void run_detect( ucmd *cmd ); -------------------------------------------------------------------------------- /MobileDevice.framework: -------------------------------------------------------------------------------- 1 | /System/Library/PrivateFrameworks/MobileDevice.framework -------------------------------------------------------------------------------- /cmd_ioreg.h: -------------------------------------------------------------------------------- 1 | void run_ioreg( ucmd *cmd ); 2 | void run_battery( ucmd *cmd ); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **~ 2 | iosif 3 | archiver/in 4 | archiver/out 5 | dump* 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /uuid.h: -------------------------------------------------------------------------------- 1 | #ifndef __UUID_H 2 | #define __UUID_H 3 | char *uuid_generate(); 4 | #endif 5 | -------------------------------------------------------------------------------- /service_testmanager.h: -------------------------------------------------------------------------------- 1 | void run_xctest( ucmd *cmd ); 2 | void run_cfa( ucmd *cmd ); 3 | void run_wda( ucmd *cmd ); 4 | -------------------------------------------------------------------------------- /cmd_listapps.h: -------------------------------------------------------------------------------- 1 | #include"cfutil.h" 2 | void run_listapps( ucmd *cmd ); 3 | 4 | CFDictionaryRef getAppInfo( void *device, char *bi ); -------------------------------------------------------------------------------- /cmd_img.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | void run_img( ucmd *cmd ); 5 | void run_iserver( ucmd *cmd ); -------------------------------------------------------------------------------- /archiver/plist_read.h: -------------------------------------------------------------------------------- 1 | uint8_t bpList__pass1( bpList *list, uint8_t refSize); 2 | void bpList__pass2( bpList *list, uint8_t refSize); 3 | uint8_t bpList__readTrailer( bpList *self, uint8_t *data, int len ); -------------------------------------------------------------------------------- /cmd_file.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | void run_getfile( ucmd *cmd ); 6 | char writeDataToAppFile( void *device, char *bundleid, char *remoteFile, uint8_t *data, uint32_t len ); 7 | -------------------------------------------------------------------------------- /archiver/nsutil.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uint8_t *cf2archive( CFTypeRef cf, int *len, char secure ); 5 | 6 | CFTypeRef archive2cf( const uint8_t *bytes, uint32_t len ); 7 | CFDictionaryRef archive2cfdict( uint8_t *bytes, uint32_t len ); 8 | -------------------------------------------------------------------------------- /cmd_info.h: -------------------------------------------------------------------------------- 1 | #ifndef __INFO_H 2 | #define __INFO_H 3 | void run_info( ucmd *cmd ); 4 | void run_ios_version( ucmd *cmd ); 5 | 6 | typedef struct { 7 | int major; 8 | int medium; 9 | int minor; 10 | } iosVersion; 11 | 12 | iosVersion getIosVersion( void *device ); 13 | #endif -------------------------------------------------------------------------------- /service_deviceinfo.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | void run_ls( ucmd *cmd ); 5 | void run_ps( ucmd *cmd ); 6 | void run_smProcList( ucmd *cmd ); 7 | void run_smSysList( ucmd *cmd ); 8 | void run_smCoalList( ucmd *cmd ); 9 | void run_machTimeInfo( ucmd *cmd ); 10 | void run_sysinfo( ucmd *cmd ); -------------------------------------------------------------------------------- /mobdev_err.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | // Generated by https://github.com/nanoscopic/mobdev_dump_errs 5 | #ifndef __MOBDEV_ERR 6 | #define __MOBDEV_ERR 7 | 8 | typedef struct { 9 | const char *name; 10 | const char *error; 11 | const uint32_t num; 12 | } mobdev_err; 13 | 14 | mobdev_err *mobdev_geterr(uint32_t num); 15 | #endif 16 | -------------------------------------------------------------------------------- /archiver/byteswap.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // MIT License 3 | 4 | #ifndef __BYTESWAP_H 5 | #define __BYTESWAP_H 6 | #include 7 | uint16_t bswap_u16( uint16_t v ); 8 | int16_t bswap_i16( int16_t v ); 9 | int32_t bswap_i32( int32_t v ); 10 | uint32_t bswap_u32( uint32_t v ); 11 | int64_t bswap_i64( int64_t v ); 12 | uint64_t bswap_u64( uint64_t v ); 13 | #endif -------------------------------------------------------------------------------- /archiver/Makefile: -------------------------------------------------------------------------------- 1 | all: in out 2 | 3 | in_c := $(wildcard *.c) ../cfutil.c ../bytearr.c nsutil.m 4 | in_c := $(filter-out out.c, $(in_c)) 5 | in_all := $(in_c) $(wildcard *.h) 6 | 7 | out_c := $(wildcard *.c) ../bytearr.c 8 | out_c := $(filter-out in.c, $(out_c)) 9 | out_all := $(out_c) $(wildcard *.h) 10 | 11 | in: $(in_all) 12 | gcc -o in $(in_c) -F ./ -lobjc -framework Foundation -framework CoreFoundation 13 | 14 | out: $(out_all) 15 | gcc -o out $(out_c) -F ./ 16 | 17 | clean: 18 | $(RM) test -------------------------------------------------------------------------------- /archiver/plist.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __PLIST_H 5 | #define __PLIST_H 6 | #include 7 | #include"types.h" 8 | #include"../bytearr.h" 9 | 10 | uint16_t tDICT__plist( tOFFS *offs, bytearr *ba, tDICT *self ); 11 | void bpList__encodeTrailer( bytearr *ba, uint32_t numObs, uint32_t offsetsPos, uint32_t rootNum, uint8_t offBytes ); 12 | uint16_t tBASE__plist( tOFFS *offs, bytearr *ba, tBASE *ob ); 13 | uint8_t *tBASE__tobin( tBASE *self, uint32_t *len ); 14 | uint8_t *tBASE__archivebin( tBASE *self, uint32_t *len ); 15 | uint8_t *encodeSize( uint32_t val, int *len ); 16 | #endif -------------------------------------------------------------------------------- /services.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __SERVICES_H 5 | #define __SERVICES_H 6 | #include"service.h" 7 | 8 | void *activateService( void *device, CFTypeRef serviceName, CFDictionaryRef options ); 9 | 10 | void *activateSyslog( void *device ); 11 | void *activateScreenshotService( void *device ); 12 | void *activateDiagService( void *device ); 13 | 14 | serviceT *service__new_instruments( void *device ); 15 | serviceT *service__new_testmanagerd( void *device ); 16 | serviceT *service__new_remoteautomation( void *device ); 17 | serviceT *service__new_afc( void *device ); 18 | #endif -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: iosif 2 | 3 | iosif_sources := $(wildcard *.c) $(wildcard *.h) $(wildcard archiver/*.c) $(wildcard archiver/*.h) $(wildcard ujsonin/*.c) $(wildcard ujsonin/*.h) 4 | c_files := $(wildcard *.c) $(wildcard archiver/*.c) $(wildcard ujsonin/*.c) sandbird/sandbird.c 5 | c_files := $(filter-out archiver/in.c archiver/out.c, $(c_files)) 6 | 7 | # nsutil.m -lobjc -framework Foundation 8 | # -L /usr/local/opt/openssl/lib -lssl -I /usr/local/opt/openssl/include 9 | # -DDEBUG -DDEBUG2 10 | iosif: $(iosif_sources) 11 | gcc -g -I /usr/local/include -o iosif $(c_files) -F ./ -framework CoreFoundation -framework MobileDevice 12 | 13 | clean: 14 | $(RM) iosif -------------------------------------------------------------------------------- /archiver/unarchiver.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __UNARCHIVER_H 5 | #define __UNARCHIVER_H 6 | #include 7 | #include"ptrarr.h" 8 | #include"archiver.h" 9 | 10 | typedef struct { 11 | uint8_t scan; 12 | uint8_t bytesPerOffset; 13 | uint8_t bytesPerRef; 14 | uint32_t maxObNum; 15 | uint32_t rootObNum; 16 | uint32_t offsetsPos; 17 | 18 | //tARR *obs; 19 | //tBASE **obsArr; 20 | ptrArr *obs; 21 | uint8_t *data; 22 | int len; 23 | } bpList; 24 | 25 | bpList *bpList__new( uint8_t *data, int len ); 26 | tBASE *dearchive( uint8_t *data, uint32_t len ); 27 | 28 | #define asBASE (tBASE *) 29 | 30 | #endif -------------------------------------------------------------------------------- /cmd_process.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include"service.h" 5 | 6 | void run_launch( ucmd *cmd ); 7 | void run_kill( ucmd *cmd ); 8 | void run_tail( ucmd *cmd ); 9 | void startObserving( channelT *chan, int32_t pid ); 10 | uint64_t launchProcess( 11 | void *device, 12 | char *bundleIdentifier, 13 | tDICT *environment, 14 | tARR *arguments, 15 | tDICT *options 16 | ); 17 | 18 | uint64_t launchProcess_withchan( 19 | void *device, 20 | char *bundleIdentifier, 21 | tDICT *environment, 22 | tARR *arguments, 23 | tDICT *options, 24 | channelT *chan 25 | ); 26 | 27 | channelT *channel__new_processcontrol( void *device ); -------------------------------------------------------------------------------- /archiver/ptrarr.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __PTRARR_H 5 | #define __PTRARR_H 6 | #include 7 | 8 | struct ptrArr_t { 9 | uint16_t max; 10 | uint16_t count; 11 | void **ptr; 12 | struct ptrArr_t *next; 13 | }; 14 | typedef struct ptrArr_t ptrArr; 15 | 16 | ptrArr *ptrArr__new(); 17 | 18 | ptrArr *ptrArr__add( ptrArr *self, void *item ); 19 | 20 | void *ptrArr__get( ptrArr *self, uint32_t pos ); 21 | 22 | void ptrArr__del( ptrArr *self ); 23 | 24 | void *ptrArr__iter( ptrArr **cur, uint32_t *pos ); 25 | 26 | #ifdef UDEBUG 27 | #define duprintf(...) printf(__VA_ARGS__) 28 | #else 29 | #define duprintf(...) (void)0 30 | #endif 31 | 32 | #endif -------------------------------------------------------------------------------- /dtxmsg.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __DTXMSG_H 5 | #define __DTXMSG_H 6 | typedef struct { 7 | uint32_t magic; 8 | uint32_t size; // 4 9 | uint16_t fragId; // 8 10 | uint16_t fragCount; // 10 11 | uint32_t length; // 12 12 | uint32_t id; // 16 13 | uint32_t conversationIndex ; // 20 14 | int32_t channelCode; // 24 15 | uint32_t expectsReply; // 28 16 | } dtxmsg; 17 | 18 | typedef struct { 19 | uint32_t type; 20 | uint32_t auxlen; // 4 21 | uint32_t totlen; // 8 22 | uint32_t flags; // 12 23 | } dtxpayload; 24 | 25 | dtxmsg *dtxmsg__new( int channel, uint32_t id, char expectsReply, uint32_t length ); 26 | dtxpayload *dtxpayload__new( char expectsReply, uint32_t auxlen, uint64_t totlen ); 27 | #endif -------------------------------------------------------------------------------- /cmd_dtxdump.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __DTXDUMP_H 5 | #define __DTXDUMP_H 6 | 7 | #include"dtxmsg.h" 8 | struct dmsg_s { 9 | uint8_t *ptr; 10 | uint16_t len; 11 | char *time; 12 | char dir; 13 | struct dmsg_s *next; 14 | }; 15 | typedef struct dmsg_s dmsg; 16 | 17 | typedef struct { 18 | uint16_t count; 19 | dmsg *head; 20 | dmsg *tail; 21 | } dmsgList; 22 | 23 | #define DIR_TO 0 24 | #define DIR_FROM 1 25 | 26 | void run_dtxdump( ucmd *cmd ); 27 | void run_dtxdumpfolder( ucmd *cmd ); 28 | void dump__messages( dmsgList *list, char *jsonFile, char *binFile, char dir ); 29 | dmsgList *dmsgList__new(); 30 | dmsg **dmsgList__toPtrs( dmsgList *self ); 31 | void decode_message( uint8_t *buffer, int len, char *time, char dir ); 32 | #endif -------------------------------------------------------------------------------- /dtxmsg.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | 7 | #include"dtxmsg.h" 8 | 9 | dtxmsg *dtxmsg__new( int channel, uint32_t id, char expectsReply, uint32_t length ) { 10 | dtxmsg *self = (dtxmsg *) calloc( 1, sizeof( dtxmsg ) ); 11 | self->magic = 0x1F3D5B79; 12 | self->size = sizeof( dtxmsg ); 13 | self->fragId = 0; 14 | self->fragCount = 1; 15 | self->length = length; 16 | self->id = id; 17 | self->conversationIndex = 0; 18 | self->channelCode = channel; 19 | self->expectsReply = expectsReply; 20 | return self; 21 | } 22 | 23 | dtxpayload *dtxpayload__new( char expectsReply, uint32_t auxlen, uint64_t totlen ) { 24 | dtxpayload *self = (dtxpayload *) calloc( 1, sizeof( dtxpayload ) ); 25 | self->type = 0x2 | (expectsReply ? 0x1000 : 0); 26 | self->auxlen = auxlen; 27 | self->totlen = totlen; 28 | return self; 29 | } -------------------------------------------------------------------------------- /cmd_gg.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include"uclop.h" 7 | #include"cfutil.h" 8 | #include"mobiledevice.h" 9 | #include"service.h" 10 | #include"services.h" 11 | 12 | static ucmd *g_cmd = NULL; 13 | void runGG( void *device ); 14 | void run_gg( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runGG ); } 15 | 16 | void runGG( void *device ) { 17 | void *diagService = activateDiagService( device ); 18 | CFDictionaryRef plist = genmap( 2, "Request", CFSTR("GasGauge") ); 19 | 20 | exitOnError( 21 | AMDServiceConnectionSendMessage( diagService, plist, kCFPropertyListXMLFormat_v1_0 ), 22 | "Send X" ); 23 | 24 | CFDictionaryRef info = NULL; 25 | exitOnError( 26 | AMDServiceConnectionReceiveMessage( diagService, &info, nil ), 27 | "Request Receive" ); 28 | 29 | cfdump( 0, info ); 30 | 31 | exit(0); 32 | } -------------------------------------------------------------------------------- /archiver/byteswap.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // MIT License 3 | 4 | #include 5 | uint16_t bswap_u16( uint16_t v ) { return (v << 8) | (v >> 8 ); } 6 | int16_t bswap_i16( int16_t v ) { return (v << 8) | ((v >> 8) & 0xFF); } 7 | 8 | int32_t bswap_i32( int32_t v ) { 9 | v = ((v << 8) & 0xFF00FF00) | ((v >> 8) & 0xFF00FF ); 10 | return (v << 16) | ((v >> 16) & 0xFFFF); 11 | } 12 | 13 | uint32_t bswap_u32( uint32_t v ) { 14 | v = ((v << 8) & 0xFF00FF00 ) | ((v >> 8) & 0xFF00FF ); 15 | return (v << 16) | (v >> 16); 16 | } 17 | 18 | int64_t bswap_i64( int64_t v ) { 19 | v = ((v << 8 ) & 0xFF00FF00FF00FF00ULL ) | ((v >> 8 ) & 0x00FF00FF00FF00FFULL ); 20 | v = ((v << 16) & 0xFFFF0000FFFF0000ULL ) | ((v >> 16) & 0x0000FFFF0000FFFFULL ); 21 | return (v << 32) | ((v >> 32) & 0xFFFFFFFFULL); 22 | } 23 | 24 | uint64_t bswap_u64( uint64_t v ) { 25 | v = ((v << 8 ) & 0xFF00FF00FF00FF00ULL ) | ((v >> 8 ) & 0x00FF00FF00FF00FFULL ); 26 | v = ((v << 16) & 0xFFFF0000FFFF0000ULL ) | ((v >> 16) & 0x0000FFFF0000FFFFULL ); 27 | return (v << 32) | (v >> 32); 28 | } -------------------------------------------------------------------------------- /ujsonin/ujsonin.h: -------------------------------------------------------------------------------- 1 | #ifndef __UJSONIN_H 2 | #define __UJSONIN_H 3 | #include"string-tree.h" 4 | typedef struct jnode_s jnode; 5 | 6 | #define NODEBASE char type; jnode *parent; 7 | // type 1=hash, 2=str 8 | 9 | #define SAFE(x) if(pos>=len) { endstate=x; goto Done; } 10 | #define SAFEGET(x) if(pos>=len) { endstate=x; goto Done; } let=data[pos++]; 11 | #define SPACES for( int j=0;j 5 | #include"plist.h" 6 | #include"archiver.h" 7 | 8 | int main( int argc, char *argv[] ) { 9 | tDICT *dict = tDICT__newPairs( 12, 10 | "i8", tI8__new( 4 ), 11 | "i16", tI16__new( 5 ), 12 | "i32", tI32__new( 6 ), 13 | "i64", tI64__new( 7 ), 14 | "bool", tBOOL__new( 1 ), 15 | "arcid", tARCID__new( 1000 ), 16 | //"null", tNULL__new(), 17 | "key", tSTR__new( "str" ), 18 | "arr", tARR__newVals( 2, tI16__new( 2 ), tI16__new( 3 ) ) 19 | ); 20 | tI16 *num = tI16__new(2); 21 | 22 | uint32_t len; 23 | //uint8_t *data = tBASE__tobin( (tBASE *) dict, &len ); 24 | //uint8_t *data = tBASE__tobin( (tBASE *) num, &len ); 25 | //uint8_t *data = tBASE__archivebin( (tBASE *) tARR__newVals( 1, (tBASE *) num ), &len ); 26 | 27 | //uint8_t *data = tBASE__archivebin( (tBASE *) num, &len ); 28 | uint8_t *data = tBASE__archivebin( (tBASE *) tSTR__new("/private/var/mobile/Containers/Data/Application/BE9D64A9-B78A-4E2C-8C5E-3E9BCFD56473/tmp/5f33ca05-b98c-40ab-b18a-e414e2d486e0.xctestconfiguration"), &len ); 29 | 30 | //uint8_t *data = tBASE__archive( (tBASE *) tARR__newVals( 1, (tBASE *) num ), &len ); 31 | 32 | FILE *fh = fopen( "data", "wb" ); 33 | if( !fh ) { 34 | fprintf(stderr,"Could not open %s for writing\n", data ); 35 | return 1; 36 | } 37 | fwrite( data, len, 1, fh ); 38 | fclose( fh ); 39 | return 0; 40 | } -------------------------------------------------------------------------------- /service_notifications.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"bytearr.h" 6 | #include 7 | #include"services.h" 8 | #include"service.h" 9 | #include"uclop.h" 10 | #include"cfutil.h" 11 | 12 | static ucmd *g_cmd = NULL; 13 | void runNotices( void *device ); 14 | void run_notices( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runNotices ); } 15 | 16 | void runNotices( void *device ) { 17 | if( !desired_device( device, g_cmd ) ) return; 18 | 19 | serviceT *service = service__new_instruments( device ); 20 | 21 | //CFTypeRef msg = NULL; 22 | tBASE *msg = NULL; 23 | 24 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.mobilenotifications" ); 25 | 26 | if( !channel__send( chan, "setApplicationStateNotificationsEnabled:", (tBASE *) tI32__new(1), 0 ) ) { 27 | fprintf( stderr, "setConfig failed\n" ); 28 | return; 29 | } 30 | 31 | for(;;) { 32 | //CFArrayRef data = NULL; 33 | tARR *data = NULL; 34 | if( !channel__recv( chan, &msg, &data ) ) { 35 | fprintf( stderr, "recvDtx failed\n" ); 36 | return; 37 | } 38 | 39 | //if( data ) cfdump( 0, data ); 40 | if( data ) tBASE__dump( (tBASE *) data, 1 ); 41 | 42 | if( msg ) { 43 | //cfdump( 0, msg ); 44 | tBASE__dump( msg, 1 ); 45 | } 46 | else sleep(1); 47 | } 48 | 49 | service__del( service ); 50 | exit(0); 51 | } -------------------------------------------------------------------------------- /archiver/in.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include"archiver.h" 5 | #include"unarchiver.h" 6 | #include"nsutil.h" 7 | #include"../cfutil.h" 8 | 9 | uint8_t checkEquals( char *descr, CFTypeRef data ); 10 | 11 | int main() { 12 | /*{ 13 | CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 14 | CFDateRef item = CFDateCreate( NULL, now ); 15 | checkEquals( "Time", item ); 16 | }*/ 17 | /*{ 18 | CFTypeRef item = f1cf( 300000.34 ); 19 | checkEquals( "Float", item ); 20 | }*/ 21 | { 22 | char data[] = { 0x43, 0x87, 0xb1 }; 23 | CFTypeRef item = datacf( data, 3 ); 24 | checkEquals( "Data", item ); 25 | } 26 | /*{ 27 | CFArrayRef arr = genarr( 1, kCFBooleanTrue ); 28 | checkEquals( arr ); 29 | }*/ 30 | /*{ 31 | CFDictionaryRef arr = genmap( 2, "a", i8cf( -2 ) ); 32 | checkEquals( arr ); 33 | }*/ 34 | /*{ 35 | #define NN 300 36 | char str[NN]; 37 | memset( str, 'x', NN ); 38 | str[NN-1] = 0x00; 39 | CFArrayRef arr = genarr( 2, i8cf( 1 ), str_c2cf( str ) ); 40 | checkEquals( arr ); 41 | }*/ 42 | 43 | 44 | } 45 | 46 | uint8_t checkEquals( char *descr, CFTypeRef item ) { 47 | printf("Checking %s\n", descr ); 48 | cfdump( 1, item ); 49 | 50 | int len; 51 | uint8_t *data = cf2archive( item, &len, 0 ); 52 | tBASE *clean = dearchive( data, len ); 53 | //printf("Clean type:%d\n", clean->type ); 54 | tBASE__dump( clean, 1 ); 55 | printf("\n"); 56 | return 0; 57 | } -------------------------------------------------------------------------------- /archiver/ptrarr.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include"ptrarr.h" 7 | 8 | ptrArr *ptrArr__new() { 9 | ptrArr *self = (ptrArr *) malloc( sizeof( ptrArr ) ); 10 | self->max = 30; 11 | self->count = 0; 12 | self->ptr = (void **) malloc( sizeof( void * ) * 30 ); 13 | self->next = 0; 14 | return self; 15 | } 16 | 17 | ptrArr *ptrArr__add( ptrArr *self, void *item ) { 18 | if( self->next ) { 19 | ptrArr *cur = self; 20 | while( cur->next ) cur = cur->next; 21 | ptrArr__add( cur, item ); 22 | return cur; 23 | } 24 | if( self->count == self->max ) { 25 | self->next = ptrArr__new(); 26 | ptrArr *next = self->next; 27 | ptrArr__add( next, item ); 28 | return next; 29 | } 30 | self->ptr[ self->count++ ] = item; 31 | return 0; 32 | } 33 | 34 | void *ptrArr__get( ptrArr *self, uint32_t pos ) { 35 | if( pos < self->count ) return self->ptr[ pos ]; 36 | ptrArr *cur = self; 37 | while( pos >= cur->count ) { 38 | pos -= cur->count; 39 | cur = cur->next; 40 | if( !cur ) return 0; 41 | } 42 | return cur->ptr[ pos ]; 43 | } 44 | 45 | void ptrArr__del( ptrArr *self ) { 46 | free( self->ptr ); 47 | if( self->next ) ptrArr__del( self->next ); 48 | free( self ); 49 | } 50 | 51 | void *ptrArr__iter( ptrArr **cur, uint32_t *pos ) { 52 | if( *pos < (*cur)->count ) { 53 | return (*cur)->ptr[ (*pos)++ ]; 54 | } 55 | while( *pos >= (*cur)->count ) { 56 | *pos -= (*cur)->count; 57 | *cur = (*cur)->next; 58 | if( !*cur ) return 0; 59 | } 60 | return (*cur)->ptr[ (*pos)++ ]; 61 | } -------------------------------------------------------------------------------- /cmd_list.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"cfutil.h" 6 | #include"mobiledevice.h" 7 | #include"uclop.h" 8 | #include"service.h" 9 | 10 | static ucmd *g_cmd = NULL; 11 | void runList( void *device ); 12 | void run_list( ucmd *cmd ) { 13 | g_cmd = cmd; 14 | setupTimeout(1); 15 | waitForConnect( runList ); 16 | } 17 | 18 | void detectConnect( void *device ); 19 | void detectDisconnect( void *device ); 20 | void run_detect( ucmd *cmd ) { 21 | g_cmd = cmd; 22 | waitForConnectDisconnect( detectConnect, detectDisconnect ); 23 | } 24 | 25 | void detectConnect( void *device ) { 26 | devUp( device ); 27 | CFStringRef udidCf = AMDeviceCopyDeviceIdentifier( device ); 28 | char *udid = str_cf2c( udidCf ); 29 | CFTypeRef nameCf = AMDeviceCopyValue( device, NULL, CFSTR("DeviceName") ); 30 | char *name = str_cf2c( nameCf ); 31 | devDown( device ); 32 | for( int i=0;i 7 | #include 8 | #include"archiver/types.h" 9 | 10 | typedef struct bytechunk_s bytechunk; 11 | struct bytechunk_s { 12 | uint8_t *data; 13 | uint32_t len; 14 | char alloc; 15 | struct bytechunk_s *next; 16 | }; 17 | 18 | typedef struct { 19 | uint32_t len; 20 | bytechunk *head; 21 | bytechunk *tail; 22 | } bytearr; 23 | 24 | bytechunk *bytechunk__new( uint8_t *data, uint32_t len, char alloc ); 25 | 26 | bytearr *bytearr__new(); 27 | 28 | void bytearr__appendba( bytearr *self, bytearr *toadd ); 29 | 30 | void bytearr__append( bytearr *self, uint8_t *data, uint32_t len, char alloc ); 31 | void bytearr__appdup( bytearr *self, uint8_t *data, uint32_t len ); 32 | 33 | void bytearr__appendu8( bytearr *self, uint8_t num ); 34 | void bytearr__appendu16( bytearr *self, uint16_t num ); 35 | void bytearr__appendi32( bytearr *self, int32_t num ); 36 | void bytearr__appendu32( bytearr *self, uint32_t num ); 37 | 38 | void bytearr__appendi64( bytearr *self, int64_t num ); 39 | 40 | uint8_t *bytearr__bytes( bytearr *self, uint32_t *len ); 41 | 42 | void bytearr__auxi32( bytearr *self, int32_t val ); 43 | 44 | void bytearr__auxi64( bytearr *self, int64_t val ); 45 | 46 | //void bytearr__auxcf( bytearr *self, CFTypeRef cf, char secure ); 47 | void bytearr__auxT( bytearr *self, tBASE *t ); 48 | 49 | uint8_t *bytearr__asaux( bytearr *self, uint32_t *len ); 50 | 51 | //bytearr *cfarr2aux( CFTypeRef argsCf, char secure ); 52 | bytearr *tarr2aux( tARR *argsT ); 53 | 54 | void ba__print( bytearr *self, char *fmt, ... ); 55 | 56 | #endif -------------------------------------------------------------------------------- /cfutil.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __CFUTIL_H 5 | #define __CFUTIL_H 6 | #include 7 | #include"archiver/archiver.h" 8 | 9 | CFNumberRef i8cf( char num ); 10 | CFNumberRef i16cf( int16_t num ); 11 | CFNumberRef i32cf( int32_t num ); 12 | CFNumberRef i64cf( int64_t num ); 13 | CFNumberRef f1cf( float num ); 14 | CFNumberRef f2cf( double num ); 15 | CFDataRef datacf( const void *data, int len ); 16 | CFBooleanRef boolcf( char val ); 17 | uint64_t cfi64( CFNumberRef num ); 18 | uint16_t cfi16( CFNumberRef num ); 19 | uint8_t cfi8( CFNumberRef num ); 20 | 21 | char cfstreq( CFStringRef cf, const char *to ); 22 | char *str_cf2c( CFStringRef cfstr ); 23 | 24 | char iscfstr( CFTypeRef cf ); 25 | char iscfdict( CFTypeRef cf ); 26 | char iscfarr( CFTypeRef cf ); 27 | char iscfnum( CFTypeRef cf ); 28 | 29 | CFStringRef str_c2cf( char *str ); 30 | 31 | CFTypeRef cfmapget( CFDictionaryRef node, char *key ); 32 | void cfdump( int depth, CFTypeRef node ); 33 | 34 | CFDictionaryRef genmap( int count, ... ); 35 | 36 | char *cftype( CFTypeRef cf ); 37 | 38 | CFArrayRef strsToArr( int count, char **strs ); 39 | 40 | CFArrayRef genarr( int count, ... ); 41 | CFArrayRef genstrarr( int count, ... ); 42 | 43 | CFArrayRef deserialize2cf( const uint8_t *buf, size_t bufsize ); 44 | tBASE *deserialize2t( const uint8_t *buf, size_t bufsize ); 45 | 46 | uint32_t crc32( uint32_t crc, const char *buf, size_t len ); 47 | 48 | char *strArchive( const char *str, uint32_t *strLen ); 49 | 50 | void dumparchive( const uint8_t *data, uint32_t len ); 51 | 52 | CFPropertyListRef xml2plist( const char *data ); 53 | CFPropertyListRef data2plist( const uint8_t *data, int len ); 54 | #endif -------------------------------------------------------------------------------- /uclop.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // github.com/nanoscopic/uclop 3 | // Anti-Corruption License 4 | 5 | #ifndef __UCLOP_H 6 | #define __UCLOP_H 7 | #define UOPT(a,b) uopt__new(a,b,1,0) 8 | #define UOPT_REQUIRED(a,b) uopt__new(a,b,1,1) 9 | #define UOPT_FLAG(a,b) uopt__new(a,b,2,0) 10 | #define UOPT_FLAG_REQUIRED(a,b) uopt__new(a,b,2,1) 11 | 12 | typedef struct uopts_s uopt; 13 | struct uopts_s { 14 | int type; 15 | int required; 16 | char *name; 17 | char *descr; 18 | char *def; // default value 19 | char *val; 20 | uopt *next; 21 | }; 22 | 23 | typedef struct ucmd_s ucmd; 24 | 25 | struct ucmd_s { 26 | char *name; 27 | char *descr; 28 | void ( *handler )( ucmd * ); 29 | ucmd *next; 30 | uopt *head; uopt *tail; 31 | int argc; 32 | char **argv; 33 | char *extrahelp; 34 | }; 35 | 36 | typedef struct uclop_s { 37 | ucmd *head; 38 | ucmd *tail; 39 | char *default_cmd; 40 | } uclop; 41 | 42 | uopt *uopt__new( char *name, char *descr, int type, int req ); 43 | 44 | void ucmd__addopt( ucmd *self, uopt *opt ); 45 | 46 | ucmd *uclop__addcmd( uclop *self, char *cmd_name, char *cmd_descr, 47 | void ( *default_handler )( ucmd * ), uopt *cmd_opts[] ); 48 | 49 | uclop *uclop__new( void ( *default_handler)( ucmd * ), uopt *default_opts[] ); 50 | 51 | void ucmd__run( ucmd *cmd ); 52 | 53 | void ucmd__usage_inline( ucmd *self ); 54 | 55 | void ucmd__usage( ucmd *self ); 56 | 57 | void uopt__usage( uopt *opt ); 58 | 59 | void uclop__usage( uclop *self, char *prog ); 60 | 61 | uopt *ucmd__find_opt( ucmd *self, char *name ); 62 | 63 | char *ucmd__get( ucmd *self, char *name ); 64 | 65 | void ucmd__ensure_required( ucmd *self ); 66 | 67 | void uclop__run( uclop *self, int argc, char *argv[] ); 68 | #endif -------------------------------------------------------------------------------- /cmd_install.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include"service.h" 7 | #include"cfutil.h" 8 | #include"uclop.h" 9 | 10 | static ucmd *g_cmd = NULL; 11 | void runInstall( void *device ); 12 | void run_install( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runInstall ); } 13 | 14 | int transferStatus( CFDictionaryRef dict, int x ) { 15 | //cfdump( 1, dict ); 16 | CFNumberRef pCf = cfmapget( dict, "PercentComplete" ); 17 | if( pCf ) { 18 | uint16_t percent = cfi16( pCf ); 19 | printf("\rCopying:%d%%", percent ); 20 | } 21 | return 0; 22 | } 23 | 24 | int installStatus( CFDictionaryRef dict, int x ) { 25 | CFNumberRef pCf = cfmapget( dict, "PercentComplete" ); 26 | if( pCf ) { 27 | uint16_t percent = cfi16( pCf ); 28 | printf("\rInstalling:%d%%", percent ); 29 | } 30 | //cfdump( 1, dict ); 31 | return 0; 32 | } 33 | 34 | void runInstall( void *device ) { 35 | char *pathAbs = realpath( ucmd__get( g_cmd, "-path" ), NULL ); 36 | CFStringRef pathCf = str_c2cf( pathAbs ); 37 | CFURLRef absUrl = CFURLCreateWithFileSystemPath( NULL, pathCf, kCFURLPOSIXPathStyle, 0 ); 38 | 39 | devUp( device ); 40 | 41 | void *afcConn; 42 | AMDeviceSecureStartService( device, CFSTR("com.apple.afc"), NULL, &afcConn ); 43 | 44 | CFDictionaryRef map = genmap( 2, "PackageType", CFSTR("Developer") ); 45 | AMDeviceSecureTransferPath( 0, device, absUrl, map, transferStatus, 0 ); 46 | printf("\rCopying:100%%\n"); 47 | close( *( (int*) afcConn ) ); 48 | 49 | AMDeviceSecureInstallApplication( 0, device, absUrl, map, installStatus, 0 ); 50 | printf("\rInstalling:100%%\n"); 51 | 52 | free( pathAbs ); 53 | 54 | devDown( device ); 55 | 56 | exit(0); 57 | } -------------------------------------------------------------------------------- /uuid.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Based on https://github.com/rxi/uuid4 - Copyright (c) 2018 rxi 3 | // MIT license 4 | 5 | #include 6 | #include 7 | #include 8 | #include"uuid.h" 9 | 10 | // ***** START PRNG ***** 11 | // License CC0 - http://creativecommons.org/publicdomain/zero/1.0/ 12 | 13 | static inline uint64_t rotl(const uint64_t x, int k) { 14 | return (x << k) | (x >> (64 - k)); 15 | } 16 | 17 | static uint64_t s[4]; 18 | 19 | static uint64_t next() { 20 | const uint64_t result = rotl(s[0] + s[3], 23) + s[0]; 21 | const uint64_t t = s[1] << 17; 22 | 23 | s[2] ^= s[0]; s[3] ^= s[1]; s[1] ^= s[2]; s[0] ^= s[3]; 24 | s[2] ^= t; 25 | s[3] = rotl(s[3], 45); 26 | 27 | return result; 28 | } 29 | 30 | // ***** END PRNG ***** 31 | 32 | static char initdone = 0; 33 | 34 | static void uuid_init() { 35 | FILE *fp = fopen("/dev/urandom", "rb"); 36 | if( !fp ) goto ERR; 37 | int bytes_read = fread(s, 1, sizeof(s), fp); 38 | fclose( fp ); 39 | if( bytes_read == sizeof(s) ) return; 40 | ERR: 41 | s[0] = 1; s[1] = 2; s[2] = 3; s[3] = 4; 42 | } 43 | 44 | char *uuid_generate() { 45 | if( !initdone ) uuid_init(); 46 | char *buf = (char *) malloc( 37 ); 47 | char *dst = buf; 48 | static const char *template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"; 49 | static const char *chars = "0123456789abcdef"; 50 | union { unsigned char b[16]; uint64_t word[2]; } s; 51 | const char *p; 52 | int i, n; 53 | s.word[0] = next(); 54 | s.word[1] = next(); 55 | 56 | p = template; 57 | i = 0; 58 | while( *p ) { 59 | n = s.b[i >> 1]; 60 | n = (i & 1) ? (n >> 4) : (n & 0xf); 61 | switch( *p ) { 62 | case 'x': 63 | *dst = chars[n]; i++; break; 64 | case 'y': 65 | *dst = chars[(n & 0x3) + 8]; i++; break; 66 | default: 67 | *dst = *p; 68 | } 69 | dst++, p++; 70 | } 71 | *dst = '\0'; 72 | return buf; 73 | } 74 | -------------------------------------------------------------------------------- /services.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"service.h" 6 | #include"cfutil.h" 7 | 8 | void *activateService( void *device, CFTypeRef serviceName, CFDictionaryRef options ) { 9 | devUp( device ); 10 | void *service; 11 | exitOnError( AMDeviceSecureStartService( device, serviceName, options, &service ), "Some Service" ); 12 | devDown( device ); 13 | return service; 14 | } 15 | 16 | void *activateSyslog( void *device ) { 17 | CFDictionaryRef unlockEscrow = genmap( 2, "UnlockEscrowBag", kCFBooleanTrue ) ; 18 | return activateService( device, CFSTR("com.apple.syslog_relay"), unlockEscrow ); 19 | } 20 | void *activateScreenshotService( void *device ) { 21 | return activateService( device, CFSTR("com.apple.mobile.screenshotr"), NULL ); 22 | } 23 | void *activateDiagService( void *device ) { 24 | return activateService( device, CFSTR("com.apple.mobile.diagnostics_relay"), NULL ); 25 | } 26 | 27 | serviceT *service__new_instruments( void *device ) { 28 | serviceT *self = service__new( device, 29 | "com.apple.instruments.remoteserver", 30 | "com.apple.instruments.remoteserver.DVTSecureSocketProxy" ); 31 | service__handshake( self ); 32 | return self; 33 | } 34 | 35 | serviceT *service__new_afc( void *device ) { 36 | serviceT *self = service__new( device, 37 | "com.apple.afc", 38 | NULL ); 39 | return self; 40 | } 41 | 42 | serviceT *service__new_testmanagerd( void *device ) { 43 | serviceT *self = service__new( device, 44 | "com.apple.testmanagerd.lockdown", 45 | "com.apple.testmanagerd.lockdown.secure" ); 46 | service__handshake2( self ); 47 | return self; 48 | } 49 | 50 | serviceT *service__new_remoteautomation( void *device ) { 51 | serviceT *self = service__new( device, 52 | "com.apple.testmanagerd.remote-automation.lockdown", 53 | "com.apple.testmanagerd.remote-automation.lockdown.secure" ); 54 | return self; 55 | } -------------------------------------------------------------------------------- /ujsonin/string-tree.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 David Helkowski 2 | 3 | #ifndef __STRING_TREE_H 4 | #define __STRING_TREE_H 5 | #include 6 | 7 | uint32_t fnv1a_len( char *str, int strlen ); 8 | 9 | struct snode_s { 10 | char *str; 11 | int strlen; 12 | char dataType; 13 | void *data; 14 | struct snode_s *next; 15 | }; 16 | typedef struct snode_s snode; 17 | 18 | snode *snode__new( char *newstr, void *newdata, char dataType, snode *newnext ); 19 | void snode__delete( snode *self ); 20 | snode *snode__new_len( char *newstr, int strlen, void *newdata, char dataType, snode *newnext ); 21 | 22 | #define XJR_ARR_MAX 5 23 | typedef struct xjr_arr_s xjr_arr; 24 | struct xjr_arr_s { 25 | int count; 26 | int max; 27 | void **items; 28 | char *types; 29 | }; 30 | xjr_arr *xjr_arr__new(); 31 | void xjr_arr__double( xjr_arr *self ); 32 | void xjr_arr__delete( xjr_arr *self ); 33 | 34 | #define XJR_KEY_ARR_MAX 5 35 | typedef struct xjr_key_arr_s xjr_key_arr; 36 | struct xjr_key_arr_s { 37 | int count; 38 | int max; 39 | char **items; 40 | int *sizes; 41 | }; 42 | xjr_key_arr *xjr_key_arr__new(); 43 | void xjr_key_arr__double( xjr_key_arr *self ); 44 | void xjr_key_arr__delete( xjr_key_arr *self ); 45 | 46 | struct string_tree_s { 47 | void *tree; 48 | }; 49 | typedef struct string_tree_s string_tree; 50 | snode *string_tree__rawget_len( string_tree *self, char *key, int keylen ); 51 | string_tree *string_tree__new(); 52 | void string_tree__delete( string_tree *self ); 53 | void *string_tree__get_len( string_tree *self, char *key, int keylen, char *dataType ); 54 | void string_tree__delkey_len( string_tree *self, char *key, int keylen ); 55 | 56 | void string_tree__store_len( string_tree *self, char *key, int keylen, void *node, char dataType ); 57 | 58 | void IntDest(void *); int IntComp(const void *,const void *); 59 | void IntPrint(const void* a); void InfoPrint(void *); void InfoDest(void *); 60 | 61 | xjr_key_arr *string_tree__getkeys( string_tree *self ); 62 | void string_tree__getkeys_rec( void *snodeV, void *arrV ); 63 | #endif 64 | -------------------------------------------------------------------------------- /ujsonin/red_black_tree.h: -------------------------------------------------------------------------------- 1 | #ifndef __RED_BLACK_TREE_H 2 | #define __RED_BLACK_TREE_H 3 | #include 4 | 5 | typedef struct rb_red_blk_node { 6 | void* key; 7 | void* info; 8 | int red; /* if red=0 then the node is black */ 9 | struct rb_red_blk_node* left; 10 | struct rb_red_blk_node* right; 11 | struct rb_red_blk_node* parent; 12 | } rb_red_blk_node; 13 | 14 | 15 | /* Compare(a,b) should return 1 if *a > *b, -1 if *a < *b, and 0 otherwise */ 16 | /* Destroy(a) takes a pointer to whatever key might be and frees it accordingly */ 17 | typedef struct rb_red_blk_tree { 18 | int (*Compare)(const void* a, const void* b); 19 | void (*DestroyKey)(void* a); 20 | void (*DestroyInfo)(void* a); 21 | void (*PrintKey)(const void* a); 22 | void (*PrintInfo)(void* a); 23 | /* A sentinel is used for root and for nil. These sentinels are */ 24 | /* created when RBTreeCreate is caled. root->left should always */ 25 | /* point to the node which is the root of the tree. nil points to a */ 26 | /* node which should always be black but has aribtrary children and */ 27 | /* parent and no key or info. The point of using these sentinels is so */ 28 | /* that the root and nil nodes do not require special cases in the code */ 29 | rb_red_blk_node* root; 30 | rb_red_blk_node* nil; 31 | } rb_red_blk_tree; 32 | 33 | rb_red_blk_tree* RBTreeCreate(int (*CompFunc)(const void*, const void*), 34 | void (*DestFunc)(void*), 35 | void (*InfoDestFunc)(void*), 36 | void (*PrintFunc)(const void*), 37 | void (*PrintInfo)(void*)); 38 | rb_red_blk_node * RBTreeInsert(rb_red_blk_tree*, void* key, void* info); 39 | void RBTreePrint(rb_red_blk_tree*); 40 | void RBDelete(rb_red_blk_tree* , rb_red_blk_node* ); 41 | void RBTreeDestroy(rb_red_blk_tree*); 42 | rb_red_blk_node* TreePredecessor(rb_red_blk_tree*,rb_red_blk_node*); 43 | rb_red_blk_node* TreeSuccessor(rb_red_blk_tree*,rb_red_blk_node*); 44 | rb_red_blk_node* RBExactQuery(rb_red_blk_tree*, void*); 45 | void NullFunction(void*); 46 | void TreeForEach(rb_red_blk_tree *tree, void (*Func)(void*), rb_red_blk_node *x); 47 | void TreeForEach1p(rb_red_blk_tree *tree, void (*Func)(void*,void*), void *param, rb_red_blk_node *x); 48 | #endif -------------------------------------------------------------------------------- /sandbird/sandbird.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 rxi 3 | * 4 | * This library is free software; you can redistribute it and/or modify it 5 | * under the terms of the MIT license. See LICENSE for details. 6 | */ 7 | 8 | 9 | #ifndef SANDBIRD_H 10 | #define SANDBIRD_H 11 | 12 | #include 13 | #include 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #define SB_VERSION "0.1.3" 20 | 21 | typedef struct sb_Server sb_Server; 22 | typedef struct sb_Stream sb_Stream; 23 | typedef struct sb_Event sb_Event; 24 | typedef struct sb_Options sb_Options; 25 | typedef int (*sb_Handler)(sb_Event*); 26 | 27 | struct sb_Event { 28 | int type; 29 | void *udata; 30 | sb_Server *server; 31 | sb_Stream *stream; 32 | const char *address; 33 | const char *method; 34 | const char *path; 35 | }; 36 | 37 | struct sb_Options { 38 | sb_Handler handler; 39 | void *udata; 40 | const char *host; 41 | const char *port; 42 | const char *timeout; 43 | const char *max_lifetime; 44 | const char *max_request_size; 45 | }; 46 | 47 | enum { 48 | SB_ESUCCESS = 0, 49 | SB_EFAILURE = -1, 50 | SB_EOUTOFMEM = -2, 51 | SB_ETRUNCATED = -3, 52 | SB_EBADSTATE = -4, 53 | SB_EBADRESULT = -5, 54 | SB_ECANTOPEN = -6, 55 | SB_ENOTFOUND = -7, 56 | SB_EFDTOOBIG = -8 57 | }; 58 | 59 | enum { 60 | SB_EV_CONNECT, 61 | SB_EV_CLOSE, 62 | SB_EV_REQUEST 63 | }; 64 | 65 | enum { 66 | SB_RES_OK, 67 | SB_RES_CLOSE 68 | }; 69 | 70 | const char *sb_error_str(int code); 71 | sb_Server *sb_new_server(const sb_Options *opt); 72 | void sb_close_server(sb_Server *srv); 73 | int sb_poll_server(sb_Server *srv, int timeout); 74 | int sb_send_status(sb_Stream *st, int code, const char *msg); 75 | int sb_send_header(sb_Stream *st, const char *field, const char *val); 76 | int sb_send_file(sb_Stream *st, const char *filename); 77 | int sb_write(sb_Stream *st, const void *data, size_t len); 78 | int sb_vwritef(sb_Stream *st, const char *fmt, va_list args); 79 | int sb_writef(sb_Stream *st, const char *fmt, ...); 80 | int sb_get_header(sb_Stream *st, const char *field, char *dst, size_t len); 81 | int sb_get_var(sb_Stream *st, const char *name, char *dst, size_t len); 82 | int sb_get_cookie(sb_Stream *st, const char *name, char *dst, size_t len); 83 | const void *sb_get_multipart(sb_Stream *st, const char *name, size_t *len); 84 | 85 | #ifdef __cplusplus 86 | } // extern "C" 87 | #endif 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /cmd_listapps.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include"cfutil.h" 5 | #include"uclop.h" 6 | #include"service.h" 7 | 8 | static ucmd *g_cmd = NULL; 9 | void runListApps( void *device ); 10 | void run_listapps( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runListApps ); } 11 | 12 | CFDictionaryRef getAppInfo( void *device, char *bi ) { 13 | CFDictionaryRef res; 14 | 15 | AMDeviceLookupApplications( device, genmap( 6, 16 | "ApplicationType", CFSTR("Any"), 17 | "ReturnAttributes", boolcf(1), 18 | "ShowLaunchProhibitedApps", boolcf(1) 19 | ), &res ); 20 | 21 | int keyCnt = CFDictionaryGetCount( res ); 22 | CFTypeRef *keysTypeRef = (CFTypeRef *) malloc( keyCnt * sizeof(CFTypeRef) ); 23 | CFDictionaryGetKeysAndValues( res, (const void **) keysTypeRef, NULL); 24 | const void **keys = (const void **) keysTypeRef; 25 | uint8_t found = 0; 26 | for( int i=0;i Browse ? 45 | // Entitlements."com.apple.developer.team-identifier" 46 | // SignerIdentity 47 | AMDeviceLookupApplications( device, genmap( 6, 48 | "ApplicationType", CFSTR("Any"), 49 | "ReturnAttributes", boolcf(1), 50 | "ShowLaunchProhibitedApps", boolcf(1) 51 | ), &res ); 52 | 53 | devDown( device ); 54 | 55 | char *bi = ucmd__get( g_cmd, "-bi" ); 56 | if( bi ) { 57 | int keyCnt = CFDictionaryGetCount( res ); 58 | CFTypeRef *keysTypeRef = (CFTypeRef *) malloc( keyCnt * sizeof(CFTypeRef) ); 59 | CFDictionaryGetKeysAndValues( res, (const void **) keysTypeRef, NULL); 60 | const void **keys = (const void **) keysTypeRef; 61 | uint8_t found = 0; 62 | for( int i=0;i 5 | #include 6 | #include 7 | //#include"cfutil.h" 8 | 9 | uint8_t *cf2archive( CFTypeRef cf, int *len, char secure ) { 10 | //@autoreleasepool { 11 | id object = (__bridge id)cf; 12 | //NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object]; 13 | 14 | NSData *data; 15 | if( 1 ) {//secure ) { 16 | data = [NSKeyedArchiver archivedDataWithRootObject:( (__bridge id) cf ) requiringSecureCoding:true error:nil]; 17 | } 18 | else { 19 | data = [NSKeyedArchiver archivedDataWithRootObject:( (__bridge id) cf ) requiringSecureCoding:false error:nil]; 20 | } 21 | if( !data ) { 22 | fprintf(stderr,"Could not code with NSKeyedArchiver\n"); 23 | exit(1); 24 | } 25 | *len = [data length]; 26 | //printf("Archived length: %i\n", *len ); 27 | 28 | return (uint8_t *) [data bytes]; 29 | //} 30 | } 31 | 32 | CFTypeRef archive2cf( const uint8_t *bytes, uint32_t len ) { 33 | if( bytes[0] != 'b' || bytes[1] != 'p' ) { 34 | int i = 0; 35 | for( i=0;i 5 | #include"bytearr.h" 6 | #include 7 | #include"services.h" 8 | #include"service.h" 9 | #include"uclop.h" 10 | #include"cfutil.h" 11 | 12 | static ucmd *g_cmd = NULL; 13 | void runSysmon( void *device ); 14 | void run_sysmon( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runSysmon ); } 15 | 16 | void runSysmon( void *device ) { 17 | if( !desired_device( device, g_cmd ) ) return; 18 | serviceT *service = service__new_instruments( device ); 19 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.sysmontap" ); 20 | 21 | //CFTypeRef msg = NULL; 22 | tBASE *msg = NULL; 23 | 24 | tARR *procAttrs = tARR__newStrs( 14, 25 | "memVirtualSize", "cpuUsage", "memRShrd", "memCompressed", 26 | "cpuTotalSystem", "physFootprint", "cpuTotalUser", "memResidentSize", 27 | "memRPrvt", "threadCount", "memAnon", "diskBytesWritten", 28 | "faults", "pid" 29 | ); 30 | 31 | tARR *sysAttrs = tARR__newStrs( 1, "threadCount" ); 32 | 33 | tDICT *dict = tDICT__newPairs( 10, 34 | "ur", tI32__new( 1000 ), 35 | "bm", tI32__new( 0 ), 36 | "procAttrs", procAttrs, 37 | "cpuUsage", tBOOL__new( 0 ), 38 | "sampleInterval", tI32__new( 1000000000 ) 39 | //"pids", tARR__newVals( 1, tI32__new( 50895 ) ) 40 | ); 41 | /*CFDictionaryRef dict = genmap( 10, 42 | "ur", i16cf( 1000 ), 43 | "bm", i16cf( 0 ), 44 | "procAttrs", procAttrs, 45 | //"sysAttrs", NULL,//sysAttrs, 46 | "cpuUsage", kCFBooleanFalse, 47 | "sampleInterval", i32cf( 1000000000 ) 48 | //"pids", genarr( 1, i16cf( 50906 ) ) 49 | );*/ 50 | 51 | tARR *args = tARR__new(); 52 | tARR__add( args, dict ); 53 | 54 | if( !channel__send( chan, "setConfig:", (tBASE *) args, 0 ) ) { 55 | fprintf( stderr, "setConfig failed\n" ); 56 | return; 57 | } 58 | 59 | if( 60 | !channel__call( chan, 61 | "start", 0, 0, 62 | &msg, NULL 63 | ) 64 | ) { 65 | fprintf( stderr, "start failed\n" ); 66 | return; 67 | } 68 | 69 | for( int i=0;i<8; ) { 70 | if( !channel__recv( chan, &msg, NULL ) ) { 71 | fprintf( stderr, "recvDtx failed\n" ); 72 | return; 73 | } 74 | 75 | if( msg ) { 76 | //cfdump( 1, CFArrayGetValueAtIndex( msg, 0 ) ); 77 | tBASE__dump( msg, 1 ); 78 | i++; 79 | } 80 | else sleep(1); 81 | } 82 | 83 | if( !channel__send( chan, "stop", 0, 0 ) ) { 84 | fprintf( stderr, "stop failed\n" ); 85 | return; 86 | } 87 | 88 | service__del( service ); 89 | exit(0); 90 | } -------------------------------------------------------------------------------- /archiver/types.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __ATYPES_H 5 | #define __ATYPES_H 6 | 7 | #include 8 | 9 | #define xfI8 1 10 | #define xfI16 2 11 | #define xfI32 3 12 | #define xfSTR 4 13 | #define xfARR 5 14 | #define xfDICT 6 15 | #define xfARCID 7 16 | #define xfOBS 8 17 | #define xfREF 9 18 | #define xfBOOL 10 19 | #define xfNULL 11 20 | #define xfI64 12 21 | #define xfTIME 13 22 | #define xfF1 14 23 | #define xfF2 15 24 | #define xfDATA 16 25 | #define xfUUID 17 26 | #define xfCAPS 18 27 | #define xfURL 19 28 | #define xfTESTCONF 20 29 | 30 | struct tBASE_t { 31 | uint8_t type; 32 | struct tBASE_t *next; 33 | }; 34 | typedef struct tBASE_t tBASE; 35 | 36 | #define BASEINFO uint8_t type; tBASE *next; 37 | typedef struct { 38 | BASEINFO 39 | uint8_t val; 40 | } tI8; 41 | 42 | typedef struct { 43 | BASEINFO 44 | uint16_t val; 45 | } tI16; 46 | 47 | typedef struct { 48 | BASEINFO 49 | int32_t val; 50 | } tI32; 51 | 52 | typedef struct { 53 | BASEINFO 54 | int64_t val; 55 | } tI64; 56 | 57 | typedef struct { 58 | BASEINFO 59 | float val; 60 | } tF1; 61 | 62 | typedef struct { 63 | BASEINFO 64 | double val; 65 | } tF2; 66 | 67 | typedef struct { 68 | BASEINFO 69 | uint8_t *val; 70 | uint32_t len; 71 | } tDATA; 72 | 73 | typedef struct { 74 | BASEINFO 75 | double val; 76 | } tTIME; 77 | 78 | typedef struct { 79 | BASEINFO 80 | const char *val; 81 | } tSTR; 82 | 83 | typedef struct { 84 | BASEINFO 85 | uint16_t count; 86 | tBASE *head; 87 | tBASE *tail; 88 | } tARR; 89 | 90 | typedef struct { 91 | BASEINFO 92 | uint8_t len; 93 | tBASE *head; 94 | tBASE *tail; 95 | int num; 96 | } tOBS; 97 | 98 | struct tOFF_t { 99 | struct tOFF_t *next; 100 | uint16_t offset; 101 | }; 102 | typedef struct tOFF_t tOFF; 103 | 104 | typedef struct { 105 | uint16_t len; 106 | tOFF *head; 107 | tOFF *tail; 108 | int num; 109 | } tOFFS; 110 | 111 | typedef struct { 112 | BASEINFO 113 | int count; 114 | tBASE *keyHead; 115 | tBASE *keyTail; 116 | tBASE *valHead; 117 | tBASE *valTail; 118 | } tDICT; 119 | 120 | typedef struct { 121 | BASEINFO 122 | tDICT *dict; 123 | } tCAPS; 124 | 125 | typedef struct { 126 | BASEINFO 127 | tDICT *dict; 128 | } tTESTCONF; 129 | 130 | typedef struct { 131 | uint8_t type; 132 | tBASE *next; 133 | uint32_t val; 134 | } tARCID; 135 | 136 | typedef struct { 137 | BASEINFO 138 | tBASE *val; 139 | } tREF; 140 | 141 | typedef struct { 142 | BASEINFO 143 | uint8_t val; 144 | } tBOOL; 145 | 146 | typedef struct { 147 | BASEINFO 148 | } tNULL; 149 | 150 | typedef struct { 151 | BASEINFO 152 | uint8_t val[16]; 153 | } tUUID; 154 | 155 | typedef struct { 156 | BASEINFO 157 | char *relative; 158 | } tURL; 159 | 160 | #endif -------------------------------------------------------------------------------- /service.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #ifndef __SERVICE_H 5 | #define __SERVICE_H 6 | 7 | #include 8 | #include"mobiledevice.h" 9 | #include"mobdev_err.h" 10 | #include"uclop.h" 11 | #include"archiver/archiver.h" 12 | 13 | typedef struct { 14 | int nextChanId; 15 | void *service; 16 | char secure; 17 | //CFDictionaryRef channels; 18 | tDICT *channels; 19 | } serviceT; 20 | 21 | typedef struct { 22 | int nextMsgId; 23 | void *service; 24 | char secure; 25 | int channel; 26 | serviceT *serviceOb; 27 | } channelT; 28 | 29 | #define SEND_HASREPLY 1 30 | #define SEND_SECUREARG 2 31 | 32 | serviceT *service__new( void *device, char *name, char *secureName ); 33 | channelT *service__connect_channel( serviceT *service, char *name ); 34 | channelT *service__connect_channel_int( serviceT *service, char *name, char skipRecv ); 35 | channelT *channel__connect_channel_int( channelT *channel, char *name, char skipRecv ); 36 | char service__handshake( serviceT *self ); 37 | char channel__handshake( channelT *self ) ; 38 | char service__handshake2( serviceT *self ); 39 | 40 | channelT *channel__new( void *service, char secure, int id ); 41 | char channel__send( channelT *chan, const char *method, tBASE *args, uint8_t flags ); 42 | char channel__send_withid( channelT *self, const char *method, tBASE *args, uint8_t flags, uint32_t id ); 43 | char channel__reply( channelT *self, tBASE *argsT, uint32_t id, int convIndex ); 44 | 45 | //char channel__recv( channelT *self, CFTypeRef *msgOut, CFArrayRef *argOut ); 46 | char channel__recv( channelT *self, tBASE **msgOut, tARR **argOut ); 47 | char channel__recv_withid( channelT *self, tBASE **msgOut, tARR **argOut, int *idout, int *convIndexOut, int *channeOut ); 48 | 49 | //char channel__call( channelT *chan, const char *method, tBASE *args, 50 | // uint8_t flags, CFTypeRef *msgOut, CFArrayRef *auxOut ); 51 | char channel__call( channelT *chan, const char *method, tBASE *args, 52 | uint8_t flags, tBASE **msgOut, tARR **auxOut ); 53 | 54 | //char service__send( serviceT *self, CFTypeRef msg, tBASE *aux, uint8_t flags ); 55 | char service__send( serviceT *self, char *msg, tBASE *ux, uint8_t flags ); 56 | 57 | //char service__recv( serviceT *self, CFTypeRef *msg, CFArrayRef *aux ); 58 | char service__recv( serviceT *self, tBASE **msg, tARR **aux ); 59 | 60 | //char service__call( serviceT *self, 61 | // const char *method, tBASE *args, uint8_t flags, 62 | // CFTypeRef *msgOut, CFArrayRef *auxOut ); 63 | char service__call( serviceT *self, 64 | const char *method, tBASE * args, uint8_t flags, 65 | tBASE **msgOut, tARR **auxOut ); 66 | 67 | void service__del( serviceT *self ); 68 | 69 | void devUp( void *device ); 70 | 71 | void devDown( void *device ); 72 | 73 | void exitOnError( int rc, const char *src ); 74 | 75 | void waitForConnect( void (*onConnect)(void *device) ); 76 | void waitForConnectDisconnect( void (*onConnect)(void *device), void (*onDisconnect)(void *device) ); 77 | 78 | void setupTimeout( int seconds ); 79 | 80 | char desired_device( void *device, ucmd *g_cmd ); 81 | #endif -------------------------------------------------------------------------------- /cmd_mg.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include"cfutil.h" 7 | #include"uclop.h" 8 | #include"mobiledevice.h" 9 | #include"service.h" 10 | #include"services.h" 11 | 12 | static ucmd *g_cmd = NULL; 13 | void runMg( void *device ); 14 | void run_mg( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runMg ); } 15 | 16 | CFDictionaryRef runMgRaw( void *device, CFArrayRef keys ) { 17 | void *diagService = activateDiagService( device ); 18 | 19 | CFDictionaryRef plist = genmap( 4, 20 | "Request", CFSTR("MobileGestalt"), 21 | "MobileGestaltKeys", keys 22 | ); 23 | 24 | exitOnError( 25 | AMDServiceConnectionSendMessage( diagService, plist, kCFPropertyListXMLFormat_v1_0 ), 26 | "Send X" ); 27 | 28 | CFDictionaryRef info = NULL; 29 | exitOnError( 30 | AMDServiceConnectionReceiveMessage( diagService, &info, nil ), 31 | "Request Receive" ); 32 | 33 | CFStringRef status = CFDictionaryGetValue( info, CFSTR("Status") ); 34 | if( !status ) { 35 | printf("Failure; did not get status back\n"); 36 | exit(1); 37 | } 38 | char *statc = str_cf2c( status ); 39 | if( strcmp( statc, "Success" ) ) { 40 | printf("Failure:%s\n", statc); 41 | exit(1); 42 | } 43 | 44 | CFDictionaryRef diag = CFDictionaryGetValue( info, CFSTR("Diagnostics") ); 45 | if( !diag ) { 46 | printf("No Diagnostics node in result\n"); 47 | exit(1); 48 | } 49 | 50 | CFDictionaryRef mg = CFDictionaryGetValue( diag, CFSTR("MobileGestalt") ); 51 | if( !mg ) { 52 | printf("No Diagnostics.MobileGestalt in result\n"); 53 | exit(1); 54 | } 55 | 56 | return mg; 57 | } 58 | 59 | void runMg( void *device ) { 60 | CFStringRef udidCf = AMDeviceCopyDeviceIdentifier( device ); 61 | char *udid = str_cf2c( udidCf ); 62 | char *goalUdid = ucmd__get( g_cmd, "-id" ); 63 | if( goalUdid && strcmp( udid, goalUdid ) ) return; 64 | 65 | char useJson = ucmd__get( g_cmd, "-json" ) ? 1 : 0; 66 | 67 | int count = g_cmd->argc; 68 | 69 | char *defaultNames[] = { "UniqueDeviceID","main-screen-width","main-screen-height" }; 70 | char **namesC; 71 | if( count == 0 ) { 72 | count = 3; 73 | namesC = defaultNames; 74 | } 75 | else namesC = g_cmd->argv; 76 | 77 | CFArrayRef names = strsToArr( count, namesC ); 78 | 79 | CFDictionaryRef mg = runMgRaw( device, names ); 80 | 81 | if( useJson ) printf("{\n"); 82 | for( int i=0;iargc;i++ ) { 27 | char *name = strdup(g_cmd->argv[i]); 28 | char *dom = NULL; 29 | char *name2 = name; 30 | for( int j=0;1;j++ ) { 31 | char let = name[j]; 32 | if( !let ) break; 33 | if( let == ':' ) { 34 | name[j] = 0x00; 35 | dom = name; 36 | name2 = &name[j+1]; 37 | } 38 | } 39 | //printf("Dom=%s Name=%s\n", dom, name2 ); 40 | CFTypeRef val = AMDeviceCopyValue( device, dom ? str_c2cf( dom ) : NULL, (name2[0]==0)?NULL:str_c2cf(name2) ); 41 | if( val ) { 42 | if( useJson ) { 43 | printf("%s:",name); 44 | cfdump( 1, val ); 45 | if( i != g_cmd->argc-1 ) { 46 | printf(",\n"); 47 | } 48 | } 49 | else { 50 | if( g_cmd->argc>1) printf("%s:",name); 51 | cfdump( 1, val ); 52 | } 53 | } 54 | free( name ); 55 | } 56 | if( useJson ) printf("}\n"); 57 | 58 | devDown( device ); 59 | 60 | exit(0); 61 | } 62 | 63 | iosVersion getIosVersion( void *device ) { 64 | iosVersion version = {0,0,0}; 65 | 66 | devUp( device ); 67 | CFTypeRef val = AMDeviceCopyValue( device, NULL, str_c2cf( "ProductVersion" ) ); 68 | devDown( device ); 69 | 70 | //cfdump( 1, val ); 71 | char *vStr = str_cf2c( val ); 72 | 73 | //printf("Raw ios version:%s\n", vStr ); 74 | int dots[3] = {0,0,0}; 75 | int dotI = 0; 76 | for( int i=0;i 11 | 44 | 45 | END 46 | 47 | my $xmlfile = $ARGV[0]; 48 | #print "File:$xmlfile\n"; 49 | 50 | my ( $ob, $root ) = XML::Bare->new( file => $xmlfile ); 51 | 52 | my $msgs = forcearray $root->{msg}; 53 | 54 | sub noteAcked { 55 | my ( $msgs, $startI, $wantId, $dirWant ) = @_; 56 | for( my $i=$startI;$i>=0;$i-- ) { 57 | my $msg = $msgs->[ $i ]; 58 | my $id = $msg->{id}{value}; 59 | if( $id eq $wantId ) { 60 | $msg->{acked} = 1; 61 | return 1; 62 | } 63 | } 64 | return 0; 65 | } 66 | 67 | my $i = 0; 68 | for my $msg ( @$msgs ) { 69 | my $id = $msg->{id}{value}; 70 | 71 | my $id1; 72 | my $id2; 73 | my $id3; 74 | if( $id =~ m/(.+)\.(.+)\.(.+)/ ) { 75 | $id1 = $1; 76 | $id2 = $2; 77 | $id3 = $3; 78 | } else { 79 | next; 80 | } 81 | my $rid3 = $id3-1; 82 | my $findId = "$id1.$id2.$rid3"; 83 | 84 | my $type = $msg->{type}{value}; 85 | if( $type eq 'ack' ) { 86 | #print "Looking for $findId\n"; 87 | my $dirWant = "in"; 88 | my $acked = noteAcked( $msgs, $i-1, $findId, $dirWant ); 89 | $msg->{done} = 1 if( $acked ); 90 | } 91 | if( $type eq 'rack' ) { 92 | #print "Looking for $findId\n"; 93 | my $dirWant = "out"; 94 | my $acked = noteAcked( $msgs, $i-1, $findId, $dirWant ); 95 | $msg->{done} = 1 if( $acked ); 96 | } 97 | $i++; 98 | } 99 | 100 | for my $msg ( @$msgs ) { 101 | next if( $msg->{done} ); 102 | my $type = $msg->{type}{value}; 103 | my $dir = $msg->{dir} ? $msg->{dir}{value} : 0; 104 | if( $type eq 'ack' ) { $dir = "out"; } 105 | if( $type eq 'rack' ) { $dir = "in"; } 106 | my $id = $msg->{id}{value}; 107 | my $itype = $msg->{itype} ? $msg->{itype}{value} : 0; 108 | 109 | my $msgt = $msg->{msg} ? $msg->{msg}{value} : ""; 110 | if( $msgt =~ m/^"(.+)"$/ ) { 111 | $msgt = $1; 112 | } 113 | #if( $msgt =~ m/(.+)\n$/ ) { 114 | # $msgt = $1; 115 | #} 116 | 117 | print "
$type $dir $id\n"; 118 | if( $msgt ) { print "
$msgt

\n"; } 119 | if( $msg->{acked} ) { print "ACKED
"; } 120 | 121 | if( $msg->{arg} ) { 122 | my $args = forcearray $msg->{arg}; 123 | #print "Args:\n"; 124 | for my $argn ( @$args ) { 125 | my $arg = $argn->{value}; 126 | if( $arg =~ m/^"(.+)\n?"$/ ) { 127 | $arg = $1; 128 | } 129 | if( $arg =~ m/(.+)\n$/s ) { 130 | $arg = $1; 131 | } 132 | print "
$arg

\n"; 133 | } 134 | } 135 | 136 | print "

\n"; 137 | } -------------------------------------------------------------------------------- /cmd_bytetest.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include"uclop.h" 5 | #include"service.h" 6 | //#include"nsutil.h" 7 | #include"cfutil.h" 8 | #include"archiver/archiver.h" 9 | #include"archiver/unarchiver.h" 10 | 11 | static ucmd *g_cmd = NULL; 12 | void runBytetest( void *device ); 13 | void run_bytetest( ucmd *cmd ) { 14 | //g_cmd = cmd; 15 | //waitForConnect( runBytetest ); 16 | runBytetest( 0 ); 17 | } 18 | 19 | void runBytetest( void *device ) { 20 | /*{ 21 | CFArrayRef arr = genarr( 2, i8cf( 1 ), str_c2cf( "two" ) ); 22 | int len; 23 | uint8_t *data = cf2archive( arr, &len, 0 ); 24 | CFTypeRef root = data2plist( data, len ); 25 | cfdump( 1, root ); 26 | }*/ 27 | 28 | /*{ 29 | //CFArrayRef arr = genarr( 1, kCFBooleanTrue ); 30 | int len; 31 | //CFDictionaryRef arr = genmap( 2, "a", i8cf( -2 ) ); 32 | 33 | #define NN 300 34 | char str[NN]; 35 | memset( str, 'x', NN ); 36 | str[NN-1] = 0x00; 37 | CFArrayRef arr = genarr( 2, i8cf( 1 ), str_c2cf( str ) ); 38 | uint8_t *data = cf2archive( arr, &len, 0 ); 39 | //printf("%.*s\n", len, data ); 40 | CFTypeRef root = data2plist( data, len ); 41 | cfdump( 1, root ); 42 | 43 | //bpList *list = bpList__new( data, len ); 44 | //tBASE *rootT = (tBASE *) list->obs->ptr[ 0 ] 45 | //tBASE__dump( rootT, 1 ); 46 | 47 | tBASE *clean = dearchive( data, len ); 48 | tBASE__dump( clean, 1 ); 49 | }*/ 50 | 51 | /*{ 52 | CFDictionaryRef arr = genmap( 2, "a", i8cf( 1 ) ); 53 | int len; 54 | uint8_t *data = cf2archive( arr, &len, 0 ); 55 | CFTypeRef root = data2plist( data, len ); 56 | cfdump( 1, root ); 57 | */ 58 | 59 | /*{ 60 | tSTR *str = tSTR__new("test"); 61 | 62 | uint32_t len; 63 | char *bytes = (char *) tBASE__archive( (tBASE *) str, &len ); 64 | printf("%s", bytes ); 65 | } 66 | { 67 | tARR *arr = tARR__new(); 68 | tARR__addI32( arr, 1 ); 69 | tARR__addSTR( arr, "two" ); 70 | 71 | uint32_t len; 72 | char *bytes = (char *) tBASE__archive( (tBASE *) arr, &len ); 73 | printf("%s", bytes ); 74 | 75 | tBASE__del( arr ); 76 | } 77 | { 78 | tDICT *dict = tDICT__newPairs( 4, 79 | "first", (tBASE *) tI32__new( 1 ), 80 | "2nd", (tBASE *) tSTR__new( "two" ) 81 | ); 82 | tBASE__dump( (tBASE *) dict, 1 ); 83 | 84 | uint32_t len; 85 | char *bytes = (char *) tBASE__archive( (tBASE *) dict, &len ); 86 | printf("%s", bytes ); 87 | }*/ 88 | //dumparchive( data, len ); 89 | 90 | /*bytearr *msgb = bytearr__new(); 91 | 92 | uint8_t bytes[] = { 1,2,3,4 }; 93 | bytearr__append( msgb, bytes, 4, 0 ); 94 | 95 | int msgLen; 96 | uint8_t *msgBytes = bytearr__bytes( msgb, &msgLen ); 97 | 98 | uint32_t crc = crc32(0,(const char *) msgBytes,msgLen); 99 | printf("%08x", crc ); 100 | printf("\n"); 101 | for( int i=0;i 8 | //extern void AMDSetLogLevel(int level); 9 | extern int AMDeviceConnect( void *device ); 10 | extern int AMDeviceDisconnect( void *device ); 11 | extern int AMDeviceValidatePairing( void *device ); 12 | extern int AMDeviceStartSession( void *device ); 13 | extern int AMDeviceStopSession( void *device ); 14 | unsigned int AMDeviceGetConnectionID( void *device ); 15 | extern CFStringRef AMDeviceCopyDeviceIdentifier( void *device ); 16 | 17 | extern int AMDeviceStartService( void *device, CFStringRef service_name, void *handle); 18 | extern int AMDeviceSecureStartService( void *device, CFStringRef serviceName, CFDictionaryRef flags, void *handle); 19 | extern int AMDeviceNotificationSubscribe( void *device, int , int , int, void ** ); 20 | extern CFTypeRef AMDeviceCopyValue( void *device, CFStringRef domain, CFStringRef cfstring ); 21 | 22 | extern int AMDServiceConnectionReceiveMessage( void *service, CFPropertyListRef message, CFPropertyListFormat *format ); 23 | extern int AMDServiceConnectionReceive( void *service, char *buf, size_t size ); 24 | extern int AMDServiceConnectionSendMessage( void *service, CFPropertyListRef message, CFPropertyListFormat format); 25 | extern int AMDServiceConnectionSend( void *service, const void *message, size_t length); 26 | extern int AMDServiceConnectionGetSocket( void *service ); 27 | //extern ??? AMDServiceConnectionGetSecureIOContext( void *service ); 28 | extern int AMDServiceConnectionInvalidate( void *service ); 29 | 30 | extern int AMDeviceSecureTransferPath( int, void *device, CFURLRef, CFDictionaryRef, void *, int); 31 | extern int AMDeviceSecureInstallApplication( int, void *device, CFURLRef, CFDictionaryRef, void *, int); 32 | extern int AMDeviceSecureUninstallApplication( void *service, void * dunno, CFStringRef bundleIdentifier, CFDictionaryRef params, void (*installCallback)(CFDictionaryRef, void *)); 33 | //extern int AMDeviceSecureInstallApplicationBundle(void *device, CFURLRef, CFDictionaryRef params, void (*installCallback)(CFDictionaryRef, void *)); 34 | 35 | extern int AMDeviceLookupApplications( void *device, CFDictionaryRef options, CFDictionaryRef *dictOut ); 36 | 37 | extern int AMDeviceCreateHouseArrestService(void *device, CFStringRef bundleIDRef, CFDictionaryRef optionsRef, void **ptr); 38 | 39 | extern int AFCFileRefOpen( void *afc, const char *path, unsigned long long mode, unsigned long long *ref); 40 | extern int AFCFileRefSeek( void *afc, unsigned long long ref, unsigned long long offset1, unsigned long long offset2); 41 | extern int AFCFileRefRead( void *afc, unsigned long long ref, void *buf, size_t *len); 42 | extern int AFCFileRefSetFileSize( void *afc, unsigned long long ref, unsigned long long offset); 43 | extern int AFCFileRefWrite( void *afc, unsigned long long ref, const void *buf, size_t len); 44 | extern int AFCFileRefClose( void *afc, unsigned long long ref); 45 | 46 | typedef struct muxListenIn_s muxListenIn; 47 | typedef struct muxListenOut_s muxListenOut; 48 | struct muxListenIn_s { 49 | unsigned int x0; 50 | unsigned char *x1; 51 | void *callback; // _AMDDeviceAttached 52 | unsigned int x3; 53 | unsigned int x4; 54 | unsigned int x5; 55 | }; 56 | struct muxListenOut_s { 57 | unsigned char x0[4144]; 58 | }; 59 | extern int USBMuxConnectByPort( int connectionID, int netBytesOrder, int *outHandle ); 60 | extern unsigned int USBMuxListenerCreate( muxListenIn *in, muxListenOut **out ); 61 | extern unsigned int USBMuxListenerHandleData( void * ); 62 | 63 | typedef struct AMDeviceNotificationCallbackInformation { 64 | void *device; 65 | uint32_t type; // ADNCI_MSG_ 66 | } noticeInfo; 67 | #endif -------------------------------------------------------------------------------- /cmd_ioreg.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include"service.h" 7 | #include"services.h" 8 | #include"cfutil.h" 9 | #include"uclop.h" 10 | 11 | static ucmd *g_cmd = NULL; 12 | void runIoreg( void *device ); 13 | void runBattery( void *device ); 14 | 15 | void run_ioreg( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runIoreg ); } 16 | void run_battery( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runBattery ); } 17 | 18 | void runIoreg( void *device ) { 19 | if( g_cmd->argc < 1 ) { 20 | fprintf(stderr, "Must specify ioreg key to query\n" ); 21 | exit(1); 22 | } 23 | 24 | void *diagService = activateDiagService( device ); 25 | 26 | CFStringRef keyCf = str_c2cf( g_cmd->argv[0] ); 27 | CFDictionaryRef plist = genmap( 4, 28 | "Request", CFSTR("IORegistry"), 29 | "EntryName", keyCf 30 | ); 31 | 32 | exitOnError( 33 | AMDServiceConnectionSendMessage( diagService, plist, kCFPropertyListXMLFormat_v1_0 ), 34 | "Send X" ); 35 | 36 | CFDictionaryRef info = NULL; 37 | exitOnError( 38 | AMDServiceConnectionReceiveMessage( diagService, &info, nil ), 39 | "Request Receive" ); 40 | 41 | cfdump( 1, info ); 42 | //printf("%s\n", cftype(info) ); 43 | //cf2json( info ); 44 | //CFPropertyListRef pl = xml2plist( str_cf2c( (CFStringRef) info ) ); 45 | //rintf("%s\n", str_cf2c( infoStr ) ); 46 | //printf("%s\n", cftype( pl ) ); 47 | //CFDictionaryRef dict = CFDictionaryGetValue( pl, CFSTR("IORegistry") ); 48 | //cfdump( 0, dict ); 49 | 50 | exit(0); 51 | } 52 | 53 | void runBattery( void *device ) { 54 | void *diagService = activateDiagService( device ); 55 | CFDictionaryRef plist = genmap( 4, 56 | "Request", CFSTR("IORegistry"), 57 | "EntryName", CFSTR("AppleARMPMUCharger") 58 | ); 59 | 60 | exitOnError( 61 | AMDServiceConnectionSendMessage( diagService, plist, kCFPropertyListXMLFormat_v1_0 ), 62 | "Send X" ); 63 | 64 | CFDictionaryRef info = NULL; 65 | exitOnError( 66 | AMDServiceConnectionReceiveMessage( diagService, &info, nil ), 67 | "Request Receive" ); 68 | 69 | CFDictionaryRef diag = cfmapget( info, "Diagnostics" ); 70 | CFDictionaryRef ioreg = cfmapget( diag, "IORegistry" ); 71 | 72 | int16_t temp = cfi16( cfmapget( ioreg, "Temperature" ) ); 73 | float tempC = (float) temp / (float) 100; 74 | float tempF = tempC * 9.0 / 5.0 + 32.0; 75 | printf( "Temperature: %.2f C / %.2f F\n", tempC, tempF ); 76 | 77 | int16_t voltage= cfi16( cfmapget( ioreg, "Voltage" ) ); 78 | float voltageF = (float) voltage / (float) 1000; 79 | printf( "Voltage: %.3f V\n", voltageF ); 80 | 81 | int16_t cycles = cfi16( cfmapget( ioreg, "CycleCount" ) ); 82 | printf("Cycle Count: %d\n", cycles ); 83 | 84 | int16_t curMah = cfi16( cfmapget( ioreg, "AppleRawCurrentCapacity" ) ); 85 | printf("Current Capacity: %d mAh\n", curMah ); 86 | 87 | int16_t maxMah = cfi16( cfmapget( ioreg, "AppleRawMaxCapacity" ) ); 88 | printf("Max Capacity: %d mAh\n", maxMah ); 89 | 90 | int16_t designMah = cfi16( cfmapget( ioreg, "DesignCapacity" ) ); 91 | printf("Design Capacity: %d mAh\n", designMah ); 92 | 93 | CFDictionaryRef batData = cfmapget( ioreg, "BatteryData" ); 94 | CFDictionaryRef lifeData = cfmapget( batData, "LifetimeData" ); 95 | 96 | int16_t opHours = cfi16( cfmapget( lifeData, "TotalOperatingTime" ) ); 97 | int8_t opHours1 = opHours % 24; 98 | opHours -= opHours1; 99 | int16_t opDays = opHours / 24; 100 | int16_t opDays1 = opDays % 365; 101 | opDays -= opDays1; 102 | int8_t opYears = opDays / 365; 103 | printf("Operating time: %d years, %d days, %d hours\n", opYears, opDays1, opHours1 ); 104 | 105 | char *serial = str_cf2c( cfmapget( ioreg, "Serial" ) ); 106 | printf("Serial: %s\n", serial ); 107 | 108 | //cfdump( 1, info ); 109 | //printf("%s\n", cftype(info) ); 110 | //cf2json( info ); 111 | //CFPropertyListRef pl = xml2plist( str_cf2c( (CFStringRef) info ) ); 112 | //rintf("%s\n", str_cf2c( infoStr ) ); 113 | //printf("%s\n", cftype( pl ) ); 114 | //CFDictionaryRef dict = CFDictionaryGetValue( pl, CFSTR("IORegistry") ); 115 | //cfdump( 0, dict ); 116 | 117 | exit(0); 118 | } -------------------------------------------------------------------------------- /cmd_file.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include"cfutil.h" 5 | #include"uclop.h" 6 | #include"service.h" 7 | #include"services.h" 8 | 9 | static ucmd *g_cmd = NULL; 10 | void runGetFile( void *device ); 11 | void run_getfile( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runGetFile ); } 12 | 13 | void *houseArrest( void *device, char *bi ) { 14 | void *conn = NULL; 15 | 16 | CFStringRef cfbi = str_c2cf( bi ); 17 | 18 | int err1 = AMDeviceCreateHouseArrestService( device, cfbi, 0, &conn ); 19 | if( err1 ) { 20 | //fprintf( stderr, "Err1\n" ); 21 | CFDictionaryRef args = genmap( 2, 22 | "Command", CFSTR("VendDocuments") ); 23 | 24 | int err2 = AMDeviceCreateHouseArrestService( device, cfbi, args, &conn ); 25 | if( err2 ) { 26 | mobdev_err *info = mobdev_geterr( err2 ); 27 | if( info ) { 28 | fprintf( stderr, "Error on x12: %s - %s\n", info->name, info->error ); 29 | } 30 | fprintf( stderr, "Err2: %d\n", err2 ); 31 | exit(0); 32 | } 33 | } 34 | 35 | return conn; 36 | } 37 | 38 | char writeDataToAppFile( void *device, char *bundleid, char *remoteFile, uint8_t *data, uint32_t len ) { 39 | devUp( device ); 40 | void *afc = houseArrest( device, bundleid ); 41 | devDown( device ); 42 | 43 | unsigned long long fhr; 44 | int err = AFCFileRefOpen( afc, remoteFile, O_WRONLY + 1, &fhr ); 45 | if( err ) { 46 | mobdev_err *info = mobdev_geterr( err ); 47 | if( info ) { 48 | fprintf( stderr, "Error on x: %s - %s\n", info->name, info->error ); 49 | } 50 | else { 51 | fprintf(stderr,"err other %d - %s\n", err, strerror( err ) ); 52 | } 53 | return 1; 54 | } 55 | 56 | AFCFileRefWrite( afc, fhr, data, len ); 57 | 58 | return 0; 59 | } 60 | 61 | char ulAppFile( void *device, char *bundleid, char *localFile, char *remoteFile ) { 62 | devUp( device ); 63 | void *afc = houseArrest( device, bundleid ); 64 | devDown( device ); 65 | 66 | unsigned long long fhr; 67 | int err = AFCFileRefOpen( afc, remoteFile, O_WRONLY + 1, &fhr ); 68 | if( err ) { 69 | mobdev_err *info = mobdev_geterr( err ); 70 | if( info ) { 71 | fprintf( stderr, "Error on x: %s - %s\n", info->name, info->error ); 72 | } 73 | else { 74 | fprintf(stderr,"err other %d - %s\n", err, strerror( err ) ); 75 | } 76 | return 1; 77 | } 78 | 79 | FILE *fhl; 80 | if( !strcmp( localFile, "-" ) ) { 81 | fhl = stdin; 82 | } 83 | else { 84 | fhl = fopen( localFile, "r" ); 85 | } 86 | 87 | if( !fhl ) { 88 | fprintf( stderr,"err %s\n", strerror( errno ) ); 89 | AFCFileRefClose( afc, fhr ); 90 | return 2; 91 | } 92 | 93 | char buffer[4096]; 94 | size_t bytesRead = 4096; 95 | 96 | while( 1 ) { 97 | bytesRead = fread( buffer, 1, 4096, fhl ); 98 | if( !bytesRead ) { 99 | AFCFileRefClose( afc, fhr ); 100 | fclose( fhl ); 101 | if( feof( fhl ) ) break; 102 | return 3; 103 | } 104 | AFCFileRefWrite( afc, fhr, buffer, bytesRead ); 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | char dlAppFile( void *device, char *bundleid, char *remoteFile, char *localFile ) { 111 | devUp( device ); 112 | void *afc = houseArrest( device, bundleid ); 113 | devDown( device ); 114 | 115 | unsigned long long fhr; 116 | int err = AFCFileRefOpen( afc, remoteFile, O_RDONLY + 1, &fhr ); 117 | if( err ) { 118 | mobdev_err *info = mobdev_geterr( err ); 119 | if( info ) { 120 | fprintf( stderr, "Error on x: %s - %s\n", info->name, info->error ); 121 | } 122 | else { 123 | fprintf(stderr,"err other %d - %s\n", err, strerror( err ) ); 124 | } 125 | return 1; 126 | } 127 | 128 | FILE *fhl = fopen( localFile, "w" ); 129 | 130 | if( !fhl ) { 131 | fprintf( stderr,"err %s\n", strerror( errno ) ); 132 | AFCFileRefClose( afc, fhr ); 133 | return 2; 134 | } 135 | 136 | char buffer[4096]; 137 | size_t bufSize = 4096; 138 | size_t bytesRead = 4096; 139 | 140 | while( 1 ) { 141 | int err = AFCFileRefRead( afc, fhr, buffer, &bytesRead ); 142 | if( !bytesRead ) break; 143 | fwrite( buffer, bytesRead, 1, fhl ); 144 | bytesRead = 4096; 145 | } 146 | 147 | AFCFileRefClose( afc, fhr ); 148 | fclose( fhl ); 149 | 150 | return 0; 151 | } 152 | 153 | void runGetFile( void *device ) { 154 | if( !desired_device( device, g_cmd ) ) return; 155 | 156 | char *remoteFile = g_cmd->argv[1]; 157 | char *localFile = g_cmd->argv[2]; 158 | char *bundleid = g_cmd->argv[0]; 159 | 160 | dlAppFile( device, bundleid, remoteFile, localFile ); 161 | 162 | exit(0); 163 | } 164 | 165 | -------------------------------------------------------------------------------- /cmd_process.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include"cfutil.h" 7 | #include"uclop.h" 8 | #include"mobiledevice.h" 9 | #include"service.h" 10 | #include"services.h" 11 | #include"cmd_process.h" 12 | 13 | static ucmd *g_cmd = NULL; 14 | void runLaunch( void *device ); 15 | void run_launch( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runLaunch ); } 16 | 17 | void runKill( void *device ); 18 | void run_kill( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runKill ); } 19 | 20 | void runTail( void *device ); 21 | void run_tail( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runTail ); } 22 | 23 | channelT *channel__new_processcontrol( void *device ) { 24 | serviceT *inst = service__new_instruments( device ); 25 | 26 | channelT *chan = service__connect_channel( inst, 27 | "com.apple.instruments.server.services.processcontrol" ); 28 | 29 | return chan; 30 | } 31 | 32 | void killPid( void *device, int64_t pid ) { 33 | tBASE *msg = NULL; 34 | 35 | channelT *chan = channel__new_processcontrol( device ); 36 | 37 | channel__call( chan, 38 | "killPid:", (tBASE *) tI32__new( pid ), 39 | 0, &msg, NULL 40 | ); 41 | if( !msg ) { 42 | //channel__del( chan ); 43 | exit(0); 44 | } 45 | 46 | tBASE__dump( msg, 1 ); 47 | } 48 | 49 | void startObserving( channelT *chan, int32_t pid ) { 50 | tBASE *msg = NULL; 51 | 52 | //channelT *chan = channel__new_processcontrol( device ); 53 | 54 | channel__send( chan, 55 | "startObservingPid:", (tBASE *) tI32__new( pid ), 56 | 0 //, &msg, NULL 57 | ); 58 | //if( !msg ) { 59 | // //channel__del( chan ); 60 | // exit(0); 61 | //} 62 | 63 | //tBASE__dump( msg, 1 ); 64 | } 65 | 66 | void runTail( void *device ) { 67 | if( !desired_device( device, g_cmd ) ) return; 68 | 69 | int pid = atoi( g_cmd->argv[0] ); 70 | 71 | channelT *chan = channel__new_processcontrol( device ); 72 | startObserving( chan, pid ); 73 | 74 | while(1) { 75 | tBASE *msg = NULL; 76 | tARR *aux = NULL; 77 | int msgid = 0; 78 | int convIndex = 0; 79 | //sleep(1); 80 | channel__recv_withid( chan, &msg, &aux, &msgid, &convIndex, NULL ); 81 | if( msg != NULL ) { 82 | tSTR *msgSTR = (tSTR *) msg; 83 | const char *msgc = msgSTR->val; 84 | if( !strcmp( msgc, "outputReceived:fromProcess:atTime:" ) ) { 85 | tBASE *output = aux->head; 86 | tSTR *outputStr = (tSTR *) output; 87 | if( strstr( outputStr->val, "Couldn't write values" ) != NULL ) continue; 88 | if( !strncmp( outputStr->val, "XCTestOutputBarrier", 19 ) ) { 89 | printf("%s", &outputStr->val[19] ); 90 | continue; 91 | } 92 | printf("%s", outputStr->val ); 93 | } 94 | else { 95 | tBASE__dump( msg, 1 ); 96 | if( aux != NULL ) { 97 | tBASE__dump( (tBASE *) aux, 1 ); 98 | } 99 | } 100 | } 101 | 102 | } 103 | } 104 | 105 | void runKill( void *device ) { 106 | if( !desired_device( device, g_cmd ) ) return; 107 | 108 | int pid = atoi( g_cmd->argv[0] ); 109 | killPid( device, pid ); 110 | 111 | exit(0); 112 | } 113 | 114 | void runLaunch( void *device ) { 115 | if( !desired_device( device, g_cmd ) ) return; 116 | 117 | tDICT *env = tDICT__new(); 118 | tARR *args = tARR__new(); 119 | tDICT *options = tDICT__new(); 120 | uint64_t pid = launchProcess( device, g_cmd->argv[0], env, args, options ); 121 | 122 | if( pid ) { 123 | printf("{Type:\"Success\",PID:%" PRId64 "}\n", pid ); 124 | } 125 | 126 | exit(0); 127 | } 128 | 129 | uint64_t launchProcess_withchan( 130 | void *device, 131 | char *bundleIdentifier, 132 | tDICT *environment, 133 | tARR *arguments, 134 | tDICT *options, 135 | channelT *chan 136 | ) { 137 | tSTR *devicePath = tSTR__new("/private/"); 138 | 139 | tARR *args = tARR__newVals( 5, 140 | devicePath, 141 | tSTR__new( bundleIdentifier ), 142 | environment, 143 | arguments, 144 | options ); 145 | 146 | tBASE *msg = NULL; 147 | 148 | //channelT *chan = channel__new_processcontrol( device ); 149 | 150 | channel__call( chan, 151 | "launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:options:", (tBASE *) args, 152 | 0, &msg, NULL 153 | ); 154 | if( !msg ) { 155 | //channel__del( chan ); 156 | exit(0); 157 | } 158 | 159 | if( !tIsnum( msg ) ) { 160 | fprintf(stderr, "Error launching process\n" ); 161 | tBASE__dump( msg, 1 ); 162 | return 0; 163 | } 164 | 165 | return tI__val64( msg ); 166 | } 167 | 168 | uint64_t launchProcess( 169 | void *device, 170 | char *bundleIdentifier, 171 | tDICT *environment, 172 | tARR *arguments, 173 | tDICT *options 174 | ) { 175 | tSTR *devicePath = tSTR__new("/private/"); 176 | 177 | tARR *args = tARR__newVals( 5, 178 | devicePath, 179 | tSTR__new( bundleIdentifier ), 180 | environment, 181 | arguments, 182 | options ); 183 | 184 | tBASE *msg = NULL; 185 | 186 | channelT *chan = channel__new_processcontrol( device ); 187 | 188 | channel__call( chan, 189 | "launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:options:", (tBASE *) args, 190 | 0, &msg, NULL 191 | ); 192 | if( !msg ) { 193 | //channel__del( chan ); 194 | exit(0); 195 | } 196 | 197 | if( !tIsnum( msg ) ) { 198 | fprintf(stderr, "Error launching process\n" ); 199 | tBASE__dump( msg, 1 ); 200 | return 0; 201 | } 202 | 203 | return tI__val64( msg ); 204 | } -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | 6 | #include"uclop.h" 7 | 8 | #include"cmd_ioreg.h" 9 | #include"cmd_install.h" 10 | #include"cmd_tunnel.h" 11 | #include"cmd_bytetest.h" 12 | #include"cmd_syscfg.h" 13 | #include"cmd_info.h" 14 | #include"cmd_file.h" 15 | #include"cmd_gg.h" 16 | #include"cmd_mg.h" 17 | #include"cmd_img.h" 18 | #include"cmd_list.h" 19 | #include"cmd_listapps.h" 20 | #include"cmd_process.h" 21 | #include"cmd_syslog.h" 22 | #include"cmd_dtxdump.h" 23 | #include"service_deviceinfo.h" 24 | #include"service_notifications.h" 25 | #include"service_sysmon.h" 26 | #include"service_testmanager.h" 27 | 28 | void run_version( ucmd *cmd ) { 29 | printf("1.0\n"); 30 | } 31 | 32 | int main (int argc, char **argv) { 33 | uopt *idopt = UOPT("-id","UDID of device"); 34 | 35 | uopt *opts_list[] = { 36 | UOPT_FLAG("-json","Output JSON format"), 0 37 | }; 38 | uopt *udid_option[] = { idopt, 0 }; 39 | uopt *udid_w_json_option[] = { UOPT_FLAG("-json","Output JSON format"), idopt, 0 }; 40 | uopt *opts_install[] = { UOPT_REQUIRED("-path","Path to .app"), idopt, 0 }; 41 | uopt *opts_ps[] = { 42 | UOPT_FLAG("-subsec","Subsecond start precision"), 43 | UOPT_FLAG("-short","Show name only, not full path"), 44 | UOPT_FLAG("-apps","Show apps only"), 45 | UOPT("-appname","Show info only for specific program"), 46 | UOPT_FLAG("-raw","Show all raw results"), 47 | idopt, 0 48 | }; 49 | uopt *opts_iserver[] = { 50 | UOPT("-port","Nanomsg port to listen on"), 51 | idopt, 0 52 | }; 53 | uopt *opts_listapps[] = { 54 | UOPT("-bi","Bundle Identifier of a specific app to list"), 55 | idopt, 0 56 | }; 57 | uopt *opts_syslog[] = { 58 | UOPT_FLAG("-raw","Show all raw results"), 59 | idopt, 0 60 | }; 61 | 62 | uclop *opts = uclop__new( 0, 0 ); 63 | uclop__addcmd( opts, "log", "Syslog", &run_syslog, opts_syslog ); 64 | uclop__addcmd( opts, "list", "List Devices", &run_list, opts_list ); 65 | uclop__addcmd( opts, "detectloop", "Detect Loop", &run_detect, 0 ); 66 | uclop__addcmd( opts, "img", "Get screenshot", &run_img, udid_option ); 67 | uclop__addcmd( opts, "gas", "Gas Guage", &run_gg, 0 ); 68 | uclop__addcmd( opts, "syscfg", "Get SysCfg", &run_syscfg, 0 ); 69 | uclop__addcmd( opts, "ps", "Process list", &run_ps, opts_ps ); 70 | uclop__addcmd( opts, "btest", "Bytearr Test", &run_bytetest, 0 ); 71 | uclop__addcmd( opts, "sysmon", "Sysmontap", &run_sysmon, 0 ); 72 | uclop__addcmd( opts, "smproclist", "Sysmon Process Attributes", &run_smProcList, 0 ); 73 | uclop__addcmd( opts, "smsyslist", "Sysmon System Attributes", &run_smSysList, 0 ); 74 | uclop__addcmd( opts, "smcoallist", "Sysmon Coalition Attributes", &run_smCoalList, 0 ); 75 | uclop__addcmd( opts, "machtimeinfo", "Mach Time Info", &run_machTimeInfo, 0 ); 76 | uclop__addcmd( opts, "notices", "Mobile Notifications", &run_notices, 0 ); 77 | uclop__addcmd( opts, "battery", "Battery Info", &run_battery, 0 ); 78 | uclop__addcmd( opts, "install", "Install Application", &run_install, opts_install ); 79 | uclop__addcmd( opts, "listapps", "List Applications", &run_listapps, opts_listapps ); 80 | uclop__addcmd( opts, "version", "Version", &run_version, 0 ); 81 | uclop__addcmd( opts, "dl", "Download file", &run_getfile, udid_option ); 82 | uclop__addcmd( opts, "launch", "Launch app", &run_launch, udid_option ); 83 | uclop__addcmd( opts, "kill", "Kill process", &run_kill, udid_option ); 84 | uclop__addcmd( opts, "tail", "Tail process", &run_tail, udid_option ); 85 | uclop__addcmd( opts, "sysinfo", "System information", &run_sysinfo, udid_option ); 86 | uclop__addcmd( opts, "wda", "Run WebDriverAgent", &run_wda, udid_option ); 87 | uclop__addcmd( opts, "cfa", "Run ControlFloorAgent", &run_cfa, udid_option ); 88 | uclop__addcmd( opts, "dd", "Dtx Dump Parser", &run_dtxdump, 0); 89 | uclop__addcmd( opts, "ddf", "Dump Dtx Folders", &run_dtxdumpfolder, 0); 90 | uclop__addcmd( opts, "xctest", "Xcui test", &run_xctest, udid_option ); 91 | uclop__addcmd( opts, "iserver", "Image Server", &run_iserver, opts_iserver ); 92 | uclop__addcmd( opts, "iosversion", "Get iOS version", &run_ios_version, udid_option ); 93 | 94 | ucmd *mg = uclop__addcmd( opts, "mg", "Mobile Gestalt", &run_mg, udid_w_json_option ); 95 | mg->extrahelp = "[key] [[key]...]"; 96 | 97 | ucmd *info = uclop__addcmd( opts, "info", "Info", &run_info, udid_w_json_option ); 98 | info->extrahelp = "[[domain:]key] [[key]...]"; 99 | 100 | ucmd *ls = uclop__addcmd( opts, "ls", "ls", &run_ls, 0 ); 101 | ls->extrahelp = "[path]"; 102 | 103 | ucmd *ioreg = uclop__addcmd( opts, "ioreg", "IO Registry", &run_ioreg, 0 ); 104 | ioreg->extrahelp = "[key]"; 105 | 106 | ucmd *tun = uclop__addcmd( opts, "tunnel", "Tunnel", &run_tunnel, udid_option ); 107 | tun->extrahelp = "[from]:[to] [[from]:[to]...]"; 108 | 109 | uclop__run( opts, argc, argv ); 110 | } -------------------------------------------------------------------------------- /cmd_tunnel.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include"service.h" 13 | #include"uclop.h" 14 | #include"cfutil.h" 15 | 16 | static ucmd *g_cmd = NULL; 17 | void runTunnel( void *device ); 18 | void run_tunnel( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runTunnel ); } 19 | 20 | typedef struct tunnel_s { 21 | int inPort; 22 | int outPort; 23 | int inSock; 24 | struct addrinfo *inAddr; 25 | } tunnel; 26 | 27 | tunnel *tunnel__new( void *device, int srcPort, int destPort ) { 28 | tunnel *self = (tunnel *) malloc( sizeof( tunnel ) ); 29 | self->inPort = srcPort; 30 | self->outPort = destPort; 31 | 32 | struct addrinfo hints,*inAddr; 33 | memset( &hints, 0, sizeof( hints ) ); 34 | hints.ai_flags = AI_PASSIVE; 35 | hints.ai_family = PF_UNSPEC; 36 | hints.ai_socktype = SOCK_STREAM; 37 | 38 | char strAddr[12]; 39 | sprintf( strAddr, "%d", srcPort ); 40 | getaddrinfo( NULL, strAddr, &hints, &inAddr ); 41 | self->inAddr = inAddr; 42 | 43 | int inSock = socket( inAddr->ai_family, inAddr->ai_socktype, inAddr->ai_protocol ); 44 | if( inSock < 0 ) { 45 | printf("Error making socket\n"); 46 | exit(1); 47 | } 48 | 49 | int opt = 1; 50 | int optRes = setsockopt( inSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof( opt ) ); 51 | if( optRes < 0 ) { 52 | printf("setsockopt error\n"); 53 | exit(1); 54 | } 55 | 56 | int bindRes = bind( inSock, inAddr->ai_addr, inAddr->ai_addrlen ); 57 | if( bindRes == -1 ) { 58 | close( inSock ); 59 | printf("failed to bind to %i\n", srcPort ); 60 | exit(1); 61 | } 62 | printf("bound to port %s\n", strAddr ); 63 | 64 | int listenRes = listen( inSock, 3 ); 65 | if( listenRes < 0 ) { 66 | printf("listen error\n"); 67 | exit(1); 68 | } 69 | 70 | self->inSock = inSock; 71 | 72 | return self; 73 | } 74 | 75 | #define NETBUFSIZE 1000 76 | void sendBytes( int inSock, int outSock ) { 77 | char buffer[NETBUFSIZE]; 78 | ssize_t readCount; 79 | for(;;) { 80 | readCount = recv( inSock, buffer, NETBUFSIZE, 0 ); 81 | if( readCount <= 0 ) break; 82 | send( outSock, buffer, readCount, 0 ); 83 | } 84 | 85 | if( readCount < 0 ) exit(1); 86 | 87 | shutdown( inSock, SHUT_RDWR ); 88 | shutdown( outSock, SHUT_RDWR ); 89 | close( inSock ); 90 | close( outSock ); 91 | } 92 | 93 | int connectOutput( void *device, int port ) { 94 | int conId = AMDeviceGetConnectionID( device ); 95 | int sock; 96 | exitOnError( USBMuxConnectByPort( conId, htons( port ), &sock ), 97 | "Connecting Port" ); 98 | return sock; 99 | } 100 | 101 | void handleClient( void *device, tunnel *tun, int clientSock, struct sockaddr_storage clientAddr ) { 102 | int outSock = connectOutput( device, tun->outPort ); 103 | if( outSock < 0 ){ 104 | close( clientSock ); 105 | return; 106 | } 107 | 108 | // data flowing to outSock 109 | if( !fork() ) { 110 | sendBytes( clientSock, outSock ); 111 | exit(0); 112 | } 113 | 114 | // data coming from outSock 115 | if( !fork() ) { 116 | sendBytes( outSock, clientSock ); 117 | exit(0); 118 | } 119 | 120 | close( clientSock ); 121 | close( outSock ); 122 | } 123 | 124 | void runTunnel( void *device ) { 125 | CFStringRef udidCf = AMDeviceCopyDeviceIdentifier( device ); 126 | char *udid = str_cf2c( udidCf ); 127 | char *goalUdid = ucmd__get( g_cmd, "-id" ); 128 | if( goalUdid && strcmp( udid, goalUdid ) ) return; 129 | 130 | devUp( device ); 131 | 132 | if( !g_cmd->argc ) { 133 | fprintf(stderr,"Must specify at least one [fromPort]:[toPort] pair\n"); 134 | devDown( device ); 135 | exit(1); 136 | } 137 | 138 | int tunCount = g_cmd->argc; 139 | int okCount = 0; 140 | tunnel *tuns[10]; 141 | 142 | for( int i=0;iargv[ i ]; 144 | int j=0; 145 | char found = 0; 146 | for( ;jinSock; 175 | FD_SET( inSock, &set ); 176 | if( inSock > maxFd ) maxFd = inSock; 177 | } 178 | 179 | select( maxFd + 1, &set, NULL, NULL, NULL ); 180 | 181 | for( int i=0;iinSock; 184 | 185 | if( !FD_ISSET( inSock, &set ) ) continue; 186 | 187 | struct sockaddr_storage clientAddr; 188 | socklen_t clientAddrLen = sizeof( clientAddr ); 189 | int clientSock = accept( inSock, (struct sockaddr*) &clientAddr, &clientAddrLen ); 190 | if( clientSock < 0 ) continue; 191 | 192 | printf("Got connection to port\n"); 193 | 194 | pid_t pid = fork(); 195 | if( pid == -1 ) { 196 | fprintf(stderr,"fork failed"); 197 | exit(1); 198 | } 199 | else if( !pid ) { 200 | close( inSock ); 201 | handleClient( device, tun, clientSock, clientAddr ); 202 | close( clientSock ); 203 | _exit(0); 204 | } 205 | else close( clientSock ); 206 | } 207 | } 208 | 209 | devDown( device ); 210 | } -------------------------------------------------------------------------------- /uclop.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // github.com/nanoscopic/uclop 3 | // Anti-Corruption License 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #define UOPT(a,b) uopt__new(a,b,1,0) 10 | #define UOPT_REQUIRED(a,b) uopt__new(a,b,1,1) 11 | #define UOPT_FLAG(a,b) uopt__new(a,b,2,0) 12 | #define UOPT_FLAG_REQUIRED(a,b) uopt__new(a,b,2,1) 13 | 14 | typedef struct uopts_s uopt; 15 | struct uopts_s { 16 | int type; 17 | int required; 18 | char *name; 19 | char *descr; 20 | char *def; // default value 21 | char *val; 22 | uopt *next; 23 | }; 24 | 25 | typedef struct ucmd_s ucmd; 26 | 27 | struct ucmd_s { 28 | char *name; 29 | char *descr; 30 | void ( *handler )( ucmd * ); 31 | ucmd *next; 32 | uopt *head; uopt *tail; 33 | int argc; 34 | char **argv; 35 | char *extrahelp; 36 | }; 37 | 38 | typedef struct uclop_s { 39 | ucmd *head; 40 | ucmd *tail; 41 | char *default_cmd; 42 | } uclop; 43 | 44 | uopt *uopt__new( char *name, char *descr, int type, int req ) { 45 | uopt *self = ( uopt * ) calloc( sizeof( uopt ), 1 ); 46 | self->type = type; 47 | self->name = name; 48 | self->descr = descr; 49 | self->required = req; 50 | return self; 51 | } 52 | 53 | void ucmd__addopt( ucmd *self, uopt *opt ) { 54 | if( !self->head ) { 55 | self->head = self->tail = opt; 56 | return; 57 | } 58 | self->tail->next = opt; 59 | self->tail = opt; 60 | } 61 | 62 | ucmd *uclop__addcmd( uclop *self, char *cmd_name, char *cmd_descr, void ( *default_handler )( ucmd * ), uopt *cmd_opts[] ) { 63 | ucmd *cmd = ( ucmd * ) calloc( sizeof( ucmd ), 1 ); 64 | cmd->name = cmd_name; 65 | cmd->descr = cmd_descr; 66 | cmd->handler = default_handler; 67 | if( cmd_opts ) for( int i=0;i<50;i++ ) { 68 | uopt *opt = cmd_opts[i]; 69 | if( opt == NULL ) break; 70 | ucmd__addopt( cmd, opt ); 71 | } 72 | if( !self->head ) { 73 | self->head = self->tail = cmd; 74 | return cmd; 75 | } 76 | self->tail->next = cmd; 77 | self->tail = cmd; 78 | return cmd; 79 | } 80 | 81 | uclop *uclop__new( void ( *default_handler)( ucmd * ), uopt *default_opts[] ) { 82 | uclop *self = ( uclop * ) calloc( sizeof( uclop ), 1 ); 83 | char *cmdDescr = "Show Usage"; 84 | uclop__addcmd( self, "default", cmdDescr, default_handler, default_opts ); 85 | return self; 86 | } 87 | 88 | void ucmd__run( ucmd *cmd ) { 89 | cmd->handler( cmd ); 90 | } 91 | 92 | void ucmd__usage_inline( ucmd *self ) { 93 | uopt *opt = self->head; 94 | while( opt ) { 95 | if( opt->required ) printf(" %s val", opt->name ); 96 | else { 97 | if( opt->type == 2 ) printf(" [%s]", opt->name ); 98 | else printf(" [%s val]", opt->name ); 99 | } 100 | opt = opt->next; 101 | } 102 | if( self->extrahelp ) printf(" %s", self->extrahelp ); 103 | printf("\n"); 104 | } 105 | 106 | void ucmd__usage( ucmd *self ) { 107 | uopt *opt = self->head; 108 | while( opt ) { 109 | printf(" %s %s\n", opt->name, opt->required ? "REQUIRED" : "" ); 110 | printf(" %s\n", opt->descr ); 111 | opt = opt->next; 112 | } 113 | } 114 | 115 | void uopt__usage( uopt *opt ) { 116 | printf(" %s %s\n", opt->name, opt->required ? "REQUIRED" : "" ); 117 | printf(" %s\n", opt->descr ); 118 | } 119 | 120 | void uclop__usage( uclop *self, char *prog ) { 121 | printf("Usage:\n"); 122 | ucmd *cmd = self->head; 123 | while( cmd ) { 124 | int isDefault = ( cmd == self->head ); 125 | char *cmdName = isDefault ? "" : cmd->name; 126 | printf("%s%s%s", prog, isDefault ? "" : " ", cmdName ); 127 | ucmd__usage_inline( cmd ); 128 | printf(" %s\n", cmd->descr ); 129 | ucmd__usage( cmd ); 130 | cmd = cmd->next; 131 | } 132 | } 133 | 134 | uopt *ucmd__find_opt( ucmd *self, char *name ) { 135 | uopt *opt = self->head; 136 | while( opt ) { 137 | if( !strcmp( name, opt->name ) ) return opt; 138 | opt = opt->next; 139 | } 140 | return NULL; 141 | } 142 | 143 | char *ucmd__get( ucmd *self, char *name ) { 144 | uopt *opt = self->head; 145 | while( opt ) { 146 | if( !strcmp( name, opt->name ) ) return opt->val; 147 | opt = opt->next; 148 | } 149 | return NULL; 150 | } 151 | 152 | void ucmd__ensure_required( ucmd *self ) { 153 | uopt *opt = self->head; 154 | int missing = 0; 155 | while( opt ) { 156 | if( opt->required && !opt->val ) { 157 | missing = 1; 158 | fprintf(stderr,"Required option %s missing\n", opt->name); 159 | uopt__usage( opt ); 160 | } 161 | opt = opt->next; 162 | } 163 | if( missing ) exit(1); 164 | } 165 | 166 | void uclop__run( uclop *self, int argc, char *argv[] ) { 167 | argc--; 168 | 169 | // Pull cmd name out of args 170 | char *cmdStr = "default"; 171 | int start = 1; 172 | if( argc >= 1 && argv[1][0] != '-' ) { 173 | start++; 174 | cmdStr = argv[1]; 175 | } 176 | 177 | // Find the cmd object using the name 178 | ucmd *cmd = self->head; 179 | while( cmd ) { 180 | if( !strcmp( cmdStr, cmd->name ) ) break; 181 | cmd = cmd->next; 182 | } 183 | if( !cmd ) { 184 | uclop__usage( self, argv[0] ); 185 | return; 186 | } 187 | 188 | // Store arguments 189 | int i; 190 | for( i=start;i<=argc;i++ ) { 191 | char *arg = argv[i]; 192 | if( arg[0] == '-' ) { 193 | uopt *opt = ucmd__find_opt( cmd, arg ); 194 | if( !opt ) { 195 | fprintf( stderr, "Unknown option %s\n", arg ); 196 | exit(1); 197 | } 198 | if( opt->type == 2 ) opt->val = "true"; 199 | else opt->val = argv[++i]; 200 | } 201 | else break; 202 | } 203 | cmd->argc = argc - i + 1; 204 | cmd->argv = &argv[i]; 205 | 206 | // Check that all required options are present 207 | ucmd__ensure_required( cmd ); 208 | 209 | if( !cmd->handler ) uclop__usage( self, argv[0] ); 210 | else ucmd__run( cmd ); 211 | } -------------------------------------------------------------------------------- /cmd_image.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"uclop.h" 6 | #include"cfutil.h" 7 | #include"mobiledevice.h" 8 | #include"service.h" 9 | #include"services.h" 10 | #ifdef NNG 11 | #include 12 | #include 13 | #endif 14 | 15 | static ucmd *g_cmd = NULL; 16 | void runImage( void *device ); 17 | void run_img( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runImage ); } 18 | 19 | void runIServer( void *device ); 20 | void run_iserver( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runIServer ); } 21 | 22 | void fatal( char *str, int rv ) { 23 | fprintf(stderr,"Err %s ; rv=%d\n", str, rv ); 24 | //exit(1); 25 | } 26 | 27 | void *initScreenshotService( void *device ) { 28 | void *imgService = activateScreenshotService( device ); 29 | 30 | CFTypeRef info = NULL; 31 | exitOnError( 32 | AMDServiceConnectionReceiveMessage( imgService, &info, nil ), 33 | "Receive Intro" ); 34 | 35 | exitOnError( 36 | AMDServiceConnectionSendMessage( 37 | imgService, 38 | genarr( 2, 39 | CFSTR("DLMessageVersionExchange"), 40 | CFSTR("DLVersionsOk") 41 | ), kCFPropertyListXMLFormat_v1_0 42 | ), 43 | "Accept Version" 44 | ); 45 | 46 | exitOnError( 47 | AMDServiceConnectionReceiveMessage(imgService, &info, nil), 48 | "Receive Version Accept" ); 49 | 50 | return imgService; 51 | } 52 | 53 | void *getImage( void *imgService, size_t *lenOut ) { 54 | exitOnError( 55 | AMDServiceConnectionSendMessage( 56 | imgService, 57 | genarr( 2, 58 | CFSTR( "DLMessageProcessMessage" ), 59 | genmap( 2, "MessageType", CFSTR("ScreenShotRequest") ) 60 | ), kCFPropertyListXMLFormat_v1_0 61 | ), 62 | "Send SC Request" 63 | ); 64 | 65 | CFTypeRef result = NULL; 66 | exitOnError( 67 | AMDServiceConnectionReceiveMessage( imgService, &result, nil ), 68 | "Get SC" 69 | ); 70 | 71 | if( result ) { 72 | CFDictionaryRef data = CFArrayGetValueAtIndex( result, 1 ); 73 | if( data ) { 74 | CFTypeRef image = CFDictionaryGetValue( data, CFSTR("ScreenShotData") ); 75 | if( image ) { 76 | int len = CFDataGetLength( image ); 77 | 78 | CFRange range = CFRangeMake(0,len); 79 | char *bytes = malloc( len ); 80 | CFDataGetBytes( image, range, (UInt8 *) bytes ); 81 | 82 | *lenOut = len; 83 | CFRelease( result ); 84 | return bytes; 85 | } 86 | } 87 | } 88 | CFRelease( result ); 89 | return 0; 90 | } 91 | 92 | #ifdef NNG 93 | void runIServer( void *device ) { 94 | if( !desired_device( device, g_cmd ) ) return; 95 | 96 | void *imgService = initScreenshotService( device ); 97 | 98 | int port = 8271; 99 | char *portStr = ucmd__get( g_cmd, "-port" ); 100 | if( portStr ) port = atoi( portStr ); 101 | 102 | char url[50]; 103 | sprintf( url, "tcp://127.0.0.1:%d", port ); 104 | 105 | nng_socket sock; 106 | int rv; 107 | 108 | rv = nng_rep0_open( &sock ); 109 | if( rv ) fatal("nng_rep0_open",rv); 110 | 111 | rv = nng_listen( sock, url, NULL, 0 ); 112 | if( rv ) fatal("nng_listen",rv); 113 | 114 | printf("listening on %s\n", url ); 115 | fflush( stdout ); 116 | 117 | void *lastdata; 118 | size_t lastlen; 119 | 120 | int n = 0; 121 | for(;;) { 122 | //printf("n:%i\n", n ); 123 | char *buf = NULL; 124 | size_t size; 125 | rv = nng_recv( sock, &buf, &size, NNG_FLAG_ALLOC ); 126 | if( rv ) fatal("nng_recv",rv); 127 | if( !size ) fatal("recv empty",0); 128 | 129 | //printf("Received %.*s\n", (int) size, buf ); 130 | 131 | if( buf && !strncmp( buf, "img", 3 ) ) { 132 | char *left = &buf[ 4 ]; 133 | int id = atoi( left ); 134 | printf("id:%d\n", id ); 135 | /*if( id <= n ) { 136 | nng_free( buf, size ); 137 | printf("Duplicate; size=%i\n", lastlen); 138 | fflush( stdout ); 139 | nng_send( sock, lastdata, lastlen, 0 ); 140 | continue; 141 | }*/ 142 | n = id; 143 | 144 | size_t imgLen; 145 | 146 | printf("Fetching image\n"); 147 | void *data = getImage( imgService, &imgLen ); 148 | printf("Fetch done; got %i\n", imgLen ); 149 | fflush( stdout ); 150 | 151 | if( data && imgLen ) { 152 | rv = nng_send( sock, data, imgLen, 0 ); 153 | if( lastdata ) free( lastdata ); 154 | lastdata = data; 155 | lastlen = imgLen; 156 | //free( data ); 157 | } 158 | else { 159 | fprintf(stderr, "Did not get image\n" ); 160 | fflush( stderr ); 161 | } 162 | 163 | //nng_send( sock, "test", 5, 0 ); 164 | } 165 | else { 166 | rv = nng_send( sock, "what?", 6, 0 ); 167 | } 168 | nng_free( buf, size ); 169 | } 170 | 171 | exit(0); 172 | } 173 | #else 174 | #include "sandbird/sandbird.h" 175 | 176 | void *imgService; 177 | static int event_handler(sb_Event *e) { 178 | if( e->type == SB_EV_REQUEST ) { 179 | size_t imgLen; 180 | 181 | printf("Fetching image\n"); 182 | void *data = getImage( imgService, &imgLen ); 183 | 184 | sb_send_status( e->stream, 200, "OK" ); 185 | sb_send_header( e->stream, "Content-Type", "image/png" ); 186 | sb_write( e->stream, data, imgLen ); 187 | } 188 | return SB_RES_OK; 189 | } 190 | 191 | void runIServer( void *device ) { 192 | if( !desired_device( device, g_cmd ) ) return; 193 | 194 | imgService = initScreenshotService( device ); 195 | 196 | char *portStr = ucmd__get( g_cmd, "-port" ); 197 | if( !portStr ) portStr = "8271"; 198 | 199 | sb_Server *srv; 200 | sb_Options opt; 201 | 202 | memset(&opt, 0, sizeof(opt)); 203 | opt.port = portStr; 204 | opt.handler = event_handler; 205 | 206 | srv = sb_new_server( &opt ); 207 | 208 | for (;;) { 209 | sb_poll_server(srv, 200); 210 | } 211 | 212 | sb_close_server(srv); 213 | } 214 | 215 | #endif 216 | 217 | void runImage( void *device ) { 218 | if( !desired_device( device, g_cmd ) ) return; 219 | 220 | void *imgService = initScreenshotService( device ); 221 | 222 | size_t imgLen; 223 | void *data = getImage( imgService, &imgLen ); 224 | 225 | if( data ) { 226 | FILE *fh = fopen( "test.png", "w" ); 227 | if( !fh ) { 228 | printf("Could not open test.png for writing\n"); 229 | exit(1); 230 | } 231 | fwrite( data, imgLen, 1, fh ); 232 | free( data ); 233 | fclose( fh ); 234 | } 235 | 236 | exit(0); 237 | } -------------------------------------------------------------------------------- /cmd_syslog.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include 6 | #include 7 | #include"mobiledevice.h" 8 | #include"uclop.h" 9 | #include"services.h" 10 | #include"service.h" 11 | #include"cfutil.h" 12 | 13 | #define BUFSIZE 40//4096 14 | 15 | static ucmd *g_cmd = NULL; 16 | void runSysLog( void *device ); 17 | void run_syslog( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runSysLog ); } 18 | 19 | typedef struct { 20 | char *data; 21 | uint16_t maxsize; 22 | uint16_t size; 23 | } msg; 24 | 25 | msg *msg__new() { 26 | msg *self = (msg *) calloc( 1, sizeof( msg ) ); 27 | self->data = (char *) calloc( 1, BUFSIZE + 1 ); 28 | self->maxsize = BUFSIZE; 29 | return self; 30 | } 31 | 32 | void msg__append( msg *self, char *data, uint16_t size ) { 33 | if( ( self->size + size ) > self->maxsize ) { 34 | uint16_t newsize = self->size * 2; 35 | while( newsize < ( self->size + size ) ) newsize *= 2; 36 | char *newdata = (char *) calloc( 1, newsize ); 37 | memcpy( newdata, self->data, self->size ); 38 | free( self->data ); 39 | self->data = newdata; 40 | } 41 | memcpy( &(self->data[ self->size ]), data, size ); 42 | self->size += size; 43 | } 44 | 45 | void msg__reset( msg *self ) { 46 | self->size = 0; 47 | } 48 | 49 | void msg__parse( msg *self ) { 50 | } 51 | 52 | void msg__output( msg *self, int procCount, char **procs, char raw ) { 53 | if( raw ) { 54 | printf("%.*s\n", self->size, self->data ); 55 | fflush( stdout ); 56 | self->size = 0; 57 | return; 58 | } 59 | 60 | char month[4] = {}; 61 | memcpy( month, self->data, 3 ); 62 | char day[3] = {}; 63 | memcpy( day, &(self->data[4]), 2 ); 64 | char time[9] = {}; 65 | memcpy( time, &(self->data[7]), 8 ); 66 | //printf("Month:[%s]\n", month ); 67 | //printf("Day:[%s]\n", day ); 68 | //printf("Time:[%s]\n", time ); 69 | 70 | // Device name 71 | int nameLen; 72 | int procStart; 73 | int k1; 74 | if( self->data[16] == '"' ) { 75 | for( k1=17; k1< self->size; k1++ ) { 76 | if( self->data[k1] == '"' ) break; 77 | } 78 | nameLen = k1 - 16 - 1; 79 | procStart = k1 + 1; 80 | } 81 | // 16 " 17 A 18 " 82 | 83 | else { 84 | for( k1=16; k1< self->size; k1++ ) { 85 | if( self->data[k1] == ' ' ) break; 86 | } 87 | nameLen = k1 - 16; 88 | procStart = k1 + 1; 89 | } 90 | // 16 A 17 B 18 " " 91 | 92 | // Process 93 | int i=procStart; 94 | for( ;isize;i++ ) { 95 | if( self->data[i] == ' ' ) break; 96 | } 97 | int k; 98 | int pidEnd = i - 2; 99 | //printf("pidEnd char: %c\n", self->data[ i - 1 ] ); 100 | for( k=pidEnd;k>procStart;k-- ) { 101 | if( self->data[k] == '[' ) break; 102 | } 103 | k++; 104 | int pidStart = k; 105 | int pidLen = pidEnd - pidStart + 1; 106 | char *pid = &self->data[pidStart]; 107 | 108 | // Process name 109 | int procLen = i-procStart-(pidLen+2); 110 | char *proc = &self->data[procStart]; 111 | 112 | if( procCount ) { 113 | int procOk = 0; 114 | for( int ii=0; iisize = 0; 123 | return; 124 | } 125 | } 126 | 127 | // PID 128 | //printf("[%.*s,", pidLen, pid ); 129 | //printf("\"%.*s\",", procLen, proc ); 130 | 131 | // Type ( Notice etc ) 132 | int j=i+2; 133 | for( ;jsize;j++ ) { 134 | if( self->data[j] == ':' ) break; 135 | } 136 | int typeStart = i+2; 137 | int typeEnd = j-1; 138 | int typeLen = typeEnd - typeStart; 139 | char *type = &self->data[typeStart]; 140 | //printf("\"%.*s\",", typeLen, type ); 141 | 142 | // Message itself 143 | int msgLen = self->size-(typeEnd+3)-1; 144 | char *msg = &self->data[typeEnd+3]; 145 | //printf("`%.*s`]\n", msgLen, msg ); 146 | 147 | char *buffer = (char *) malloc( pidLen + 2 + procLen + 3 + typeLen + 3 + msgLen + 3 + 10 ); 148 | sprintf( buffer, "[%.*s,\"%.*s\",\"%.*s\",`%.*s`]\n", 149 | pidLen, pid, 150 | procLen, proc, 151 | typeLen, type, 152 | msgLen, msg ); 153 | int bufLen = strlen( buffer ); 154 | printf("*%d%s", bufLen, buffer ); 155 | free( buffer ); 156 | 157 | fflush( stdout ); 158 | 159 | //msg__reset( self ); 160 | self->size = 0; 161 | } 162 | 163 | void runSysLog( void *device ) { 164 | char *udid = ucmd__get( g_cmd, "-id" ); 165 | 166 | int procCount = 0; 167 | char **procs = NULL; 168 | int argc = g_cmd->argc; 169 | if( argc > 0 ) { 170 | for( int i=0;iargv[i]; 172 | //char *val = g_cmd->argv[i+1]; 173 | if( !strncmp( filter, "proc", 4 ) ) { 174 | procCount++; 175 | } 176 | } 177 | 178 | if( procCount ) { 179 | procs = ( char ** ) malloc( sizeof( char * ) * procCount ); 180 | int procI = 0; 181 | for( int i=0;iargv[i]; 183 | char *val = g_cmd->argv[i+1]; 184 | if( !strncmp( filter, "proc", 4 ) ) { 185 | procs[ procI++ ] = val; 186 | //printf("Filtering by proc %s\n", val ); 187 | } 188 | } 189 | } 190 | } 191 | //printf("Proc count:%i\n", procCount ); 192 | //exit(0); 193 | 194 | CFStringRef devId = AMDeviceCopyDeviceIdentifier( device ); 195 | char *audid = str_cf2c( devId ); 196 | if( udid && strcmp( audid, udid ) ) return; 197 | //fprintf(stderr,"udid:%s\n", udid ); 198 | 199 | void *service = activateSyslog( device ); 200 | 201 | msg *curmsg = msg__new(); 202 | 203 | char buf[ BUFSIZE ]; 204 | 205 | char *raw = ucmd__get( g_cmd, "-raw" ); 206 | 207 | int rc, len; 208 | while( 1 ) { 209 | rc = AMDServiceConnectionReceive( service, buf, BUFSIZE-1 ); 210 | if( rc <= 0 ) break; 211 | //printf("rc:%d\n", rc ); 212 | //continue; 213 | 214 | if( buf[0] == 0 ) { 215 | if( curmsg->size ) { 216 | //fwrite( curmsg->data, curmsg->size, 1, stdout ); 217 | //fwrite( "\n", 1, 1, stdout ); 218 | msg__output( curmsg, procCount, procs, raw ? 1 : 0 ); 219 | } 220 | //len = strlen( &buf[1] ); 221 | msg__append( curmsg, &buf[1], rc-1 ); 222 | //fwrite( &buf[1], len, 1, stdout ); 223 | } 224 | else { 225 | len = strlen( buf ); 226 | msg__append( curmsg, buf, rc ); 227 | //fputs( buf, stdout ); 228 | } 229 | 230 | // We only need to clear the portion of the buffer used 231 | //memset( buf, 0, len ); 232 | } 233 | } -------------------------------------------------------------------------------- /ujsonin/string-tree.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 David Helkowski 2 | 3 | #include "string-tree.h" 4 | #include 5 | #include"red_black_tree.h" 6 | 7 | uint32_t fnv1a_len( char *str, int strlen ) { 8 | uint32_t hval = 0; 9 | unsigned char *s = (unsigned char *) str; 10 | 11 | for( int i=0;itree, &hash ); 24 | 25 | // We unfortunately cannot just delete the rbnode; as multiple keys may hash to this same value 26 | //if( rbnode ) RBDelete( (rb_red_blk_tree *) self->tree, rbnode ); // automatically deletes info nodes 27 | 28 | if( !rbnode ) { return; } 29 | snode *node = (snode *) rbnode->info; 30 | snode *prev = NULL; 31 | while( node ) { 32 | snode *next = node->next; 33 | int delete = 0; 34 | if( node->strlen ) { 35 | if( keylen == node->strlen && !strncmp( node->str, key, node->strlen ) ) delete = 1; 36 | } 37 | else { 38 | int nslen = strlen( node->str ); 39 | if( nslen == keylen && !strncmp( node->str, key, keylen ) ) delete = 1; 40 | } 41 | if( delete ) { 42 | free( node );// destroy the snode 43 | } 44 | else { 45 | if( prev ) prev->next = node; 46 | else rbnode->info = node; 47 | prev = node; 48 | } 49 | node = next; 50 | } 51 | if( prev ) { 52 | prev->next = NULL; 53 | } 54 | else { 55 | rbnode->info = NULL; 56 | } 57 | } 58 | 59 | string_tree *string_tree__new() { 60 | string_tree *self = ( string_tree * ) malloc( sizeof( string_tree ) ); 61 | self->tree = (void *) RBTreeCreate(IntComp,IntDest,InfoDest,IntPrint,InfoPrint); 62 | return self; 63 | } 64 | 65 | void string_tree__delete( string_tree *self ) { 66 | RBTreeDestroy( (rb_red_blk_tree *) self->tree ); 67 | free( self ); 68 | } 69 | 70 | void *string_tree__get_len( string_tree *self, char *key, int keylen, char *dataType ) { 71 | //printf("Getting %s\n", key ); 72 | snode *node = string_tree__rawget_len( self, key, keylen ); 73 | if( !node ) { 74 | //printf("Could not find node %s\n", key ); 75 | return 0; 76 | } 77 | *dataType = node->dataType; 78 | return node->data; 79 | } 80 | 81 | snode *string_tree__rawget_len( string_tree *self, char *key, int keylen ) { 82 | //printf("Attempting to get node %s\n", key ); 83 | uint32_t hash = fnv1a_len( key, keylen ); 84 | rb_red_blk_node* rbnode = RBExactQuery( (rb_red_blk_tree *) self->tree, &hash ); 85 | if( !rbnode ) { return 0; } 86 | //printf("Found rbnode\n"); 87 | snode *node = (snode *) rbnode->info; 88 | //printf("got %i\n", (int) node ); 89 | while( node ) { 90 | if( node->strlen ) { 91 | if( keylen == node->strlen && !strncmp( node->str, key, node->strlen ) ) return node; 92 | } 93 | else { 94 | int nslen = strlen( node->str ); 95 | if( nslen == keylen && !strncmp( node->str, key, keylen ) ) return node; 96 | } 97 | node = node->next; 98 | } 99 | 100 | //printf("ret\n"); 101 | return NULL; 102 | } 103 | 104 | void string_tree__store_len( string_tree *self, char *key, int keylen, void *node, char dataType ) { 105 | uint32_t hash = fnv1a_len( key, keylen ); 106 | snode *curnode = string_tree__rawget_len( self, key, keylen ); 107 | if( curnode ) { 108 | //snode *next = curnode->next; 109 | while( curnode->next ) curnode = curnode->next; 110 | 111 | snode *newnode = snode__new_len( key, keylen, node, dataType, NULL ); 112 | curnode->next = newnode; 113 | } 114 | else { 115 | curnode = snode__new_len( key, keylen, node, dataType, NULL ); 116 | uint32_t *hdup = malloc( sizeof( uint32_t ) ); 117 | *hdup = hash; 118 | RBTreeInsert( (rb_red_blk_tree *) self->tree, hdup, curnode ); 119 | } 120 | } 121 | 122 | void IntDest(void* a) { 123 | free((uint32_t*)a); 124 | } 125 | int IntComp(const void* a,const void* b) { 126 | if( *(uint32_t*)a > *(uint32_t*)b) return(1); 127 | if( *(uint32_t*)a < *(uint32_t*)b) return(-1); 128 | return(0); 129 | } 130 | void IntPrint(const void* a) { 131 | } 132 | void InfoPrint(void* a) { 133 | } 134 | void InfoDest(void *a){ 135 | free( a ); 136 | } 137 | 138 | void snode__delete( snode *self ) { 139 | snode *curnode = self; 140 | while( curnode ) { 141 | snode *nextnode = curnode->next; 142 | free( curnode ); 143 | curnode = nextnode; 144 | } 145 | } 146 | 147 | snode *snode__new_len( char *newstr, int nstrlen, void *newdata, char dataType, snode *newnext ) { 148 | snode *self = ( snode * ) malloc( sizeof( snode ) ); 149 | self->next = newnext; 150 | self->str = newstr; 151 | self->strlen = nstrlen; 152 | self->data = newdata; 153 | self->dataType = dataType; 154 | //printf("New snodec - next=%i str=%s data=%i\n", (int)next, str, (int)data ); 155 | return self; 156 | } 157 | 158 | xjr_arr *xjr_arr__new() { 159 | xjr_arr *arr = ( xjr_arr * ) calloc( sizeof( xjr_arr ), 1 ); // calloc to ensure initial count is 0 160 | arr->items = malloc( sizeof( void * ) * XJR_ARR_MAX ); 161 | arr->max = XJR_ARR_MAX; 162 | return arr; 163 | } 164 | 165 | void xjr_arr__double( xjr_arr *self) { 166 | void **olditems = self->items; 167 | int max = self->max * 2; 168 | self->items = malloc( sizeof( void * ) * max ); 169 | memcpy( self->items, olditems, sizeof( void * ) * self->max ); 170 | free( olditems ); 171 | self->max = max; 172 | } 173 | 174 | void xjr_arr__delete( xjr_arr *self ) { 175 | free( self->items ); 176 | free( self ); 177 | } 178 | 179 | xjr_key_arr *xjr_key_arr__new() { 180 | xjr_key_arr *arr = ( xjr_key_arr * ) calloc( sizeof( xjr_key_arr ), 1 ); // calloc to ensure initial count is 0 181 | arr->items = malloc( sizeof( void * ) * XJR_KEY_ARR_MAX ); 182 | arr->sizes = malloc( sizeof( int ) * XJR_KEY_ARR_MAX ); 183 | arr->max = XJR_KEY_ARR_MAX; 184 | return arr; 185 | } 186 | 187 | void xjr_key_arr__double( xjr_key_arr *self) { 188 | char **olditems = self->items; 189 | void *oldsizes = self->sizes; 190 | int max = self->max * 2; 191 | self->items = malloc( sizeof( char * ) * max ); 192 | self->sizes = malloc( sizeof( int ) * max ); 193 | memcpy( self->items, olditems, sizeof( char * ) * self->max ); 194 | memcpy( self->sizes, oldsizes, sizeof( int ) * self->max ); 195 | free( olditems ); 196 | free( oldsizes ); 197 | self->max = max; 198 | } 199 | 200 | void xjr_key_arr__delete( xjr_key_arr *self ) { 201 | free( self->items ); 202 | free( self->sizes ); 203 | free( self ); 204 | } 205 | 206 | xjr_key_arr *string_tree__getkeys( string_tree *self ) { 207 | xjr_key_arr *arr = xjr_key_arr__new(); 208 | TreeForEach1p( self->tree, string_tree__getkeys_rec, arr, NULL ); 209 | return arr; 210 | } 211 | void string_tree__getkeys_rec( void *snodeV, void *arrV ) { 212 | snode *snodex = ( snode * ) snodeV; 213 | xjr_key_arr *arr = ( xjr_key_arr * ) arrV; 214 | arr->sizes[ arr->count ] = snodex->strlen; 215 | arr->items[ arr->count++ ] = snodex->str; 216 | if( arr->count >= arr->max ) xjr_key_arr__double( arr ); 217 | } 218 | -------------------------------------------------------------------------------- /bytearr.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include"bytearr.h" 5 | #include"archiver/nsutil.h" 6 | #include"cfutil.h" 7 | #include"archiver/archiver.h" 8 | #include"archiver/plist.h" 9 | 10 | bytechunk *bytechunk__new( uint8_t *data, uint32_t len, char alloc ) { 11 | bytechunk *self = (bytechunk *) malloc( sizeof( bytechunk ) ); 12 | uint8_t *datacopy = (uint8_t *) malloc( len ); 13 | memcpy( datacopy, data, len ); 14 | self->data = datacopy; 15 | self->len = len; 16 | self->alloc = alloc; 17 | self->next = NULL; 18 | return self; 19 | } 20 | 21 | bytearr *bytearr__new() { 22 | bytearr *self = (bytearr *) calloc( 1, sizeof( bytearr ) ); 23 | return self; 24 | } 25 | 26 | void ba__print( bytearr *self, char *fmt, ... ) { 27 | va_list args; 28 | va_start( args, fmt ); 29 | char *data; 30 | int len = vasprintf( &data, fmt, args ); 31 | va_end( args ); 32 | bytearr__append( self, (uint8_t *) data, len, 0 ); 33 | } 34 | 35 | void bytearr__appdup( bytearr *self, uint8_t *data, uint32_t len ) { 36 | uint8_t *dup = (uint8_t *) malloc( len ); 37 | memcpy( dup, data, len ); 38 | bytearr__append( self, dup, len, 1 ); 39 | } 40 | 41 | void bytearr__append( bytearr *self, uint8_t *data, uint32_t len, char alloc ) { 42 | //printf("Appending %i bytes\n", len ); 43 | self->len += len; 44 | 45 | bytechunk *chunk = bytechunk__new( data, len, alloc ); 46 | if( !self->head ) { 47 | self->head = self->tail = chunk; 48 | return; 49 | } 50 | if( self->head == self->tail ) { 51 | self->head->next = chunk; 52 | self->tail = chunk; 53 | return; 54 | } 55 | bytechunk *oldtail = self->tail; 56 | self->tail = chunk; 57 | oldtail->next = chunk; 58 | } 59 | 60 | void bytearr__appendba( bytearr *self, bytearr *toadd ) { 61 | self->len += toadd->len; 62 | 63 | if( !self->head ) { 64 | self->head = toadd->head; 65 | self->tail = toadd->tail; 66 | return; 67 | } 68 | if( self->head == self->tail ) { 69 | self->head->next = toadd->head; 70 | self->tail = toadd->tail; 71 | return; 72 | } 73 | self->tail->next = toadd->head; 74 | self->tail = toadd->tail; 75 | } 76 | 77 | void bytearr__appendu8( bytearr *self, uint8_t num ) { 78 | uint8_t *nump = (uint8_t *) malloc(2); 79 | *nump = num; 80 | bytearr__append( self, (uint8_t *) nump, 1, 1 ); 81 | } 82 | 83 | void bytearr__appendu16( bytearr *self, uint16_t num ) { 84 | uint16_t *nump = (uint16_t *) malloc(2); 85 | *nump = num; 86 | bytearr__append( self, (uint8_t *) nump, 2, 1 ); 87 | } 88 | 89 | 90 | void bytearr__appendi32( bytearr *self, int32_t num ) { 91 | //printf("Appending i32 %i\n", num ); 92 | int32_t *nump = (int32_t *) malloc(4); 93 | *nump = num; 94 | bytearr__append( self, (uint8_t *) nump, 4, 1 ); 95 | } 96 | 97 | void bytearr__appendu32( bytearr *self, uint32_t num ) { 98 | //printf("Appending i32 %i\n", num ); 99 | uint32_t *nump = (uint32_t *) malloc(4); 100 | *nump = num; 101 | bytearr__append( self, (uint8_t *) nump, 4, 1 ); 102 | } 103 | 104 | void bytearr__appendi64( bytearr *self, int64_t num ) { 105 | //printf("Appending i64 %" PRId64 "\n", num ); 106 | int64_t *nump = (int64_t *) malloc(8); 107 | *nump = num; 108 | bytearr__append( self, (uint8_t *) nump, 8, 1 ); 109 | } 110 | 111 | uint8_t *bytearr__bytes( bytearr *self, uint32_t *len ) { 112 | bytechunk *chunk = self->head; 113 | uint32_t total = 0; 114 | while( chunk ) { 115 | total += chunk->len; 116 | chunk = chunk->next; 117 | } 118 | uint8_t *bytes = (uint8_t *) malloc( total ); 119 | *len = total; 120 | chunk = self->head; 121 | uint32_t pos = 0; 122 | while( chunk ) { 123 | memcpy( &bytes[ pos ], chunk->data, chunk->len ); 124 | pos += chunk->len; 125 | chunk = chunk->next; 126 | } 127 | return bytes; 128 | } 129 | 130 | void bytearr__auxi32( bytearr *self, int32_t val ) { 131 | bytearr__appendi32( self, 10 ); // empty dict 132 | bytearr__appendi32( self, 3 ); // i32 133 | bytearr__appendi32( self, val ); 134 | } 135 | 136 | void bytearr__auxi64( bytearr *self, int64_t val ) { 137 | bytearr__appendi32( self, 10 ); // empty dict 138 | bytearr__appendi32( self, 4 ); // i64 139 | bytearr__appendi64( self, val ); 140 | } 141 | 142 | /*void bytearr__auxcf( bytearr *self, CFTypeRef cf, char secure ) { 143 | bytearr__appendi32( self, 10 ); // empty dict 144 | bytearr__appendi32( self, 2 ); // cfTypeRef 145 | 146 | int len = 0; 147 | uint8_t *data = cf2archive( cf, &len, secure ); 148 | 149 | bytearr__appendi32( self, len ); 150 | bytearr__append( self, data, len, 1 ); 151 | }*/ 152 | 153 | void bytearr__auxT( bytearr *self, tBASE *t ) { 154 | bytearr__appendi32( self, 10 ); // empty dict 155 | bytearr__appendi32( self, 2 ); // cfTypeRef 156 | 157 | uint32_t len = 0; 158 | uint8_t *data = tBASE__archivebin( t, &len ); 159 | 160 | bytearr__appendi32( self, len ); 161 | bytearr__append( self, data, len, 1 ); 162 | } 163 | 164 | uint8_t *bytearr__asaux( bytearr *self, uint32_t *len ) { 165 | bytechunk *chunk = self->head; 166 | int64_t total = 16; 167 | while( chunk ) { 168 | total += chunk->len; 169 | chunk = chunk->next; 170 | } 171 | //printf("Aux total size: %" PRId64 "\n", total ); 172 | //printf("Aux data size: %" PRId64 "\n", total-16 ); 173 | uint8_t *bytes = (uint8_t *) calloc( 1, total ); 174 | int64_t magic = 0x1F0; 175 | memcpy( bytes, &magic, 8 ); 176 | int64_t justDataLen = total - 16; 177 | memcpy( &bytes[8], &justDataLen, 8 ); 178 | 179 | *len = total; 180 | chunk = self->head; 181 | int pos = 16; 182 | while( chunk ) { 183 | memcpy( &bytes[ pos ], chunk->data, chunk->len ); 184 | pos += chunk->len; 185 | chunk = chunk->next; 186 | } 187 | return bytes; 188 | } 189 | 190 | /*bytearr *cfarr2aux( CFTypeRef argsCf, char secure ) { 191 | bytearr *args = bytearr__new(); 192 | if( iscfarr( argsCf ) ) { 193 | int count = CFArrayGetCount( (CFArrayRef) argsCf ); 194 | //printf("Count = %i\n", count ); 195 | for( int i=0;itype == xfARR ) { 220 | int count = argsT->count; 221 | //printf("Count = %i\n", count ); 222 | for( int i=0;itype == xfI8 ) { 226 | bytearr__auxi32( args, ( (tI8 *) el )->val ); 227 | } 228 | else if( el->type == xfI16 ) { 229 | bytearr__auxi32( args, ( (tI16 *) el )->val ); 230 | } 231 | else if( el->type == xfI32 ) { 232 | bytearr__auxi32( args, ( (tI32 *) el )->val ); 233 | } 234 | else if( el->type == xfI64 ) { 235 | bytearr__auxi64( args, ( (tI64 *) el )->val ); 236 | } 237 | else bytearr__auxT( args, el ); 238 | } 239 | } 240 | else { 241 | bytearr__auxT( args, (tBASE *) argsT ); 242 | } 243 | return args; 244 | } -------------------------------------------------------------------------------- /cmd_syscfg.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"service.h" 6 | #include"uclop.h" 7 | #include"archiver/byteswap.h" 8 | 9 | static ucmd *g_cmd = NULL; 10 | void runSysCfg( void *device ); 11 | void run_syscfg( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runSysCfg ); } 12 | 13 | void bswap( unsigned char *in ) { 14 | char out[4]; 15 | char temp; 16 | bcopy( in, out, 4 ); 17 | int dest = 3; 18 | for( int i=0;i<2;i++ ) { 19 | temp = out[i]; 20 | out[i] = out[dest]; 21 | out[dest--] = temp; 22 | } 23 | bcopy( out, in, 4 ); 24 | } 25 | //#define bswapul( n ) bswap( (char *) &(n) ); 26 | unsigned long bswapul( unsigned long in ) { 27 | unsigned long out; 28 | char *outPtr = ( char * ) &out; 29 | char *inPtr = ( char * ) ∈ 30 | outPtr[3] = inPtr[0]; 31 | outPtr[2] = inPtr[1]; 32 | outPtr[1] = inPtr[2]; 33 | outPtr[0] = inPtr[3]; 34 | return out; 35 | } 36 | 37 | typedef struct __attribute__((packed)) { 38 | char scfg[4]; // 0-3 39 | unsigned long size; // 4-7 40 | unsigned long maxSize; // 8-11 41 | unsigned long version; // 12-15 42 | unsigned long bigEndian; // 16 - 19 43 | unsigned long keyCount; // 20-24 44 | } BaseInfo; 45 | 46 | char buf[20]; 47 | char *hex4( unsigned char *addr ) { 48 | sprintf(buf,"%02x%02x%02x%02x", addr[0], addr[1], addr[2], addr[3] ); 49 | buf[8] = 0x00; 50 | return buf; 51 | } 52 | 53 | char *hex4ul( unsigned long n ) { 54 | char *np = (char *) &n; 55 | sprintf(buf,"%02x%02x%02x%02x", np[0], np[1], np[2], np[3] ); 56 | buf[8] = 0x00; 57 | return buf; 58 | } 59 | 60 | typedef struct { 61 | char *shortx; 62 | char *longx; 63 | } NameEntry; 64 | 65 | NameEntry *NM( char *a, char *b ) { 66 | NameEntry *self = (NameEntry *) malloc( sizeof( NameEntry ) ); 67 | self->shortx = a; 68 | self->longx = b; 69 | return self; 70 | } 71 | 72 | void runSysCfg( void *device ) { 73 | NameEntry *names[] = { 74 | NM("AICl","Accelerator Interrupt Calibration"), 75 | NM("ARot","Accelerometer Orientation Calibration"), 76 | NM("ASCi","Accelerometer Sensitivity Inverse Matrix"), 77 | NM("ASCl","Accelerometer Sensitivity Calibration"), 78 | NM("ATGa","Acoustic Trim Gains"), 79 | NM("Batt","Battery Serial Number"), 80 | NM("BCAL","Bluetooth Taurus Calibration"), 81 | NM("BCAR","BackCamera Autofocus Recalibration"), 82 | NM("BCMB","Back Camera Module Board"), 83 | NM("BCMS","Back Camera Module Serialnumber"), 84 | NM("BGMt","Backing Glass Material"), 85 | NM("BLCl","Backlight Calibration"), 86 | NM("BMac","Bluetooth Mac Address"), 87 | NM("BTRx","Bluetooth Reception Calibration"), 88 | NM("BTTx","Bluetooth Transmission Calibration"), 89 | NM("CBAT","Charget input limit calibration"), 90 | NM("CDCC","Compass hilow calibration"), 91 | NM("CGMt","Coverglass Material"), 92 | NM("CGSp","Coverglass type"), 93 | NM("CLBG","Backing Color"), 94 | NM("CLHS","Housing Color"), 95 | NM("CLCG","Coverglass Color"), 96 | NM("CRot","???"), 97 | NM("CSCM","Compass Sensor Calibration"), 98 | NM("CVCC","Compass VBUS Compensation"), 99 | NM("DBCl","Display Backlight Compensation"), 100 | NM("DClr","Device color"), 101 | NM("DPCl","Primary Calibration Matrix"), 102 | NM("DTCl","Display Temperature Calibration"), 103 | NM("EMac","Ethernet Mac Address"), 104 | NM("EnMt","Enclosure Material"), 105 | NM("FCMB","Front Camera Module Board"), 106 | NM("FCMS","Front Camera Module Serialnumber"), 107 | NM("FDAC","Orb Dynamic Accelerator Calibration"), 108 | NM("FG2G","WiFi Calibration Frequency Group 2G"), 109 | NM("GICl","Gyro Interrupt Calibration"), 110 | NM("GLCl","Gamma Tables Calibration"), 111 | NM("GRot","Gyro Orientation Calibration"), 112 | NM("GSCi","Gyro Sensitivity Matrix Inverse"), 113 | NM("GSCl","Gyro Sensitivity Calibration"), 114 | NM("GTCl","Gyro Trim Calibration"), 115 | NM("GYTT","Gyro Temp. Calibration"), 116 | NM("LCM#","Liquid Crystal Monitor Serialnumber (LCD)"), 117 | NM("LSCI","Ambient Lightsensor Calibration"), 118 | NM("LTAO","Low Temperature Accelerometer Offset"), 119 | NM("MLB#","Main Logicboard Serialnumber"), 120 | NM("MdlC","Murata WiFi Configuration"), 121 | NM("MkBH","Marketing Hardware Behavior"), 122 | NM("Mod#","Model number"), 123 | NM("MtCl","Multitouch Calibration"), 124 | NM("MtSN","Multitouch Serialnumber"), 125 | NM("NFCl","Stockholm NFC Calibration"), 126 | NM("NSrN","Touch-ID Serial Number"), 127 | NM("NoCl","---? Calibration"), 128 | NM("NvSn","Apple SandDollar SerialNumber"), 129 | NM("OFCl","Orb Force Calibration"), 130 | NM("OOCl","???"), 131 | NM("OrbC","Orb Calibration"), 132 | NM("OrbG","Orb Gap Calibration"), 133 | NM("OrbM","???"), 134 | NM("PACV","---?"), 135 | NM("PrCL","Pearl calibration"), 136 | NM("PRSq","---?"), 137 | NM("PRTT","Pressure Temperature compensation Table"), 138 | NM("PSCl","Halleffect Calibration"), 139 | NM("PxCl","Proximity Calibration"), 140 | NM("RMd#","Regulatory Model Number"), 141 | NM("RxCL","Rosaline Calibration"), 142 | NM("Regn","Region code"), 143 | NM("SBVr","Software Bundle Version"), 144 | NM("SDAC","??? Sound DAC"), 145 | NM("SFCl","Bt Pico Calibration"), 146 | NM("SIFC","Bt Inverse Filter Calibration"), 147 | NM("SPPO","Pressure Offset Calibration"), 148 | NM("SpCl","Speaker Calibration"), 149 | NM("SrNm","Device Serialnumber"), 150 | NM("STRB","Camera Strobe Color Calibration"), 151 | NM("SwBh","Software Behaviour Bits"), 152 | NM("TCal","Audio Actuator Calibration"), 153 | NM("THPC","Turtle Hot Probe Calibration"), 154 | NM("VBCA","Speaker Configuration"), 155 | NM("VBST","Speaker Configuration"), 156 | NM("VPBR","Speaker Configuration"), 157 | NM("W24R","Wifi Receiver 2.4Ghz Calibration"), 158 | NM("WCAL","Wifi Calibration"), 159 | NM("WMac","Wifi mac address"), 160 | NM("WRxT","Wifi Receiver temp. Calibration") 161 | }; 162 | int nameCount = sizeof( names ) / sizeof( NameEntry * ); 163 | devUp( device ); 164 | 165 | CFDataRef data = AMDeviceCopyValue( device, CFSTR("com.apple.mobile.internal"), CFSTR("SysCfgData") ); 166 | //cfdump( 0, val ); 167 | unsigned long len = CFDataGetLength( data ); 168 | CFRange range = CFRangeMake(0,len); 169 | unsigned char *bytes = malloc( len ); 170 | CFDataGetBytes( data, range, (UInt8 *) bytes ); 171 | 172 | bswap( bytes ); 173 | printf("%.4s\n", bytes ); 174 | 175 | for( int i=0;i<25;i++ ) { 176 | printf("%02i ", i ); 177 | } 178 | printf("\n"); 179 | for( int i=0;i<25;i++ ) { 180 | printf("%02x ", *( bytes + i ) ); 181 | } 182 | 183 | printf("\n"); 184 | 185 | //bswap( (char *) bytes + 12 ); 186 | printf("Version: %s\n", hex4( bytes + 12 ) ); 187 | 188 | //bswap( (char *) bytes + 20 ); 189 | printf("Key count: %s\n", hex4( bytes + 20 ) ); 190 | uint32_t keyCount = * ( (uint32_t *) ( (unsigned char *) bytes + 20 ) ); 191 | printf("Key count: %i\n", keyCount ); 192 | 193 | uint32_t total = 0x18 + 0x14 * keyCount; 194 | uint32_t dataStart = total; 195 | for( int e=0;e= dataStart && entryStart <= len ) ) total += entryLen; 221 | 222 | bswap( entry ); 223 | bswap( entry + 4 ); 224 | 225 | unsigned char *namepos = entry; 226 | if( entry[0]=='C' && entry[1] == 'N' ) { 227 | namepos = entry + 4; 228 | } 229 | 230 | printf("Name:%.4s", namepos ); 231 | char name4[5]=" "; 232 | sprintf(name4,"%.4s", namepos ); 233 | char found = 0; 234 | for( int i=0;ishortx, name4 ) ) { 237 | printf(" -%s", entry->longx ); 238 | found = 1; 239 | } 240 | } 241 | printf("\n"); 242 | if( !found ) { 243 | printf("\n\n---- %s ----\n\n", name4); 244 | } 245 | 246 | printf("Length: %u\n", entryLen ); 247 | printf("Start: %u\n", entryStart ); 248 | } 249 | printf("\n"); 250 | printf("Total: %lu\n", (unsigned long) total ); 251 | printf("Size: %lu\n", (unsigned long) len ); 252 | printf("Diff: %i\n", (int) (total - len) ); 253 | devDown( device ); 254 | 255 | exit(0); 256 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 David Helkowski 2 | Free Use Anti-Corruption License 3 | https://faircoding.com/license 4 | 5 | ======================================================================= 6 | 7 | The content of this project is licensed for free conditional use by LICENSEE 8 | as defined below. The conditional aspect is detailed in THE RESTRICTION below. 9 | 10 | A DIRECT RESTRICTED ENTITY is defined to be any of the following: 11 | - Any company present on the current online list: https://faircoding.com/license/list 12 | - Accenture https://en.wikipedia.org/wiki/Accenture 13 | - Amazon https://en.wikipedia.org/wiki/Amazon_(company) 14 | - Apple 15 | - AptEdge https://aptedge.io 16 | - Avalara https://www.avalara.com 17 | - Baltimore Sun 18 | - BCG https://en.wikipedia.org/wiki/Boston_Consulting_Group 19 | - BrowserStack https://www.browserstack.com 20 | - The Canton Group https://cantongroup.com 21 | - Comcast 22 | - Cruise LLC https://en.wikipedia.org/wiki/Cruise_(autonomous_vehicle) 23 | - Disney 24 | - Ebay 25 | - Epic Games 26 | - EQT Partners https://en.wikipedia.org/wiki/EQT_Partners 27 | - Equifax 28 | - Experian 29 | - Extrahop https://www.extrahop.com 30 | - Facebook 31 | - FBI https://www.fbi.gov 32 | - Fox Entertainment Group 33 | - Google 34 | - Headspin https://www.headspin.io 35 | - IBM 36 | - Insight Global https://www.insightglobal.com 37 | - Jamf https://www.jamf.com 38 | - Kobiton https://www.kobiton.com 39 | - Logic 20/20 https://www.logic2020.com 40 | - Micro Focus https://en.wikipedia.org/wiki/Micro_Focus 41 | - MIT https://www.mit.edu 42 | - NBC 43 | - Nintendo https://en.wikipedia.org/wiki/Nintendo 44 | - Oracle Corporation https://en.wikipedia.org/wiki/Oracle_Corporation 45 | - Palantir 46 | - Perfecto https://www.perfecto.io 47 | - ProKarma https://pkglobal.com 48 | - Reddit https://reddit.com 49 | - Sauce Labs https://saucelabs.com 50 | - Sinclair https://en.wikipedia.org/wiki/Sinclair_Broadcast_Group 51 | - Smartbear https://smartbear.com 52 | - Sony Corporation https://en.wikipedia.org/wiki/Sony 53 | - Steam https://steampowered.com 54 | - Systems Alliance https://www.systemsalliance.com 55 | - SUSE https://en.wikipedia.org/wiki/SUSE 56 | - TEKsystems https://www.teksystems.com 57 | - Tesla https://www.tesla.com 58 | - TransUnion 59 | - T. Rowe Price https://en.wikipedia.org/wiki/T._Rowe_Price 60 | - UMB https://www.umaryland.edu 61 | - UMBC https://umbc.edu 62 | - UMCP https://www.umd.edu 63 | - Verizon 64 | - Wells Fargo 65 | - Ycombinator https://www.ycombinator.com 66 | - Zulily 67 | 68 | The links given are to clarify which entities exactly are meant. Should 69 | those links become invalid see the online list to find the latest updated 70 | website for the company/group. 71 | 72 | The online list may be updated at any time. If a company is added, causing 73 | a party to become a RESTRICTED ENTITY, then that party remains free to use 74 | versions of THE CONTENT created prior to becoming a RESTRICTED ENTITY under 75 | the license terms previous to the change. If this is a concern, it is suggested 76 | that LICENSEE fork THE CONTENT and opt to make use of the option to remove 77 | the online list described below in condition point 6. 78 | 79 | Changes made to THE CONTENT of any sort after the date of addition will be 80 | forbidden from use in that case, and those new changes are only licensed under 81 | the new license terms with the updated DIRECT RESTRICTED ENTITY list. 82 | 83 | A RESTRICTED ENTITY is defined to be any of the following: 84 | 1. A DIRECT RESTRICTED ENTITY 85 | 2. An owner of a RESTRICTED ENTITY 86 | 3. A subsidiary or any functional business unit of a RESTRICTED ENTITY 87 | 4. Any entity of which 50% or more of its annual revenue comes from work done 88 | for a RESTRICTED ENTITY 89 | 5. An entity that broke off from a RESTRICTED ENTITY ( such as a company 90 | splitting up into different legal entities ) 91 | 6. An international counterpart of a RESTRICTED ENTITY. 92 | 7. An employee of a RESTRICTED ENTITY 93 | 8. A contractor delivering work to a RESTRICTED ENTITY at more than 20hrs per week. 94 | 95 | A PARTIALLY RESTRICTED ENTITY is defined to be any of the following: 96 | 1. A contractor delivering work to a RESTRICTED ENTITY at less than 20hrs per week. 97 | 2. A person or legal entity acting under command, request, or legal contract 98 | by/with a RESTRICTED ENTITY. 99 | 100 | Should a PARTIALLY RESTRICTED ENTITY fall under any of the points defining them 101 | as A RESTRICTED ENTITY, they are not a PARTIALLY RESTRICTED ENTITY. 102 | 103 | A PARTIALLY RESTRICTED ENTITY shall be considered a RESTRICTED ENTITY to the extent 104 | that their usage of THE CONTENT is related to commands, requests, or legal contract 105 | with a RESTRICTED ENTITY. That is, A PARTIALLY RESTRICTED ENTITY cannot utilize 106 | THE CONTENT in any way in relation to a RESTRICTED ENTITY. 107 | 108 | A PARTIALLY RESTRICTED ENTITY remains able to be a LICENSEE of the content, to the 109 | extent that all usage and access to THE CONTENT remains within the license terms. 110 | That is, a PARTIALLY RESTRICTED ENTITY may utilize THE CONTENT in work related to 111 | other LICENSEE. They remain bound by THE RESTRICTION, prevented from enabling use 112 | of THE CONTENT by any RESTRICTED ENTITY. 113 | 114 | LICENSEE refers to any party ( person or legal entity ) who/that is not a 115 | RESTRICTED ENTITY and accepts this license by making use of THE CONTENT or 116 | utilizing any of the permissions provided by the license. 117 | 118 | THE CONTENT refers to the content in full, any portion of it, and anything 119 | derived from it. 120 | 121 | LICENSEE agrees not to provide THE CONTENT to any RESTRICTED ENTITY, nor to 122 | allow THE CONTENT to be used in any way by any RESTRICTED ENTITY. 123 | 124 | THE RESTRICTION is defined to be this license in full, specifically to 125 | refer to the way the license restricts use of THE CONTENT in any way by 126 | any RESTRICTED ENTITY. 127 | 128 | THE RESTRICTION shall apply to all projects with Copyright 129 | ownership by any RESTRICTED ENTITY. This shall remain true even if the 130 | project contributions themselves are done by a LICENSEE. LICENSEE 131 | are forbidden from contributing THE CONTENT to a project Copyrighted by 132 | any RESTRICTED ENTITY. 133 | 134 | Should any portion of this license be found to be unenforceable, the remaining 135 | portion of the license shall continue to be in effect, preserving the intent. 136 | The intent is to prevent any DIRECT RESTRICTED ENTITY from benefiting from 137 | THE CONTENT in any way. 138 | 139 | Should it be found or enacted into law that using such a restriction list is 140 | illegal as a whole, then the entire license shall dissolve and zero permissions 141 | given to anyone by the broken license. 142 | 143 | ======================================================================= 144 | 145 | Permission is hereby granted, free of charge, to LICENSEE, to conditionally 146 | use, modify, publish, distribute, or sell copies of THE CONTENT. 147 | 148 | These permissions are granted with the following conditions: 149 | 150 | 1. THE CONTENT may not be distributed or sold to any RESTRICTED ENTITY. 151 | 152 | 2. Access to a service containing or utilizing THE CONTENT may not be 153 | given, sold, or licensed to any RESTRICTED ENTITY. 154 | 155 | 3. Any service containing or utilizing THE CONTENT shall be considered a 156 | derivative of this license and therefore by bound by THE RESTRICTION. 157 | This includes use of THE CONTENT by way of dynamic libraries, indirect calls, 158 | scripting, virtualization, containerization, or instantiation as a remote 159 | callable service. Such restricted software must be prevented from being 160 | used by any RESTRICTED ENTITY. 161 | 162 | 4. THE CONTENT cannot be sold to any RESTRICTED ENTITY. 163 | 164 | 5. THE CONTENT may not be published to or distributed through a system 165 | owned or controlled by any RESTRICTED ENTITY. 166 | 167 | 6. Any derivatives of THE CONTENT must be licensed under this same license. 168 | By same license this means the contents of this LICENSE file in its 169 | entirety. The license "duplicate" may have the online restricted list removed, 170 | effectively fixing the DIRECT RESTRICTED ENTITY from that point onward for 171 | that derivative. At the moment in time of that removal, the online list must 172 | be checked, and any new DIRECT RESTRICTED ENTITY present in the online list 173 | added to the new updated fixed list in the license file. Besides that single 174 | permitted modification, the LICENSE may not be modified in any other way. 175 | 176 | 7. Any derivatives of THE CONTENT must be publicly released within 2 months 177 | of the change or discarded. 178 | 179 | 8. The above copyright notice and this LICENSE file must be included in 180 | all copies and derivative forms of THE CONTENT. 181 | 182 | 9. LICENSEE understands and agrees that this content is provided "as is", 183 | without warranty of any kind, express or implied, including but not limited 184 | to the warranties of merchantability, fitness for a particular purpose and 185 | noninfringement. In no event shall the authors or copyright holders be liable 186 | for any claim, damages or other liability, whether in an action of contract, 187 | tort or otherwise, arising from, out of or in connection with THE CONTENT or 188 | the use or other dealings of it. 189 | -------------------------------------------------------------------------------- /ujsonin/red_black_tree.c: -------------------------------------------------------------------------------- 1 | #include "red_black_tree.h" 2 | 3 | rb_red_blk_tree* RBTreeCreate( int (*CompFunc) (const void*,const void*), 4 | void (*DestFunc) (void*), 5 | void (*InfoDestFunc) (void*), 6 | void (*PrintFunc) (const void*), 7 | void (*PrintInfo)(void*)) { 8 | rb_red_blk_tree* newTree; 9 | rb_red_blk_node* temp; 10 | 11 | newTree=(rb_red_blk_tree*) malloc(sizeof(rb_red_blk_tree)); 12 | newTree->Compare= CompFunc; 13 | newTree->DestroyKey= DestFunc; 14 | newTree->PrintKey= PrintFunc; 15 | newTree->PrintInfo= PrintInfo; 16 | newTree->DestroyInfo= InfoDestFunc; 17 | 18 | temp=newTree->nil= (rb_red_blk_node*) malloc(sizeof(rb_red_blk_node)); 19 | temp->parent=temp->left=temp->right=temp; 20 | temp->red=0; 21 | temp->key=0; 22 | temp=newTree->root= (rb_red_blk_node*) malloc(sizeof(rb_red_blk_node)); 23 | temp->parent=temp->left=temp->right=newTree->nil; 24 | temp->key=0; 25 | temp->red=0; 26 | return(newTree); 27 | } 28 | 29 | void LeftRotate(rb_red_blk_tree* tree, rb_red_blk_node* x) { 30 | rb_red_blk_node* y; 31 | rb_red_blk_node* nil=tree->nil; 32 | y=x->right; 33 | x->right=y->left; 34 | if (y->left != nil) y->left->parent=x; 35 | y->parent=x->parent; 36 | if( x == x->parent->left) { 37 | x->parent->left=y; 38 | } else { 39 | x->parent->right=y; 40 | } 41 | y->left=x; 42 | x->parent=y; 43 | 44 | } 45 | 46 | void RightRotate(rb_red_blk_tree* tree, rb_red_blk_node* y) { 47 | rb_red_blk_node* x; 48 | rb_red_blk_node* nil=tree->nil; 49 | x=y->left; 50 | y->left=x->right; 51 | if (nil != x->right) x->right->parent=y; /*used to use sentinel here */ 52 | x->parent=y->parent; 53 | if( y == y->parent->left) { 54 | y->parent->left=x; 55 | } else { 56 | y->parent->right=x; 57 | } 58 | x->right=y; 59 | y->parent=x; 60 | } 61 | 62 | void TreeInsertHelp(rb_red_blk_tree* tree, rb_red_blk_node* z) { 63 | rb_red_blk_node* x; 64 | rb_red_blk_node* y; 65 | rb_red_blk_node* nil=tree->nil; 66 | 67 | z->left=z->right=nil; 68 | y=tree->root; 69 | x=tree->root->left; 70 | while( x != nil) { 71 | y=x; 72 | if (1 == tree->Compare(x->key,z->key)) { /* x.key > z.key */ 73 | x=x->left; 74 | } else { /* x,key <= z.key */ 75 | x=x->right; 76 | } 77 | } 78 | z->parent=y; 79 | if ( (y == tree->root) || 80 | (1 == tree->Compare(y->key,z->key))) { /* y.key > z.key */ 81 | y->left=z; 82 | } else { 83 | y->right=z; 84 | } 85 | 86 | } 87 | 88 | rb_red_blk_node * RBTreeInsert(rb_red_blk_tree* tree, void* key, void* info) { 89 | rb_red_blk_node * y; 90 | rb_red_blk_node * x; 91 | rb_red_blk_node * newNode; 92 | 93 | x=(rb_red_blk_node*) malloc(sizeof(rb_red_blk_node)); 94 | x->key=key; 95 | x->info=info; 96 | 97 | TreeInsertHelp(tree,x); 98 | newNode=x; 99 | x->red=1; 100 | while(x->parent->red) { /* use sentinel instead of checking for root */ 101 | if (x->parent == x->parent->parent->left) { 102 | y=x->parent->parent->right; 103 | if (y->red) { 104 | x->parent->red=0; 105 | y->red=0; 106 | x->parent->parent->red=1; 107 | x=x->parent->parent; 108 | } else { 109 | if (x == x->parent->right) { 110 | x=x->parent; 111 | LeftRotate(tree,x); 112 | } 113 | x->parent->red=0; 114 | x->parent->parent->red=1; 115 | RightRotate(tree,x->parent->parent); 116 | } 117 | } else { /* case for x->parent == x->parent->parent->right */ 118 | y=x->parent->parent->left; 119 | if (y->red) { 120 | x->parent->red=0; 121 | y->red=0; 122 | x->parent->parent->red=1; 123 | x=x->parent->parent; 124 | } else { 125 | if (x == x->parent->left) { 126 | x=x->parent; 127 | RightRotate(tree,x); 128 | } 129 | x->parent->red=0; 130 | x->parent->parent->red=1; 131 | LeftRotate(tree,x->parent->parent); 132 | } 133 | } 134 | } 135 | tree->root->left->red=0; 136 | return(newNode); 137 | 138 | } 139 | 140 | rb_red_blk_node* TreeSuccessor(rb_red_blk_tree* tree,rb_red_blk_node* x) { 141 | rb_red_blk_node* y; 142 | rb_red_blk_node* nil=tree->nil; 143 | rb_red_blk_node* root=tree->root; 144 | 145 | if (nil != (y = x->right)) { /* assignment to y is intentional */ 146 | while(y->left != nil) { /* returns the minium of the right subtree of x */ 147 | y=y->left; 148 | } 149 | return(y); 150 | } else { 151 | y=x->parent; 152 | while(x == y->right) { /* sentinel used instead of checking for nil */ 153 | x=y; 154 | y=y->parent; 155 | } 156 | if (y == root) return(nil); 157 | return(y); 158 | } 159 | } 160 | 161 | rb_red_blk_node* TreePredecessor(rb_red_blk_tree* tree, rb_red_blk_node* x) { 162 | rb_red_blk_node* y; 163 | rb_red_blk_node* nil=tree->nil; 164 | rb_red_blk_node* root=tree->root; 165 | 166 | if (nil != (y = x->left)) { /* assignment to y is intentional */ 167 | while(y->right != nil) { /* returns the maximum of the left subtree of x */ 168 | y=y->right; 169 | } 170 | return(y); 171 | } else { 172 | y=x->parent; 173 | while(x == y->left) { 174 | if (y == root) return(nil); 175 | x=y; 176 | y=y->parent; 177 | } 178 | return(y); 179 | } 180 | } 181 | 182 | void TreeForEach(rb_red_blk_tree *tree, void (*Func)(void*), rb_red_blk_node *x) { 183 | rb_red_blk_node* nil = tree->nil; 184 | rb_red_blk_node* root = tree->root; 185 | if( !x ) x = tree->root->left; 186 | if( x->left != nil ) TreeForEach( tree, Func, x->left ); 187 | Func( x->info ); 188 | if( x->right != nil ) TreeForEach( tree, Func, x->right ); 189 | } 190 | 191 | void TreeForEach1p(rb_red_blk_tree *tree, void (*Func)(void*,void*), void *param, rb_red_blk_node *x) { 192 | rb_red_blk_node* nil = tree->nil; 193 | rb_red_blk_node* root = tree->root; 194 | if( !x ) x = tree->root->left; 195 | if( x->left != nil ) TreeForEach1p( tree, Func, param, x->left ); 196 | Func( x->info, param ); 197 | if( x->right != nil ) TreeForEach1p( tree, Func, param, x->right ); 198 | } 199 | 200 | void TreeDestHelper(rb_red_blk_tree* tree, rb_red_blk_node* x) { 201 | rb_red_blk_node* nil=tree->nil; 202 | if (x != nil) { 203 | TreeDestHelper(tree,x->left); 204 | TreeDestHelper(tree,x->right); 205 | tree->DestroyKey(x->key); 206 | tree->DestroyInfo(x->info); 207 | free(x); 208 | } 209 | } 210 | 211 | void RBTreeDestroy(rb_red_blk_tree* tree) { 212 | TreeDestHelper(tree,tree->root->left); 213 | free(tree->root); 214 | free(tree->nil); 215 | free(tree); 216 | } 217 | 218 | rb_red_blk_node* RBExactQuery(rb_red_blk_tree* tree, void* q) { 219 | rb_red_blk_node* x=tree->root->left; 220 | rb_red_blk_node* nil=tree->nil; 221 | int compVal; 222 | if (x == nil) return(0); 223 | compVal=tree->Compare(x->key,(int*) q); 224 | while(0 != compVal) {/*assignemnt*/ 225 | if (1 == compVal) { /* x->key > q */ 226 | x=x->left; 227 | } else { 228 | x=x->right; 229 | } 230 | if ( x == nil) return(0); 231 | compVal=tree->Compare(x->key,(int*) q); 232 | } 233 | return(x); 234 | } 235 | 236 | void RBDeleteFixUp(rb_red_blk_tree* tree, rb_red_blk_node* x) { 237 | rb_red_blk_node* root=tree->root->left; 238 | rb_red_blk_node* w; 239 | 240 | while( (!x->red) && (root != x)) { 241 | if (x == x->parent->left) { 242 | w=x->parent->right; 243 | if (w->red) { 244 | w->red=0; 245 | x->parent->red=1; 246 | LeftRotate(tree,x->parent); 247 | w=x->parent->right; 248 | } 249 | if ( (!w->right->red) && (!w->left->red) ) { 250 | w->red=1; 251 | x=x->parent; 252 | } else { 253 | if (!w->right->red) { 254 | w->left->red=0; 255 | w->red=1; 256 | RightRotate(tree,w); 257 | w=x->parent->right; 258 | } 259 | w->red=x->parent->red; 260 | x->parent->red=0; 261 | w->right->red=0; 262 | LeftRotate(tree,x->parent); 263 | x=root; /* this is to exit while loop */ 264 | } 265 | } else { /* the code below is has left and right switched from above */ 266 | w=x->parent->left; 267 | if (w->red) { 268 | w->red=0; 269 | x->parent->red=1; 270 | RightRotate(tree,x->parent); 271 | w=x->parent->left; 272 | } 273 | if ( (!w->right->red) && (!w->left->red) ) { 274 | w->red=1; 275 | x=x->parent; 276 | } else { 277 | if (!w->left->red) { 278 | w->right->red=0; 279 | w->red=1; 280 | LeftRotate(tree,w); 281 | w=x->parent->left; 282 | } 283 | w->red=x->parent->red; 284 | x->parent->red=0; 285 | w->left->red=0; 286 | RightRotate(tree,x->parent); 287 | x=root; /* this is to exit while loop */ 288 | } 289 | } 290 | } 291 | x->red=0; 292 | } 293 | 294 | void RBDelete(rb_red_blk_tree* tree, rb_red_blk_node* z){ 295 | rb_red_blk_node* y; 296 | rb_red_blk_node* x; 297 | rb_red_blk_node* nil=tree->nil; 298 | rb_red_blk_node* root=tree->root; 299 | 300 | y= ((z->left == nil) || (z->right == nil)) ? z : TreeSuccessor(tree,z); 301 | x= (y->left == nil) ? y->right : y->left; 302 | if (root == (x->parent = y->parent)) { /* assignment of y->p to x->p is intentional */ 303 | root->left=x; 304 | } else { 305 | if (y == y->parent->left) { 306 | y->parent->left=x; 307 | } else { 308 | y->parent->right=x; 309 | } 310 | } 311 | if (y != z) { /* y should not be nil in this case */ 312 | 313 | /* y is the node to splice out and x is its child */ 314 | 315 | if (!(y->red)) RBDeleteFixUp(tree,x); 316 | 317 | tree->DestroyKey(z->key); 318 | tree->DestroyInfo(z->info); 319 | y->left=z->left; 320 | y->right=z->right; 321 | y->parent=z->parent; 322 | y->red=z->red; 323 | z->left->parent=z->right->parent=y; 324 | if (z == z->parent->left) { 325 | z->parent->left=y; 326 | } else { 327 | z->parent->right=y; 328 | } 329 | free(z); 330 | } else { 331 | tree->DestroyKey(y->key); 332 | tree->DestroyInfo(y->info); 333 | if (!(y->red)) RBDeleteFixUp(tree,x); 334 | free(y); 335 | } 336 | } -------------------------------------------------------------------------------- /service_deviceinfo.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"bytearr.h" 6 | #include 7 | #include"services.h" 8 | #include"service.h" 9 | #include"uclop.h" 10 | #include"cfutil.h" 11 | 12 | static ucmd *g_cmd = NULL; 13 | void runSmProcList( void *device ); 14 | void runSmSysList( void *device ); 15 | void runSmCoalList( void *device ); 16 | void runMachTimeInfo( void *device ); 17 | void runLs( void *device ); 18 | void runPs( void *device ); 19 | void runSysInfo( void *device ); 20 | 21 | void run_ls( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runLs ); } 22 | void run_ps( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runPs ); } 23 | void run_smProcList( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runSmProcList ); } 24 | void run_smSysList( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runSmSysList ); } 25 | void run_smCoalList( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runSmCoalList ); } 26 | void run_machTimeInfo( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runMachTimeInfo ); } 27 | void run_sysinfo( ucmd *cmd ) { g_cmd = cmd; waitForConnect( runSysInfo ); } 28 | 29 | void runSysInfo( void *device ) { 30 | if( !desired_device( device, g_cmd ) ) return; 31 | serviceT *service = service__new_instruments( device ); 32 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.deviceinfo" ); 33 | 34 | tBASE *ref; 35 | channel__call( chan, 36 | "systemInformation", NULL, 0, 37 | &ref, NULL 38 | ); 39 | tBASE__dump( ref, 1 ); 40 | 41 | service__del( service ); 42 | exit(0); 43 | } 44 | 45 | void runSmProcList( void *device ) { 46 | if( !desired_device( device, g_cmd ) ) return; 47 | serviceT *service = service__new_instruments( device ); 48 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.deviceinfo" ); 49 | 50 | //CFTypeRef ref; 51 | tBASE *ref; 52 | channel__call( chan, 53 | "sysmonProcessAttributes", NULL, 0, 54 | &ref, NULL 55 | ); 56 | //printf("%s",cftype( ls ) ); 57 | tBASE__dump( ref, 1 ); 58 | 59 | service__del( service ); 60 | exit(0); 61 | } 62 | 63 | void runSmSysList( void *device ) { 64 | if( !desired_device( device, g_cmd ) ) return; 65 | serviceT *service = service__new_instruments( device ); 66 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.deviceinfo" ); 67 | 68 | //CFTypeRef ref; 69 | tBASE *ref; 70 | channel__call( chan, 71 | "sysmonSystemAttributes", NULL, 0, 72 | &ref, NULL 73 | ); 74 | //printf("%s",cftype( ls ) ); 75 | tBASE__dump( ref, 1 ); 76 | 77 | service__del( service ); 78 | exit(0); 79 | } 80 | 81 | void runSmCoalList( void *device ) { 82 | if( !desired_device( device, g_cmd ) ) return; 83 | serviceT *service = service__new_instruments( device ); 84 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.deviceinfo" ); 85 | 86 | //CFTypeRef ref; 87 | tBASE *ref; 88 | channel__call( chan, 89 | "sysmonCoalitionAttributes", NULL, 0, 90 | &ref, NULL 91 | ); 92 | //printf("%s",cftype( ref ) ); 93 | tBASE__dump( ref, 1 ); 94 | 95 | service__del( service ); 96 | exit(0); 97 | } 98 | 99 | void runMachTimeInfo( void *device ) { 100 | if( !desired_device( device, g_cmd ) ) return; 101 | serviceT *service = service__new_instruments( device ); 102 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.deviceinfo" ); 103 | 104 | //CFTypeRef ls; 105 | tARR *arr; 106 | channel__call( chan, "machTimeInfo", NULL, 0, (tBASE **) &arr, NULL ); 107 | 108 | //uint16_t numerator = cfi16( CFArrayGetValueAtIndex( arr, 1 ) ); 109 | //uint16_t denominator = cfi16( CFArrayGetValueAtIndex( arr, 2 ) ); 110 | //uint64_t upTimeMach = cfi64( CFArrayGetValueAtIndex( arr, 3 ) ); 111 | uint16_t numerator = ( (tI16 *) tARR__get( arr, 1 ) )->val; 112 | uint16_t denominator = ( (tI16 *) tARR__get( arr, 2 ) )->val; 113 | uint64_t upTimeMach = ( (tI64 *) tARR__get( arr, 3 ) )->val; 114 | upTimeMach /= 1000000000; 115 | uint32_t cur = upTimeMach * numerator / denominator; 116 | 117 | uint8_t seconds = cur % 60; 118 | cur -= seconds; 119 | cur /= 60; 120 | 121 | uint8_t minutes = cur % 60; 122 | cur -= minutes; 123 | cur /= 60; 124 | 125 | uint8_t hours = cur % 24; 126 | cur -= hours; 127 | cur /= 24; 128 | 129 | printf("Uptime: %d days, %02d:%02d.%02d\n", cur, hours, minutes, seconds ); 130 | 131 | float time_factor = (float)numerator / (float)denominator; 132 | printf("Time factor: %.2f\n", time_factor ); 133 | 134 | printf("Mach absolute time: "); 135 | //cfdump(0,CFArrayGetValueAtIndex( arr, 0 )); 136 | tBASE__dump( tARR__get( arr, 0 ), 1 ); 137 | 138 | service__del( service ); 139 | exit(0); 140 | } 141 | 142 | void runLs( void *device ) { 143 | if( !desired_device( device, g_cmd ) ) return; 144 | 145 | serviceT *service = service__new_instruments( device ); 146 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.deviceinfo" ); 147 | 148 | //CFTypeRef ls; 149 | tBASE *ls; 150 | channel__call( chan, 151 | "directoryListingForPath:", (tBASE *) tSTR__new( g_cmd->argv[0] ), 0, 152 | &ls, NULL 153 | ); 154 | //cfdump( 1, ls ); 155 | tBASE__dump( ls, 1 ); 156 | 157 | service__del( service ); 158 | exit(0); 159 | } 160 | 161 | void runPs( void *device ) { 162 | if( !desired_device( device, g_cmd ) ) return; 163 | 164 | serviceT *service = service__new_instruments( device ); 165 | channelT *chan = service__connect_channel( service, "com.apple.instruments.server.services.deviceinfo" ); 166 | 167 | char subsec = ucmd__get( g_cmd, "-subsec" ) ? 1 : 0; 168 | char nameonly = ucmd__get( g_cmd, "-short" ) ? 1 : 0; 169 | char appsonly = ucmd__get( g_cmd, "-apps" ) ? 1 : 0; 170 | 171 | //CFTypeRef msg; 172 | tBASE *msg = NULL; 173 | 174 | channel__call( chan, 175 | "runningProcesses", NULL, 0, 176 | &msg, NULL 177 | ); 178 | if( !msg ) { 179 | service__del( service ); 180 | exit(0); 181 | } 182 | 183 | //cfdump( 1, msg ); 184 | 185 | char ok = 1; 186 | /*if( iscfarr( msg ) ) { 187 | CFArrayRef array = (CFArrayRef) msg; 188 | 189 | for( size_t i = 0, size = CFArrayGetCount(array); i < size; i++ ) { 190 | CFDictionaryRef dict = (CFDictionaryRef) CFArrayGetValueAtIndex(array, i); 191 | CFStringRef nameCf; 192 | if( nameonly ) { 193 | nameCf = (CFStringRef) CFDictionaryGetValue( dict, CFSTR("name") ); 194 | } 195 | else { 196 | nameCf = (CFStringRef) CFDictionaryGetValue( dict, CFSTR("realAppName") ); 197 | } 198 | char *name = str_cf2c( nameCf ); 199 | 200 | CFNumberRef _pid = (CFNumberRef) CFDictionaryGetValue( dict, CFSTR("pid") ); 201 | int32_t pid = 0; 202 | CFNumberGetValue( _pid, kCFNumberSInt32Type, &pid ); 203 | 204 | CFBooleanRef boolCf = (CFBooleanRef) CFDictionaryGetValue( dict, CFSTR("isApplication") ); 205 | char isapp = CFBooleanGetValue( boolCf ); 206 | if( appsonly && !isapp ) continue; 207 | 208 | CFDateRef start = (CFDateRef) CFDictionaryGetValue( dict, CFSTR("startDate") ); 209 | double unix = (double) CFDateGetAbsoluteTime( start ) + kCFAbsoluteTimeIntervalSince1970; 210 | 211 | if( subsec ) { 212 | printf( "{ pid:%d,\n path:\"%s\",\n start:%.2f },\n", pid, name, unix ); 213 | } 214 | else { 215 | uint32_t unixSec = (uint32_t) unix; 216 | printf( "{ pid:%d,\n path:\"%s\",\n start:%d },\n", pid, name, unixSec ); 217 | } 218 | } 219 | }*/ 220 | if( msg->type == xfARR ) { 221 | tARR *array = (tARR *) msg; 222 | 223 | char *oneApp = ucmd__get( g_cmd, "-appname" ); 224 | char *raw = ucmd__get( g_cmd, "-raw" ); 225 | 226 | uint8_t found = 0; 227 | for( size_t i = 0, size = array->count; i < size; i++ ) { 228 | tDICT *dict = (tDICT *) tARR__get( array, i ); 229 | if( dict->type == xfREF ) dict = (tDICT *) ( (tREF *) dict )->val; 230 | 231 | tSTR *shortNameT = (tSTR *) tDICT__get( dict, "name" ); 232 | if( shortNameT->type == xfREF ) shortNameT = (tSTR *) ( (tREF *) shortNameT )->val; 233 | 234 | //printf("Comparing %s with %s\n", shortNameT->val, oneApp ); 235 | if( oneApp && strcmp( shortNameT->val, oneApp ) ) continue; 236 | found = 1; 237 | if( raw ) { 238 | tBASE__dump( (tBASE *) dict, 1 ); 239 | break; 240 | } 241 | 242 | const char *shortName = shortNameT->val; 243 | 244 | tSTR *nameT; 245 | if( nameonly ) nameT = shortNameT; 246 | else nameT = (tSTR *) tDICT__get( dict, "realAppName" ); 247 | if( nameT->type == xfREF ) nameT = (tSTR *) ( (tREF *) nameT )->val; 248 | 249 | const char *name = nameT->val; 250 | tBASE *pidT = tDICT__get( dict, "pid" ); 251 | if( pidT->type == xfREF ) pidT = (tBASE *) ( (tREF *) pidT )->val; 252 | 253 | int32_t pid = tI__val32( pidT ); 254 | //CFNumberGetValue( _pid, kCFNumberSInt32Type, &pid ); 255 | 256 | //tBOOL *boolT = (tBOOL *) tDICT__get( dict, "isApplication" ); 257 | //char isapp = boolT->val; 258 | //if( appsonly && !isapp ) continue; 259 | 260 | //CFDateRef start = (CFDateRef) CFDictionaryGetValue( dict, CFSTR("startDate") ); 261 | //double unix = (double) CFDateGetAbsoluteTime( start ) + kCFAbsoluteTimeIntervalSince1970; 262 | tTIME *startT = (tTIME *) tDICT__get( dict, "startDate" ); 263 | double unix = 0; 264 | if( startT ) { 265 | if( startT->type == xfREF ) startT = (tTIME *) ( (tREF *) startT )->val; 266 | unix = startT->val;// + kCFAbsoluteTimeIntervalSince1970; 267 | } 268 | else continue; // mach_kernel has no startDate... just don't output it 269 | if( subsec ) { 270 | printf( "{ pid:%" PRIu32 ",\n path:\"%s\",\n start:%.2f,\n name:\"%s\" },\n", pid, name, unix, shortName ); 271 | } 272 | else { 273 | uint32_t unixSec = (uint32_t) unix; 274 | printf( "{ pid:%" PRIu32 ",\n path:\"%s\",\n start:%d,\n name:\"%s\" },\n", pid, name, unixSec, shortName ); 275 | } 276 | } 277 | if( oneApp && !found ) { 278 | fprintf( stderr, "Could not find running app with name %s\n", oneApp ); 279 | service__del( service ); 280 | exit(1); 281 | } 282 | } 283 | else { 284 | fprintf(stderr, "Process result not array; is: %s\n", cftype(msg) ); 285 | ok = 0; 286 | } 287 | 288 | //CFRelease( msg ); 289 | 290 | service__del( service ); 291 | exit(0); 292 | } -------------------------------------------------------------------------------- /cmd_dtxdump.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | //#include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include"uclop.h" 12 | #include"ujsonin/ujsonin.h" 13 | #include"cmd_dtxdump.h" 14 | #include"dtxmsg.h" 15 | #include"archiver/types.h" 16 | #include"archiver/archiver.h" 17 | #include"archiver/unarchiver.h" 18 | #include"cfutil.h" 19 | 20 | static ucmd *g_cmd = NULL; 21 | 22 | void run_dtxdump( ucmd *cmd ) { 23 | char *jsonFile = cmd->argv[0]; 24 | char *dataFile = cmd->argv[1]; 25 | 26 | dmsgList *list = dmsgList__new(); 27 | dump__messages( list, jsonFile, dataFile, 0 ); 28 | 29 | exit(0); 30 | } 31 | 32 | void dump_folder( dmsgList *list, char *folder ) { 33 | struct dirent *entry; 34 | DIR *dh = opendir( folder ); 35 | if( !dh ) return; 36 | 37 | char hasTo = 0; 38 | char hasFrom = 0; 39 | while( ( entry = readdir( dh ) ) != NULL ) { 40 | char *name = entry->d_name; 41 | if( name[0] == '.' ) continue; 42 | 43 | if( entry->d_type == DT_REG ) { 44 | //printf("%s/%s\n", folder, name ); 45 | if( !strcmp( name, "to-device.json" ) ) { 46 | hasTo = 1; 47 | } 48 | if( !strcmp( name, "from-device.json" ) ) { 49 | hasFrom = 1; 50 | } 51 | } 52 | if( entry->d_type == DT_DIR ) { 53 | //printf("DIR %s\n", name ); 54 | char sub[400]; 55 | sprintf( sub, "%s/%s", folder, name ); 56 | dump_folder( list, sub ); 57 | } 58 | //printf("%s\n", dir->d_name); 59 | } 60 | 61 | if( hasTo ) { 62 | char toJson[1000]; 63 | char toBin[1000]; 64 | sprintf(toJson,"%s/to-device.json",folder); 65 | sprintf(toBin,"%s/to-device.bin",folder); 66 | printf("%s\n%s\n======================\n",toJson,toBin); 67 | dump__messages( list, toJson, toBin, 0 ); 68 | } 69 | 70 | if( hasFrom ) { 71 | char fromJson[1000]; 72 | char fromBin[1000]; 73 | sprintf(fromJson,"%s/from-device.json",folder); 74 | sprintf(fromBin,"%s/from-device.bin",folder); 75 | printf("%s\n%s\n======================\n",fromJson,fromBin); 76 | dump__messages( list, fromJson, fromBin, 1 ); 77 | } 78 | 79 | closedir(dh); 80 | } 81 | 82 | int dmsg__compare( const void *av, const void *bv ) { 83 | dmsg **ap = (dmsg **) av; 84 | dmsg **bp = (dmsg **) bv; 85 | dmsg *a = *ap; 86 | dmsg *b = *bp; 87 | return strcmp( a->time, b->time ); 88 | } 89 | 90 | void run_dtxdumpfolder( ucmd *cmd ) { 91 | char *folder = cmd->argv[0]; 92 | 93 | dmsgList *list = dmsgList__new(); 94 | dump_folder( list, folder ); 95 | 96 | dmsg **flat = dmsgList__toPtrs( list ); 97 | 98 | qsort( flat, list->count, sizeof( dmsg * ), dmsg__compare ); 99 | 100 | for( uint16_t i=0;icount;i++ ) { 101 | dmsg *msg = flat[i]; 102 | if( msg == NULL ) { 103 | printf("null err\n"); 104 | exit(0); 105 | } 106 | decode_message( msg->ptr, msg->len, msg->time, msg->dir ); 107 | } 108 | 109 | exit(0); 110 | } 111 | 112 | dmsg *dmsg__new( uint8_t *ptr, uint16_t len, char *time, char dir ) { 113 | dmsg *self = (dmsg *) calloc( sizeof( dmsg ), 1 ); 114 | self->ptr = ( uint8_t * ) malloc( len ); 115 | memcpy( self->ptr, ptr, len ); 116 | self->len = len; 117 | self->time = time; 118 | self->dir = dir; 119 | return self; 120 | } 121 | 122 | void dmsg__delete( dmsg *self ) { 123 | free( self->ptr ); 124 | free( self->time ); 125 | free( self ); 126 | } 127 | 128 | dmsgList *dmsgList__new() { 129 | dmsgList *self = (dmsgList *) calloc( sizeof( dmsgList ), 1 ); 130 | return self; 131 | } 132 | 133 | dmsg **dmsgList__toPtrs( dmsgList *self ) { 134 | dmsg **ptrs = ( dmsg ** ) calloc( sizeof( dmsg * ) * self->count, 1 ); 135 | dmsg *msg = self->head; 136 | uint16_t i = 0; 137 | while( msg ) { 138 | ptrs[i++] = msg; 139 | msg = msg->next; 140 | } 141 | return ptrs; 142 | } 143 | 144 | void dmsgList__add( dmsgList *self, dmsg *msg ) { 145 | self->count++; 146 | 147 | if( !self->head ) { 148 | self->head = self->tail = msg; 149 | return; 150 | } 151 | self->tail->next = msg; 152 | self->tail = msg; 153 | } 154 | 155 | void dump__messages( dmsgList *list, char *jsonFile, char *binFile, char dir ) { 156 | printf("json File: %s\n", jsonFile ); 157 | printf("bin File: %s\n", binFile ); 158 | 159 | int flen; 160 | char *fdata = slurp_file( (char *) jsonFile, &flen ); 161 | if( !fdata ) { 162 | printf("Could not read %s\n", jsonFile ); 163 | return; 164 | } 165 | 166 | int dlen; 167 | char *ddata = slurp_file( (char *) binFile, &dlen ); 168 | if( !ddata ) { 169 | printf("Could not read %s\n", binFile ); 170 | } 171 | 172 | //printf("json len: %i\n", flen); 173 | //printf("data len: %i\n", dlen ); 174 | 175 | int ferr; 176 | 177 | int jsonStart = 0; 178 | int jsonEnd = 0; 179 | int pos = 0; 180 | int prevOffset = 0; 181 | char *timeDup = NULL; 182 | char *prevTime = NULL; 183 | while(1) { 184 | //printf("Json start:%i\n", pos ); 185 | jsonStart = pos; 186 | for( ;pos '9' ) break; 206 | } 207 | 208 | int tOffPos = jsonStart; 209 | for(;tOffPosstr; 232 | char offsetStr2[10]; 233 | memcpy( offsetStr2, offsetStr, offsetN->len ); 234 | offsetStr2[ offsetN->len -1 ] = 0x00; 235 | int offset = atoi( offsetStr2 ); 236 | 237 | int msgLen = offset - prevOffset;**/ 238 | char offsetStr[10]; 239 | sprintf(offsetStr, "%.*s", offEndPos-offPos, &fdata[offPos] ); 240 | int offset = atoi( offsetStr ); 241 | 242 | int msgLen = offset-prevOffset+1; 243 | 244 | if( offset != 0 ) { 245 | //printf("Message - From: %i to %i; len=%i\n", prevOffset, offset, msgLen ); 246 | dmsg *msg = dmsg__new( (uint8_t *) &ddata[ prevOffset ], msgLen, prevTime, dir ); 247 | dmsgList__add( list, msg ); 248 | //decode_message( (uint8_t *) &ddata[ prevOffset ], msgLen, prevTime ); 249 | } 250 | 251 | prevOffset = offset; 252 | prevTime = timeDup; 253 | 254 | if( pos == flen ) break; 255 | } 256 | dmsg *msg = dmsg__new( (uint8_t *) &ddata[ prevOffset ], dlen - prevOffset, prevTime, dir ); 257 | dmsgList__add( list, msg ); 258 | //decode_message( (uint8_t *) &ddata[ prevOffset ], dlen - prevOffset, prevTime ); 259 | 260 | //node_hash *root = parse( fdata, flen, NULL, &ferr ); 261 | } 262 | 263 | void dtxmsg__dump( dtxmsg *msg ) { 264 | //printf(" Fragment: %i/%i\n", msg->fragId+1, msg->fragCount ); 265 | //printf(" Length: %i\n", msg->length ); 266 | printf("id=\"%i.%i.%i\" ", msg->channelCode, msg->id, msg->conversationIndex ); 267 | if( msg->expectsReply ) printf("wantreply=\"1\" " ); 268 | } 269 | 270 | void dtxmsg__dumpack( dtxmsg *msg ) { 271 | //printf("Ack: "); 272 | //printf(" Fragment: %i/%i\n", msg->fragId+1, msg->fragCount ); 273 | //printf(" Length: %i\n", msg->length ); 274 | printf("id=\"%i.%i.%i\" ", msg->channelCode, msg->id, msg->conversationIndex ); 275 | //if( msg->expectsReply ) printf(" Expects Reply\n" ); 276 | } 277 | 278 | void payloadHeader__dump( dtxpayload *header ) { 279 | if( !header->type && !header->auxlen && !header->totlen && !header->flags ) { 280 | return; 281 | } 282 | 283 | //printf("Payload - "); 284 | printf("itype=\"%i\" ", header->type ); 285 | //printf(" Auxlen: %i\n", header->auxlen ); 286 | //printf(" Totlen: %i\n", header->totlen ); 287 | if( header->flags ) printf("flags=\"%i\" ", header->flags ); 288 | } 289 | 290 | void decode_message( uint8_t *buffer, int len, char *time, char dir ) { 291 | dtxmsg msg; 292 | int pos = 0; 293 | 294 | printf("\n\n"); 313 | return; 314 | } 315 | else { 316 | printf("type=\"msg\" "); 317 | if( dir == DIR_TO ) printf("dir=\"out\" "); 318 | else printf("dir=\"in\" "); 319 | 320 | dtxmsg__dump( &msg ); 321 | } 322 | 323 | payloadHeader__dump( &payloadHeader ); 324 | 325 | printf(">\n"); 326 | 327 | pos += sizeof( payloadHeader ); 328 | 329 | if( payloadHeader.auxlen ) { 330 | tARR *auxArr = (tARR *) deserialize2t( &buffer[pos], payloadHeader.auxlen ); 331 | if( auxArr == NULL ) { 332 | printf("Aux: decode failure\n"); 333 | } 334 | else { 335 | //printf(" count == 1 ) { 337 | tBASE *arg = auxArr->head; 338 | for( int i=0;icount;i++ ) { 339 | printf(" \n"); 342 | arg = arg->next; 343 | } 344 | //tBASE__dump( (tBASE *) auxArr->head, 1 ); 345 | //} 346 | //else { 347 | // tBASE__dump( (tBASE *) auxArr, 1 ); 348 | //} 349 | //printf("]]>\n"); 350 | } 351 | pos += payloadHeader.auxlen; 352 | } 353 | 354 | if( payloadHeader.totlen ) { 355 | int msgLen = payloadHeader.totlen - payloadHeader.auxlen; 356 | //printf("Raw msg:(%d)%.*s\n", msgLen, msgLen, &buffer[pos] ); 357 | 358 | if( msgLen ) { 359 | tBASE *tMsg = dearchive( (uint8_t *) &buffer[pos], msgLen ); 360 | if( tMsg == NULL ) { 361 | if( buffer[pos] == '<' ) { 362 | printf(" \n"); 364 | } 365 | else { 366 | printf(" \n"); 372 | } 373 | } 374 | else { 375 | printf(" \n"); 378 | } 379 | } 380 | } 381 | 382 | printf("\n"); 383 | //uint32_t auxlen = payloadHeader->auxlen; 384 | } -------------------------------------------------------------------------------- /archiver/unarchiver.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"unarchiver.h" 6 | #include"byteswap.h" 7 | 8 | #include"ptrarr.h" 9 | 10 | //#define UDEBUG 11 | 12 | typedef struct { 13 | uint32_t obCount; 14 | tBASE **obs; 15 | } tARCHIVE; 16 | 17 | tARCHIVE *tARCHIVE__new( uint32_t obCount, tBASE **obs ) { 18 | tARCHIVE *self = (tARCHIVE *) malloc( sizeof( tARCHIVE ) ); 19 | self->obCount = obCount; 20 | self->obs = obs; 21 | return self; 22 | } 23 | 24 | uint8_t willExpand( tBASE *self ) { 25 | if( self->type == xfREF ) self = ( (tREF *) self )->val; 26 | switch( self->type ) { 27 | case xfDICT: return 1; 28 | case xfARR: return 1; 29 | } 30 | return 0; 31 | } 32 | 33 | tBASE *tARCHIVE__expand( tARCHIVE *self, tBASE *ob ); 34 | 35 | tDICT *expandDict( tARCHIVE *self, tDICT *ob ) { 36 | if( !ob->keyHead ) return ob; 37 | 38 | tARR *keys = (tARR *) tDICT__get( (tDICT *) ob, "NS.keys" ); 39 | tARR *vals = (tARR *) tDICT__get( (tDICT *) ob, "NS.objects" ); 40 | tDICT *dict = tDICT__new(); 41 | uint32_t keyCount = keys->count; 42 | 43 | duprintf(" keycount=%d\n", keyCount); 44 | for( int i=0;itype == xfREF ) keyRef = (tARCID *) ( (tREF *) keyRef )->val; 48 | if( valRef->type == xfREF ) valRef = (tARCID *) ( (tREF *) valRef )->val; 49 | //duprintf(" key otype: %d, val otype: %d\n", keyRef->type, valRef->type ); 50 | tBASE *key = self->obs[ keyRef->val ]; 51 | tBASE *val = self->obs[ valRef->val ]; 52 | //duprintf(" key type: %d, val type: %d\n", key->type, val->type ); 53 | if( willExpand( val ) ) { 54 | duprintf("Subexpand\n"); 55 | val = tARCHIVE__expand( self, val ); 56 | } 57 | tDICT__seto( dict, tBASE__dup( key ), tREF__new( val ) ); 58 | } 59 | return dict; 60 | } 61 | 62 | tCAPS *expandCaps( tARCHIVE *self, tDICT *ob ) { 63 | //if( !ob->keyHead ) return ob; 64 | 65 | tBASE *capDict = tDICT__get( (tDICT *) ob, "capabilities-dictionary" ); 66 | if( capDict->type == xfREF ) capDict = (tBASE *) ( (tREF *) capDict )->val; 67 | if( capDict->type == xfARCID ) capDict = self->obs[ (( tARCID * ) capDict )->val ]; 68 | 69 | tDICT *capDictE = (tDICT *) expandDict( self, (tDICT *) capDict ); 70 | tCAPS *caps = tCAPS__new( capDictE ); 71 | 72 | return caps; 73 | } 74 | 75 | tDICT *expandTestConf( tARCHIVE *self, tDICT *ob ) { 76 | tDICT *dict = tDICT__new(); 77 | 78 | duprintf(" keycount=%d\n", ob->count); 79 | 80 | tBASE *curKey = ob->keyHead; 81 | for( int i=0; icount; i++ ) { 82 | tBASE *key = curKey; 83 | 84 | if( key->type == xfREF ) key = (tBASE *) ( (tREF *) key )->val; 85 | 86 | //if( key->type == xfARCID ) { 87 | // tARCID *keyRef = (tARCID *) ( (tREF *) key )->val; 88 | // key = self->obs[ keyRef->val ]; 89 | //} 90 | 91 | tSTR *keyStr = (tSTR *) key; 92 | tBASE *val = tDICT__get( ob, keyStr->val ); 93 | 94 | if( val->type == xfREF ) val = (tBASE *) ( (tREF *) val )->val; 95 | 96 | //printf("val type: %i\n", val->type ); 97 | if( val->type == xfARCID ) { 98 | tARCID *valRef = (tARCID *) val; 99 | val = self->obs[ valRef->val ]; 100 | 101 | //printf("val? %i\n", val ? 1 : 0 ); 102 | //printf("new val type: %i\n", val->type ); 103 | } 104 | 105 | if( strcmp( keyStr->val, "$class" ) && willExpand( val ) ) { 106 | duprintf("Subexpand\n"); 107 | val = tARCHIVE__expand( self, val ); 108 | } 109 | tDICT__seto( dict, tBASE__dup( key ), tREF__new( val ) ); 110 | 111 | curKey = curKey->next; 112 | if( !curKey ) break; 113 | } 114 | return dict; 115 | } 116 | 117 | tBASE *expandUUID( tARCHIVE *self, tDICT *ob ) { 118 | tDICT *dict = tDICT__new(); 119 | 120 | tARCID *classArcId = (tARCID *) tDICT__get( (tDICT *) ob, "$class" ); 121 | if( classArcId->type == xfREF ) classArcId = (tARCID *) ( (tREF *) classArcId )->val; 122 | tDICT *classDict = (tDICT *) self->obs[ classArcId->val ]; 123 | if( classDict->type == xfREF ) classDict = (tDICT *) ( (tREF *) classDict )->val; 124 | tSTR *classNameT = (tSTR *) tDICT__get( classDict, "$classname" ); 125 | tDICT__set( dict, "$class", classNameT ); 126 | 127 | tBASE *base = tDICT__get( ob, "NS.uuidbytes" ); 128 | if( base->type == xfREF ) base = ( (tREF *) base )->val; 129 | //if( base->type == xfARCID ) base = self->obs[ (( tARCID * ) base )->val ]; 130 | tDICT__set( dict, "NS.uuidbytes", tREF__new( base ) ); 131 | 132 | return (tBASE *) dict; 133 | } 134 | 135 | tBASE *expandURL( tARCHIVE *self, tDICT *ob ) { 136 | tDICT *dict = tDICT__new(); 137 | 138 | tARCID *classArcId = (tARCID *) tDICT__get( (tDICT *) ob, "$class" ); 139 | if( classArcId->type == xfREF ) classArcId = (tARCID *) ( (tREF *) classArcId )->val; 140 | tDICT *classDict = (tDICT *) self->obs[ classArcId->val ]; 141 | if( classDict->type == xfREF ) classDict = (tDICT *) ( (tREF *) classDict )->val; 142 | tSTR *classNameT = (tSTR *) tDICT__get( classDict, "$classname" ); 143 | tDICT__set( dict, "$class", classNameT ); 144 | 145 | tBASE *base = tDICT__get( ob, "NS.base" ); 146 | if( base->type == xfREF ) base = ( (tREF *) base )->val; 147 | if( base->type == xfARCID ) base = self->obs[ (( tARCID * ) base )->val ]; 148 | tDICT__set( dict, "NS.base", tREF__new( base ) ); 149 | 150 | tBASE *rel = tDICT__get( ob, "NS.relative" ); 151 | if( rel->type == xfREF ) rel = ( (tREF *) rel )->val; 152 | if( rel->type == xfARCID ) rel = self->obs[ (( tARCID * ) rel )->val ]; 153 | tDICT__set( dict, "NS.relative", tREF__new( rel ) ); 154 | 155 | return (tBASE *) dict; 156 | } 157 | 158 | tBASE *tARCHIVE__expand( tARCHIVE *self, tBASE *ob ) { 159 | if( ob->type == xfREF ) ob = ( (tREF *) ob )->val; 160 | 161 | if( ob->type == xfDICT ) { 162 | duprintf("Expanding dict/array\n"); 163 | tARCID *classArcId = (tARCID *) tDICT__get( (tDICT *) ob, "$class" ); 164 | //printf(" arcid type:%d\n", classArcId->type ); 165 | if( classArcId->type == xfREF ) classArcId = (tARCID *) ( (tREF *) classArcId )->val; 166 | //printf(" arcid:%d\n", classArcId->val ); 167 | tDICT *classDict = (tDICT *) self->obs[ classArcId->val ]; 168 | 169 | if( classDict->type == xfREF ) classDict = (tDICT *) ( (tREF *) classDict )->val; 170 | 171 | tSTR *classNameT = (tSTR *) tDICT__get( classDict, "$classname" ); 172 | if( !classNameT ) { 173 | printf("Could not find classname in dict\n"); 174 | tBASE__dump( (tBASE *) classDict, 1 ); 175 | } 176 | 177 | //printf("ClassnameT type:%d\n", classNameT->type ); 178 | const char *class; 179 | if( classNameT->type == xfREF ) { 180 | class = ((tSTR *) ( ( (tREF *) classNameT )->val ))->val; 181 | } 182 | else { 183 | class = classNameT->val; 184 | } 185 | 186 | //printf("Class:" ); 187 | //tBASE__dump( (tBASE *) classDict, 1 ); 188 | //printf("Ob:" ); 189 | //tBASE__dump( ob, 1 ); 190 | 191 | if( !strcmp( class, "NSURL" ) ) { 192 | return (tBASE *) expandURL( self, (tDICT *) ob ); 193 | } 194 | 195 | if( !strcmp( class, "NSUUID" ) ) { 196 | return (tBASE *) expandUUID( self, (tDICT *) ob ); 197 | } 198 | 199 | if( !strcmp( class, "NSDictionary" ) || 200 | !strcmp( class, "NSMutableDictionary" ) 201 | ) { 202 | duprintf("Expanding dict\n"); 203 | //printf(" done\n"); 204 | return (tBASE *) expandDict( self, (tDICT *) ob ); 205 | } 206 | 207 | if( !strcmp( class, "XCTestConfiguration" ) ) { 208 | duprintf("Expanding XCTestConfiguration\n"); 209 | //printf(" done\n"); 210 | return (tBASE *) expandTestConf( self, (tDICT *) ob ); 211 | } 212 | 213 | if( !strcmp( class, "XCTCapabilities" ) ) { 214 | duprintf("Expanding XCTCapabilities\n"); 215 | //printf(" done\n"); 216 | return (tBASE *) expandCaps( self, (tDICT *) ob ); 217 | } 218 | 219 | if( !strcmp( class, "NSArray" ) || 220 | !strcmp( class, "NSMutableArray" ) || 221 | !strcmp( class, "NSSet" ) || 222 | !strcmp( class, "NSMutableSet" ) 223 | ) { 224 | duprintf("Expanding array\n"); 225 | tARR *vals = (tARR *) tDICT__get( (tDICT *) ob, "NS.objects" ); 226 | tARR *arr = tARR__new(); 227 | uint32_t valCount = vals->count; 228 | 229 | duprintf("valcount=%d\n", valCount); 230 | for( int i=0;itype == xfREF ) valRef = (tARCID *) ( (tREF *) valRef )->val; 233 | duprintf("Adding val at %i\n", valRef->val ); 234 | 235 | tBASE *val = self->obs[ valRef->val ]; 236 | if( !val ) { 237 | printf("Could not grab %d from obs\n", valRef->val ); 238 | printf("Ob count %d\n", self->obCount ); 239 | } 240 | //tBASE__dump( val, 1 ); 241 | 242 | if( willExpand( val ) ) { 243 | if( val->type == xfREF ) val = ( (tREF *) val )->val; 244 | duprintf("Subexpand\n"); 245 | duprintf(" sub type:%d\n", val->type ); 246 | val = tARCHIVE__expand( self, val ); 247 | } 248 | tARR__add( arr, tREF__new( val ) ); 249 | } 250 | return (tBASE *) arr; 251 | } 252 | if( !strcmp( class, "NSDate" ) ) { 253 | duprintf("Expanding date\n"); 254 | tF2 *valT = (tF2 *) tDICT__get( (tDICT *) ob, "NS.time" ); 255 | valT->val += 978307200; 256 | //tBASE__dump( valT, 1 ); 257 | return (tBASE *) valT; 258 | } 259 | if( !strcmp( class, "DTSysmonTapMessage" ) ) { 260 | //printf("Contents of tap message:"); 261 | //tBASE__dump( ob, 1 ); 262 | tARCID *plistRef = (tARCID *) tDICT__get( (tDICT *) ob, "DTTapMessagePlist" ); 263 | tBASE *plist = self->obs[ plistRef->val ]; 264 | //tBASE__dump( plist, 1 ); 265 | return (tBASE *) expandDict( self, (tDICT *) plist ); 266 | } 267 | if( !strcmp( class, "NSError" ) ) { 268 | tDICT *obd = (tDICT *) ob; 269 | 270 | tDICT *res = tDICT__new(); 271 | tDICT__set( res, "Type", tSTR__new("NSError") ); 272 | tDICT__set( res, "NSCode", tDICT__get( obd, "NSCode" ) ); 273 | tARCID *userInfoRef = (tARCID *) tDICT__get( obd, "NSUserInfo" ); 274 | tBASE *userInfo = self->obs[ userInfoRef->val ]; 275 | printf("user info type:%d\n", userInfo->type ); 276 | tDICT__set( res, "NSUserInfo", expandDict( self, (tDICT *) userInfo ) ); 277 | printf("user info set\n"); 278 | //tARCID *domainRef = (tARCID *) tDICT__get( obd, "NSDomain" ); 279 | //if( !domainRef ) { 280 | // printf("Blank domain ref\n"); 281 | //} 282 | //printf("Domain ref type:%d\n", domainRef->type ); 283 | //tSTR *domain = (tSTR *) self->obs[ domainRef->val ]; 284 | //printf("domain type: %d\n", domain->type ); 285 | //printf("domain: %s\n", domain->val ); 286 | //tDICT__set( res, "NSDomain", domain ); 287 | 288 | return (tBASE *) res; 289 | } 290 | if( !strcmp( class, "NSNull" ) ) { 291 | return (tBASE *) tNULL__new(); 292 | } 293 | //printf("Other class:%s\n", class ); 294 | } 295 | return ob; 296 | } 297 | 298 | tBASE *dearchive( uint8_t *data, uint32_t len ) { 299 | //printf("raw data:%.*s\n", len, data ); 300 | bpList *list = bpList__new( data, len ); 301 | if( !list ) return NULL; 302 | tDICT *root = (tDICT *) list->obs->ptr[ 0 ]; 303 | 304 | #ifdef UDEBUG 305 | tBASE__dump( (tBASE *) root, 1 ); 306 | printf("root type:%d\n", root->type ); 307 | printf("------\n"); 308 | #endif 309 | 310 | tARR *obsT = (tARR *) tDICT__get( root, "$objects" ); 311 | duprintf("$objects type %d\n", obsT->type ); 312 | uint32_t count = obsT->count; 313 | if( obsT ) duprintf("Found $objects; count=%d\n", count ); 314 | 315 | tBASE **obs = (tBASE **) tARR__flatten( obsT ); 316 | duprintf("Flattened\n"); 317 | 318 | tARCHIVE *archive = tARCHIVE__new( count, obs ); 319 | 320 | //tBASE__dump( root, 1 ); 321 | tBASE *expanded = tARCHIVE__expand( archive, obs[1] ); 322 | #ifdef UDEBUG 323 | tBASE__dump( expanded, 1 ); 324 | #endif 325 | 326 | return expanded; 327 | } 328 | -------------------------------------------------------------------------------- /archiver/plist.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 David Helkowski 2 | // Anti-Corruption License 3 | 4 | #include 5 | #include"../bytearr.h" 6 | #include"byteswap.h" 7 | #include"types.h" 8 | #include"unarchiver.h" 9 | #include"plist.h" 10 | 11 | uint32_t tOBS__plist( tOBS *self, bytearr *ba, tOFFS *offs ) { 12 | tBASE *cur = self->head; 13 | uint32_t rootid; 14 | char doset = 1; 15 | while( cur ) { 16 | uint32_t itemid = tBASE__plist( offs, ba, cur ); 17 | if( doset ) { 18 | rootid = itemid; 19 | doset = 0; 20 | } 21 | cur = cur->next; 22 | } 23 | return rootid; 24 | } 25 | 26 | tARR * tOBS__2arr( tOBS *self ) { 27 | tBASE *cur = self->head; 28 | tARR *arr = tARR__new(); 29 | //tARR__add( arr, tSTR__new("") ); 30 | tARR__add( arr, tSTR__new("$null") ); 31 | //tARR__add( arr, tNULL__new() ); 32 | while( cur ) { 33 | tARR__add( arr, cur ); 34 | cur = cur->next; 35 | } 36 | return arr; 37 | } 38 | 39 | void tBOOL__plist( tOFFS *obs, bytearr *ba, tBOOL *self ) { 40 | uint8_t byte = self->val ? 0b00001001 : 0b00001000; 41 | bytearr__appendu8( ba, byte ); 42 | } 43 | 44 | void tNULL__plist( tOFFS *obs, bytearr *ba, tNULL *self ) { 45 | uint8_t byte = 0x00; 46 | bytearr__appendu8( ba, byte ); 47 | } 48 | 49 | void tI8__plist( tOFFS *obs, bytearr *ba, tI8 *self ) { 50 | uint8_t byte = 0b00010000; 51 | bytearr__appendu8( ba, byte ); 52 | bytearr__appdup( ba, (uint8_t *) &self->val, 1 ); 53 | } 54 | 55 | void tI16__plist( tOFFS *offs, bytearr *ba, tI16 *self ) { 56 | uint8_t byte = 0b00010001; 57 | bytearr__appendu8( ba, byte ); 58 | int16_t val = bswap_i16( self->val ); 59 | bytearr__appdup( ba, (uint8_t *) &val, 2 ); 60 | } 61 | 62 | void tI32__plist( tOFFS *offs, bytearr *ba, tI32 *self ) { 63 | uint8_t byte = 0b00010010; 64 | bytearr__appendu8( ba, byte ); 65 | int32_t val = bswap_i32( self->val ); 66 | bytearr__appdup( ba, (uint8_t *) &val, 4 ); 67 | } 68 | 69 | void tI64__plist( tOFFS *offs, bytearr *ba, tI64 *self ) { 70 | uint8_t byte = 0b00010011; 71 | bytearr__appendu8( ba, byte ); 72 | int64_t val = bswap_i64( self->val ); 73 | bytearr__appdup( ba, (uint8_t *) &val, 8 ); 74 | } 75 | 76 | void tF1__plist( tOFFS *offs, bytearr *ba, tF1 *self ) { 77 | uint8_t byte = 0b00100001; 78 | // TODO 79 | } 80 | 81 | void tF2__plist( tOFFS *offs, bytearr *ba, tF2 *self ) { 82 | uint8_t byte = 0b00100010; 83 | // TODO 84 | } 85 | 86 | void tTIME__plist( tOFFS *offs, bytearr *ba, tTIME *self ) { 87 | uint8_t byte = 0b00110000; 88 | // TODO 89 | } 90 | 91 | void tDATA__plist( tOFFS *offs, bytearr *ba, tDATA *self ) { 92 | uint8_t byte = 0b01000000; 93 | int sizelen = 0; 94 | uint8_t *sizebuf = encodeSize( self->len, &sizelen ); 95 | if( sizelen ) { 96 | byte |= 0b1111; 97 | bytearr__appendu8( ba, byte ); 98 | bytearr__appdup( ba, sizebuf, sizelen ); 99 | } 100 | else { 101 | byte |= self->len; 102 | bytearr__appendu8( ba, byte ); 103 | } 104 | if( self->len ) bytearr__appdup( ba, (uint8_t *) self->val, self->len ); 105 | } 106 | 107 | uint8_t *encodeSize( uint32_t val, int *len ) { 108 | if( val < 0b1111 ) { 109 | *len = 0; 110 | return 0; 111 | } 112 | if( val < INT8_MAX ) { 113 | *len = 2; 114 | uint8_t *buf = (uint8_t *) malloc(2); 115 | *buf = 0x10; 116 | *(buf+1) = val; 117 | return buf; 118 | } 119 | if( val < INT16_MAX ) { 120 | *len = 3; 121 | uint8_t *buf = (uint8_t *) malloc(3); 122 | *buf = 0x11; 123 | *( (uint16_t *) (buf+1) ) = bswap_u16( val ); 124 | return buf; 125 | } 126 | *len = 5; 127 | uint8_t *buf = (uint8_t *) malloc(5); 128 | *buf = 0x12; 129 | *( (uint32_t *) (buf+1) ) = bswap_u32( val ); 130 | return buf; 131 | } 132 | 133 | void tSTR__plist( tOFFS *offs, bytearr *ba, tSTR *self ) { 134 | uint8_t byte = 0b01010000; 135 | int sizelen = 0; 136 | uint16_t len = strlen( self->val ); 137 | uint8_t *sizebuf = encodeSize( len, &sizelen ); 138 | if( sizelen ) { 139 | byte |= 0b1111; 140 | bytearr__appendu8( ba, byte ); 141 | //if( sizelen == 1 ) bytearr__appendu8( ba, 0x10 ); 142 | //if( sizelen == 2 ) bytearr__appendu8( ba, 0x11 ); 143 | bytearr__appdup( ba, sizebuf, sizelen ); 144 | } 145 | else { 146 | if( len ) { 147 | byte |= len; 148 | } 149 | bytearr__appendu8( ba, byte ); 150 | } 151 | bytearr__appdup( ba, (uint8_t *) self->val, len ); 152 | } 153 | 154 | void tARCID__plist( tOFFS *offs, bytearr *ba, tARCID *self ) { 155 | uint8_t byte = 0b10000000; 156 | int32_t val1 = self->val; 157 | if( val1 <= INT8_MAX ) { 158 | //byte |= 0b0000; 159 | bytearr__appendu8( ba, byte ); 160 | bytearr__appdup( ba, (uint8_t *) &val1, 1 ); 161 | return; 162 | } 163 | if( val1 <= INT16_MAX ) { 164 | byte |= 0b0001; 165 | bytearr__appendu8( ba, byte ); 166 | int16_t val16 = val1; 167 | int16_t val = bswap_i16( val16 ); 168 | bytearr__appdup( ba, (uint8_t *) &val, 2 ); 169 | return; 170 | } 171 | byte |= 0b0011; 172 | bytearr__appendu8( ba, byte ); 173 | int16_t val16 = val1; 174 | int32_t val = bswap_i32( val16 ); 175 | bytearr__appdup( ba, (uint8_t *) &val, 4 ); 176 | } 177 | 178 | uint16_t tARR__plist( tOFFS *offs, bytearr *ba, tARR *self ) { 179 | uint8_t byte = 0b10100000; 180 | 181 | uint16_t offset = ba->len; 182 | 183 | // encode type and length 184 | int sizelen = 0; 185 | uint8_t *sizebuf = encodeSize( self->count, &sizelen ); 186 | if( sizelen ) { 187 | byte |= 0b1111; 188 | bytearr__appendu8( ba, byte ); 189 | bytearr__appdup( ba, sizebuf, sizelen ); 190 | } 191 | else { 192 | byte |= self->count; 193 | bytearr__appendu8( ba, byte ); 194 | } 195 | 196 | bytechunk *chunk = ba->tail; 197 | for( uint32_t i=0;icount;i++ ) { 198 | bytearr__appendu16( ba, 0 ); 199 | } 200 | bytechunk *entry = chunk->next; 201 | 202 | tBASE *val = self->head; 203 | for( uint32_t i=0;icount;i++ ) { 204 | uint32_t oid = tBASE__plist( offs, ba, val ); 205 | //bytearr__appendu16( ba, bswap_u16( oid ) ); 206 | uint16_t oid2 = bswap_u16( oid ); 207 | memcpy( entry->data, &oid2, 2 ); 208 | entry = entry->next; 209 | val = val->next; 210 | } 211 | 212 | return offset; 213 | } 214 | 215 | uint16_t tDICT__plist( tOFFS *offs, bytearr *ba, tDICT *self ) { 216 | uint8_t byte = 0b11010000; 217 | 218 | uint16_t offset = ba->len; 219 | 220 | // encode type and length 221 | int sizelen = 0; 222 | uint8_t *sizebuf = encodeSize( self->count, &sizelen ); 223 | if( sizelen ) { 224 | byte |= 0b1111; 225 | bytearr__appendu8( ba, byte ); 226 | bytearr__appdup( ba, sizebuf, sizelen ); 227 | } 228 | else { 229 | byte |= self->count; 230 | bytearr__appendu8( ba, byte ); 231 | } 232 | 233 | bytechunk *keyentry = ba->tail; 234 | for( uint32_t i=0;icount;i++ ) { 235 | bytearr__appendu16( ba, 0 ); 236 | } 237 | keyentry = keyentry->next; 238 | 239 | bytechunk *valentry = ba->tail; 240 | for( uint32_t i=0;icount;i++ ) { 241 | bytearr__appendu16( ba, 0 ); 242 | } 243 | valentry = valentry->next; 244 | 245 | tBASE *key = self->keyHead; 246 | for( uint32_t i=0;icount;i++ ) { 247 | uint16_t koid = tBASE__plist( offs, ba, key ); 248 | //printf("Key id: %d\n", koid ); 249 | //bytearr__appendu16( ba2, bswap_u16( koid ) ); 250 | uint16_t koid2 = bswap_u16( koid ); 251 | memcpy( keyentry->data, &koid2, 2 ); 252 | key = key->next; 253 | keyentry = keyentry->next; 254 | } 255 | 256 | tBASE *val = self->valHead; 257 | for( uint32_t i=0;icount;i++ ) { 258 | uint16_t oid = tBASE__plist( offs, ba, val ); 259 | //printf("Val id: %d\n", oid ); 260 | //bytearr__appendu16( ba2, bswap_u16( oid ) ); 261 | uint16_t oid2 = bswap_u16( oid ); 262 | memcpy( valentry->data, &oid2, 2 ); 263 | val = val->next; 264 | valentry = valentry->next; 265 | } 266 | 267 | return offset; 268 | } 269 | 270 | char *typeText( uint8_t num ) { 271 | switch(num) { 272 | case xfI8: return "i8"; 273 | case xfI16: return "i16"; 274 | case xfI32: return "i32"; 275 | case xfI64: return "i64"; 276 | case xfBOOL: return "bool"; 277 | case xfSTR: return "str"; 278 | case xfARR: return "arr"; 279 | case xfDICT: return "dict"; 280 | case xfARCID: return "arcid"; 281 | case xfREF: return "ref"; 282 | case xfDATA: return "data"; 283 | case xfNULL: return "null"; 284 | case xfOBS: return "obs"; 285 | } 286 | return "?"; 287 | } 288 | 289 | uint16_t tBASE__plist( tOFFS *offs, bytearr *ba, tBASE *ob ) { 290 | uint16_t offset = ba->len; 291 | if( ob->type == xfREF ) return tBASE__plist( offs, ba, ( (tREF *) ob )->val ); 292 | if( ob->type == xfOBS ) return tOBS__plist( (tOBS *) ob, ba, offs ); 293 | uint16_t index = tOFFS__add( offs, offset ); 294 | switch( ob->type ) { 295 | case xfI8: tI8__plist( offs, ba, (tI8 *) ob ); break; 296 | case xfI16: tI16__plist( offs, ba, (tI16 *) ob ); break; 297 | case xfI32: tI32__plist( offs, ba, (tI32 *) ob ); break; 298 | case xfI64: tI64__plist( offs, ba, (tI64 *) ob ); break; 299 | case xfBOOL: tBOOL__plist( offs, ba, (tBOOL *) ob ); break; 300 | case xfSTR: tSTR__plist( offs, ba, (tSTR *) ob ); break; 301 | case xfARR: tARR__plist( offs, ba, (tARR *) ob ); break; 302 | case xfDICT: tDICT__plist( offs, ba, (tDICT *) ob ); break; 303 | case xfARCID: tARCID__plist( offs, ba, (tARCID *) ob ); break; 304 | case xfDATA: tDATA__plist( offs, ba, (tDATA *) ob ); break; 305 | case xfNULL: tNULL__plist( offs, ba, (tNULL *) ob ); break; 306 | default: return 0; 307 | } 308 | //printf("Writing %s to offset %02x\n", typeText( ob->type ), offset ); 309 | return index; 310 | } 311 | 312 | uint8_t *tBASE__tobin( tBASE *self, uint32_t *len ) { 313 | tOFFS *offs = tOFFS__new( self ); 314 | bytearr *ba = bytearr__new(); 315 | bytearr__append( ba, (uint8_t *) "bplist00", 8, 0 ); 316 | 317 | uint32_t rootNum = tBASE__plist( offs, ba, self ); 318 | 319 | //printf("Root ob num: %d\n", rootNum ); 320 | 321 | // Note the location of the offsets table 322 | uint32_t offsetsPos = ba->len; 323 | //printf("Offsets position: %d\n", offsetsPos ); 324 | 325 | uint8_t offBytes = 1; 326 | if( offsetsPos > INT8_MAX ) { 327 | offBytes = 2; 328 | } else if( offsetsPos > INT16_MAX ) { 329 | offBytes = 4; 330 | } 331 | 332 | // Write the offsets table 333 | uint16_t numOffs = offs->len; 334 | tOFF *curOff = offs->head; 335 | for( uint16_t i=0;ioffset ); 337 | if( offBytes == 1 ) { 338 | bytearr__appendu8( ba, curOff->offset ); 339 | } else if( offBytes == 2 ) { 340 | bytearr__appendu16( ba, bswap_u16( curOff->offset ) ); 341 | } else if( offBytes == 4 ) { 342 | bytearr__appendu32( ba, bswap_u32( curOff->offset ) ); 343 | } 344 | curOff = curOff->next; 345 | } 346 | 347 | //printf("Number of objects: %d\n", numOffs ); 348 | 349 | // Write the trailer 350 | bpList__encodeTrailer( ba, numOffs, offsetsPos, rootNum, offBytes ); 351 | 352 | uint8_t *bytes = bytearr__bytes( ba, len ); 353 | 354 | return bytes; 355 | } 356 | 357 | uint8_t *tBASE__archivebin( tBASE *self, uint32_t *len ) { 358 | tOBS *obs = tOBS__new( self ); 359 | 360 | tDICT *root = tDICT__newPairs( 8, 361 | "$objects", (tBASE *) tOBS__2arr( obs ), 362 | "$top", tDICT__newPairs( 2, 363 | "root", tARCID__new( 1 ) 364 | ), 365 | "$version", tI32__new( 100000 ), 366 | "$archiver", tSTR__new( "NSKeyedArchiver" ) 367 | ); 368 | 369 | #ifdef DEBUG2 370 | tBASE__dump( (tBASE *) root, 1 ); 371 | #endif 372 | //tBASE__dumpxml( (tBASE *) root ); 373 | 374 | return tBASE__tobin( (tBASE *) root, len ); 375 | } 376 | 377 | void bpList__encodeTrailer( bytearr *ba, uint32_t numObs, uint32_t offsetsPos, uint32_t rootNum, uint8_t offBytes ) { 378 | // Initial blank 6 bytes 379 | bytearr__appendu32( ba, 0 ); // 0-3 380 | bytearr__appendu16( ba, 0 ); // 4-5 381 | 382 | bytearr__appendu8( ba, offBytes ); // 6 bytes per offset 383 | bytearr__appendu8( ba, 2 ); // 7 bytes per ref 384 | 385 | bytearr__appendu32( ba, 0 ); // 8-11 386 | bytearr__appendu32( ba, bswap_u32( numObs ) ); // 12-15 max ob num 387 | 388 | bytearr__appendu32( ba, 0 ); // 16-19 389 | bytearr__appendu32( ba, bswap_u32( rootNum ) ); // 20-23 root ob num 390 | 391 | bytearr__appendu32( ba, 0 ); // 24-27 392 | bytearr__appendu32( ba, bswap_u32( offsetsPos ) ); // 28-31 offsets pos 393 | } --------------------------------------------------------------------------------