//-------------------------------------------------------------------------- static void create_segment_registers(void) { for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { segreg_t *sr = getSRarea(s->startEA); if ( sr == NULL ) { segreg_t sr; memset(&sr, 0, sizeof(sr)); sr.startEA = s->startEA; sr.endEA = s->endEA; sr.settags(SR_autostart); SRareas.create_area(&sr); } } }
//---------------------------------------------------------------------- static void apply_symbols(void) { free_mappings(); if ( dataseg != BADADDR ) { for ( int i=0; i < numports; i++ ) { ea_t ea = calc_data_mem(ports[i].address); segment_t *s = getseg(ea); if ( s == NULL || s->type != SEG_IMEM ) continue; doByte(ea, 1); const char *name = ports[i].name; if ( !set_name(ea, name, SN_NOWARN) ) set_cmt(ea, name, 0); } for ( segment_t *d = getseg(dataseg); d != NULL; d = get_next_seg(d->startEA) ) { if ( d->type != SEG_IMEM ) continue; ea_t ea = d->startEA; ea_t dataend = d->endEA; while ( 1 ) { ea = next_unknown(ea, dataend); if ( ea == BADADDR ) break; ea_t end = nextthat(ea, dataend, f_isHead, NULL); if ( end == BADADDR ) end = dataend; doByte(ea, end-ea); } } create_mappings(); } }
static int notify(processor_t::idp_notify msgid, ...) // Various messages { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::newfile: { // ig: вообще у меня теперь такая точка зрения: // не надо в коде задавать вид имен. // при желании это можно сделать в ida.cfg: // #ifdef __80196__ // DUMMY_NAMES_TYPE = NM_SHORT // #endif segment_t *sptr = get_first_seg(); if( sptr != NULL ) set_segm_class( sptr, "CODE" ); ea_t ea, ea1; for( int i = 0; i < qnumber(entries); i++ ) { ea = toEA( inf.baseaddr, entries[i].off ); if( isEnabled(ea) ) { switch( entries[i].type ) { case I196F_BTS: doByte( ea, entries[i+1].off-entries[i].off ); set_cmt( ea, entries[i].cmt, 0 ); break; case I196F_CMT: if( entries[i].cmt ) add_long_cmt( ea, 1, "%s", entries[i].cmt ); else describe( ea, 1, "" ); break; case I196F_OFF: doWord( ea, 2 ); set_offset( ea, 0, toEA( inf.baseaddr, 0 ) ); ea1 = toEA( inf.baseaddr, get_word( ea ) ); auto_make_proc( ea1 ); //dash: long_cmt здесь не смотрится, так как рисуется до заголовка // хорошо бы поставить func_cmt, но к этому моменту функций еще нет // как быть? //ig: воспользоваться простым комментарием // при создании функции комментарий перетащится set_cmt( ea1, entries[i].cmt, 1 ); } set_name( ea, entries[i].name ); } } ea = toEA( inf.baseaddr, 0x2080 ); if( isEnabled( ea ) ) { inf.beginEA = ea; inf.startIP = 0x2080; } segment_t s; s.startEA = toEA( inf.baseaddr, 0 ); s.endEA = toEA( inf.baseaddr, 0x400 ); s.sel = inf.baseaddr; s.type = SEG_IMEM; // internal memory // ig: лучше искать дырку не от нуля, а от базы загрузки // ea_t bottom = toEA( inf.baseaddr, 0 ); // intmem = s.startEA = freechunk( bottom, 1024, 0xF ); // s.endEA = s.startEA + 1024; // s.sel = ushort(s.startEA >> 4); // dash: дырку искать не пришлось, но я оставил это как пример на будущее add_segm_ex( &s, "INTMEM", NULL, ADDSEG_OR_DIE); predefined_t *ptr; for( ptr = iregs; ptr->name != NULL; ptr++ ) { ea_t ea = toEA( inf.baseaddr, ptr->addr ); ea_t oldea = get_name_ea( BADADDR, ptr->name ); if( oldea != ea ) { if( oldea != BADADDR ) set_name( oldea, NULL ); do_unknown( ea, DOUNK_EXPAND ); set_name( ea, ptr->name ); } if( ptr->cmt != NULL ) set_cmt( ea, ptr->cmt, 1 ); } } // do16bit( 0x18, 2 ); // SP always word break; case processor_t::oldfile: for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { if ( getSRarea(s->startEA) == NULL ) { segreg_t sr; sr.startEA = s->startEA; sr.endEA = s->endEA; sr.reg(WSR) = 0; sr.reg(WSR1) = 0; sr.reg(rVds) = inf.baseaddr; sr.settags(SR_autostart); SRareas.create_area(&sr); } } break; case processor_t::newseg: // default DS is equal to Base Address (va_arg(va, segment_t *))->defsr[rVds-ph.regFirstSreg] = inf.baseaddr; break; case processor_t::newprc: extended = va_arg(va,int) != 0; if ( !extended ) ph.flag &= ~PR_SEGS; else ph.flag |= PR_SEGS; default: break; } va_end(va); return(1); }
// The kernel event notifications // Here you may take desired actions upon some kernel events static int notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behavior processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::newfile: helper.create("$ m7700"); if ( choose_device() ) set_device_name(device, IORESP_ALL); // Set the default segment register values : // -1 (badsel) for DR // 0 for fM and fX for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { SetDefaultRegisterValue(s, rDR, BADSEL); SetDefaultRegisterValue(s, rfM, 0); SetDefaultRegisterValue(s, rfX, 0); } info(m7700_help_message); break; case processor_t::term: free_ioports(ports, numports); default: break; case processor_t::newprc: ptype = processor_subtype_t(va_arg(va, int)); break; case processor_t::setsgr: { ea_t ea1 = va_arg(va, ea_t); ea_t ea2 = va_arg(va, ea_t); int reg = va_arg(va, int); sel_t v = va_arg(va, sel_t); sel_t ov = va_arg(va, sel_t); if ( (reg == rfM || reg == rfX) && v != ov ) set_sreg_at_next_code(ea1, ea2, reg, ov); } break; case processor_t::oldfile: helper.create("$ m7700"); { char buf[MAXSTR]; if ( helper.supval(-1, buf, sizeof(buf)) > 0 ) set_device_name(buf, IORESP_ALL); } break; case processor_t::savebase: case processor_t::closebase: helper.supset(-1, device); break; } va_end(va); return(1); }
//-------------------------------------------------------------------------- // 0 - run uunp interactively // 1 - run without questions // 2 - run manual reconstruction void idaapi run(int arg) { if ( arg == 2 ) { area_t impdir = area_t(0, 0); ea_t oep; netnode n; // Settings never stored before? if ( n.create("$ uunp") ) { // Populate default values oep = get_screen_ea(); segment_t *s = getseg(oep); if ( s != NULL ) { oep_area.startEA = s->startEA; oep_area.endEA = s->endEA; } } else { // Restore previous settings oep = n.altval(0); oep_area.startEA = n.altval(1); oep_area.endEA = n.altval(2); impdir.startEA = n.altval(3); impdir.endEA = n.altval(4); } if ( !AskUsingForm_c( "Reconstruction parameters\n" "\n" " <~O~riginal entrypoint:N:128:32::>\n" " <Code ~s~tart address:N:128:32::>\n" " <Code ~e~nd address :N:128:32::>\n" "\n" " <IAT s~t~art address:N:128:32::>\n" " <IAT e~n~d address:N:128:32::>\n" "\n", &oep, &oep_area.startEA, &oep_area.endEA, &impdir.startEA, &impdir.endEA) ) { // Cancelled? return; } // Invalid settings? if ( impdir.startEA == 0 || impdir.endEA == 0 ) { msg("Invalid import address table boundaries"); return; } // Store settings n.altset(0, oep); n.altset(1, oep_area.startEA); n.altset(2, oep_area.endEA); n.altset(3, impdir.startEA); n.altset(4, impdir.endEA); if ( !create_impdir(impdir) ) return; // reanalyze the unpacked code do_unknown_range(oep_area.startEA, oep_area.size(), DOUNK_EXPAND); auto_make_code(oep); noUsed(oep_area.startEA, oep_area.endEA); auto_mark_range(oep_area.startEA, oep_area.endEA, AU_FINAL); // mark the program's entry point move_entry(oep); take_memory_snapshot(true); return; } // Determine the original entry point area for ( segment_t *s = get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { if ( s->type != SEG_GRP ) { oep_area = *s; break; } } if ( arg == 0 && askyn_c(0, "HIDECANCEL\n" "AUTOHIDE REGISTRY\n" "Universal PE unpacker\n" "\n" "IMPORTANT INFORMATION, PLEASE READ CAREFULLY!\n" "\n" "This plugin will start the program execution and try to suspend it\n" "as soon as the packer finishes its work. Since there might be many\n" "variations in packers and packing methods, the execution might go out\n" "of control. There are many ways how things can go wrong, but since you\n" "have the source code of this plugin, you can modify it as you wish.\n" "\n" "Do you really want to launch the program?\n") <= 0 ) { return; } success = false; set_file_ext(resfile, sizeof(resfile), database_idb, "res"); if ( arg == 0 && !AskUsingForm_c( "Uunp parameters\n" "IDA will suspend the program when the execution reaches\n" "the original entry point area. The default values are in\n" "this dialog box. Please verify them and correct if you wish.\n" "\n" "ORIGINAL ENTRY POINT AREA\n" " <~S~tart address:N:128:32::>\n" " <~E~nd address :N:128:32::>\n" "\n" "OUTPUT RESOURCE FILE NAME\n" " <~R~esource file:A:256:32::>\n" "\n", &oep_area.startEA, &oep_area.endEA, resfile) ) { return; } if ( !hook_to_notification_point(HT_DBG, callback, NULL) ) { warning("Could not hook to notification point\n"); return; } if ( dbg == NULL ) load_debugger("win32", false); // Let's start the debugger if ( !run_to(inf.beginEA) ) { warning("Sorry, could not start the process"); unhook_from_notification_point(HT_DBG, callback, NULL); } }
unsigned int loadIntoIdb(FILE *dll) { _IMAGE_DOS_HEADER dos, *pdos; _IMAGE_NT_HEADERS nt, *pnt; _IMAGE_SECTION_HEADER sect, *psect; unsigned int exp_size, exp_rva, exp_fileoff; _IMAGE_EXPORT_DIRECTORY *expdir = NULL; unsigned int len, handle; if (fread(&dos, sizeof(_IMAGE_DOS_HEADER), 1, dll) != 1) { return 0xFFFFFFFF; } if (dos.e_magic != 0x5A4D || fseek(dll, dos.e_lfanew, SEEK_SET)) { return 0xFFFFFFFF; } if (fread(&nt, sizeof(_IMAGE_NT_HEADERS), 1, dll) != 1) { return 0xFFFFFFFF; } if (nt.Signature != 0x4550) { return 0xFFFFFFFF; } if (fread(§, sizeof(_IMAGE_SECTION_HEADER), 1, dll) != 1) { return 0xFFFFFFFF; } //read all header bytes into buff len = sect.PointerToRawData; unsigned char *dat = (unsigned char*)malloc(len); if (dat == NULL || fseek(dll, 0, SEEK_SET) || fread(dat, len, 1, dll) != 1) { free(dat); return 0xFFFFFFFF; } pdos = (_IMAGE_DOS_HEADER*)dat; pnt = (_IMAGE_NT_HEADERS*)(dat + pdos->e_lfanew); handle = pnt->OptionalHeader.ImageBase; psect = (_IMAGE_SECTION_HEADER*)(pnt + 1); //now loop to find hole large enough to accomodate image //try ImageBase first bool found = false; bool triedDefault = handle == 0x10000000; do { msg("Trying base address of 0x%x\n", handle); segment_t *s = getseg(handle); if (s == NULL) { #if (IDA_SDK_VERSION < 530) segment_t *n = (segment_t *)segs.getn_area(segs.get_next_area(handle)); #else segment_t *n = get_next_seg(handle); #endif if (n != NULL) { unsigned int moduleEnd = getModuleEnd(n->startEA); if (moduleEnd == 0xffffffff) { moduleEnd = n->endEA; } if ((n->startEA - handle) >= nt.OptionalHeader.SizeOfImage) { found = true; } else { handle = (moduleEnd + 0x10000) & ~0xffff; } } else if ((0x80000000 - handle) >= nt.OptionalHeader.SizeOfImage) { found = true; } } else { unsigned int moduleEnd = getModuleEnd(s->startEA); if (moduleEnd == 0xffffffff) { moduleEnd = s->endEA; } handle = (moduleEnd + 0x10000) & ~0xffff; } if (!found && (handle >= 0x80000000 || (0x80000000 - handle) < nt.OptionalHeader.SizeOfImage)) { if (triedDefault) { //no room to load this library free(dat); return 0xFFFFFFFF; } else { handle = 0x10000000; triedDefault = true; } } } while (!found); createSegment(handle, len, dat); applyPEHeaderTemplates(handle); exp_rva = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; exp_size = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (exp_rva && exp_size) { exp_fileoff = rvaToFileOffset(psect, nt.FileHeader.NumberOfSections, exp_rva); expdir = (_IMAGE_EXPORT_DIRECTORY*)malloc(exp_size); } if (expdir == NULL || fseek(dll, exp_fileoff, SEEK_SET) || fread(expdir, exp_size, 1, dll) != 1) { free(dat); free(expdir); return 0xFFFFFFFF; } createSegment(handle + exp_rva, exp_size, (unsigned char*)expdir); if (expdir->AddressOfFunctions < exp_rva || expdir->AddressOfFunctions >= (exp_rva + exp_size)) { //EAT lies outside directory bounds msg("EAT lies outside directory bounds\n"); } if (expdir->AddressOfNames != 0 && expdir->AddressOfNames < exp_rva || expdir->AddressOfNames >= (exp_rva + exp_size)) { //ENT lies outside directory bounds msg("ENT lies outside directory bounds\n"); } if (expdir->AddressOfNameOrdinals != 0 && expdir->AddressOfNameOrdinals < exp_rva || expdir->AddressOfNameOrdinals >= (exp_rva + exp_size)) { //EOT lies outside directory bounds msg("EOT lies outside directory bounds\n"); } free(dat); free(expdir); return handle; }
static int notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::init: helper.create("$ tms320c3x"); inf.mf = 1; // MSB first inf.wide_high_byte_first = 1; init_analyzer(); break; case processor_t::term: free_ioports(ports, numports); default: break; case processor_t::newfile: // new file loaded inf.wide_high_byte_first = 0; { segment_t *s0 = get_first_seg(); if ( s0 != NULL ) { set_segm_name(s0, "CODE"); segment_t *s1 = get_next_seg(s0->startEA); for (int i = dp; i <= rVds; i++) { SetDefaultRegisterValue(s0, i, BADSEL); SetDefaultRegisterValue(s1, i, BADSEL); } } } select_device(IORESP_ALL); break; case processor_t::oldfile: // old file loaded inf.wide_high_byte_first = 0; idpflags = (ushort)helper.altval(-1); { char buf[MAXSTR]; if ( helper.supval(-1, buf, sizeof(buf)) > 0 ) set_device_name(buf, IORESP_NONE); } break; case processor_t::closebase: case processor_t::savebase: helper.altset(-1, idpflags); break; case processor_t::is_basic_block_end: return is_basic_block_end() ? 2 : 0; } va_end(va); return 1; }
static int notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch(msgid) { case processor_t::init: helper.create("$ pic"); helper.supval(0, device, sizeof(device)); default: break; case processor_t::term: free_mappings(); free_ioports(ports, numports); break; case processor_t::newfile: // new file loaded { segment_t *s0 = get_first_seg(); if ( s0 != NULL ) { set_segm_name(s0, "CODE"); dataseg = AdditionalSegment(0x200, 0, "DATA"); segment_t *s1 = get_next_seg(s0->startEA); SetDefaultRegisterValue(s0, BANK, 0); SetDefaultRegisterValue(s1, BANK, 0); SetDefaultRegisterValue(s0, PCLATH, 0); SetDefaultRegisterValue(s1, PCLATH, 0); SetDefaultRegisterValue(s0, PCLATU, 0); SetDefaultRegisterValue(s1, PCLATU, 0); setup_device(IORESP_INT); apply_symbols(); } } break; case processor_t::oldfile: // old file loaded idpflags = (ushort)helper.altval(-1); dataseg = helper.altval(0); create_mappings(); for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { if ( s->defsr[PCLATH-ph.regFirstSreg] == BADSEL ) s->defsr[PCLATH-ph.regFirstSreg] = 0; } break; case processor_t::closebase: case processor_t::savebase: helper.altset(0, dataseg); helper.altset(-1, idpflags); helper.supset(0, device); break; case processor_t::newprc: // new processor type { int n = va_arg(va, int); static bool set = false; if ( set ) return 0; set = true; if ( ptypes[n] != ptype ) { ptype = ptypes[n]; ph.cnbits = 12 + 2*n; } switch ( ptype ) { case PIC12: register_names[PCLATH] = "status"; cfgname = "pic12.cfg"; break; case PIC14: cfgname = "pic14.cfg"; break; case PIC16: register_names[BANK] = "bsr"; cfgname = "pic16.cfg"; idpflags = 0; ph.cnbits = 8; ph.regLastSreg = PCLATU; break; default: error("interr in setprc"); break; } } break; case processor_t::newasm: // new assembler type break; case processor_t::newseg: // new segment break; } va_end(va); return 1; }
static int notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch(msgid) { case processor_t::init: // __emit__(0xCC); // debugger trap helper.create("$ f2mc"); { char buf[MAXSTR]; if ( helper.supval(0, buf, sizeof(buf)) > 0 ) f2mc_set_device_name(buf, IORESP_NONE); } inf.wide_high_byte_first = 1; break; case processor_t::term: free_ioports(ports, numports); default: break; case processor_t::newfile: // new file loaded set_segm_name(get_first_seg(), "CODE"); if ( choose_ioport_device(cfgname, device, sizeof(device), parse_area_line0) ) f2mc_set_device_name(device, IORESP_ALL); for ( int i = DTB; i <= rVds; i++ ) { for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) SetDefaultRegisterValue(s, i, 0); } break; case processor_t::oldfile: // old file loaded idpflags = (ushort)helper.altval(-1); break; case processor_t::closebase: case processor_t::savebase: helper.altset(-1, idpflags); break; case processor_t::newprc: // new processor type { ptype = ptypes[va_arg(va, int)]; switch ( ptype ) { case F2MC16L: cfgname = "f2mc16l.cfg"; break; case F2MC16LX: cfgname = "f2mc16lx.cfg"; break; default: error("interr: setprc"); break; } device[0] = '\0'; if ( get_first_seg() != NULL ) choose_device(NULL, 0); } break; case processor_t::newasm: // new assembler type break; case processor_t::newseg: // new segment break; } va_end(va); return 1; }