/parsembdb.m

http://github.com/petewarden/iPhoneTracker · Objective C · 206 lines · 142 code · 32 blank · 32 comment · 15 complexity · 79ac20e613eef3f0f6903ddd5abe7896 MD5 · raw file

  1. //
  2. // iPhoneTracking
  3. //
  4. // Created by Pete Warden on 4/15/11.
  5. //
  6. /***********************************************************************************
  7. *
  8. * All code (C) Pete Warden, 2011
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. *
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. *
  24. ************************************************************************************/
  25. #import <Cocoa/Cocoa.h>
  26. #import "parsembdb.h"
  27. static NSNumber* getint(uint8_t* data, size_t* offset, size_t intsize);
  28. static NSString* getstring(uint8_t* data, size_t* offset);
  29. static NSDictionary* process_mbdb_file(NSString* filename);
  30. static NSDictionary* process_mbdx_file(NSString* filename);
  31. @implementation ParseMBDB
  32. + (NSDictionary*) getFileListForPath:(NSString*)path
  33. {
  34. NSDictionary* mbdb = process_mbdb_file([path stringByAppendingPathComponent:@"Manifest.mbdb"]);
  35. NSDictionary* mbdx = process_mbdx_file([path stringByAppendingPathComponent:@"Manifest.mbdx"]);
  36. if ((mbdb==nil)||(mbdx==nil)) {
  37. return nil;
  38. }
  39. for (NSNumber* offset in mbdb) {
  40. NSMutableDictionary* fileinfo = [mbdb objectForKey:offset];
  41. NSString* fileID = [mbdx objectForKey:offset];
  42. if (fileID==nil) {
  43. fileID = @"<nofileID>";
  44. }
  45. [fileinfo setObject: fileID forKey:@"fileID"];
  46. }
  47. return mbdb;
  48. }
  49. @end
  50. // Adapted from Python at
  51. // http://stackoverflow.com/questions/3085153/how-to-parse-the-manifest-mbdb-file-in-an-ios-4-0-itunes-backup
  52. NSNumber* getint(uint8_t* data, size_t* offset, size_t intsize){
  53. // Retrieve an integer (big-endian) and new offset from the current offset
  54. int value = 0;
  55. while (intsize > 0) {
  56. value = (value<<8) + data[*offset];
  57. *offset = *offset + 1;
  58. intsize = intsize - 1;
  59. }
  60. return [NSNumber numberWithInteger: value];
  61. }
  62. NSString* getstring(uint8_t* data, size_t* offset) {
  63. // Retrieve a string and new offset from the current offset into the data
  64. if ((data[*offset]==0xFF) && (data[*offset+1]==0xFF)) {
  65. // Blank string
  66. char* value = malloc(2);
  67. strcpy(value, "");
  68. *offset += 2;
  69. NSString* result = [[NSString alloc] initWithUTF8String:value];
  70. // NSLog(@"result=<blank>", result);
  71. return result;
  72. }
  73. int length = [getint(data, offset, 2) integerValue];
  74. size_t start = *offset;
  75. char* value = malloc(length+1);
  76. strncpy(value, (data+start), length);
  77. value[length] = 0;
  78. *offset += length;
  79. NSString* result = [[NSString alloc] initWithUTF8String:value];
  80. if (result==nil) {
  81. result = @"<null>";
  82. }
  83. // NSLog(@"result=%@", result);
  84. return result;
  85. }
  86. NSDictionary* process_mbdb_file(NSString* filename) {
  87. NSMutableDictionary* mbdb = [NSMutableDictionary dictionary]; // Map offset of info in this file => file info
  88. NSData* fileData = [NSData dataWithContentsOfFile: filename];
  89. size_t dataLength = [fileData length];
  90. uint8_t* data = (uint8_t*)[fileData bytes];
  91. if (data==NULL) {
  92. NSLog(@"No MBDB file found at '%@'", filename);
  93. return nil;
  94. }
  95. if ((data[0]!='m')||
  96. (data[1]!='b')||
  97. (data[2]!='d')||
  98. (data[3]!='b')) {
  99. fprintf(stderr, "Bad header found for mbdb file");
  100. return mbdb;
  101. }
  102. size_t offset = 4;
  103. offset = offset + 2; // value x05 x00, not sure what this is
  104. while (offset < dataLength) {
  105. NSMutableDictionary* fileinfo = [NSMutableDictionary dictionary];
  106. [fileinfo setObject: [NSNumber numberWithInteger: offset] forKey:@"start_offset"];
  107. [fileinfo setObject:getstring(data, &offset) forKey:@"domain"];
  108. [fileinfo setObject:getstring(data, &offset) forKey:@"filename"];
  109. [fileinfo setObject:getstring(data, &offset) forKey:@"linktarget"];
  110. [fileinfo setObject:getstring(data, &offset) forKey:@"datahash"];
  111. [fileinfo setObject:getstring(data, &offset) forKey:@"unknown1"];
  112. [fileinfo setObject:getint(data, &offset, 2) forKey:@"mode"];
  113. [fileinfo setObject:getint(data, &offset, 4) forKey:@"unknown2"];
  114. [fileinfo setObject:getint(data, &offset, 4) forKey:@"unknown3"];
  115. [fileinfo setObject:getint(data, &offset, 4) forKey:@"userid"];
  116. [fileinfo setObject:getint(data, &offset, 4) forKey:@"groupid"];
  117. [fileinfo setObject:getint(data, &offset, 4) forKey:@"mtime"];
  118. [fileinfo setObject:getint(data, &offset, 4) forKey:@"atime"];
  119. [fileinfo setObject:getint(data, &offset, 4) forKey:@"ctime"];
  120. [fileinfo setObject:getint(data, &offset, 8) forKey:@"filelen"];
  121. [fileinfo setObject:getint(data, &offset, 1) forKey:@"flag"];
  122. [fileinfo setObject:getint(data, &offset, 1) forKey:@"numprops"];
  123. NSMutableDictionary* properties = [NSMutableDictionary dictionary];
  124. const int numProps = [[fileinfo objectForKey:@"numprops"] integerValue];
  125. for (int ii=0; ii<numProps; ii++) {
  126. NSString* propname = getstring(data, &offset);
  127. NSString* propval = getstring(data, &offset);
  128. [properties setObject: propval forKey:propname];
  129. }
  130. [fileinfo setObject:properties forKey:@"properties"];
  131. [mbdb setObject: fileinfo forKey:[fileinfo objectForKey:@"start_offset"]];
  132. }
  133. return mbdb;
  134. }
  135. NSDictionary* process_mbdx_file(NSString* filename) {
  136. NSMutableDictionary* mbdx = [NSMutableDictionary dictionary]; // Map offset of info in the MBDB file => fileID string
  137. NSData* fileData = [NSData dataWithContentsOfFile: filename];
  138. size_t dataLength = [fileData length];
  139. uint8_t* data = (uint8_t*)[fileData bytes];
  140. if (data==NULL) {
  141. NSLog(@"No MBDX file found at '%@'", filename);
  142. return nil;
  143. }
  144. if ((data[0]!='m')||
  145. (data[1]!='b')||
  146. (data[2]!='d')||
  147. (data[3]!='x')) {
  148. fprintf(stderr, "Bad header found for mbdx file");
  149. return mbdx;
  150. }
  151. size_t offset = 4;
  152. offset = offset + 2; // value 0x02 0x00, not sure what this is
  153. char* hexArray = "0123456789abcdef";
  154. NSNumber* filecount = getint(data, &offset, 4); // 4-byte count of records
  155. while (offset < dataLength) {
  156. // 26 byte record, made up of ...
  157. char* fileID_string = malloc(41);
  158. for (int i=0; i<20; i+=1) {
  159. uint8_t v = data[offset+i];
  160. uint8_t l = (v&0x0f);
  161. uint8_t h = (v&0xf0)>>4;
  162. fileID_string[(i*2)+0] = hexArray[h];
  163. fileID_string[(i*2)+1] = hexArray[l];
  164. }
  165. fileID_string[40] = 0;
  166. NSString* fileID_nsString = [[NSString alloc] initWithUTF8String:fileID_string];
  167. offset = offset + 20;
  168. NSNumber* mbdb_offset = getint(data, &offset, 4); // 4-byte offset field
  169. mbdb_offset = [NSNumber numberWithInteger: ([mbdb_offset integerValue] + 6)]; // Add 6 to get past prolog
  170. NSNumber* mode = getint(data, &offset, 2); // 2-byte mode field
  171. [mbdx setObject:fileID_nsString forKey: mbdb_offset];
  172. }
  173. return mbdx;
  174. }