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; }
//-------------------------------------------------------------------------- static DWORD calc_our_crc32(const char *fname) { linput_t *li = open_linput(fname, false); DWORD crc32 = calc_file_crc32(li); close_linput(li); return crc32; }
//-------------------------------------------------------------------------- // return the address of all names exported by a DLL in 'ni' // if 'exported_name' is given, only the address of this exported name will be returned in 'ni' bool win32_debmod_t::get_dll_exports( const images_t &dlls, ea_t imagebase, name_info_t &ni, const char *exported_name) { char prefix[MAXSTR]; images_t::const_iterator p = dlls.find(imagebase); if ( p == dlls.end() ) { dwarning("get_dll_exports: can't find dll name for imagebase %a", imagebase); return false; } const char *dllname = p->second.name.c_str(); linput_t *li = open_linput(dllname, false); if ( li == NULL ) { // sysWOW64: ntdll32.dll does not exist but there is a file called ntdll.dll if ( stricmp(qbasename(dllname), "ntdll32.dll") != 0 ) return false; qstrncpy(prefix, dllname, sizeof(prefix)); char *fname = qbasename(prefix); qstrncpy(fname, "ntdll.dll", sizeof(prefix)-(fname-prefix)); dllname = prefix; li = open_linput(dllname, false); if ( li == NULL ) return false; } // prepare nice name prefix for exported functions names qstrncpy(prefix, qbasename(dllname), sizeof(prefix)); char *ptr = strrchr(prefix, '.'); if ( ptr != NULL ) *ptr = '\0'; qstrlwr(prefix); bool ok = get_dll_exports_from_file(prefix, li, imagebase, ni, exported_name); close_linput(li); return ok; }
//-------------------------------------------------------------------------- bool debmod_t::check_input_file_crc32(uint32 orig_crc) { // take this opportunity to check that the derived class initialized // register related fields correctly QASSERT(30016, sp_idx != -1 && pc_idx != -1 && nregs > 0); if ( orig_crc == 0 ) return true; // the database has no crc linput_t *li = open_linput(input_file_path.c_str(), false); if ( li == NULL ) return false; uint32 crc = calc_file_crc32(li); close_linput(li); return crc == orig_crc; }
//-------------------------------------------------------------------------- // 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; }
//-------------------------------------------------------------------------- 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; }