static int parameters_present(IF_NOT_X64(bool x64_in_wow64)) { char path[MAX_PATH]; int retval; /* We should do some sanity checking on our parameters, to make sure we can really inject in applications. War story: When renaming the product from DynamoRIO to SecureCore we'd start injecting and then failing to load a dll for all apps. */ #ifndef X64 if (x64_in_wow64) { ASSERT(is_wow64_process(NT_CURRENT_PROCESS)); retval = get_parameter_64(PARAM_STR(DYNAMORIO_VAR_AUTOINJECT), path, MAX_PATH); } else #endif retval = get_parameter(PARAM_STR(DYNAMORIO_VAR_AUTOINJECT), path, MAX_PATH); if (IS_GET_PARAMETER_SUCCESS(retval)) { return 1; } else { return 0; } }
static bool load_dynamorio_lib(IF_NOT_X64(bool x64_in_wow64)) { HMODULE dll = NULL; char path[MAX_PATH]; #ifdef DEBUG char msg[3 * MAX_PATH]; #endif int retval = -1; /* failure */ #ifndef X64 bool wow64 = is_wow64_process(NT_CURRENT_PROCESS); if (x64_in_wow64) { ASSERT(wow64); retval = get_parameter_64(PARAM_STR(DYNAMORIO_VAR_AUTOINJECT), path, MAX_PATH); } else #endif retval = get_parameter(PARAM_STR(DYNAMORIO_VAR_AUTOINJECT), path, MAX_PATH); if (IS_GET_PARAMETER_SUCCESS(retval)) { dr_marker_t mark; VERBOSE_MESSAGE("Loading \"%hs\"", path); /* The read_and_verify_dr_marker is the canonical check for dr in a * process, we double check against GetModuleHandle here just to be * extra safe (in case dr failed to initialize before). Note that * GetModuleHandle won't find dr's dll if we implement certian -hide * or early_injection proposals. */ if (read_and_verify_dr_marker(GetCurrentProcess(), &mark) != DR_MARKER_FOUND && GetModuleHandle(DYNAMORIO_LIBRARY_NAME) == NULL #ifndef X64 /* these ifdefs are rather ugly: just export all routines in x64 builds? */ && /* check for 64-bit as well */ (!wow64 || read_and_verify_dr_marker_64(GetCurrentProcess(), &mark) != DR_MARKER_FOUND) /* FIXME PR 251677: need 64-bit early injection to fully test * read_and_verify_dr_marker_64 */ #endif ) { /* OK really going to load dr now, verify that we are injecting * early enough (i.e. user32.dll is statically linked). This * presumes preinject is only used with app_init injection which is * currently the case. FIXME - should we also check_sole_thread * here? We can't really handle more then one thread when dr is * loading, but this can happen with early remote injected threads * many of which (CTRL) are relatively harmless. */ LDR_MODULE *mod = get_ldr_module_by_name(L"user32.dll"); ASSERT(mod != NULL); if (ldr_module_statically_linked(mod)) { #ifndef X64 if (x64_in_wow64) dll = load_library_64(path); else #endif dll = LoadLibrary(path); } else { /* FIXME - would be really nice to communicate this back to * the controller. */ #ifdef DEBUG _snprintf(msg, BUFFER_SIZE_ELEMENTS(msg), PRODUCT_NAME " Error: improper injection - " PRODUCT_NAME " (%s) can't inject into process %s (%s) (user32.dll " "not statically linked)\n", path, get_application_name(), get_application_pid()); NULL_TERMINATE_BUFFER(msg); display_error(msg); #endif } } else { /* notify failure only in debug builds, otherwise just return */ #ifdef DEBUG /* with early injection this becomes even more likely */ if (read_and_verify_dr_marker(GetCurrentProcess(), &mark) == DR_MARKER_FOUND # ifndef X64 || (wow64 && read_and_verify_dr_marker_64(GetCurrentProcess(), &mark) == DR_MARKER_FOUND) # endif ) { /* ok, early injection should always beat this */ # if VERBOSE /* can't readily tell what was expected */ _snprintf(msg, BUFFER_SIZE_ELEMENTS(msg), PRODUCT_NAME " ok if early injection, otherwise ERROR: " "double injection, " PRODUCT_NAME " (%s) is already loaded " "in process %s (%s), continuing\n", path, get_application_name(), get_application_pid()); NULL_TERMINATE_BUFFER(msg); display_error(msg); # endif /* VERBOSE */ } else { /* if GetModuleHandle finds us but we don't have a marker * we may have failed somehow */ _snprintf(msg, BUFFER_SIZE_ELEMENTS(msg), PRODUCT_NAME " Error: failed injection, " PRODUCT_NAME " (%s) is " "loaded but not initialized in process %s (%s), continuing\n", path, get_application_name(), get_application_pid()); NULL_TERMINATE_BUFFER(msg); display_error(msg); } #endif /* DEBUG */ return false; } } else path[0] = 0; if (dll == NULL) { #ifdef DEBUG int err = GetLastError(); _snprintf(msg, BUFFER_SIZE_ELEMENTS(msg), PRODUCT_NAME " Error %d loading %s\n", err, path); NULL_TERMINATE_BUFFER(msg); display_error(msg); #endif return false; } else { int_func_t init_func; void_func_t take_over_func; int res; #ifndef X64 if (x64_in_wow64) { init_func = (int_func_t)(ptr_uint_t) /*we know <4GB*/ get_proc_address_64((uint64)dll, "dynamorio_app_init"); take_over_func = (void_func_t)(ptr_uint_t) /*we know <4GB*/ get_proc_address_64((uint64)dll, "dynamorio_app_take_over"); VERBOSE_MESSAGE("dynamorio_app_init: 0x%08x; dynamorio_app_take_over: " "0x%08x\n", init_func, take_over_func); } else { #endif init_func = (int_func_t)GetProcAddress(dll, "dynamorio_app_init"); take_over_func = (void_func_t)GetProcAddress(dll, "dynamorio_app_take_over"); #ifndef X64 } #endif if (init_func == NULL || take_over_func == NULL) { /* unload the library so that it's clear DR is not in control * (o/w the DR library is in the process and it's not clear * what's going on) */ #ifndef X64 if (x64_in_wow64) { # ifdef DEBUG bool ok = # endif free_library_64(dll); ASSERT(ok); } else #endif FreeLibrary(dll); #ifdef DEBUG display_error("Error getting " PRODUCT_NAME " functions\n"); #endif return false; } VERBOSE_MESSAGE("about to inject dynamorio"); #ifndef X64 if (x64_in_wow64) res = switch_modes_and_call(init_func, NULL, NULL, NULL); else #endif res = (*init_func)(); VERBOSE_MESSAGE("dynamorio_app_init() returned %d\n", res); #ifndef X64 if (x64_in_wow64) switch_modes_and_call(take_over_func, NULL, NULL, NULL); else #endif (*take_over_func)(); VERBOSE_MESSAGE("inside " PRODUCT_NAME " now\n"); } return true; }