//-------------------------------------------------------------------------- // check and send to the remote server the specified stub // do it only if its crc does not match the specified crc // this function runs on the local machine with ida interface static uchar *sync_stub(const char *fname, uint32 crc, size_t *psize) { char path[QMAXPATH]; bool told = false; if ( getsysfile(path, sizeof(path), fname, NULL) != NULL ) { linput_t *li = open_linput(path, false); if ( li != NULL ) { int32 size = qlsize(li); if ( size > 0 ) { uchar *buf = qnewarray(uchar, size); if ( buf != NULL ) { if ( qlread(li, buf, size) == size ) { if ( calc_crc32(0, buf, size) != crc ) { close_linput(li); *psize = size; return buf; } else { msg("Kernel debugger stub is up to date...\n"); told = true; *psize = 1; // signal ok } } qfree(buf); } } close_linput(li); } } if ( !told ) warning("AUTOHIDE NONE\nCould not find/read debugger stub %s", fname); return NULL; }
//----------------------------------------------------------------------- static void read_fixup(linput_t *li) { fixup fix; const int size = offsetof(fixup, fixups); lread(li, &fix, size); uint32 fptr = qltell(li); ea_t sea = getsea(fix.where_IN); if ( sea != BADADDR ) { uchar *b = qnewarray(uchar, fix.length); if ( b == NULL ) nomem("read_fixup"); lread(li, b, fix.length); // show_hex(b, fix.length, "\nFIXUP SEG %04X, %04X BYTES, KIND %02X\n", // fix.where_IN, // fix.length, // b[0]); const uchar *ptr = b; const uchar *end = b + fix.length; while ( ptr < end ) { fixup_data_t fd; uint32 where_offset = 0; uint32 what_offset = 0; ushort what_in = 9; bool selfrel = false; bool isfar = false; fd.type = FIXUP_OFF32; switch ( *ptr++ ) { case 0x2C: // GEN isfar = true; ask_for_feedback("Untested relocation type"); case 0x24: // GEN where_offset = readdw(ptr, false); what_offset = readdw(ptr, false); what_in = (ushort)readdw(ptr, false); break; case 0x2D: isfar = true; case 0x25: // INTRA where_offset = readdw(ptr, false); what_offset = readdw(ptr, false); what_in = fix.where_IN; break; case 0x2A: // CALL where_offset = readdw(ptr, false); what_offset = 0; what_in = (ushort)readdw(ptr, false); selfrel = true; break; case 0x2E: // OFF32? isfar = true; case 0x26: where_offset = readdw(ptr, false); what_offset = 0; what_in = (ushort)readdw(ptr, false); break; default: ask_for_feedback("Unknown relocation type %02X", ptr[-1]); add_pgm_cmt("!!! Unknown relocation type %02X", ptr[-1]); break; } ea_t source = sea + where_offset; ea_t target = BADADDR; switch ( what_in >> 12 ) { case 0x02: // segments target = getsea(what_in); break; case 0x06: // externs target = xea + 4 * ((what_in & 0xFFF) - 1); fd.type |= FIXUP_EXTDEF; break; default: ask_for_feedback("Unknown relocation target %04X", what_in); add_pgm_cmt("!!! Unknown relocation target %04X", what_in); break; } segment_t *ts = getseg(target); fd.sel = ts ? (ushort)ts->sel : 0; if ( (fd.type & FIXUP_EXTDEF) == 0 ) { target += what_offset; what_offset = 0; } fd.off = target; fd.displacement = what_offset; target += what_offset; if ( selfrel ) { fd.type |= FIXUP_SELFREL; target -= source + 4; } set_fixup(source, &fd); put_long(source, target); if ( isfar ) { fd.type = FIXUP_SEG16; set_fixup(source+4, &fd); put_word(source+4, fd.sel); } } qfree(b); }
//-------------------------------------------------------------------------- int main(int argc,char *argv[]) { int i; fprintf(stderr,"ARM Library unpacker. Copyright 1997 by Ilfak Guilfanov. Version 1.00\n"); if ( argc < 2 ) fatal("Usage: unlib libfile"); strcpy(infile,argv[1]); FILE *fp = qfopen(infile,"rb"); if ( fp == NULL ) fatal("Can't open library %s",infile); chunk_header_t hd; if ( qfread(fp, &hd, sizeof(hd)) != sizeof(hd) || (hd.ChunkFileId != AOF_MAGIC && hd.ChunkFileId != AOF_MAGIC_B) ) fatal("Bad library format"); if ( hd.ChunkFileId == AOF_MAGIC_B ) { // BIG ENDIAN mf = 1; hd.max_chunks = swap(hd.max_chunks); hd.num_chunks = swap(hd.num_chunks); } chunk_entry_t *ce = qnewarray(chunk_entry_t,size_t(hd.max_chunks)); if ( ce == NULL ) nomem("chunk entries (%d)",size_t(hd.max_chunks)); qfread(fp, ce, sizeof(chunk_entry_t)*size_t(hd.max_chunks)); if ( mf ) for ( i=0; i < hd.max_chunks; i++ ) swap_chunk_entry(ce+i); int vrsn = -1; int diry = -1; int data = 0; for ( i=0; i < hd.max_chunks; i++ ) { if ( ce[i].file_offset == 0 ) continue; if ( strncmp(ce[i].chunkId,LIB_DIRY,sizeof(ce[i].chunkId)) == 0 ) diry = i; if ( strncmp(ce[i].chunkId,LIB_VRSN,sizeof(ce[i].chunkId)) == 0 ) vrsn = i; if ( strncmp(ce[i].chunkId,LIB_DATA,sizeof(ce[i].chunkId)) == 0 ) data++; } if ( diry == -1 ) fatal("Can't find library directory!"); if ( data == 0 ) fatal("No modules in the library!"); if ( vrsn == -1 ) fatal("Can't determine library version!"); ulong *version = (ulong *)read_chunk(fp,ce,vrsn); if ( mf ) *version = swap(*version); if ( *version != 1 ) fatal("Wrong library version (%ld)",*version); qfree(version); ulong *dir = (ulong *)read_chunk(fp,ce,diry); ulong *end = dir + size_t(ce[diry].size/4); while ( dir < end ) { ulong idx = *dir++; /* ulong elen = */ *dir++; ulong dlen = *dir++; if ( mf ) { idx = swap(idx); dlen = swap(dlen); } if ( idx != 0 ) { printf("%ld. %s\n",idx,dir); strncpy(modname,(char *)dir,sizeof(modname)); modname[sizeof(modname)-1] = '\0'; void *core = read_chunk(fp,ce,idx); outfp = qfopen(modname,"wb"); if ( outfp == NULL ) { warning("Can't open output file %s",modname); } else { qfwrite(outfp,core,size_t(ce[size_t(idx)].size)); qfclose(outfp); } qfree(core); } dir += size_t(dlen/4); } qfree(dir); qfclose(fp); return 0; }