//-------------------------------------------------------------------------- // returns true-lowcnd was false, resumed the application // nb: recursive calls to this function are not handled in any special way! bool debmod_t::handle_lowcnd(lowcnd_t *lc, debug_event_t *event, int elc_flags) { if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 ) { // difficult case: we have to reset pc, remove the bpt, single step, and resume the app QASSERT(616, !handling_lowcnds.has(lc->ea)); handling_lowcnds.push_back(lc->ea); int code; if ( (elc_flags & ELC_KEEP_EIP) == 0 ) { regval_t rv; rv._set_int(lc->ea); code = dbg_write_register(event->tid, pc_idx, &rv); if ( code <= 0 ) { handling_lowcnds.del(lc->ea); return false; } } code = dbg_freeze_threads_except(event->tid); if ( code > 0 ) { int bptlen = lc->type == BPT_SOFT ? lc->orgbytes.size() : lc->size; code = dbg_del_bpt(lc->type, lc->ea, lc->orgbytes.begin(), bptlen); if ( code > 0 ) { code = dbg_perform_single_step(event, lc->cmd); if ( code <= 0 ) dmsg("%a: failed to single step\n", event->ea); // may happen if ( dbg_add_bpt(lc->type, lc->ea, bptlen) <= 0 ) { // if this fails, it may be because the breakpoint is invalid // at this time so we should notify IDA it isn't available // any more code = 0; dwarning("%a: could not restore deleted bpt\n", lc->ea); // odd } } if ( dbg_thaw_threads_except(event->tid) <= 0 ) { dwarning("%d: could not resume suspended threads\n", event->tid); // odd code = 0; } } handling_lowcnds.del(lc->ea); if ( code <= 0 || event->eid != STEP ) return false; // did not resume } if ( (elc_flags & ELC_KEEP_SUSP) != 0 ) return true; return dbg_continue_after_event(event) > 0; }
static uint64_t _adjustPartitionSize( const char* description, uint64_t imageBytes, uint64_t defaultBytes, int inAndroidBuild ) { char temp[64]; unsigned imageMB; unsigned defaultMB; if (imageBytes <= defaultBytes) return defaultBytes; imageMB = convertBytesToMB(imageBytes); defaultMB = convertBytesToMB(defaultBytes); if (imageMB > defaultMB) { snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB); } else { snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes); } if (inAndroidBuild) { dwarning("%s partition size adjusted to match image file %s\n", description, temp); } return convertMBToBytes(imageMB); }
void auserConfig_save( AUserConfig* uconfig ) { IniFile* ini; char temp[256]; if (uconfig->changed == 0) { D("User-config was not changed."); return; } bufprint(temp, temp+sizeof(temp), "%s = %d\n" "%s = %d\n" "%s = %lld\n", KEY_WINDOW_X, uconfig->windowX, KEY_WINDOW_Y, uconfig->windowY, KEY_UUID, uconfig->uuid ); DD("Generated user-config file:\n%s", temp); ini = iniFile_newFromMemory(temp, uconfig->iniPath); if (ini == NULL) { D("Weird: can't create user-config iniFile?"); return; } if (iniFile_saveToFile(ini, uconfig->iniPath) < 0) { dwarning("could not save user configuration: %s: %s", uconfig->iniPath, strerror(errno)); } else { D("User configuration saved to %s", uconfig->iniPath); } iniFile_free(ini); }
void android_adb_service_init(void) { static int _inited = 0; if (!adb_server_is_initialized()) { return; } if (!_inited) { /* Register main ADB service. */ QemudService* serv = qemud_service_register(SERVICE_NAME, 0, NULL, _adb_service_connect, NULL, NULL); if (serv == NULL) { derror("%s: Could not register '%s' service", __FUNCTION__, SERVICE_NAME); return; } D("%s: Registered '%s' qemud service", __FUNCTION__, SERVICE_NAME); /* Register debugging ADB service. */ serv = qemud_service_register(DEBUG_SERVICE_NAME, 0, NULL, _adb_debug_service_connect, NULL, NULL); if (serv != NULL) { DD("Registered '%s' qemud service", DEBUG_SERVICE_NAME); } else { dwarning("%s: Could not register '%s' service", __FUNCTION__, DEBUG_SERVICE_NAME); } } }
//-------------------------------------------------------------------------- // returns true-lowcnd was false, resumed the application // nb: recursive calls to this function are not handled in any special way! bool debmod_t::handle_lowcnd(lowcnd_t *lc, debug_event_t *event) { if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 ) { // difficult case: we have to reset pc, remove the bpt, single step, and resume the app handling_lowcnd = true; regval_t rv; rv._set_int(lc->ea); int code = dbg_write_register(event->tid, pc_idx, &rv); if ( code <= 0 ) { handling_lowcnd = false; return false; } code = dbg_freeze_threads_except(event->tid); if ( code > 0 ) { code = dbg_del_bpt(lc->type, lc->ea, lc->orgbytes.begin(), lc->orgbytes.size()); if ( code > 0 ) { code = dbg_perform_single_step(event, lc->cmd); if ( code <= 0 ) dmsg("%a: failed to single step\n", event->ea); // may happen if ( dbg_add_bpt(lc->type, lc->ea, lc->orgbytes.size()) <= 0 ) { code = 0; dwarning("%a: could not restore deleted bpt\n", lc->cmd.ea); // odd } } if ( dbg_thaw_threads_except(event->tid) <= 0 ) { dwarning("%d: could not resume suspended threads\n", event->tid); // odd code = 0; } } handling_lowcnd = false; if ( code <= 0 || event->eid != STEP ) return false; // did not resume } return dbg_continue_after_event(event); }
/* Prints the warning string corresponding to the error code returned by * boot_propery_add2(). */ static void boot_property_raise_warning( int ret, const char* name, int namelen, const char* value, int valuelen ) { switch (ret) { case -1: dwarning("boot property name too long: '%.*s'", namelen, name); break; case -2: dwarning("boot property value too long: '%.*s'", valuelen, value); break; case -3: dwarning("boot property name contains invalid chars: %.*s", namelen, name); break; } }
//-------------------------------------------------------------------------- // 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; }
char* avdInfo_getSdCardPath( AvdInfo* i ) { const char* imageName = _imageFileNames[ AVD_IMAGE_SDCARD ]; char* path; /* Special case, the config.ini can have a SDCARD_PATH entry * that gives the full path to the SD Card. */ if (i->configIni != NULL) { path = iniFile_getString(i->configIni, SDCARD_PATH, NULL); if (path != NULL) { if (path_exists(path)) return path; dwarning("Ignoring invalid SDCard path: %s", path); AFREE(path); } } /* Otherwise, simply look into the content directory */ return _avdInfo_getContentFilePath(i, imageName); }
void boot_property_parse_option( const char* param ) { char* q = strchr(param,'='); const char* name; const char* value; int namelen, valuelen, ret; if (q == NULL) { dwarning("boot property missing (=) separator: %s", param); return; } name = param; namelen = q - param; value = q+1; valuelen = strlen(name) - (namelen+1); ret = boot_property_add2(name, namelen, value, valuelen); if (ret < 0) { boot_property_raise_warning(ret, name, namelen, value, valuelen); } }
void parse_nand_limits(char* limits) { int pid = -1, signal = -1; int64_t reads = 0, writes = 0; char* item = limits; /* parse over comma-separated items */ while (item && *item) { char* next = strchr(item, ','); char* end; if (next == NULL) { next = item + strlen(item); } else { *next++ = 0; } if ( !memcmp(item, "pid=", 4) ) { pid = strtol(item+4, &end, 10); if (end == NULL || *end) { derror( "bad parameter, expecting pid=<number>, got '%s'", item ); exit(1); } if (pid <= 0) { derror( "bad parameter: process identifier must be > 0" ); exit(1); } } else if ( !memcmp(item, "signal=", 7) ) { signal = strtol(item+7,&end, 10); if (end == NULL || *end) { derror( "bad parameter: expecting signal=<number>, got '%s'", item ); exit(1); } if (signal <= 0) { derror( "bad parameter: signal number must be > 0" ); exit(1); } } else if ( !memcmp(item, "reads=", 6) ) { reads = parse_nand_rw_limit(item+6); } else if ( !memcmp(item, "writes=", 7) ) { writes = parse_nand_rw_limit(item+7); } else { derror( "bad parameter '%s' (see -help-nand-limits)", item ); exit(1); } item = next; } if (pid < 0) { derror( "bad paramater: missing pid=<number>" ); exit(1); } else if (signal < 0) { derror( "bad parameter: missing signal=<number>" ); exit(1); } else if (reads == 0 && writes == 0) { dwarning( "no read or write limit specified. ignoring -nand-limits" ); } else { nand_threshold* t; t = &android_nand_read_threshold; t->pid = pid; t->signal = signal; t->counter = 0; t->limit = reads; t = &android_nand_write_threshold; t->pid = pid; t->signal = signal; t->counter = 0; t->limit = writes; } }
/* Create a new AUserConfig object from a given AvdInfo */ AUserConfig* auserConfig_new( AvdInfo* info ) { AUserConfig* uc; char inAndroidBuild = avdInfo_inAndroidBuild(info); char needUUID = 1; char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); char* parentPath; IniFile* ini = NULL; ANEW0(uc); /* If we are in the Android build system, store the configuration * in ~/.android/emulator-user.ini. otherwise, store it in the file * emulator-user.ini in the AVD's content directory. */ if (inAndroidBuild) { p = bufprint_config_file(temp, end, USER_CONFIG_FILE); } else { p = bufprint(temp, end, "%s/%s", avdInfo_getContentPath(info), USER_CONFIG_FILE); } /* handle the unexpected */ if (p >= end) { /* Hmmm, something is weird, let's use a temporary file instead */ p = bufprint_temp_file(temp, end, USER_CONFIG_FILE); if (p >= end) { derror("Weird: Cannot create temporary user-config file?"); exit(2); } dwarning("Weird: Content path too long, using temporary user-config."); } uc->iniPath = ASTRDUP(temp); DD("looking user-config in: %s", uc->iniPath); /* ensure that the parent directory exists */ parentPath = path_parent(uc->iniPath, 1); if (parentPath == NULL) { derror("Weird: Can't find parent of user-config file: %s", uc->iniPath); exit(2); } if (!path_exists(parentPath)) { if (!inAndroidBuild) { derror("Weird: No content path for this AVD: %s", parentPath); exit(2); } DD("creating missing directory: %s", parentPath); if (path_mkdir_if_needed(parentPath, 0755) < 0) { derror("Using empty user-config, can't create %s: %s", parentPath, strerror(errno)); exit(2); } } if (path_exists(uc->iniPath)) { DD("reading user-config file"); ini = iniFile_newFromFile(uc->iniPath); if (ini == NULL) { dwarning("Can't read user-config file: %s\nUsing default values", uc->iniPath); } } if (ini != NULL) { uc->windowX = iniFile_getInteger(ini, KEY_WINDOW_X, DEFAULT_X); DD(" found %s = %d", KEY_WINDOW_X, uc->windowX); uc->windowY = iniFile_getInteger(ini, KEY_WINDOW_Y, DEFAULT_Y); DD(" found %s = %d", KEY_WINDOW_Y, uc->windowY); if (iniFile_getValue(ini, KEY_UUID) != NULL) { uc->uuid = (uint64_t) iniFile_getInt64(ini, KEY_UUID, 0LL); needUUID = 0; DD(" found %s = %lld", KEY_UUID, uc->uuid); } iniFile_free(ini); } else { uc->windowX = DEFAULT_X; uc->windowY = DEFAULT_Y; uc->changed = 1; } /* Generate a 64-bit UUID if necessary. We simply take the * current time, which avoids any privacy-related value. */ if (needUUID) { struct timeval tm; gettimeofday( &tm, NULL ); uc->uuid = (uint64_t)tm.tv_sec*1000 + tm.tv_usec/1000; uc->changed = 1; DD(" Generated UUID = %lld", uc->uuid); } return uc; }
//-------------------------------------------------------------------------- // Read/write a model specific register using the driver provided by WinDbg. // The following requirements are imposed by this code: // - debugger module should be run with admin privileges // - System must be loaded with /debug switch (use bcdedit.exe to turn it on) // - Windbg local kernel debugging should be used at least once // This code is based on a sample kindly provided by Alex Ionescu. int win32_debmod_t::kldbgdrv_access_msr(SYSDBG_MSR *msr, bool write) { NTSTATUS code; IO_STATUS_BLOCK IoStatusBlock; if ( DriverHandle == NULL ) { // // Acquire 'load driver' privilege // BOOLEAN Old; code = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &Old); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to acquire 'load driver' privilege, please run as admin!\n" "Error: %s\n", winerr(code)); return code; } // // And need this for the driver to accept our commands // Additionally, system must be booted in /DEBUG mode // code = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &Old); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to acquire 'debug' privilege, is system booted in /debug mode?\n" "Error: %s\n", winerr(code)); return code; } // // Now load the driver // code = NtLoadDriver(&DriverPath); if ( FAILED(code) && code != STATUS_IMAGE_ALREADY_LOADED ) { dwarning("AUTOHIDE NONE\n" "Failed to load 'kldbgdrv', please use local kernel debugging at least once!\n" "Error: %s\n", winerr(code)); return code; } // // Open a handle to it // OBJECT_ATTRIBUTES ObjectAttributes; InitializeObjectAttributes(&ObjectAttributes, &DriverName, OBJ_CASE_INSENSITIVE, NULL, NULL); code = NtCreateFile(&DriverHandle, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_NON_DIRECTORY_FILE, NULL, 0); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to open 'kldbgdrv'\n" "Error: %s\n", winerr(code)); return code; } } // // Package the input parameters into the private structure // KLDD_DATA_DEBUG_CONTROL KldDebugCommand; KldDebugCommand.Command = write ? SysDbgWriteMsr : SysDbgReadMsr; KldDebugCommand.InputBuffer = msr; KldDebugCommand.InputBufferLength = sizeof(*msr); // // Send the request -- output isn't packaged, just specify directly the buffer // code = NtDeviceIoControlFile(DriverHandle, NULL, NULL, NULL, &IoStatusBlock, KLDD_CODE_DEBUG_CONTROL, &KldDebugCommand, sizeof(KldDebugCommand), msr, sizeof(*msr)); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to access model specific register, is system booted in /debug mode?\n" "Error: %s\n", winerr(code)); return code; } // all ok! return code; }
//-------------------------------------------------------------------------- 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; }
int crypto_run(struct fcrypt *fcr, struct kernel_crypt_op *kcop) { struct csession *ses_ptr; struct crypt_op *cop = &kcop->cop; int ret; if (unlikely(cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) { ddebug(1, "invalid operation op=%u", cop->op); return -EINVAL; } /* this also enters ses_ptr->sem */ ses_ptr = crypto_get_session_by_sid(fcr, cop->ses); if (unlikely(!ses_ptr)) { derr(1, "invalid session ID=0x%08X", cop->ses); return -EINVAL; } if (ses_ptr->hdata.init != 0 && (cop->flags == 0 || cop->flags & COP_FLAG_RESET)) { ret = cryptodev_hash_reset(&ses_ptr->hdata); if (unlikely(ret)) { derr(1, "error in cryptodev_hash_reset()"); goto out_unlock; } } if (ses_ptr->cdata.init != 0) { int blocksize = ses_ptr->cdata.blocksize; if (unlikely(cop->len % blocksize)) { derr(1, "data size (%u) isn't a multiple of block size (%u)", cop->len, blocksize); ret = -EINVAL; goto out_unlock; } cryptodev_cipher_set_iv(&ses_ptr->cdata, kcop->iv, min(ses_ptr->cdata.ivsize, kcop->ivlen)); } if (likely(cop->len)) { if (cop->flags & COP_FLAG_NO_ZC) { if (unlikely(ses_ptr->alignmask && !IS_ALIGNED((unsigned long)cop->src, ses_ptr->alignmask))) { dwarning(2, "source address %p is not %d byte aligned - disabling zero copy", cop->src, ses_ptr->alignmask + 1); cop->flags &= ~COP_FLAG_NO_ZC; } if (unlikely(ses_ptr->alignmask && !IS_ALIGNED((unsigned long)cop->dst, ses_ptr->alignmask))) { dwarning(2, "destination address %p is not %d byte aligned - disabling zero copy", cop->dst, ses_ptr->alignmask + 1); cop->flags &= ~COP_FLAG_NO_ZC; } } if (cop->flags & COP_FLAG_NO_ZC) ret = __crypto_run_std(ses_ptr, &kcop->cop); else ret = __crypto_run_zc(ses_ptr, kcop); if (unlikely(ret)) goto out_unlock; } if (ses_ptr->cdata.init != 0) { cryptodev_cipher_get_iv(&ses_ptr->cdata, kcop->iv, min(ses_ptr->cdata.ivsize, kcop->ivlen)); } if (ses_ptr->hdata.init != 0 && ((cop->flags & COP_FLAG_FINAL) || (!(cop->flags & COP_FLAG_UPDATE) || cop->len == 0))) { ret = cryptodev_hash_final(&ses_ptr->hdata, kcop->hash_output); if (unlikely(ret)) { derr(0, "CryptoAPI failure: %d", ret); goto out_unlock; } kcop->digestsize = ses_ptr->hdata.digestsize; } if (ses_ptr->rdata.init != 0 && cop->len > 0) { kcop->rng_output = kmalloc(cop->len, GFP_KERNEL); if (unlikely(!kcop->rng_output)) { derr(0, "Not enough space to store %d random bytes.", cop->len); ret = -ENOMEM; goto out_unlock; } ret = cryptodev_rng_get_bytes(&ses_ptr->rdata, kcop->rng_output, cop->len); // some RNGs return 0 for success, while // some return the number of bytes generated if (unlikely(ret != 0 && ret != cop->len)) { derr(0, "RNG failure: %d", ret); kfree(kcop->rng_output); kcop->rng_output = NULL; goto out_unlock; } ret = 0; kcop->rnglen = cop->len; } out_unlock: crypto_put_session(ses_ptr); return ret; }