├── Makefile ├── README.md └── main.c /Makefile: -------------------------------------------------------------------------------- 1 | all: main.c 2 | gcc main.c -o modex 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | patch the DEX crc in ODEX files 2 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mod_odex by Collin Mulliner 3 | * - patch the DEX crc in ODEX files 4 | * license: GPLv3 5 | * http://www.mulliner.org/android/ 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define DEBUG 1 19 | 20 | struct oat_header_t 21 | { 22 | char magic[4]; 23 | char version[4]; 24 | uint32_t adler32_checksum; 25 | uint32_t instruction_set; 26 | uint32_t instruction_set_features; 27 | uint32_t dex_file_count; 28 | uint32_t data[11]; // this seams to change deppening on the oat version (11 = 064) 29 | uint32_t key_value_store_size; 30 | // unsigned char key_value_store; 31 | }; 32 | 33 | // not used, just to remember the structure 34 | /* 35 | struct oat_dex_file_header_t 36 | { 37 | uint32_t dex_file_location_size; 38 | char dex_file_location[1]; 39 | uint32_t dex_file_location_checksum; 40 | uint32_t dex_file_pointer; 41 | // classes_offsets 42 | }; 43 | */ 44 | 45 | void parse_oat_dex_file_header(unsigned char *data, int count, uint32_t oldcrc, uint32_t newcrc) 46 | { 47 | // this is the name of the apk once it gets installed on the device 48 | char baseapk[] = {"base.apk"}; 49 | unsigned char *dp = data; 50 | int c = count; 51 | char name_tmp[128]; 52 | 53 | while (c > 0) { 54 | if (memcmp(dp, baseapk, 8) == 0) { 55 | uint32_t *namelen = (uint32_t*) (dp - 4); 56 | printf("classes len: %d\n", *namelen); 57 | memcpy(name_tmp, dp, *namelen); 58 | name_tmp[*namelen] = 0; 59 | printf("classes: %s\n", name_tmp); 60 | uint32_t *crc32 = (uint32_t*)(dp + *namelen); 61 | printf("classes crc32: %.8X\n", *crc32); 62 | 63 | if (oldcrc != 0 && newcrc != 0) { 64 | if (*crc32 == oldcrc) { 65 | *crc32 = newcrc; 66 | printf("!classes crc32: %.8X\n", *crc32); 67 | } 68 | } 69 | 70 | c--; 71 | dp += *namelen + 8; 72 | } 73 | dp++; 74 | } 75 | } 76 | 77 | void parse_odex(unsigned char *odex, uint32_t oldcrc, uint32_t newcrc) 78 | { 79 | struct oat_header_t *oat = (struct oat_header_t*) odex; 80 | printf("%c%c%c%c\n", oat->magic[0],oat->magic[1],oat->magic[2],oat->magic[3]); 81 | printf("dex file count: %d\n", oat->dex_file_count); 82 | printf("key_value_store_size: %d\n", oat->key_value_store_size); 83 | 84 | // find key value store 85 | char *kvs = odex + sizeof(struct oat_header_t); 86 | printf("kvs[0]: %s\n", kvs); 87 | 88 | parse_oat_dex_file_header(kvs + oat->key_value_store_size, oat->dex_file_count, oldcrc, newcrc); 89 | } 90 | 91 | int main(int argc, char **argv) 92 | { 93 | if (argc == 1) { 94 | printf("%s: file_name.odex [oldcrc:newcrc]\n\tif CRCs are provided the oldcrc will be replaced with the newcrc\n", argv[0]); 95 | exit(0); 96 | } 97 | 98 | struct stat fs; 99 | int fp = open(argv[1], O_RDWR); 100 | fstat(fp, &fs); 101 | void *dex = mmap(0, fs.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fp, 0); 102 | 103 | uint32_t oldcrc = 0; 104 | uint32_t newcrc = 0; 105 | 106 | if (argc == 3) { 107 | if (strlen(argv[2]) == 17) { 108 | argv[2][8] = 0; 109 | oldcrc = strtol(&argv[2][0], 0, 16); 110 | newcrc = strtol(&argv[2][9], 0, 16); 111 | printf("old crc: %.8X new crc: %.8X\n", oldcrc, newcrc); 112 | } 113 | } 114 | 115 | // search (e.g. oat/odex files) 116 | char dexid[] = {'o','a','t', '\n'}; 117 | unsigned char *d = (unsigned char*)dex; 118 | for (uint32_t i = 0; i < fs.st_size; i++) { 119 | if (memcmp(d, dexid, 4) == 0) { 120 | printf("%s\n", d); 121 | printf("offset = %d\n", i); 122 | break; 123 | } 124 | d++; 125 | } 126 | 127 | parse_odex((unsigned char*)d, oldcrc, newcrc); 128 | 129 | munmap(dex, fs.st_size); 130 | close(fp); 131 | } 132 | --------------------------------------------------------------------------------