//------------------------------------------------------------------------- // Since the Palm Pilot programs are really poorly recognized by usual // methods, we are forced to read the resource tablee to determine // if everying is ok //return 0 if not a PRC, 2 if has ARM code segments, 1 otherwise int is_prc_file(linput_t *li) { DatabaseHdrType h; if ( qlread(li,&h,sizeof(h)) != sizeof(h) ) return 0; swap_prc(h); if ( (h.attributes & dmHdrAttrResDB) == 0 ) return 0; if ( short(h.numRecords) <= 0 ) return 0; const uint32 filesize = qlsize(li); const uint32 lowestpos = h.numRecords*sizeof(ResourceMapEntry) + sizeof(h); if ( lowestpos > filesize ) return 0; // the dates can be plain wrong, so don't check them: //uint32 now = time(NULL); //&& uint32(h.lastBackupDate) <= now // use unsigned comparition! //&& uint32(h.creationDate) <= now // use unsigned comparition! //&& uint32(h.modificationDate) <= now // use unsigned comparition! size_t size = sizeof(ResourceMapEntry) * h.numRecords; ResourceMapEntry *re = (ResourceMapEntry *)alloca(size); if ( re == NULL ) return 0; if ( qlread(li,re,size) != size ) return 0; bool hasArmCode = false; for ( int i=0; i < h.numRecords; i++ ) { swap_resource_map_entry(re[i]); if ( re[i].ulOffset >= filesize || re[i].ulOffset < lowestpos ) return 0; if ( re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL ) hasArmCode = true; } return hasArmCode ? 2 : 1; }
void create_load_seg(linput_t *li, ea_t start, ea_t end, int type, const char *name) { add_segm(0, start, end, name, ""); switch (type) { case 1: for (ea_t i = 0; i < end-start; i+=4) { uint32 data; qlread(li, &data, 4); put_long(start+i, data); } break; case 2: // Word Swap for (ea_t i = 0; i < end-start; i+=4) { uint16 data, data2; qlread(li, &data, 2); qlread(li, &data2, 2); put_long(start+i, (data << 16) | data2); } break; case 3: // Reverse order for (ea_t i = 0; i < end-start; i+=4) { uint32 data; qlread(li, &data, 4); data = swap32(data); put_long(end-i-1, data); } break; default: break; } }
bool load_header(linput_t *li) { int headerversion; int size; qlseek(li, 3); if (qlread(li, &yssEndian, 1) != 1) { error("Truncated file"); return false; } qlread(li, &headerversion, 4); qlread(li, &size, 4); int headersize=0xC; if (headerversion == 2) { qlseek(li, 8, SEEK_CUR); headersize+=8; } // Make sure size variable matches actual size minus header if (size != (qlsize(li) - headersize)) { error("Header size isn't valid"); return false; } return true; }
//----------------------------------------------------------------------- bool is_intelomf_file(linput_t *li) { uchar magic; lmh h; qlseek(li, 0); if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic) || qlread(li, &h, sizeof(h)) != sizeof(h) ) return false; int fsize = qlsize(li); return magic == INTELOMF_MAGIC_BYTE && h.tot_length < fsize; }
//---------------------------------------------------------------------- // // store CHR ROM pages to netnode // static bool save_chr_rom_pages_as_blobs( linput_t *li, uchar count ) { netnode node; char chr_node_name[MAXSTR]; uchar *buffer = (uchar *)qalloc( CHR_PAGE_SIZE ); if( buffer == 0 ) return false; qlseek( li, INES_HDR_SIZE + (INES_MASK_TRAINER(hdr.rom_control_byte_0) ? TRAINER_SIZE : 0) + PRG_PAGE_SIZE * hdr.prg_page_count_16k ); for(int i=0; i<count; i++) { qlread( li, buffer, CHR_PAGE_SIZE ); qsnprintf( chr_node_name, sizeof(chr_node_name), "$ CHR-ROM page %d", i ); if( !node.create( chr_node_name ) ) { qfree( buffer ); return false; } if( !node.setblob( buffer, CHR_PAGE_SIZE, 0, 'I' ) ) msg("Could not store CHR-ROM pages to netnode!\n"); } qfree( buffer ); return true; }
//---------------------------------------------------------------------- // // check input file format. if recognized, then return 1 // and fill 'fileformatname'. // otherwise return 0 // int accept_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { if( n!= 0 ) return 0; // quit if file is smaller than size of iNes header if (qlsize(li) < sizeof(ines_hdr)) return 0; // set filepos to offset 0 qlseek(li, 0, SEEK_SET); // read NES header if(qlread(li, &hdr, INES_HDR_SIZE) != INES_HDR_SIZE) return 0; // is it a valid ROM image in iNes format? if( memcmp("NES", &hdr.id, sizeof(hdr.id)) != 0 || hdr.term != 0x1A ) return 0; // this is the name of the file format which will be // displayed in IDA's dialog qstrncpy(fileformatname, "Nintendo Entertainment System ROM", MAX_FILE_FORMAT_NAME); // set processor to 6502 if ( ph.id != PLFM_6502 ) { msg("Nintendo Entertainment System ROM detected: setting processor type to M6502.\n"); set_processor_type("M6502", SETPROC_ALL|SETPROC_FATAL); } return (1 | ACCEPT_FIRST); }
//---------------------------------------------------------------------- // // store trainer to netnode // static bool save_trainer_as_blob( linput_t *li ) { netnode node; uchar *buffer; if( !INES_MASK_TRAINER( hdr.rom_control_byte_0 ) ) return false; buffer = (uchar *)qalloc( TRAINER_SIZE ); if( buffer == 0 ) return false; qlseek( li, INES_HDR_SIZE ); qlread( li, buffer, TRAINER_SIZE ); if( !node.create( "$ Trainer" ) ) { qfree( buffer ); return false; } if( !node.setblob( buffer, TRAINER_SIZE, 0, 'I' ) ) msg("Could not store trainer to netnode!\n"); qfree( buffer ); return true; }
/* verify if we can process the target file * return true if yes * false otherwise */ int idaapi accept_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { if (n != 0) { return 0; } qlseek(li, 0); EFI_IMAGE_TE_HEADER teHeader = {0}; if (qlread(li, &teHeader, sizeof(EFI_IMAGE_TE_HEADER)) == sizeof(EFI_IMAGE_TE_HEADER) && teHeader.Signature == EFI_IMAGE_TE_SIGNATURE) { msg("Signature: 0x%hx\n", teHeader.Signature); msg("Machine: 0x%hx\n", teHeader.Machine); msg("Number of Sections: 0x%hhx\n", teHeader.NumberOfSections); msg("Subsystem: 0x%hhx\n", teHeader.Subsystem); msg("Stripped size: 0x%hx\n", teHeader.StrippedSize); msg("Address of EntryPoint: 0x%0x\n", teHeader.AddressOfEntryPoint); msg("Base of code: 0x%x\n", teHeader.BaseOfCode); msg("Image base: 0x%llx\n", teHeader.ImageBase); qstrncpy(fileformatname, "TE put.as Loader", MAX_FILE_FORMAT_NAME); return true; } return 0; }
//-------------------------------------------------------------------------- int accept_file(linput_t *li,char fileformatname[MAX_FILE_FORMAT_NAME],int n) { if ( n ) return 0; header h; qlseek(li, 0); if ( qlread(li, &h, sizeof(h)) != sizeof(h) ) return 0; if ( compute_som_checksum(&h) != 0 ) return 0; h.swap(); char *type; switch ( h.a_magic ) { case EXELIB_MAGIC : type = "Executable Library"; break; case REL_MAGIC : type = "Relocatable"; break; case EXE_MAGIC : type = "Non-sharable, executable"; break; case SHREXE_MAGIC : type = "Sharable, executable"; break; case SHREXELD_MAGIC: type = "Sharable, demand-loadable executable"; break; case DLL_MAGIC : type = "Dynamic Load Library"; break; case SHLIB_MAGIC : type = "Shared Library"; break; case RELLIB_MAGIC : type = "Relocatable Library"; break; default: return 0; } qsnprintf(fileformatname, MAX_FILE_FORMAT_NAME, "HP-UX SOM (%s)", type); return 1; }
static int copy_to_remote(const char *lname, const char *rname) { int code = 0; int fn = s_open_file(rname, NULL, false); if ( fn != -1 ) { linput_t *li = open_linput(lname, false); if ( li != NULL ) { size_t size = qlsize(li); if ( size > 0 ) { char *buf = (char *)qalloc(size); qlread(li, buf, size); if ( s_write_file(fn, 0, buf, size) != ssize_t(size) ) code = qerrcode(); } close_linput(li); } else { code = qerrcode(); } s_close_file(fn); #if DEBUGGER_ID == DEBUGGER_ID_X86_IA32_LINUX_USER // chmod +x s_ioctl(0, rname, strlen(rname)+1, NULL, 0); #endif } else { code = qerrcode(); } return code; }
//---------------------------------------------------------------------------- int idaapi accept_file( linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { if ( n > 0 ) return 0; int32 spc_file_size = qlsize(li); if ( spc_file_size < 0x10200 ) return 0; spc_file_t spc_info; if ( qlseek(li, 0) != 0 ) return 0; if ( qlread(li, &spc_info, sizeof(spc_file_t)) != sizeof(spc_file_t) ) return 0; if (memcmp(spc_info.signature, "SNES-SPC700 Sound File Data", 27) != 0 || spc_info.signature[0x21] != 0x1a || spc_info.signature[0x22] != 0x1a) return 0; qstrncpy(fileformatname, "SNES-SPC700 Sound File Data", MAX_FILE_FORMAT_NAME); return 1; }
//----------------------------------------------------------------------------- // load a macro assembler file in IDA. void load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) { // already read the 2 first bytes qlseek(li, 2); // initialize static variables qstrncpy(creator, "UNKNOWN", sizeof(creator)); entry_point = -1; bool finished = false; while (!finished) { uchar record_type = 0; // read the record type if (qlread(li, &record_type, 1) != 1) mas_error("unable to read the record type"); finished = process_record(li, record_type, true); } #if defined(DEBUG) msg("MAS: reading complete\n"); #endif mas_write_comments(); }
void ScuLoadState (linput_t *li, ea_t *pc, int size) { scuregs_struct Scu; scudspregs_struct ScuDsp; qlread(li, (void *)&Scu, sizeof(Scu)); qlread(li, (void *)&ScuDsp, sizeof(ScuDsp)); if (pc) { *pc = ScuDsp.PC; ea_t start=0, end=0x100; add_segm(0, start, end, "RAM", ""); for (ea_t i = 0; i < end-start; i++) put_long(start+i, ScuDsp.ProgramRam[i]); } }
//-------------------------------------------------------------------------- int idaapi accept_file(linput_t *li,char fileformatname[MAX_FILE_FORMAT_NAME],int n) { if ( n ) return 0; union { GEOSheader h1; GEOS2header h2; } h; qlseek(li, 0); if ( qlread(li, &h, sizeof(h)) != sizeof(h) ) return false; int32 apppos; int version; if ( h.h1.ID == GEOS_ID && h.h1.fclass == 0 ) { apppos = 0xC8; version = 1; } else if ( h.h2.ID == GEOS2_ID && h.h2.fclass == 1 ) { apppos = sizeof(GEOS2header); version = 2; } else { return false; } GEOSappheader ah; qlseek(li, apppos, SEEK_SET); if ( qlread(li, &ah, sizeof(ah)) != sizeof(ah) ) return false; const char *stype; switch ( ah.type ) { case 1: stype = "Application"; break; case 2: stype = "Library"; break; case 3: stype = "Driver"; break; default: stype = "Unknown type";break; } qsnprintf(fileformatname, MAX_FILE_FORMAT_NAME, "GEOS%d %s", version, stype); return true; }
void SH2LoadState(linput_t *li, bool isslave, sh2regs_struct *regs, int size) { if (isslave == 1) qlseek(li, 1, SEEK_CUR); // Read registers qlread(li, (void *)regs, sizeof(sh2regs_struct)); qlseek(li, size-sizeof(sh2regs_struct), SEEK_CUR); }
static INLINE int StateCheckRetrieveHeader(linput_t *li, const char *name, int *version, int *size) { char id[4]; size_t ret; if ((ret = qlread(li, id, 4)) != 4) return -1; if (strncmp(name, id, 4) != 0) return -2; if ((ret = qlread(li, version, 4)) != 4) return -1; if (qlread(li, size, 4) != 4) return -1; return 0; }
//-------------------------------------------------------------------------- bool macho_file_t::parse_fat_header() { qlseek(li, start_offset); if ( qlread(li, &fheader, sizeof(fheader)) != sizeof(fheader) ) return false; int code = (fheader.magic == FAT_MAGIC); if ( fheader.magic == FAT_CIGAM ) { swap_fat_header(&fheader); code = 2; } if ( code == 0 || fheader.nfat_arch > 16 ) return false; uint32 fsize = qlsize(li); uint32 archs_size = fheader.nfat_arch * sizeof(fat_arch); if ( sizeof(fat_header) + archs_size >= fsize ) return false; fat_archs.resize(fheader.nfat_arch); if ( qlread(li, fat_archs.begin(), archs_size) != archs_size ) { fat_archs.clear(); return false; } for ( uint32_t i=0; i < fheader.nfat_arch; i++ ) { fat_arch *parch = &fat_archs[i]; if ( code == 2 ) swap_fat_arch(parch); if ( parch->size <= sizeof(mach_header) || parch->size >= fsize || parch->offset < sizeof(fat_header) + archs_size || parch->offset + parch->size > fsize ) { fat_archs.clear(); return false; } } return true; }
//-------------------------------------------------------------------------- bool is_elf_file(linput_t *li) { Elf32_Ehdr h; qlseek(li, 0); if ( qlread(li, &h, sizeof(h)) != sizeof(h) || h.e_ident[EI_MAG0] != ELFMAG0 || h.e_ident[EI_MAG1] != ELFMAG1 || h.e_ident[EI_MAG2] != ELFMAG2 || h.e_ident[EI_MAG3] != ELFMAG3 ) return false; return true; }
//-------------------------------------------------------------------------- bool macho_file_t::parse_header() { qlseek(li, start_offset); uint32 magic; if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic) ) return false; if ( magic == FAT_MAGIC || magic == FAT_CIGAM ) return parse_fat_header(); else return is_magic(magic) || is_cigam(magic); }
static void read_dyninfo(size_t offset, size_t size, dyninfo_t *dyninfo) { if ( size == 0 ) return; qlseek(li, offset); const int entsize = elf64 ? sizeof(Elf64_Dyn) : sizeof(Elf32_Dyn); for ( int i=0; i < size; i+=entsize ) { Elf64_Dyn d; if ( elf64 ) { if ( qlread(li, &d, sizeof(d)) != sizeof(d) ) errstruct(); if ( mf ) { d.d_tag = swap64(d.d_tag); d.d_un = swap64(d.d_un); } } else { Elf32_Dyn d32; if ( qlread(li, &d32, sizeof(d32)) != sizeof(d32) ) errstruct(); if ( mf ) { d.d_tag = swap32(d32.d_tag); d.d_un = swap32(d32.d_un.d_val); } else { d.d_tag = d32.d_tag; d.d_un = d32.d_un.d_val; } } dyninfo->push_back(d); if ( d.d_tag == DT_NULL ) break; } }
//---------------------------------------------------------------------- bool is_pef_file(linput_t *li) { pef_t pef; if ( qlread(li, &pef, sizeof(pef_t)) != sizeof(pef_t) ) return false; swap_pef(pef); return strncmp(pef.tag1,PEF_TAG_1,4) == 0 // Joy! && strncmp(pef.tag2,PEF_TAG_2,4) == 0 // peff && pef.formatVersion == PEF_VERSION // 1 && (strncmp(pef.architecture,PEF_ARCH_PPC,4) == 0 // PowerPC || strncmp(pef.architecture,PEF_ARCH_68K,4) == 0); // or 68K }
void SoundLoadState (linput_t *li, ea_t *pc, int size) { char IsM68KRunning; int pos=qltell(li); qlread(li, (void *)&IsM68KRunning, 1); qlseek(li, 4 * (8+8+1), SEEK_CUR); if (pc) qlread(li, (void *)pc, 4); else qlseek(li, 4, SEEK_CUR); qlseek (li, 0x1000, SEEK_CUR); if (pc) create_load_seg(li, 0, 0x80000, 2, "RAM"); else create_load_seg(li, 0x25A00000, 0x25A80000, 2, "SOUNDRAM"); qlseek(li, size-(qltell(li)-pos), SEEK_CUR); }
//-------------------------------------------------------------------------- int get_aout_file_format_index(linput_t *li) { exec ex; register int i = 0; if(qlread(li, &ex, sizeof(ex)) != sizeof(ex)) return false; if(N_BADMAG(ex)) { ex.a_info = swap32(ex.a_info); switch(N_MACHTYPE(ex)) { case M_386_NETBSD: case M_68K_NETBSD: case M_68K4K_NETBSD: case M_532_NETBSD: case M_SPARC_NETBSD: case M_PMAX_NETBSD: case M_VAX_NETBSD: case M_ALPHA_NETBSD: case M_ARM6_NETBSD: break; default: return false; } } switch(N_MAGIC(ex)) { case NMAGIC: ++i; case CMAGIC: ++i; case ZMAGIC: ++i; case OMAGIC: ++i; case QMAGIC: // msg("text=%d data=%d symsize=%d txtoff=%d sum=%d\n", ex.a_text, ex.a_data, // N_SYMSIZE(ex), N_TXTOFF(ex), ex.a_text + ex.a_data + N_SYMSIZE(ex) + N_TXTOFF(ex)); if ( qlsize(li) >= ex.a_text + ex.a_data + N_SYMSIZE(ex) + N_TXTOFF(ex) ) break; if ( N_MAGIC(ex) == ZMAGIC && qlsize(li) >= ex.a_text + ex.a_data + N_SYMSIZE(ex) ) { i = 5; // OpenBSD demand-paged break; } default: return false; } return i+1; }
//---------------------------------------------------------------------- bool idaapi init_loader_options(linput_t *li) { // already read the 2 first bytes qlseek(li, 2); bool finished = false; while (!finished) { uchar record_type = 0; // read the record type if (qlread(li, &record_type, 1) != 1) return false; finished = process_record(li, record_type, false); } return true; }
//-------------------------------------------------------------------------- // // check input file format. if recognized, then return 1 // and fill 'fileformatname'. // otherwise return 0 // static int idaapi accept_yss_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { // read as much of the file as you need to to determine whether // it is something that you recognize char id[3]; if (n || qlread(li, id, 3) == -1) return 0; if (memcmp(id, "YSS", 3) != 0) { return 0; } //if you recognize the file, then say so qsnprintf(fileformatname, MAX_FILE_FORMAT_NAME, "YSS File"); return 1; }
//---------------------------------------------------------------------- // // loads the whole file into IDA // this is a wrapper function, which: // // - checks the header for validity and fixes broken headers // - creates all necessary segments // - saves the whole file to blobs // - loads prg pages/banks // - adds informational descriptions to the database // static void load_ines_file( linput_t *li ) { // go to file offset 0 - just to be sure qlseek(li, 0, SEEK_SET); // read the whole header if( qlread(li, &hdr, sizeof(ines_hdr)) != sizeof(ines_hdr) ) vloader_failure("File read error!",0); // check if header is corrupt // show a warning msg, but load the rom nonetheless if( is_corrupt_ines_hdr() ) { //warning("The iNES header seems to be corrupt.\nLoader might give inaccurate results!"); int code = askyn_c(1, "The iNES header seems to be corrupt.\n" "The NES loader could produce wrong results!\n" "Do you want to internally fix the header ?\n\n" "(this will not affect the input file)"); if( code == 1 ) fix_ines_hdr(); } // create NES segments create_segments( li ); // save NES file to blobs save_image_as_blobs( li ); // load relevant ROM banks into database load_rom_banks( li ); // make vectors public add_entry_points( li ); // fill inf structure set_ida_export_data(); // add information about the ROM image describe_rom_image(); // let IDA add some information about the loaded file create_filename_cmt(); }
//------------------------------------------------------------------------ inline bool pe_loader_t::read_header(linput_t *li, off_t _peoff, bool silent) { peoff = _peoff; qlseek(li, peoff); memset(&pe64, 0, sizeof(pe64)); qlseek(li, peoff); size_t size = qlread(li, &pe64, sizeof(pe64)); size_t minsize = pe64.magic == MAGIC_P32_PLUS ? qoffsetof(peheader64_t, subsys) : qoffsetof(peheader_t, subsys); bool ok = size > minsize && size <= sizeof(pe64) && (pe64.signature == PEEXE_ID || pe64.signature == BPEEXE_ID || pe64.signature == PLEXE_ID) && pe64_to_pe(pe, pe64, silent); if ( ok ) //initialize imagebase for loading set_imagebase((ea_t)pe.imagebase()); return ok; }
//-------------------------------------------------------------------------- // 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; }
//------------------------------------------------------------------------ inline bool pe_loader_t::read_header(linput_t *li, bool silent) { uint32 peoff = 0; link_ulink = false; qlseek(li, peoff); lread(li, &exe, sizeof(exe)); if ( exe.exe_ident != PEEXE_ID ) { if ( exe.exe_ident == EXE_ID ) { char tmp[8]; if ( qlread(li, tmp, sizeof(tmp)) == sizeof(tmp) && memcmp(tmp, "UniLink", 8) == 0 ) { link_ulink = true; } } qlseek(li, PE_PTROFF); lread(li, &peoff, sizeof(peoff)); } return read_header(li, peoff, silent); }
//----------------------------------------------------------------------------- // detect macro assembler files using the start sequence. int accept_file(linput_t *li, char fileformatname[MAX_FILE_FORMAT_NAME], int n) { short word = 0; if (n) return 0; // read the first word if (qlread(li, &word, 2) != 2) return 0; #if defined(DEBUG) msg("MAS: 2 first bytes : 0x%X\n", word); #endif // first word must match the start_sequence if (word != START_SEQUENCE) return 0; qstrncpy(fileformatname, "Macro Assembler by Alfred Arnold", MAX_FILE_FORMAT_NAME); #if defined(DEBUG) msg("MAS: detected mas binary file !\n"); #endif return 1; }