diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2014-01-12 22:07:32 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2014-01-12 22:07:32 +0100 |
| commit | f2df25ca202300fe04672703ea7fb30d8431b302 (patch) | |
| tree | 23c4fe224266a3c76d18af359247eba8c428cb07 /src | |
| parent | a5e0e84b98553c3198b6d78a095e96baa57e1fed (diff) | |
Make extract code for old phone books much more generic and detect necessary values automatically
Diffstat (limited to 'src')
| -rw-r--r-- | src/extractblocks_new.c | 121 |
1 files changed, 80 insertions, 41 deletions
diff --git a/src/extractblocks_new.c b/src/extractblocks_new.c index 94ab0b7..53c16f2 100644 --- a/src/extractblocks_new.c +++ b/src/extractblocks_new.c | |||
| @@ -5,76 +5,115 @@ | |||
| 5 | #include <stdint.h> | 5 | #include <stdint.h> |
| 6 | #include <unistd.h> | 6 | #include <unistd.h> |
| 7 | 7 | ||
| 8 | /* lha header: | ||
| 9 | |||
| 10 | 00 Header length | ||
| 11 | 01 Header checksum [02-length] | ||
| 12 | 02 0x2d ('-') | ||
| 13 | 03 0x6c ('l') | ||
| 14 | 04 0x68 ('h') | ||
| 15 | 05 0x?? ('0' or '5') unsure | ||
| 16 | 06 0x2d ('-') | ||
| 17 | 07 0x?? LSB of compressed size | ||
| 18 | 08 0x?? .. | ||
| 19 | 09 0x00 .. | ||
| 20 | 10 0x00 MSB of compressed size, i.e. 0 | ||
| 21 | .. | ||
| 22 | 21 Length of path name | ||
| 23 | |||
| 24 | |||
| 25 | */ | ||
| 26 | |||
| 27 | static uint8_t mantra_in[] = { 0x68, 0x00, 0x2d, 0x6c }; | ||
| 28 | |||
| 8 | int main( int args, char **argv ) | 29 | int main( int args, char **argv ) |
| 9 | { | 30 | { |
| 10 | int filenum = 0; | 31 | int filenum = 0, run = 1; |
| 11 | size_t offset = 0, oldoffset = -1; | 32 | size_t offset = 0, oldoffset = -1, enc_len = 32; |
| 12 | uint8_t *mappedfile; | 33 | uint8_t mantra[4], id0, id5, *mappedfile; |
| 13 | MAP map; | 34 | MAP map; |
| 14 | 35 | ||
| 15 | uint8_t mantra0 = 0x1b, mantra1 = 0x35, mantra2 = 0x2d, mantra3 = 0x6c; /* clean*/ | 36 | /* For streets we do have a enc_len of 34 */ |
| 16 | // unsigned char mantra0 = 0x08, mantra1 = 0x57, mantra2 = 0x64, mantra3 = 0x69; /* 98 H */ | 37 | while( run ) { |
| 17 | // unsigned char mantra0 = 0x13, mantra1 = 0xe4, mantra2 = 0x55, mantra3 = 0x05; /* 99 F */ | 38 | switch( getopt( args, argv, ":e:" ) ) { |
| 18 | // unsigned char mantra0 = 0x12, mantra1 = 0x08, mantra2 = 0x23, mantra3 = 0x01; /* 99 H */ | 39 | case -1 : run = 0; break; |
| 40 | case 'e': | ||
| 41 | enc_len = atol( optarg ); | ||
| 42 | break; | ||
| 43 | default: | ||
| 44 | fputs( "Syntax: %s [-e encrypted_length (default: 32, for streets 34 or 0)] path-to-teiln.dat", stderr ); exit( 1 ); | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | run = 1; | ||
| 19 | 49 | ||
| 20 | if( args != 2 ) | 50 | if( optind == args ) |
| 21 | { fputs( "Missing filenames.", stderr ); exit( 1 ); } | 51 | { fputs( "Missing filename.", stderr ); exit( 1 ); } |
| 22 | 52 | ||
| 23 | map = map_file( argv[1], 1 ); | 53 | map = map_file( argv[optind], 1 ); |
| 24 | mappedfile = map->addr; | 54 | mappedfile = map->addr; |
| 25 | 55 | ||
| 26 | mantra0 ^= mappedfile[0]; | 56 | mantra[0] = mantra_in[0] ^ mappedfile[4]; |
| 27 | mantra1 ^= mappedfile[5]; | 57 | mantra[1] = mantra_in[1] ^ mappedfile[9]; |
| 28 | mantra2 ^= mappedfile[2]; | 58 | mantra[2] = mantra_in[2] ^ mappedfile[2]; |
| 29 | mantra3 ^= mappedfile[3]; | 59 | mantra[3] = mantra_in[3] ^ mappedfile[3]; |
| 60 | |||
| 61 | id0 = mappedfile[0]; | ||
| 62 | id5 = mappedfile[5]; | ||
| 30 | 63 | ||
| 31 | while( 1 ) | 64 | while( run ) |
| 32 | { | 65 | { |
| 33 | while( ( offset < map->size ) && ( | 66 | while( ( offset < map->size ) && ( |
| 34 | ( mappedfile[ offset + 0 ] != ( 0x1b^ mantra0 )) || | 67 | ( mappedfile[ offset + 0 ] != id0 ) || |
| 35 | ( mappedfile[ offset + 2 ] != ( '-' ^ mantra2 )) || | 68 | ( mappedfile[ offset + 2 ] != ( '-' ^ mantra[2] )) || |
| 36 | ( mappedfile[ offset + 3 ] != ( 'l' ^ mantra3 )) || | 69 | ( mappedfile[ offset + 3 ] != ( 'l' ^ mantra[3] )) || |
| 37 | ( mappedfile[ offset + 4 ] != ( 'h' ^ mantra0 )) || | 70 | ( mappedfile[ offset + 4 ] != ( 'h' ^ mantra[0] )) || |
| 38 | ( mappedfile[ offset + 5 ] != ( '5' ^ mantra1 )) || | 71 | ( mappedfile[ offset + 5 ] != id5 ) || |
| 39 | ( mappedfile[ offset + 6 ] != ( '-' ^ mantra2 )) | 72 | ( mappedfile[ offset + 6 ] != ( '-' ^ mantra[2] )) |
| 40 | ) ) offset++; | 73 | ) ) offset++; |
| 41 | 74 | ||
| 42 | printf( "Found an appropriate offset at: %zd\n", oldoffset ); | 75 | printf( "Found an appropriate offset at: %zd\n", offset ); |
| 43 | 76 | ||
| 44 | if( offset == map->size ) | 77 | if( offset == map->size ) |
| 45 | { | 78 | run = 0; |
| 46 | unmap_file( &map ); | ||
| 47 | exit(0); | ||
| 48 | } | ||
| 49 | 79 | ||
| 50 | if( oldoffset != -1 ) | 80 | if( oldoffset != -1 ) |
| 51 | { | 81 | { |
| 52 | uint8_t cs = 0, *mf = mappedfile + oldoffset, df[32]; | 82 | uint8_t *mf = mappedfile + oldoffset, df[128]; |
| 53 | char filename[20]; | 83 | size_t filename_len, header_len; |
| 84 | char filename_template[32], filename[32]; | ||
| 54 | int i; | 85 | int i; |
| 55 | 86 | ||
| 56 | for( i=0; i<8; ++i) | 87 | /* De-"crypt" obfuscation to our header copy */ |
| 57 | { | 88 | for( i=0; i<enc_len; ++i) |
| 58 | df[4*i+0] = mf[4*i+0] ^ mantra0; | 89 | df[i] = mf[i] ^ mantra[i%4]; |
| 59 | df[4*i+1] = mf[4*i+1] ^ mantra1; | 90 | |
| 60 | df[4*i+2] = mf[4*i+2] ^ mantra2; | 91 | /* Get values from LHA header */ |
| 61 | df[4*i+3] = mf[4*i+3] ^ mantra3; | 92 | header_len = df[0]; |
| 62 | } | 93 | filename_len = df[21]; |
| 94 | |||
| 95 | /* Copy rest of header, so we can checksum */ | ||
| 96 | for( i=enc_len; i<header_len+2; ++i) | ||
| 97 | df[i] = mf[i]; | ||
| 63 | 98 | ||
| 64 | snprintf( filename, sizeof( filename ), "%05d.lha", filenum++ ); | 99 | /* Make up new sequental file name */ |
| 65 | memcpy( ((uint8_t*)df) + 22, filename, 5); | 100 | snprintf( filename_template, sizeof(filename_template), "%%0%dd.lha", (int)filename_len ); |
| 101 | snprintf( filename, sizeof( filename ), filename_template, filenum++ ); | ||
| 102 | memcpy( ((uint8_t*)df) + 22, filename, filename_len); | ||
| 66 | 103 | ||
| 67 | for( i=2; i<29; ++i) cs += ((uint8_t*)df)[i]; | 104 | /* Recalculate checksum with new file name */ |
| 68 | ((uint8_t*)df)[1] = cs; | 105 | df[1] = 0; for( i=2; i<header_len+2; ++i) df[1] += df[i]; |
| 69 | 106 | ||
| 107 | /* Open file and dump our de-"crypted" header and then rest of file */ | ||
| 70 | i = open( filename, O_CREAT | O_TRUNC | O_WRONLY, 0644 ); | 108 | i = open( filename, O_CREAT | O_TRUNC | O_WRONLY, 0644 ); |
| 71 | write( i, df, 32 ); | 109 | write( i, df, enc_len ); |
| 72 | write( i, mf + 32, offset - oldoffset - 32 ); | 110 | write( i, mf + enc_len, offset - oldoffset - enc_len ); |
| 73 | close( i ); | 111 | close( i ); |
| 74 | } | 112 | } |
| 75 | oldoffset = offset; | 113 | oldoffset = offset; |
| 76 | offset++; | 114 | offset++; |
| 77 | } | 115 | } |
| 78 | 116 | ||
| 117 | unmap_file( &map ); | ||
| 79 | return 0; | 118 | return 0; |
| 80 | } | 119 | } |
