#include #include "mystdlib.h" #include #include #include #include /* lha header: 00 Header length 01 Header checksum [02-length] 02 0x2d ('-') 03 0x6c ('l') 04 0x68 ('h') 05 0x?? ('0' or '5') unsure 06 0x2d ('-') 07 0x?? LSB of compressed size 08 0x?? .. 09 0x00 .. 10 0x00 MSB of compressed size, i.e. 0 .. 21 Length of path name */ static uint8_t mantra_in[] = { 0x68, 0x35, 0x2d, 0x6c }; int main( int args, char **argv ) { int filenum = 0, run = 1, first_run = 1; size_t offset = 0, old_offset = 0, reported = 0, enc_len = 32; uint8_t mantra[4], id0, id5, *mapped_file; MAP map; /* For streets we do have a enc_len of 34 */ while( run ) { switch( getopt( args, argv, ":e:" ) ) { case -1 : run = 0; break; case 'e': enc_len = strtoul( optarg, 0, 0 ); break; default: fputs( "Syntax: %s [-e encrypted_length (default: 32, for streets 34 or 0)] path-to-teiln.dat", stderr ); exit( 1 ); } } run = 1; if( optind == args ) { fputs( "Missing filename.", stderr ); exit( 1 ); } map = map_file( argv[optind], 1 ); mapped_file = map->addr; mantra[0] = mantra_in[0] ^ mapped_file[4]; mantra[1] = mantra_in[1] ^ mapped_file[5]; mantra[2] = mantra_in[2] ^ mapped_file[2]; mantra[3] = mantra_in[3] ^ mapped_file[3]; id0 = mapped_file[0]; id5 = mapped_file[5]; while( run ) { while( ( offset < map->size ) && ( ( mapped_file[ offset + 0 ] != id0 ) || ( mapped_file[ offset + 2 ] != ( '-' ^ mantra[2] )) || ( mapped_file[ offset + 3 ] != ( 'l' ^ mantra[3] )) || ( mapped_file[ offset + 4 ] != ( 'h' ^ mantra[0] )) || ( mapped_file[ offset + 5 ] != id5 ) || ( mapped_file[ offset + 6 ] != ( '-' ^ mantra[2] )) ) ) offset++; // printf( "Found an appropriate offset at: %zd\n", offset ); if( reported < ( offset * 10 ) / map->size ) { reported++; printf( "%zd%% ", 10 * reported ); fflush( stdout ); } if( offset == map->size ) run = 0; if( !first_run ) { uint8_t *mf = mapped_file + old_offset, df[128]; size_t filename_len, header_len, i; int fh; char filename[32]; /* De-"crypt" obfuscation to our header copy */ for( i=0; i header_len ) { write( fh, df, enc_len ); write( fh, mf + enc_len, offset - old_offset - enc_len ); } else { write( fh, df, header_len ); write( fh, mf + header_len, offset - old_offset - header_len ); } close( fh ); } first_run = 0; old_offset = offset++; } unmap_file( &map ); return 0; }