From f4c4b783c8dbe2fe8e7e6f6b5f19f0d44b489c9a Mon Sep 17 00:00:00 2001 From: Zach C Date: Sun, 31 Aug 2008 11:25:22 -0700 Subject: Added binary-plist support (tweaked slightly to move stuff around) Signed-off-by: Matt Colyer fix makefile to take correct main function into account --- dev/Makefile.am | 9 +- dev/plutil.c | 171 ++++++++++++++++++++++++++++++++++ dev/plutil.h | 13 +++ src/AFC.c | 46 ++++----- src/AFC.h | 10 +- src/lockdown.c | 14 +-- src/plist.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/plist.h | 38 ++++++++ src/usbmux.c | 2 +- src/usbmux.h | 20 ++-- 10 files changed, 557 insertions(+), 50 deletions(-) create mode 100644 dev/plutil.c create mode 100644 dev/plutil.h diff --git a/dev/Makefile.am b/dev/Makefile.am index 4833728..95b4d61 100644 --- a/dev/Makefile.am +++ b/dev/Makefile.am @@ -3,7 +3,7 @@ INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = $(libxml2_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g AM_LDFLAGS = $(libxml2_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) -bin_PROGRAMS = iphoneclient lckd-client afccheck +bin_PROGRAMS = iphoneclient lckd-client afccheck plutil iphoneclient_SOURCES = main.c iphoneclient_LDADD = ../src/libiphone.la @@ -16,4 +16,9 @@ lckd_client_LDADD = ../src/libiphone.la afccheck_SOURCES = afccheck.c afccheck_CFLAGS = $(AM_CFLAGS) afccheck_LDFLAGS = $(AM_LDFLAGS) -afccheck_LDADD = ../src/libiphone.la \ No newline at end of file +afccheck_LDADD = ../src/libiphone.la + +plutil_SOURCES = plutil.c +plutil_CFLAGS = $(AM_CFLAGS) +plutil_LDFLAGS = $(AM_LDFLAGS) +plutil_LDADD = ../src/libiphone.la diff --git a/dev/plutil.c b/dev/plutil.c new file mode 100644 index 0000000..208d7df --- /dev/null +++ b/dev/plutil.c @@ -0,0 +1,171 @@ +/* + * main.c for plistutil + * right now just prints debug shit + */ + +#include "../src/plist.h" +#include "plutil.h" + +int debug = 0; + +void print_nodes(bplist_node *root_node) { + // Yay, great. Let's print the list of nodes recursively... + int i = 0; + if (!root_node) return; // or not, because the programmer's stupid. + + switch (root_node->type) { + case BPLIST_DICT: + printf("Dictionary node.\nLength %i\n", root_node->length); + for (i = 0; i < (root_node->length * 2); i+=2) { + // HI! + printf("Key: "); + print_nodes(root_node->subnodes[i]); + printf("Value: "); + print_nodes(root_node->subnodes[i+1]); + } + printf("End dictionary node.\n\n"); + break; + + case BPLIST_ARRAY: + printf("Array node.\n"); + for (i = 0; i < root_node->length; i++) { + printf("\tElement %i: ", i); + print_nodes(root_node->subnodes[i]); + } + break; + + case BPLIST_INT: + if (root_node->length == sizeof(uint8_t)) { + printf("Integer: %i\n", root_node->intval8); + } else if (root_node->length == sizeof(uint16_t)) { + printf("Integer: %i\n", root_node->intval16); + } else if (root_node->length == sizeof(uint32_t)) { + printf("Integer: %i\n", root_node->intval32); + } + break; + + case BPLIST_STRING: + case BPLIST_DATA: + printf("String/data: "); + fwrite(root_node->strval, sizeof(char), root_node->length, stdout); + fflush(stdout); + printf("\n"); + break; + + case BPLIST_UNICODE: + printf("Unicode data, may appear crappy: "); + fwrite(root_node->unicodeval, sizeof(wchar_t), root_node->length, stdout); + fflush(stdout); + printf("\n"); + break; + + case BPLIST_TRUE: + printf("True.\n"); + break; + + case BPLIST_FALSE: + printf("False.\n"); + break; + + case BPLIST_REAL: + case BPLIST_DATE: + printf("Real(?): %f\n", root_node->realval); + break; + + default: + printf("oops\nType set to %x and length is %i\n", root_node->type, root_node->length); + break; + } +} + +int main(int argc, char *argv[]) { + struct stat *filestats = (struct stat *)malloc(sizeof(struct stat)); + uint32_t position = 0; + Options *options = parse_arguments(argc, argv); + int argh = 0; + + printf("plistutil version 0.2 written by FxChiP\n"); + + if (!options) { + print_usage(); + return 0; + } + + debug = options->debug; + + FILE *bplist = fopen(options->in_file, "r"); + + stat(options->in_file, filestats); + + printf("here?\n"); + char *bplist_entire = (char*)malloc(sizeof(char) * (filestats->st_size + 1)); + //argh = fgets(bplist_entire, filestats->st_size, bplist); + argh = fread(bplist_entire, sizeof(char), filestats->st_size, bplist); + printf("read %i bytes\n", argh); + fclose(bplist); + printf("or here?\n"); + // bplist_entire contains our stuff + bplist_node *root_node; + root_node = parse_nodes(bplist_entire, filestats->st_size, &position); + printf("plutil debug mode\n\n"); + printf("file size %i\n\n", filestats->st_size); + if (!root_node) { + printf("Invalid binary plist (or some other error occurred.)\n"); + return 0; + } + print_nodes(root_node); + return 0; + } + +Options *parse_arguments(int argc, char *argv[]) { + int i = 0; + + Options *options = (Options*)malloc(sizeof(Options)); + memset(options, 0, sizeof(Options)); + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--infile") || !strcmp(argv[i], "-i")) { + if ((i+1) == argc) { + free(options); + return NULL; + } + options->in_file = argv[i+1]; + i++; + continue; + } + + if (!strcmp(argv[i], "--outfile") || !strcmp(argv[i], "-o")) { + if ((i+1) == argc) { + free(options); + return NULL; + } + options->out_file = argv[i+1]; + i++; + continue; + } + + if (!strcmp(argv[i], "--debug") || !strcmp(argv[i], "-d") || !strcmp(argv[i], "-v")) { + options->debug = 1; + } + + if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) { + free(options); + return NULL; + } + } + + if (!options->in_file /*|| !options->out_file*/) { + free(options); + return NULL; + } + + return options; +} + +void print_usage() { + printf("Usage: plistutil -i|--infile in_file.plist -o|--outfile out_file.plist [--debug]\n"); + printf("\n"); + printf("\t-i or --infile: The file to read in.\n"); + printf("\t-o or --outfile: The file to convert to.\n"); + printf("\t-d, -v or --debug: Provide extended debug information.\n\n"); +} diff --git a/dev/plutil.h b/dev/plutil.h new file mode 100644 index 0000000..2146307 --- /dev/null +++ b/dev/plutil.h @@ -0,0 +1,13 @@ + +/* + * main.h - header for plistutil + * Written by FxChiP + */ + +typedef struct _options { + char *in_file, *out_file; + uint8_t debug, in_fmt, out_fmt; +} Options; + +Options *parse_arguments(int argc, char *argv[]); +void print_usage(); diff --git a/src/AFC.c b/src/AFC.c index 54ea1bb..899bd47 100644 --- a/src/AFC.c +++ b/src/AFC.c @@ -245,7 +245,7 @@ static int receive_AFC_data(iphone_afc_client_t client, char **dump_here) return retval; } - uint32 param1 = buffer[sizeof(AFCPacket)]; + uint32_t param1 = buffer[sizeof(AFCPacket)]; free(buffer); if (r_packet->operation == AFC_ERROR && !(client->afc_packet->operation == AFC_DELETE && param1 == 7)) { @@ -474,7 +474,7 @@ iphone_error_t iphone_afc_delete_file(iphone_afc_client_t client, const char *pa iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *from, const char *to) { char *response = NULL; - char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); + char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t))); int bytes = 0; if (!client || !from || !to || !client->afc_packet || !client->connection) @@ -660,7 +660,7 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename, iphone_afc_file_mode_t file_mode, iphone_afc_file_t * file) { iphone_afc_file_t file_loc = NULL; - uint32 ag = 0; + uint32_t ag = 0; int bytes = 0, length = 0; char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1)); @@ -795,7 +795,7 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file, { char *acknowledgement = NULL; const int MAXIMUM_WRITE_SIZE = 1 << 15; - uint32 zero = 0, bytes_loc = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0; + uint32_t zero = 0, bytes_loc = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0; char *out_buffer = NULL; if (!client || !client->afc_packet || !client->connection || !file || !bytes) @@ -812,8 +812,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file, client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE; client->afc_packet->operation = AFC_WRITE; out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); - memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32)); - memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32)); + memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t)); + memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t)); memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE); bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); if (bytes_loc < 0) { @@ -845,8 +845,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file, client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count); client->afc_packet->operation = AFC_WRITE; out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); - memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32)); - memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32)); + memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t)); + memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t)); memcpy(out_buffer + 8, data + current_count, (length - current_count)); bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8); free(out_buffer); @@ -881,7 +881,7 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file if (!client || !file) return IPHONE_E_INVALID_ARG; char *buffer = malloc(sizeof(char) * 8); - uint32 zero = 0; + uint32_t zero = 0; int bytes = 0; afc_lock(client); @@ -889,8 +889,8 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file log_debug_msg("afc_close_file: File handle %i\n", file->filehandle); // Send command - memcpy(buffer, &file->filehandle, sizeof(uint32)); - memcpy(buffer + sizeof(uint32), &zero, sizeof(zero)); + memcpy(buffer, &file->filehandle, sizeof(uint32_t)); + memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero)); client->afc_packet->operation = AFC_FILE_CLOSE; client->afc_packet->entire_length = client->afc_packet->this_length = 0; bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8); @@ -926,7 +926,7 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) { char *buffer = (char *) malloc(sizeof(char) * 24); - uint32 seekto = 0, bytes = 0, zero = 0; + uint32_t seekto = 0, bytes = 0, zero = 0; if (seekpos < 0) seekpos = file->size - abs(seekpos); @@ -935,12 +935,12 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_ // Send the command seekto = seekpos; - memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle - memcpy(buffer + 4, &zero, sizeof(uint32)); // pad - memcpy(buffer + 8, &zero, sizeof(uint32)); // fromwhere - memcpy(buffer + 12, &zero, sizeof(uint32)); // pad - memcpy(buffer + 16, &seekto, sizeof(uint32)); // offset - memcpy(buffer + 20, &zero, sizeof(uint32)); // pad + memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle + memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad + memcpy(buffer + 8, &zero, sizeof(uint32_t)); // fromwhere + memcpy(buffer + 12, &zero, sizeof(uint32_t)); // pad + memcpy(buffer + 16, &seekto, sizeof(uint32_t)); // offset + memcpy(buffer + 20, &zero, sizeof(uint32_t)); // pad client->afc_packet->operation = AFC_FILE_SEEK; client->afc_packet->this_length = client->afc_packet->entire_length = 0; bytes = dispatch_AFC_packet(client, buffer, 23); @@ -979,14 +979,14 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize) { char *buffer = (char *) malloc(sizeof(char) * 16); - uint32 bytes = 0, zero = 0; + uint32_t bytes = 0, zero = 0; afc_lock(client); // Send command - memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle - memcpy(buffer + 4, &zero, sizeof(uint32)); // pad - memcpy(buffer + 8, &newsize, sizeof(uint32)); // newsize + memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle + memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad + memcpy(buffer + 8, &newsize, sizeof(uint32_t)); // newsize memcpy(buffer + 12, &zero, 3); // pad client->afc_packet->operation = AFC_FILE_TRUNCATE; client->afc_packet->this_length = client->afc_packet->entire_length = 0; @@ -1012,7 +1012,7 @@ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_f } } -uint32 iphone_afc_get_file_handle(iphone_afc_file_t file) +uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file) { return file->filehandle; } diff --git a/src/AFC.h b/src/AFC.h index 463c13e..5e4d17c 100644 --- a/src/AFC.h +++ b/src/AFC.h @@ -29,12 +29,12 @@ #include typedef struct { - uint32 header1, header2; - uint32 entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4; + uint32_t header1, header2; + uint32_t entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4; } AFCPacket; typedef struct { - uint32 filehandle, unknown1, size, unknown2; + uint32_t filehandle, unknown1, size, unknown2; } AFCFilePacket; typedef struct __AFCToken { @@ -51,7 +51,7 @@ struct iphone_afc_client_int { }; struct iphone_afc_file_int { - uint32 filehandle, blocks, size, type; + uint32_t filehandle, blocks, size, type; }; @@ -74,4 +74,4 @@ enum { AFC_WRITE = 0x00000010 }; -uint32 iphone_afc_get_file_handle(iphone_afc_file_t file); +uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file); diff --git a/src/lockdown.c b/src/lockdown.c index 65cbf90..6b8f298 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -127,7 +127,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, char **dump_data, u return IPHONE_E_INVALID_ARG; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; char *receive; - uint32 datalen = 0, bytes = 0; + uint32_t datalen = 0, bytes = 0; if (!client->in_SSL) ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); @@ -211,7 +211,7 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control) dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); char *XML_content; - uint32 length; + uint32_t length; xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); ret = iphone_lckd_send(control, XML_content, length, &bytes); @@ -265,7 +265,7 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, char *r char **dictionary = NULL; int bytes = 0, i = 0; char *XML_content = NULL; - uint32 length = 0; + uint32_t length = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; /* Setup DevicePublicKey request plist */ @@ -420,7 +420,7 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch char **dictionary = NULL; int bytes = 0, i = 0; char *XML_content = NULL; - uint32 length = 0; + uint32_t length = 0; char *device_cert_b64 = NULL; char *host_cert_b64 = NULL; @@ -658,7 +658,7 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); xmlNode *key; char *what2send = NULL, **dictionary = NULL; - uint32 len = 0, bytes = 0, return_me = 0, i = 0; + uint32_t len = 0, bytes = 0, return_me = 0, i = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; // end variables @@ -893,8 +893,8 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char return IPHONE_E_SSL_ERROR; char *XML_query, **dictionary; - uint32 length, i = 0, port_loc = 0, bytes = 0; - uint8 result = 0; + uint32_t length, i = 0, port_loc = 0, bytes = 0; + uint8_t result = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; free(host_id); diff --git a/src/plist.c b/src/plist.c index c4d6bfa..0024577 100644 --- a/src/plist.c +++ b/src/plist.c @@ -23,8 +23,10 @@ #include #include #include +#include "utils.h" #include "plist.h" + const char *plist_base = "\n\ \n\ \n\ @@ -243,3 +245,285 @@ void free_dictionary(char **dictionary) free(dictionary); } + +/* + * Binary propertylist code follows + */ + + +/* + * This is how parsing a bplist is going to have to work: + * - The entire binary plist is going to have to be in memory. + * - A function, parse_nodes(), will have to be a recursive function + * which iterates over the binary plist and reads in elements into bplist_node structs + * and handles them accordingly. The end result should be a somewhat-hierarchical layout + * of bplist_nodes. + * - parse_nodes() will return the first node it encounters, which is usually the "root" node. + */ + +uint32_t uipow(uint32_t value, uint32_t power) { + if (!power) return 1; + int i = 0, oVal = value; + for (i = 1; i < power; i++) { + value *= oVal; + } + return value; +} + +void byte_convert(char *address, size_t size) { + int i = 0, j = 0; + char tmp = '\0'; + + for (i = 0; i < (size / 2); i++) { + tmp = address[i]; + j = ((size-1) + 0) - i; + address[i] = address[j]; + address[j] = tmp; + } +} + +bplist_node *parse_raw_node(const char *bpbuffer, uint32_t bplength, uint32_t *position, uint8_t ref_size) { + if (!position || !bpbuffer || !bplength) return NULL; + + uint8_t modifier = 0; + bplist_node *new_node = (bplist_node*)malloc(sizeof(bplist_node)); + bplist_node *length_stupidity = NULL; + memset(new_node, 0, sizeof(bplist_node)); // initialize the new struct + + int myPos = *position; + if (myPos == bplength || (myPos+1) == bplength) { free(new_node); return NULL; } // end of string + + uint32_t length = 0; + if (!myPos) { + if (strncmp(bpbuffer, "bplist00", strlen("bplist00"))) { + return NULL; // badness! + } + myPos += strlen("bplist00"); + } + + // Get the node's type. + if (bpbuffer[myPos] == BPLIST_DATE) { // handle date separately, but do it as a real + // better handling of date; basically interpret as real or double + new_node->type = BPLIST_DATE; + new_node->length = 8; // always 8 for "date" (Apple intended it, not me) + myPos++; + memcpy(&new_node->realval, bpbuffer+myPos, sizeof(new_node->realval)); + byte_convert(&new_node->realval, sizeof(new_node->realval)); + myPos += new_node->length; + *position = myPos; + return new_node; + } + + new_node->type = bpbuffer[myPos] & BPLIST_MASK; + new_node->length = bpbuffer[myPos] & BPLIST_FILL; + if (!new_node->type) { + // what? check if it's a boolean. + if (bpbuffer[myPos] == BPLIST_TRUE || bpbuffer[myPos] == BPLIST_FALSE) { + // okay, so it is. Carry on. + new_node->type = bpbuffer[myPos]; + new_node->length = 0; + } else { + // er, what? we have a bad type here. Return NULL. + free(new_node); + //printf("parse_raw_node: lol type: type given %x\n", bpbuffer[myPos]); + return NULL; + } + } + + myPos++; // puts us in the data. + if (new_node->length == BPLIST_FILL) { // Data happens to contain length... + // what? you're going to make me parse an int for the length. You suck. + *position = myPos; + length_stupidity = parse_raw_node(bpbuffer, bplength, &myPos, ref_size); + switch (length_stupidity->length) { + case sizeof(uint8_t): + new_node->length = length_stupidity->intval8; + break; + case sizeof(uint16_t): + new_node->length = length_stupidity->intval16; + break; + case sizeof(uint32_t): + new_node->length = length_stupidity->intval32; + break; + case sizeof(uint64_t): + new_node->length = length_stupidity->intval64; + break; + default: + free(new_node); + free(length_stupidity); + return NULL; + } + // There, we have our fucking length now. + *position = myPos; + free(length_stupidity); // cleanup + } + + // Now we're in the data. + // Error-checking sorta + if ((myPos + new_node->length) >= bplength) { + new_node->length = bplength - myPos; // truncate the object + } + + // And now for the greatest show on earth: the giant fucking switch statement. + switch (new_node->type) { + case BPLIST_INT: + new_node->length = uipow(2, new_node->length); // make length less misleading + switch (new_node->length) { + case sizeof(uint8_t): + new_node->intval8 = bpbuffer[myPos]; + break; + case sizeof(uint16_t): + memcpy(&new_node->intval16, bpbuffer+myPos, sizeof(uint16_t)); + new_node->intval16 = ntohs(new_node->intval16); + break; + case sizeof(uint32_t): + memcpy(&new_node->intval32, bpbuffer+myPos, sizeof(uint32_t)); + new_node->intval32 = ntohl(new_node->intval32); + break; + case sizeof(uint64_t): + memcpy(&new_node->intval64, bpbuffer+myPos, sizeof(uint64_t)); + byte_convert(&new_node->intval64, sizeof(uint64_t)); + break; + default: + free(new_node); + printf("parse_raw_node: lol: invalid int: size given %i\n", new_node->length); + printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t)); + return NULL; + } + break; + + case BPLIST_REAL: + new_node->length = uipow(2, new_node->length); + memcpy(&new_node->realval, bpbuffer+myPos, new_node->length); // XXX: probable buffer overflow here + //new_node->realval = bpbuffer[myPos]; // why not + byte_convert(&new_node->realval, sizeof(double)); + break; + + case BPLIST_DICT: /* returning a raw dict, it forward-references, so. */ + new_node->length = new_node->length * 2; // dicts lie + case BPLIST_ARRAY: /* returning a raw array, it forward-references, so. */ + new_node->intval8 = ref_size; // in arrays and dicts, the "ref size" alluded to in the trailer applies, and should be stored in intval8 so as to save space. + case BPLIST_STRING: + case BPLIST_DATA: + default: /* made to hold raw data. */ + modifier = (new_node->intval8 > 0) ? new_node->intval8 : 1; + new_node->strval = (char*)malloc(sizeof(char) * (new_node->length * modifier)); + memcpy(new_node->strval, bpbuffer+myPos, (new_node->length * modifier)); + break; + + case BPLIST_UNICODE: + new_node->unicodeval = (wchar_t*)malloc(sizeof(wchar_t) * new_node->length); + memcpy(new_node->unicodeval, bpbuffer+myPos, new_node->length); + break; + } + + myPos += new_node->length; + *position = myPos; + return new_node; +} + +void print_bytes(char *val, size_t size) { + int i = 0; + for (i = 0; i < size; i++) { + printf("Byte %i: 0x%x\n", i, val[i]); + } +} + +bplist_node *parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t *position) { + bplist_node **nodeslist = NULL, **newaddr = NULL; + bplist_node *new_node = NULL, *root_node = NULL; + + uint32_t nodeslength = 0; + uint8_t offset_size = 0, dict_param_size = 0; + offset_size = bpbuffer[bplength-26]; + dict_param_size = bpbuffer[bplength-25]; + uint64_t current_offset = 0; + //uint64_t num_objects = *(bpbuffer+(bplength-24)), root_object = *(bpbuffer+(bplength-16)), offset_table_index = *(bpbuffer+(bplength-8)); + uint64_t num_objects = 0, root_object = 0, offset_table_index = 0; + memcpy(&num_objects, bpbuffer+bplength-24, sizeof(uint64_t)); + memcpy(&root_object, bpbuffer+bplength-16, sizeof(uint64_t)); + memcpy(&offset_table_index, bpbuffer+bplength-8, sizeof(uint64_t)); + byte_convert(&num_objects, sizeof(uint64_t)); + byte_convert(&root_object, sizeof(uint64_t)); + byte_convert(&offset_table_index, sizeof(uint64_t)); + + log_debug_msg("Offset size: %i\nGiven: %i\n", offset_size, bpbuffer[bplength-26]); + log_debug_msg("Ref size: %i\nGiven: %i\n", dict_param_size, bpbuffer[bplength-25]); + log_debug_msg("Number of objects: %lli\nGiven: %llu\n", num_objects, *(bpbuffer+bplength-24)); + log_debug_msg("Root object index: %lli\nGiven: %llu\n", root_object, *(bpbuffer+bplength-16)); + log_debug_msg("Offset table index: %lli\nGiven: %llu\n", offset_table_index, *(bpbuffer+bplength-8)); + log_debug_msg("Size of uint64: %i\n", sizeof(uint64_t)); + + int i = 0, j = 0, k = 0, str_i = 0, str_j = 0; + uint32_t index1 = 0, index2 = 0; + + nodeslist = (bplist_node**)malloc(sizeof(bplist_node*) * num_objects); + if (!nodeslist) return NULL; + + for (i = 0; i < num_objects; i++) { + memcpy(¤t_offset, bpbuffer+(offset_table_index+(i*offset_size)), offset_size); + //current_offset = (offset_size == 2) ? ntohs(current_offset) : (offset_size == 4) ? ntohl(current_offset) : current_offset; + //if (offset_size == 8) byte_convert(¤t_offset, 8); + byte_convert(¤t_offset, (offset_size <= sizeof(current_offset)) ? offset_size : sizeof(current_offset)); + log_debug_msg("parse_nodes: current_offset = %x\n", current_offset); + nodeslist[i] = parse_raw_node(bpbuffer, bplength, ¤t_offset, dict_param_size); + log_debug_msg("parse_nodes: parse_raw_node done\n"); + } + + + for (i = 0; i < num_objects; i++) { + // set elements for dicts and arrays and leave the rest alone + log_debug_msg("parse_nodes: on node %i\n", i); + switch (nodeslist[i]->type) { + case BPLIST_DICT: + log_debug_msg("parse_nodes: dictionary found\n"); + nodeslist[i]->subnodes = (bplist_node*)malloc(sizeof(bplist_node) * nodeslist[i]->length); + for (j = 0; j < (nodeslist[i]->length / 2); j++) { + str_i = j * nodeslist[i]->intval8; + str_j = (j + (nodeslist[i]->length / 2)) * nodeslist[i]->intval8; + + memcpy(&index1, nodeslist[i]->strval+str_i, nodeslist[i]->intval8); + memcpy(&index2, nodeslist[i]->strval+str_j, nodeslist[i]->intval8); + //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1; + //index2 = (dict_param_size == 1) ? index2 : (dict_param_size == 2) ? ntohs(index2) : (dict_param_size == 4) ? ntohl(index2) : index2; + byte_convert(&index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index2)); + byte_convert(&index2, (dict_param_size <= sizeof(index2)) ? dict_param_size : sizeof(index2)); + //printf("parse_nodes: key index %i value %i\n", index1, index2); + //printf("parse_nodes: key type %x and length %i\n", nodeslist[index1]->type, nodeslist[index1]->length); + //printf("parse_nodes: value type %x and length %i\n", nodeslist[index2]->type, nodeslist[index2]->length); + nodeslist[i]->subnodes[k++] = nodeslist[index1]; + nodeslist[i]->subnodes[k++] = nodeslist[index2]; + } + + nodeslist[i]->length = nodeslist[i]->length / 2; + free(nodeslist[i]->strval); + k = 0; + break; + + case BPLIST_ARRAY: + log_debug_msg("parse_nodes: array found\n"); + nodeslist[i]->subnodes = (bplist_node*)malloc(sizeof(bplist_node) * nodeslist[i]->length); // memory allocation helps a lot when storing data + + for (j = 0; j < nodeslist[i]->length; j++) { + log_debug_msg("parse_nodes: array index %i\n", j); + str_j = j * nodeslist[i]->intval8; + //index1 = nodeslist[i]->strval[j]; + memcpy(&index1, nodeslist[i]->strval+str_j, nodeslist[i]->intval8); + log_debug_msg("parse_nodes: post-memcpy\n"); + //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1; + byte_convert(&index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index1)); + log_debug_msg("parse_nodes: post-ntohl\nindex1 = %i\n", index1); + nodeslist[i]->subnodes[j] = nodeslist[index1]; + log_debug_msg("parse_nodes: post-assignment\n"); + } + free(nodeslist[i]->strval); + break; + default: + //printf("lol... type %x\n", nodeslist[i]->type); + break; + } // those are the only two we need to correct for. + } + + root_node = nodeslist[root_object]; + return root_node; +} diff --git a/src/plist.h b/src/plist.h index b27a0c5..98c7d91 100644 --- a/src/plist.h +++ b/src/plist.h @@ -24,6 +24,12 @@ #include #include +#include +#include + +#include +#include +#include xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth); xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth); @@ -35,4 +41,36 @@ xmlDocPtr new_plist(); char **read_dict_element_strings(xmlNode * dict); void free_dictionary(char **dictionary); + +/* Binary plist stuff */ + +enum { + BPLIST_TRUE = 0x08, + BPLIST_FALSE = 0x09, + BPLIST_FILL = 0x0F, /* will be used for length grabbing */ + BPLIST_INT = 0x10, + BPLIST_REAL = 0x20, + BPLIST_DATE = 0x33, + BPLIST_DATA = 0x40, + BPLIST_STRING = 0x50, + BPLIST_UNICODE = 0x60, + BPLIST_UID = 0x70, + BPLIST_ARRAY = 0xA0, + BPLIST_SET = 0xC0, + BPLIST_DICT = 0xD0, + BPLIST_MASK = 0xF0 +}; + +typedef struct _bplist_node { + struct _bplist_node *next, **subnodes; // subnodes is for arrays, dicts and (potentially) sets. + uint64_t length, intval64; + uint32_t intval32; // length = subnodes + uint16_t intval16; + uint8_t intval8; + uint8_t type, *indexes; // indexes for array-types; essentially specify the order in which to access for key => value pairs + char *strval; + double realval; + wchar_t *unicodeval; +} bplist_node; + #endif diff --git a/src/usbmux.c b/src/usbmux.c index 2114758..f0499fa 100644 --- a/src/usbmux.c +++ b/src/usbmux.c @@ -37,7 +37,7 @@ static int clients = 0; * * @return A USBMux packet */ -usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) +usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port) { usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header)); conn->type = htonl(6); diff --git a/src/usbmux.h b/src/usbmux.h index da8a361..4b18e07 100644 --- a/src/usbmux.h +++ b/src/usbmux.h @@ -22,6 +22,7 @@ #include #include #include +#include "libiphone/libiphone.h" #ifndef USBMUX_H #define USBMUX_H @@ -30,17 +31,12 @@ #include "iphone.h" #endif -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint8_t uint8; - - typedef struct { - uint32 type, length; - uint16 sport, dport; - uint32 scnt, ocnt; - uint8 offset, tcp_flags; - uint16 window, nullnull, length16; + uint32_t type, length; + uint16_t sport, dport; + uint32_t scnt, ocnt; + uint8_t offset, tcp_flags; + uint16_t window, nullnull, length16; } usbmux_tcp_header; struct iphone_umux_client_int { @@ -50,10 +46,10 @@ struct iphone_umux_client_int { int r_len; }; -usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port); +usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port); typedef struct { - uint32 type, length, major, minor, allnull; + uint32_t type, length, major, minor, allnull; } usbmux_version_header; usbmux_version_header *version_header(); -- cgit v1.1-32-gdbae