//------------------------------------------------------------------------- // Initialize TRK connection over a serial port. // Returns success. bool metrotrk_t::init(int port) { sseq = 0; if ( port == DEBUGGER_PORT_NUMBER ) { int p = find_smartphone_port(); if ( p > 0 ) { port = p; msg("Using COM%d: to communicate with the smartphone...\n", port); } else { warning("Could not autodetect the smartphone port.\n" "Please specify it manually in the process options"); } } char name[32]; qsnprintf(name, sizeof(name), "\\\\.\\COM%d", port); qstring friendly_name; if ( !is_serial_port_present(port, &friendly_name) ) { if ( askyn_c(0, "HIDECANCEL\n" "Serial port COM%d seems to be unavailable. Do you want to proceed?", port ) <= 0 ) { SetLastError(ERROR_DEVICE_NOT_CONNECTED); return false; } } msg("Opening serial port %s: (%s)...\n", &name[4], friendly_name.c_str()); // port exists, open it hp = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if ( hp == INVALID_HANDLE_VALUE ) return false; DCB dcb; memset(&dcb, 0, sizeof(dcb)); dcb.DCBlength = sizeof(dcb); dcb.BaudRate = CBR_115200; dcb.fBinary = true; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if ( !SetCommState(hp, &dcb) ) { CloseHandle(hp); return false; } GetCommTimeouts(hp, &ct); return true; }
//-------------------------------------------------------------------------- static void _errstruct(int line) { static bool asked = false; if ( !asked ) { if ( askyn_c(1, "HIDECANCEL\n" "Bad file structure or read error (line %d). Continue?", line) <= 0 ) loader_failure(); asked = true; } }
inline void pe_failure(const char *format, ...) { va_list va; va_start(va, format); qstring question("AUTOHIDE REGISTRY\n"); question.cat_vsprnt(format, va); question.append("\nDo you wish to continue?"); if ( askyn_c(1, question.c_str()) != 1 ) { loader_failure(NULL); } va_end(va); }
//-------------------------------------------------------------------------- static bool create_idata_segm(const area_t &impdir) { segment_t ns; segment_t *s = getseg(impdir.startEA); if ( s != NULL ) ns = *s; else ns.sel = setup_selector(0); ns.startEA = impdir.startEA; ns.endEA = impdir.endEA; ns.type = SEG_XTRN; ns.set_loader_segm(true); bool ok = add_segm_ex(&ns, ".idata", "XTRN", ADDSEG_NOSREG) != 0; if ( !ok ) ok = askyn_c(0, "HIDECANCEL\nCan not create the import segment. Continue anyway?") == 1; return ok; }
//---------------------------------------------------------------------- // // 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(); }
//-------------------------------------------------------------------------- // 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); } }
//-------------------------------------------------------------------------- static int idaapi callback( void * /*user_data*/, int notification_code, va_list va) { static int stage = 0; static bool is_dll; static char needed_file[QMAXPATH]; switch ( notification_code ) { case dbg_process_start: case dbg_process_attach: get_input_file_path(needed_file, sizeof(needed_file)); // no break case dbg_library_load: if ( stage == 0 ) { const debug_event_t *pev = va_arg(va, const debug_event_t *); if ( !strieq(pev->modinfo.name, needed_file) ) break; if ( notification_code == dbg_library_load ) is_dll = true; // remember the current module bounds if ( pev->modinfo.rebase_to != BADADDR ) curmod.startEA = pev->modinfo.rebase_to; else curmod.startEA = pev->modinfo.base; curmod.endEA = curmod.startEA + pev->modinfo.size; deb(IDA_DEBUG_PLUGIN, "UUNP: module space %a-%a\n", curmod.startEA, curmod.endEA); ++stage; } break; case dbg_library_unload: if ( stage != 0 && is_dll ) { const debug_event_t *pev = va_arg(va, const debug_event_t *); if ( curmod.startEA == pev->modinfo.base || curmod.startEA == pev->modinfo.rebase_to ) { deb(IDA_DEBUG_PLUGIN, "UUNP: unload unpacked module\n"); if ( stage > 2 ) enable_step_trace(false); stage = 0; curmod.startEA = 0; curmod.endEA = 0; _hide_wait_box(); } } break; case dbg_run_to: // Parameters: const debug_event_t *event dbg->stopped_at_debug_event(true); bp_gpa = get_name_ea(BADADDR, "kernel32_GetProcAddress"); #ifndef __X64__ if( (LONG)GetVersion() < 0 ) // win9x mode -- use thunk's { is_9x = true; win9x_resolve_gpa_thunk(); } #endif if ( bp_gpa == BADADDR ) { bring_debugger_to_front(); warning("Sorry, could not find kernel32.GetProcAddress"); FORCE_STOP: stage = 4; // last stage clear_requests_queue(); request_exit_process(); run_requests(); break; } else if( !my_add_bpt(bp_gpa) ) { bring_debugger_to_front(); warning("Sorry, can not set bpt to kernel32.GetProcAddress"); goto FORCE_STOP; } else { ++stage; set_wait_box("Waiting for a call to GetProcAddress()"); } continue_process(); break; case dbg_bpt: // A user defined breakpoint was reached. // Parameters: thid_t tid // ea_t breakpoint_ea // int *warn = -1 // Return (in *warn): // -1 - to display a breakpoint warning dialog // if the process is suspended. // 0 - to never display a breakpoint warning dialog. // 1 - to always display a breakpoint warning dialog. { thid_t tid = va_arg(va, thid_t); qnotused(tid); ea_t ea = va_arg(va, ea_t); //int *warn = va_arg(va, int*); if ( stage == 2 ) { if ( ea == bp_gpa ) { regval_t rv; if ( get_reg_val(REGNAME_ESP, &rv) ) { ea_t esp = ea_t(rv.ival); invalidate_dbgmem_contents(esp, 1024); ea_t gpa_caller = getPtr(esp); if ( !is_library_entry(gpa_caller) ) { ea_t nameaddr; if ( ptrSz == 4 ) { nameaddr = get_long(esp+8); } else { get_reg_val(REGNAME_ECX, &rv); nameaddr = ea_t(rv.ival); } invalidate_dbgmem_contents(nameaddr, 1024); char name[MAXSTR]; size_t len = get_max_ascii_length(nameaddr, ASCSTR_C, ALOPT_IGNHEADS); name[0] = '\0'; get_ascii_contents2(nameaddr, len, ASCSTR_C, name, sizeof(name)); if ( !ignore_win32_api(name) ) { deb(IDA_DEBUG_PLUGIN, "%a: found a call to GetProcAddress(%s)\n", gpa_caller, name); if ( !my_del_bpt(bp_gpa) || !my_add_bpt(gpa_caller) ) error("Can not modify breakpoint"); } } } } else if ( ea == bpt_ea ) { my_del_bpt(ea); if ( !is_library_entry(ea) ) { msg("Uunp: reached unpacker code at %a, switching to trace mode\n", ea); enable_step_trace(true); ++stage; uint64 eax; if ( get_reg_val(REGNAME_EAX, &eax) ) an_imported_func = ea_t(eax); set_wait_box("Waiting for the unpacker to finish"); } else { warning("%a: bpt in library code", ea); // how can it be? my_add_bpt(bp_gpa); } } // not our bpt? skip it else { // hide the wait box to allow others plugins to properly stop _hide_wait_box(); break; } } } // while continue_process() would work here too, request+run is more universal // because they do not ignore the request queue request_continue_process(); run_requests(); break; case dbg_trace: // A step occured (one instruction was executed). This event // notification is only generated if step tracing is enabled. // Parameter: none if ( stage == 3 ) { thid_t tid = va_arg(va, thid_t); qnotused(tid); ea_t ip = va_arg(va, ea_t); // ip reached the OEP range? if ( oep_area.contains(ip) ) { // stop the trace mode enable_step_trace(false); msg("Uunp: reached OEP %a\n", ip); set_wait_box("Reanalyzing the unpacked code"); // reanalyze the unpacked code do_unknown_range(oep_area.startEA, oep_area.size(), DOUNK_EXPAND); auto_make_code(ip); // plan to make code noUsed(oep_area.startEA, oep_area.endEA); // plan to reanalyze auto_mark_range(oep_area.startEA, oep_area.endEA, AU_FINAL); // plan to analyze move_entry(ip); // mark the program's entry point _hide_wait_box(); // inform the user bring_debugger_to_front(); if ( askyn_c(1, "HIDECANCEL\n" "The universal unpacker has finished its work.\n" "Do you want to take a memory snapshot and stop now?\n" "(you can do it yourself if you want)\n") > 0 ) { set_wait_box("Recreating the import table"); invalidate_dbgmem_config(); if ( is_9x ) find_thunked_imports(); create_impdir(); set_wait_box("Storing resources to 'resource.res'"); if ( resfile[0] != '\0' ) extract_resource(resfile); _hide_wait_box(); if ( take_memory_snapshot(true) ) goto FORCE_STOP; } suspend_process(); unhook_from_notification_point(HT_DBG, callback, NULL); } } break; case dbg_process_exit: { stage = 0; // stop the tracing _hide_wait_box(); unhook_from_notification_point(HT_DBG, callback, NULL); if ( success ) jumpto(inf.beginEA, -1); else tell_about_failure(); } break; case dbg_exception:// Parameters: const debug_event_t *event // int *warn = -1 // Return (in *warn): // -1 - to display an exception warning dialog // if the process is suspended. // 0 - to never display an exception warning dialog. // 1 - to always display an exception warning dialog. { // const debug_event_t *event = va_arg(va, const debug_event_t *); // int *warn = va_arg(va, int *); // FIXME: handle code which uses SEH to unpack itself if ( askyn_c(1, "AUTOHIDE DATABASE\n" "HIDECANCEL\n" "An exception occurred in the program.\n" "UUNP does not support exceptions yet.\n" "The execution has been suspended.\n" "Do you want to continue the unpacking?") <= 0 ) { _hide_wait_box(); stage = 0; enable_step_trace(false); // stop the trace mode suspend_process(); } else { continue_process(); } } break; case dbg_request_error: // An error occured during the processing of a request. // Parameters: ui_notification_t failed_command // dbg_notification_t failed_dbg_notification { ui_notification_t failed_cmd = va_arg(va, ui_notification_t); dbg_notification_t failed_dbg_notification = va_arg(va, dbg_notification_t); _hide_wait_box(); stage = 0; warning("dbg request error: command: %d notification: %d", failed_cmd, failed_dbg_notification); } break; } return 0; }
//-------------------------------------------------------------------------- // ipath==input file path static bool ask_user_and_copy(const char *ipath) { // check if the input file exists at the current dir of the remote host const char *input_file = ipath; #if DEBUGGER_ID != DEBUGGER_ID_ARM_EPOC_USER input_file = qbasename(input_file); #endif int fn = -1; // try to open remote file in the current dir if not tried before if ( input_file != ipath ) fn = s_open_file(input_file, NULL, true); if ( fn != -1 ) { s_close_file(fn); switch ( askbuttons_c("~U~se found", "~C~opy new", "Cancel", 1, "IDA could not find the remote file %s.\n" "But it could find remote file %s.\n" "Do you want to use the found file?", ipath, input_file) ) { case 1: set_root_filename(input_file); return true; case -1: return false; } // the user wants to overwrite the old file } else { if ( askyn_c(1, "HIDECANCEL\n" "The remote file %s could not be found.\n" "Do you want IDA to copy the executable to the remote computer?", ipath) <= 0 ) return false; } // We are to copy the input file to the remote computer's current directory const char *lname = ipath; // check if the file path is valid on the local system if ( !qfileexist(lname) ) { lname = askfile_c(false, lname, "Please select the file to copy"); if ( lname == NULL ) return false; } #if DEBUGGER_ID == DEBUGGER_ID_ARM_EPOC_USER const char *rname = input_file; #else const char *rname = qbasename(lname); #endif int code = copy_to_remote(lname, rname); if ( code != 0 ) { #if DEBUGGER_ID == DEBUGGER_ID_ARM_WINCE_USER // Windows CE does not have errno and uses GetLastError() const char *err = winerr(code); #else const char *err = qerrstr(code); #endif warning("Failed to copy %s -> %s\n%s", lname, rname, err); } set_root_filename(rname); return true; }
// 插件可以从plugins.cfg文件中,被传进一个整型参数。 // 当按下不同的热键或者菜单时,您需要一个插件做不同 // 的事情时,这非常有用。 void __stdcall IDAP_run(int arg) { // 插件的实体 //在LOG中显示一个字符串 char *lpInBuf = NULL; char *lpTmpBuf = NULL; char *lpFilePath = NULL; char szValue[MAXSTR + 1] = ""; char szInValue[MAXSTR + 1] = ""; // char szTmp[100] = {0}; int nPatchLogFlags = 1; uval_t nAddres = get_screen_ea(); asize_t nCount = 1; USHORT nWriteRadio = 0; //单选按钮 USHORT nSerializeRadio = -1; //单选按钮 USHORT checkmask = 0; asize_t j = 0; asize_t i = 0; // qstrncpy(szInValue,"",sizeof(szInValue)); if(AskUsingForm_c(dialog, szInValue, &nAddres, &nCount, &nWriteRadio, &nSerializeRadio, &checkmask) == 1) { if(checkmask & 1) { nAddres = get_screen_ea(); } size_t len = strlen(szInValue); for(i = 0; i < len; i++) { if(szInValue[i] != ' ') { szValue[j++] = szInValue[i]; } } len = strlen(szValue); size_t nHexLen = len / 2; if(!len) { if( lpFilePath = askfile_cv(0, "*.*", "OpenPath", 0)) { FILE* handle = fopen(lpFilePath, "rb"); if(handle == NULL) { warning("打开文件失败 Error!\n"); return; } fseek(handle, 0, SEEK_END); nHexLen = ftell(handle); fseek(handle, 0, SEEK_SET); lpTmpBuf = (char *)malloc(nHexLen + 1); memset(lpTmpBuf, 0, nHexLen + 1); fread(lpTmpBuf, 1, nHexLen, handle); fclose(handle); strcpy(szValue, lpFilePath); } else { warning("请输入数据"); return; } } else if(len % 2) { warning("数据长度不是2的倍数"); return; } else { for(i = 0;i < len;i++) { if(!isxdigit(szValue[i])) { warning("数据中含有非16进制值"); return; } } lpTmpBuf = (char *) malloc(nHexLen * 2 + 1); memset(lpTmpBuf, 0, nHexLen * 2 + 1); for(i = 0; i < nHexLen; i++) { sscanf(&szValue[i * 2],"%02x",lpTmpBuf + i); } } if(nSerializeRadio >= 0) { asize_t nSerializeSize = (nSerializeRadio + 1) * 4; asize_t nSerializeCount = nHexLen * nCount / nSerializeSize; for(i = 0; i < nSerializeCount; i++) { reversedbuf((unsigned char*)lpTmpBuf + nSerializeSize *i, nSerializeSize); } } lpInBuf = (char*)malloc(nHexLen * nCount * 2 + 1); memset(lpInBuf, 0, nHexLen * nCount * 2 + 1); for(i = 0; i < nCount; i++) { memcpy(lpInBuf + i * nHexLen, lpTmpBuf, nHexLen); } free(lpTmpBuf); msg("==============修补数据库数据==============\n"); msg("String Value = %s\n",szValue); #ifdef __EA64__ msg("Addres:0x%llX ValueSize = 0x%llX Index:%d check = %d\n",nAddres, nHexLen, nCount,checkmask); #else msg("Addres:0x%08X ValueSize = 0x%08X Index:%d check = %d\n",nAddres, nHexLen, nCount,checkmask); #endif if(!nWriteRadio) { msg("WriteData \n",nWriteRadio); } else { msg("XorWrite Data \n",nWriteRadio); } if( nHexLen * nCount > 0x100) { nPatchLogFlags = askyn_c(0, "%s", "是否打印日志!(默认不打印)\n因为数据量过大会影响IDA会假死!\nNo或Cancel表示不打印日志!\n"); } //////////////////// uint32 nSum = 0; uchar *mem = NULL; if(isLoaded(nAddres) && isLoaded(nAddres + nCount * nHexLen - 1)) { mem = (uchar *)malloc(nCount * nHexLen + 1); if(mem == NULL) { warning("malloc 函数执行失败!"); return; } get_many_bytes(nAddres,mem, nCount * nHexLen); if(nPatchLogFlags > 0) { msg("原始数据:\n"); for(i = 0; i < nCount * nHexLen; i++) { msg("%02X", mem[i]); } msg("\n"); } } else { if(!isLoaded(nAddres)) { warning("数据地址错误: 0x%p",nAddres); } else { warning("写入数据长度过大"); } return; } /////////////////////////// // long nValue = 0; for(j = 0;j < nCount;j++) { for(i = 0;i < nHexLen; i++) { // memcpy(szTmp,&szInValue[j * len + i * 2],2); //sscanf(&szValue[i * 2],"%02x",&nValue); if(nWriteRadio == 1) { lpInBuf[nSum] ^= mem[nSum]; } mem[nSum++] = lpInBuf[nSum]; } } put_many_bytes(nAddres, mem, nSum); if(nPatchLogFlags > 0) { msg("补丁数据:\n"); for(i = 0; i < nSum; i++) { msg("%02X", mem[i]); } msg("\n"); } refresh_idaview_anyway(); //刷新反汇编窗口 free(mem); free(lpInBuf); } return; }
//-------------------------------------------------------------------------- static void ask_for_exit(const char *str) { if ( askyn_c(1, "HIDECANCEL\n%s. Continue?", str) <= 0 ) loader_failure(); }
//-------------------------------------------------------------------------- bool win32_debmod_t::create_process( const char *path, const char *args, const char *startdir, bool is_gui, PROCESS_INFORMATION *ProcessInformation) { #ifndef __X64__ linput_t *li = open_linput(path, false); if ( li == NULL ) return false; pe_loader_t pl; pl.read_header(li, true); close_linput(li); if ( pl.pe.is_pe_plus() ) { static const char server_name[] = "win64_remotex64.exe"; #ifdef __EA64__ if ( askyn_c(1, "AUTOHIDE REGISTRY\nHIDECANCEL\nDebugging 64-bit applications is only possible with the %s server. Launch it now?", server_name) == 1 ) do { // Switch to the remote win32 debugger if ( !load_debugger("win32_stub", true)) { warning("Failed to switch to the remote windows debugger!"); break; } // Form the server path char server_exe[QMAXPATH]; qmakepath(server_exe, sizeof(server_exe), idadir(NULL), server_name, NULL); // Try to launch the server STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi; if ( !::CreateProcess(server_exe, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) ) { warning("Failed to run the 64-bit remote server!"); break; } // Set the remote debugging options: localhost set_remote_debugger("localhost", "", -1); // Notify the user info("Debugging server has been started, please try debugging the program again."); } while ( false ); #else dwarning("AUTOHIDE NONE\n" "Please use %s remote server to debug 64-bit applications", server_name); #endif // __EA64__ SetLastError(ERROR_NOT_SUPPORTED); return false; } #endif // __X64__ // Empty directory means our directory if ( startdir != NULL && startdir[0] == '\0' ) startdir = NULL; // Args passed as empty string? if ( args != NULL && args[0] == '\0' ) args = NULL; launch_process_params_t lpp; lpp.flags |= LP_TRACE | LP_PATH_WITH_ARGS; if ( !is_gui ) lpp.flags |= LP_NEW_CONSOLE; lpp.path = path; lpp.args = args; lpp.startdir = startdir; lpp.info = ProcessInformation; qstring errbuf; if ( launch_process(lpp, &errbuf) == NULL ) { dwarning("AUTOHIDE NONE\n%s", errbuf.c_str()); return false; } return true; }
//-------------------------------------------------------------------------- void run(int /*arg*/) { if ( !autoIsOk() && askyn_c(-1, "HIDECANCEL\n" "The autoanalysis has not finished yet.\n" "The result might be incomplete. Do you want to continue?") < 0 ) return; // gather information about the entry points entrylist_t *li = new entrylist_t; size_t n = get_entry_qty(); for ( size_t i=0; i < n; i++ ) { asize_t ord = get_entry_ordinal((int)i); ea_t ea = get_entry(ord); if ( ord == ea ) continue; qtype type, fnames; char decl[MAXSTR]; char true_name[MAXSTR]; asize_t argsize = 0; get_entry_name(ord, true_name, sizeof(true_name)); if ( get_tinfo(ea, &type, &fnames) && print_type_to_one_line( decl, sizeof(decl), idati, type.c_str(), true_name, NULL, fnames.c_str()) == T_NORMAL ) { // found type info -- calc the args size func_type_info_t fi; int a = build_funcarg_info(idati, type.c_str(), fnames.c_str(), &fi, 0); if ( a != 0 ) { for ( int k=0; k < a; k++ ) { const type_t *ptr = fi[k].type.c_str(); int s1 = (int)get_type_size(idati, ptr); s1 = qmax(s1, inf.cc.size_i); argsize += s1; } } } else if ( get_long_name(BADADDR, ea, decl, sizeof(decl)) != NULL && get_true_name(BADADDR, ea, true_name, sizeof(true_name)) != NULL && strcmp(decl, true_name) != 0 ) { // found mangled name } else { // found nothing, just show the name const char *name = get_name(BADADDR, ea, true_name, sizeof(true_name)); if ( name == NULL ) continue; qstrncpy(decl, name, sizeof(decl)); } if ( argsize == 0 ) { func_t *pfn = get_func(ea); if ( pfn != NULL ) argsize = pfn->argsize; } item_t x; x.ord = (int)ord; x.ea = ea; x.decl = decl; x.argsize = (uint32)argsize; li->push_back(x); } // now open the window choose2(false, // non-modal window -1, -1, -1, -1, // position is determined by Windows li, // pass the created array qnumber(header), // number of columns widths, // widths of columns sizer, // function that returns number of lines desc, // function that generates a line "Exported functions", // window title -1, // use the default icon for the window 0, // position the cursor on the first line NULL, // "kill" callback NULL, // "new" callback NULL, // "update" callback NULL, // "edit" callback enter_cb, // function to call when the user pressed Enter destroy_cb, // function to call when the window is closed NULL, // use default popup menu items NULL); // use the same icon for all lines }
static int notify(processor_t::idp_notify msgid, ...) { static int first_time = 1; 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("$ intel 8051"); inf.mf = 1; // Set a big endian mode of the IDA kernel default: break; case processor_t::term: free_ioports(ports, numports); break; case processor_t::newfile: { segment_t *sptr = get_first_seg(); if ( sptr != NULL ) { if ( sptr->startEA-get_segm_base(sptr) == 0 ) { inf.beginEA = sptr->startEA; inf.startIP = 0; for ( int i=0; i < qnumber(entries); i++ ) { if ( entries[i].proc > ptype ) continue; ea_t ea = inf.beginEA+entries[i].off; if ( isEnabled(ea) && get_byte(ea) != 0xFF ) { add_entry(ea, ea, entries[i].name, 1); set_cmt(ea, entries[i].cmt, 1); } } } } segment_t *scode = get_first_seg(); set_segm_class(scode, "CODE"); if ( ptype > prc_51 ) { AdditionalSegment(0x10000-256-128, 256+128, "RAM"); if ( scode != NULL ) { ea_t align = (scode->endEA + 0xFFF) & ~0xFFF; if ( getseg(align-7) == scode ) // the code segment size is { // multiple of 4K or near it uchar b0 = get_byte(align-8); // 251: // 0 : 1-source, 0-binary mode // 6,7: must be 1s // 82930: // 0 : 1-source, 0-binary mode // 7 : must be 1s // uchar b1 = get_byte(align-7); // 251 // 0: eprommap 0 - FE2000..FE4000 is mapped into 00E000..100000 // 1 - .............. is not mapped ............... // 1: must be 1 // 3: // 2: must be 1 // 4: intr 1 - upon interrupt PC,PSW are pushed into stack // 0 - upon interrupt only PC is pushed into stack // 5: must be 1 // 6: must be 1 // 7: must be 1 // 82930: // 3: must be 1 // 5: must be 1 // 6: must be 1 // 7: must be 1 // msg("b0=%x b1=%x\n", b0, b1); // if ( (b0 & 0x80) == 0x80 && (b1 & 0xEA) == 0xEA ) { // the init bits are correct char pname[sizeof(inf.procName)+1]; inf.get_proc_name(pname); char ntype = (b0 & 1) ? 's' : 'b'; char *ptr = tail(pname)-1; if ( ntype != *ptr && askyn_c(1, "HIDECANCEL\n" "The input file seems to be for the %s mode of the processor. " "Do you want to change the current processor type?", ntype == 's' ? "source" : "binary") > 0 ) { *ptr = ntype; first_time = 1; set_processor_type(pname, SETPROC_COMPAT); } } } } } // the default data segment will be INTMEM { segment_t *s = getseg(intmem); if ( s != NULL ) set_default_dataseg(s->sel); } if ( choose_ioport_device(cfgname, device, sizeof(device), parse_area_line0) ) set_device_name(device, IORESP_ALL); if ( get_segm_by_name("RAM") == NULL ) AdditionalSegment(256, 0, "RAM"); if ( get_segm_by_name("FSR") == NULL ) AdditionalSegment(128, 128, "FSR"); setup_data_segment_pointers(); } break; case processor_t::oldfile: setup_data_segment_pointers(); break; case processor_t::newseg: // make the default DS point to INTMEM // (8051 specific issue) { segment_t *newseg = va_arg(va, segment_t *); segment_t *intseg = getseg(intmem); if ( intseg != NULL ) newseg->defsr[rVds-ph.regFirstSreg] = intseg->sel; } break; case processor_t::newprc: { processor_subtype_t prcnum = processor_subtype_t(va_arg(va, int)); if ( !first_time && prcnum != ptype ) { warning("Sorry, it is not possible to change" // (this is 8051 specific) " the processor mode on the fly." " Please reload the input file" " if you want to change the processor."); return 0; } first_time = 0; ptype = prcnum; } break; case processor_t::newasm: // new assembler type { char buf[MAXSTR]; if ( helper.supval(-1, buf, sizeof(buf)) > 0 ) set_device_name(buf, IORESP_NONE); } break; case processor_t::move_segm:// A segment is moved // Fix processor dependent address sensitive information // args: ea_t from - old segment address // segment_t - moved segment { // ea_t from = va_arg(va, ea_t); // segment_t *s = va_arg(va, segment_t *); // Add commands to adjust your internal variables here // Most of the time this callback will be empty // // If you keep information in a netnode's altval array, you can use // node.altshift(from, s->startEA, s->endEA - s->startEA); // // If you have a variables pointing to somewhere in the disassembled program memory, // you can adjust it like this: // // asize_t size = s->endEA - s->startEA; // if ( var >= from && var < from+size ) // var += s->startEA - from; } break; case processor_t::is_sane_insn: // is the instruction sane for the current file type? // arg: int no_crefs // 1: the instruction has no code refs to it. // ida just tries to convert unexplored bytes // to an instruction (but there is no other // reason to convert them into an instruction) // 0: the instruction is created because // of some coderef, user request or another // weighty reason. // The instruction is in 'cmd' // returns: 1-ok, <=0-no, the instruction isn't // likely to appear in the program { int no_crefs = va_arg(va, int); return is_sane_insn(no_crefs); } } va_end(va); return(1); }
//---------------------------------------------------------------------- int upgrade_db_format(int ver, netnode constnode) { if(askyn_c(1, "AUTOHIDE REGISTRY\nHIDECANCEL\n" "The database has an old java data format.\n" "Do you want to upgrade it?") <= 0) qexit(1); switch ( ver ) { default: INTERNAL("upgrade::ver"); case IDP_JDK12: break; } // change format: jdk-version if ( curClass.MinVers > 0x8000u ) { badbase: return(0); } curClass.MajVers = JDK_MIN_MAJOR; if ( curClass.MinVers >= 0x8000 ) { curClass.MinVers &= ~0; ++curClass.MajVers; curClass.JDKsubver = 2; } else if ( curClass.MinVers >= JDK_1_1_MINOR ) ++curClass.JDKsubver; // change format: This #ifdef __BORLANDC__ #if offsetof(ClassInfo, This.Ref) != offsetof(ClassInfo, This.Name) || \ offsetof(ClassInfo, This.Dscr) != offsetof(ClassInfo, This.Name) + 2 #error #endif #endif curClass.This.Ref = (curClass.This.Ref << 16) | curClass.This.Dscr; if ( !curClass.This.Name ) goto badbase; // change format: Super #ifdef __BORLANDC__ #if offsetof(ClassInfo, super.Ref) != offsetof(ClassInfo, super.Name) || \ offsetof(ClassInfo, super.Dscr) != offsetof(ClassInfo, super.Name) + 2 #error #endif #endif switch ( curClass.super.Name ) { case 0: // absent curClass.super.Ref &= 0; break; case 0xFFFF: // bad index ++curClass.super.Name; break; default: // reverse order curClass.super.Ref = (curClass.super.Ref << 16) | curClass.super.Dscr; break; } // validate: impNode if ( curClass.impNode && !netnode(curClass.impNode).altval(0) ) goto badbase; // change variable 'errload' in previous version if ( curClass.maxSMsize ) { curClass.extflg |= XFL_C_ERRLOAD; curClass.maxSMsize &= 0; } // set segments type type for special segments segment_t *S; if ( (S = getseg(curClass.startEA)) == NULL ) goto badbase; S->set_hidden_segtype(true); S->update(); if ( curClass.xtrnCnt ) { if ( (S = getseg(curClass.xtrnEA)) == NULL ) goto badbase; S->set_hidden_segtype(true); S->update(); } curClass.extflg |= XFL_C_DONE; // do not repeat datalabel destroyer :) // change: method/fields format #define SGEXPSZ (sizeof(SegInfo) - offsetof(SegInfo, varNode)) #define FMEXPSZ (sizeof(_FMid_) - offsetof(_FMid_, _UNUSED_ALING)) #define FLEXPSZ (sizeof(FieldInfo) - offsetof(FieldInfo, annNodes)) uval_t oldsize = sizeof(SegInfo) - FMEXPSZ - SGEXPSZ; for(int pos=-(int)curClass.MethodCnt; pos<=(int)curClass.FieldCnt; pos++) { union { SegInfo s; FieldInfo f; _FMid_ id; uchar _space[qmax(sizeof(SegInfo), sizeof(FieldInfo)) + 1]; }u; if ( !pos ) { // class node oldsize += (sizeof(FieldInfo) - FLEXPSZ) - (sizeof(SegInfo) - SGEXPSZ); continue; } if ( ClassNode.supval(pos, &u, sizeof(u)) != oldsize ) goto badbase; memmove((uchar *)&u.id + sizeof(u.id), &u.id._UNUSED_ALING, (size_t)oldsize - offsetof(_FMid_, _UNUSED_ALING)); u.id._UNUSED_ALING = 0; u.id.utsign = 0; if ( u.id.extflg & ~EFL__MASK ) goto badbase; u.id.extflg &= (EFL_NAMETYPE); if ( pos > 0 ) { // fields memset(&u.f.annNodes, 0, sizeof(u.f)-offsetof(FieldInfo, annNodes)); ClassNode.supset(pos, &u.f, sizeof(u.f)); continue; } // segments memset(&u.s.varNode, 0, sizeof(u.s) - offsetof(SegInfo, varNode)); if ( u.s.thrNode && !netnode(u.s.thrNode).altval(0) ) { netnode(u.s.thrNode).kill(); // empty node (old format) u.s.thrNode = 0; } // have locvars? if ( u.s.DataSize ) { if ( (S = getseg(u.s.DataBase)) == NULL ) goto badbase; S->type = SEG_BSS; S->set_hidden_segtype(true); S->update(); } // change: Exception format if ( u.s.excNode ) { register ushort i, j; netnode enode(u.s.excNode); if ( (j = (ushort)enode.altval(0)) == 0 ) goto badbase; ea_t ea = u.s.startEA + u.s.CodeSize; i = 1; do { Exception exc; if ( enode.supval(i, &exc, sizeof(exc)) != sizeof(exc) ) goto badbase; #ifdef __BORLANDC__ #if offsetof(Exception, filter.Ref) != offsetof(Exception, filter.Name) || \ offsetof(Exception, filter.Dscr) != offsetof(Exception, filter.Name) + 2 #error #endif #endif if ( !exc.filter.Name != !exc.filter.Dscr ) goto badbase; exc.filter.Ref = (exc.filter.Ref << 16) | exc.filter.Dscr; // was reverse order if ( exc.filter.Name == 0xFFFF ) ++exc.filter.Name; enode.supset(i, &exc, sizeof(exc)); set_exception_xref(&u.s, exc, ea); }while ( ++i <= j ); } ClassNode.supset(pos, &u.s, sizeof(u.s)); //rename local variables (for references) if ( u.s.DataSize ) { int i = u.s.DataSize; ea_t ea = u.s.DataBase + i; do { char str[MAXNAMELEN]; qsnprintf(str, sizeof(str), "met%03u_slot%03u", u.s.id.Number, --i); --ea; if ( do_name_anyway(ea, str)) make_name_auto(ea ); else hide_name(ea); }while ( i ); coagulate_unused_data(&u.s); } } // for //change format of string presentation in constant pool for(int pos = 0; (ushort)pos <= curClass.maxCPindex; pos++) { ConstOpis co; if ( constnode.supval(pos, &co, sizeof(co)) != sizeof(co) ) goto badbase; switch ( co.type ) { default: continue; case CONSTANT_Unicode: error("Base contain CONSTANT_Unicode, but it is removed from " "the standard in 1996 year and never normal loaded in IDA"); case CONSTANT_Utf8: break; } uint32 v, n, i = pos << 16; if( ((n = (uint32)constnode.altval(i)) & UPG12_BADMASK) || (v = n & ~UPG12_CLRMASK) == 0) goto badbase; if ( n & UPG12_EXTMASK ) v |= UPG12_EXTSET; if ( (n = (ushort)v) != 0 ) { register uchar *po = (uchar*)append_tmp_buffer(v); n *= sizeof(ushort); uint32 pos = 0; do { uint32 sz = n - pos; if ( sz > MAXSPECSIZE ) sz = MAXSPECSIZE; if ( constnode.supval(++i, &po[pos], sz) != sz ) goto badbase; constnode.supdel(i); pos += sz; }while ( pos < n ); constnode.setblob(po, n, i & ~0xFFFF, BLOB_TAG); if ( !(v & UPG12_EXTSET) ) do { #ifdef __BORLANDC__ #if ( sizeof(ushort) % 2) || (MAXSPECSIZE % 2 ) #error #endif #endif ushort cw = *(ushort *)&po[pos]; if ( cw >= CHP_MAX ) { if ( !javaIdent(cw) ) goto extchar; } else if ( (uchar)cw <= CHP_MIN ) { extchar: v |= UPG12_EXTSET; break; } }while ( (pos -= sizeof(ushort)) != 0 ); v = upgrade_ResW(v); } constnode.altset(i, v); co._Sopstr = v; // my be not needed? (next also) constnode.supset(pos, &co, sizeof(co)); } // rename 'import' variables for refernces for(unsigned ip = 1; (ushort)ip <= curClass.xtrnCnt; ip++) { ConstOpis co; { register unsigned j; if( (j = (unsigned)XtrnNode.altval(ip)) == 0 || !LoadOpis((ushort)j, 0, &co)) goto badbase; } switch ( co.type ) { default: goto badbase; case CONSTANT_Class: if ( !(co.flag & HAS_CLSNAME) ) continue; break; case CONSTANT_InterfaceMethodref: case CONSTANT_Methodref: if ( (co.flag & NORM_METOD) != NORM_METOD ) continue; break; case CONSTANT_Fieldref: if ( (co.flag & NORM_FIELD) != NORM_FIELD ) continue; break; } make_new_name(co._name, co._subnam, co.type != CONSTANT_Class, ip); } if ( curClass.This.Dscr ) make_new_name(curClass.This.Name, 0, (uchar)-1, (unsigned)curClass.startEA); return(_TO_VERSION); }