├── Makefile ├── README.md ├── dt.h ├── LICENSE └── dtdump.c /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -O2 2 | 3 | all: dtdump 4 | 5 | clean: 6 | rm dtdump 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS-device-tree-dump 2 | Dump non-encrypted iOS device tree extracted from im4p 3 | 4 | iOS device tree files are not encrypted after iOS 10. So, with [img4tool](https://github.com/xerub/img4tool.git) from @xerub , 5 | ``` 6 | > img4 -image ./all_flash/DeviceTree.d22ap.im4p /tmp/d22ap-dt.bin 7 | ``` 8 | Then we can do something like 9 | ``` 10 | > ./dtdump /tmp/d22ap-dt.bin 11 | ``` 12 | or 13 | ``` 14 | > ./dtdump -v /tmp/d22ap-dt.bin 15 | ``` 16 | `-v` means dump values in hexdecimal 17 | -------------------------------------------------------------------------------- /dt.h: -------------------------------------------------------------------------------- 1 | // also from Jonathan Levin's 2 | // but originally from XNU source code I guess 3 | 4 | #define kPropNameLength 32 5 | 6 | typedef struct DeviceTreeNodeProperty { 7 | char name[kPropNameLength]; // NUL terminated property name 8 | uint32_t length; // Length (bytes) of folloing prop value 9 | // unsigned long value[1]; // Variable length value of property 10 | // Padded to a multiple of a longword? 11 | } DeviceTreeNodeProperty; 12 | 13 | typedef struct OpaqueDTEntry { 14 | uint32_t nProperties; // Number of props[] elements (0 => end) 15 | uint32_t nChildren; // Number of children[] elements 16 | // DeviceTreeNodeProperty props[];// array size == nProperties 17 | // DeviceTreeNode children[]; // array size == nChildren 18 | } DeviceTreeNode; 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, "freedom" Koan-Sin Tan 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /dtdump.c: -------------------------------------------------------------------------------- 1 | // code adapted from Jonathan Levin's http://www.newosxbook.com/src.jl?tree=listings&file=6-bonus.c 2 | // clean-up a bit to 3 | // 1. make "clang -Wall" happy 4 | // 2. remove img3 stuff: device tree files are in im4p nowadays 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "dt.h" // for DeviceTree 16 | 17 | int verbose = 0; 18 | 19 | void copyValue (char *dest, char *src, int length) 20 | { 21 | int i = 0; 22 | for (i = 0; src[i] || i < length; i++); 23 | 24 | if (i != length) { 25 | strcpy(dest, "(null)"); 26 | return; 27 | } 28 | memcpy(dest, src, length); 29 | } 30 | 31 | uint32_t dumpTreeNode(DeviceTreeNode *Node, int indent) 32 | { 33 | char buffer[819200]; 34 | char temp[409600]; 35 | char h_temp[81920]; 36 | char *name; 37 | 38 | int prop = 0, child = 0; 39 | int i = 0; 40 | memset(buffer, '\0', 819200); 41 | 42 | DeviceTreeNodeProperty *dtp = (DeviceTreeNodeProperty * ) ((char*)Node + sizeof(DeviceTreeNode)); 43 | 44 | char *offset = 0; 45 | int real_len; 46 | for (prop = 0; prop < Node->nProperties; prop++) { 47 | real_len = dtp->length; 48 | temp[0] = '\0'; // strcat will do the rest 49 | for (i=0; i< indent ; i++) { 50 | strcat(temp,"| "); 51 | } 52 | strcat(temp, "+--"); 53 | strncat(buffer, temp, 1024); 54 | if ((real_len & 0x80000000) > 0) 55 | real_len = real_len - 0x80000000; 56 | sprintf(temp, "%s %d bytes: ", dtp->name, real_len); 57 | strncat(buffer, temp, 1024); 58 | 59 | if (strcmp(dtp->name,"name") == 0) { 60 | name = (char *) &dtp->length + sizeof(uint32_t); 61 | strncat(buffer, name, dtp->length); 62 | strcat(buffer,"\n"); 63 | } else { 64 | copyValue(temp, ((char *) &dtp->length) + sizeof(uint32_t), real_len); 65 | // Yeah, Yeah, Buffer overflows, etc.. :-) 66 | if (verbose) { 67 | char *hex = h_temp; 68 | for (i=0; i < real_len; i++) { 69 | sprintf(hex, " 0x%02x", 0xff & *(((char *) &dtp->length) + sizeof(uint32_t) + i)); 70 | hex += 5; // len(" 0x??") = 5 71 | } 72 | } 73 | strncat(buffer, temp, real_len); 74 | if (verbose) 75 | strcat(buffer, h_temp); 76 | strcat(buffer, "\n"); 77 | } 78 | dtp = (DeviceTreeNodeProperty *) (((char *) dtp) + sizeof(DeviceTreeNodeProperty) + real_len); 79 | 80 | // Align 81 | dtp = (((long) dtp %4) ? (DeviceTreeNodeProperty *) (((char *) dtp) + (4 - ((long)dtp) %4)): dtp); 82 | offset = (char *) dtp; 83 | } 84 | 85 | for (i=0; i < indent-1; i++) { 86 | printf(" "); 87 | } 88 | 89 | if (indent > 1) 90 | printf ("+--"); 91 | printf("%s:\n", name); 92 | printf("%s", buffer); 93 | 94 | // Now do children: 95 | for (child = 0; child < Node->nChildren; child++) { 96 | offset+= dumpTreeNode((DeviceTreeNode *) offset, indent+1); 97 | } 98 | 99 | return ( (char *) offset - (char*) Node); 100 | } 101 | 102 | 103 | int 104 | main(int argc, char **argv) 105 | { 106 | struct stat stbuf; 107 | char *filename; 108 | int rc; 109 | int fd; 110 | int filesize; 111 | char *mmapped; 112 | 113 | if (argc < 2) { 114 | fprintf (stderr,"Usage: %s [-v] _filename_\n", argv[0]); 115 | exit(0); 116 | } 117 | 118 | if (strcmp(argv[1], "-v") == 0) 119 | verbose = 1; 120 | 121 | filename = argv[argc -1]; 122 | 123 | rc = stat(filename, &stbuf); 124 | 125 | if (rc == -1) { perror (filename); exit (1); } 126 | 127 | filesize = stbuf.st_size; 128 | 129 | fd = open (filename, O_RDONLY); 130 | if (fd < 0) { perror (filename); exit(2);} 131 | 132 | mmapped = mmap(NULL, 133 | filesize, // size_t len, 134 | PROT_READ, // int prot, 135 | MAP_SHARED | MAP_FILE, // int flags, 136 | fd, // int fd, 137 | 0); // off_t offset); 138 | 139 | if (!mmapped) { 140 | perror ("mmap"); 141 | exit(3); 142 | } 143 | 144 | char *data = mmapped; 145 | DeviceTreeNode *dtn = (DeviceTreeNode *) data; 146 | printf ("\tDevice Tree with %d properties and %d children\n", dtn->nProperties, dtn->nChildren); 147 | 148 | printf("Properties:\n"); 149 | dumpTreeNode (dtn,1); 150 | 151 | return 0; 152 | } 153 | 154 | --------------------------------------------------------------------------------