/* add a dll to the list of imports */ void add_import_dll( const char *name, const char *filename ) { struct import *imp = xmalloc( sizeof(*imp) ); imp->spec = alloc_dll_spec(); imp->spec->file_name = get_dll_name( name, filename ); imp->delay = 0; imp->imports = NULL; imp->nb_imports = 0; imp->exports = NULL; imp->nb_exports = 0; if (filename) imp->full_name = xstrdup( filename ); else imp->full_name = find_library( name ); if (read_import_lib( imp )) { dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) ); dll_imports[nb_imports++] = imp; } else { free_imports( imp ); if (nb_errors) exit(1); } }
void* dlopen(const char* filename, int flag) { ScopedPthreadMutexLocker locker(&gDlMutex); soinfo* result = find_library(filename); if (result == NULL) { __bionic_format_dlerror("dlopen failed", linker_get_error()); return NULL; } soinfo_call_constructors(result); result->refcount++; return result; }
void *dlopen(const char *filename, int flag) { soinfo *ret; pthread_mutex_lock(&dl_lock); ret = find_library(filename); if (unlikely(ret == NULL)) { set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY); } else { ret->refcount++; } pthread_mutex_unlock(&dl_lock); return ret; }
/** * load card/reader driver modules * Every module should contain a function " void * sc_module_init(char *) " * that returns a pointer to the function _sc_get_xxxx_driver() * used to initialize static modules * Also, an exported "char *sc_module_version" variable should exist in module */ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name) { const char *version, *libname; void *handle; void *(*modinit)(const char *) = NULL; void *(**tmodi)(const char *) = &modinit; const char *(*modversion)(void) = NULL; const char *(**tmodv)(void) = &modversion; if (dll == NULL) { sc_log(ctx, "No dll parameter specified"); return NULL; } if (name == NULL) { /* should not occur, but... */ sc_log(ctx, "No module specified"); return NULL; } libname = find_library(ctx, name); if (libname == NULL) return NULL; handle = sc_dlopen(libname); if (handle == NULL) { sc_log(ctx, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror()); return NULL; } /* verify correctness of module */ *(void **)tmodi = sc_dlsym(handle, "sc_module_init"); *(void **)tmodv = sc_dlsym(handle, "sc_driver_version"); if (modinit == NULL || modversion == NULL) { sc_log(ctx, "dynamic library '%s' is not a OpenSC module",libname); sc_dlclose(handle); return NULL; } /* verify module version */ version = modversion(); /* XXX: We really need to have ABI version for each interface */ if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) { sc_log(ctx, "dynamic library '%s': invalid module version", libname); sc_dlclose(handle); return NULL; } *dll = handle; sc_log(ctx, "successfully loaded card driver '%s'", name); return modinit(name); }
/** * Preload a specific library. * * * @param library The library to be preloaded. */ static void preload_library(const char *library) { #ifdef __APPLE__ /* For apple systems, add the library to DYLD_INSERT_LIBRARIES, the macOS * version of LD_PRELOAD. DYLD_FORCE_FLAT_NAMESPACE has to be set, to get all * symbols in the same namespace. Otherwise P^nMPI and libmpi won't see each * other and no preloading will happen. */ char *lib = find_library(library); appendenv("DYLD_INSERT_LIBRARIES", lib, 0); setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", 1); free(lib); #else /* For other systems (Linux and other UNIX platforms), add the library to * LD_PRELOAD to load P^nMPI in front of libmpi. No path to the shared object, * but just the filename is required, as the dynamic loader searches in the * LD_LIBRARY_PATH for this file. */ appendenv("LD_LIBRARY_PATH", PNMPI_LIBRARY_PATH, 0); appendenv("LD_PRELOAD", library, 0); #endif }
int C_TransOCTcap32::analyze_init_string (char *P_buf) { int L_ret = 0 ; char *L_value ; char *L_path_value = NULL ; char *L_lib_name_value = NULL ; L_value = find_value(P_buf, (char*)"flavour"); if (L_value == NULL) { LOG_ERROR("Flavour not defined in your config file"); L_ret = -1 ; } else { m_flavour = analyze_flavour (L_value); if (m_flavour != C_TransOCTcap32::E_FLAVOUR_UNKNOWN) { L_path_value = find_value(P_buf, (char*)"path"); L_lib_name_value = find_value(P_buf, (char*)"library"); L_ret = find_library (L_value, L_path_value, L_lib_name_value); if (L_ret == 0) { if (m_flavour == C_TransOCTcap32::E_FLAVOUR_ITU) { m_stack = create_tcap_itu_stack(m_library_name); // NEW_VAR(m_stack, C_TcapStackITU(m_library_name)); } else { m_stack = create_tcap_ansi_stack(m_library_name); // NEW_VAR(m_stack, C_TcapStackANSI(m_library_name)); } } FREE_TABLE(L_path_value); FREE_TABLE(L_lib_name_value); } else { LOG_ERROR("Flavour unknown"); L_ret = -1 ; } FREE_TABLE(L_value); } return (L_ret); }
int fprintf_process(pid_t pid) { // attach to the process if (ptrace(PTRACE_ATTACH, pid, NULL, NULL)) { perror("PTRACE_ATTACH"); check_yama(); return -1; } // wait for the process to actually stop if (waitpid(pid, 0, WSTOPPED) == -1) { perror("wait"); return -1; } // save the register state of the remote process struct user_regs_struct oldregs; if (ptrace(PTRACE_GETREGS, pid, NULL, &oldregs)) { perror("PTRACE_GETREGS"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return -1; } void *rip = (void *)oldregs.rip; printf("their %%rip %p\n", rip); // First, we are going to allocate some memory for ourselves so we don't // need // to stop on the remote process' memory. We will do this by directly // invoking // the mmap(2) system call and asking for a single page. struct user_regs_struct newregs; memmove(&newregs, &oldregs, sizeof(newregs)); newregs.rax = 9; // mmap newregs.rdi = 0; // addr newregs.rsi = PAGE_SIZE; // length newregs.rdx = PROT_READ | PROT_EXEC; // prot newregs.r10 = MAP_PRIVATE | MAP_ANONYMOUS; // flags newregs.r8 = -1; // fd newregs.r9 = 0; // offset uint8_t old_word[8]; uint8_t new_word[8]; new_word[0] = 0x0f; // SYSCALL new_word[1] = 0x05; // SYSCALL new_word[2] = 0xff; // JMP %rax new_word[3] = 0xe0; // JMP %rax // insert the SYSCALL instruction into the process, and save the old word if (poke_text(pid, rip, new_word, old_word, sizeof(new_word))) { goto fail; } // set the new registers with our syscall arguments if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } // invoke mmap(2) if (singlestep(pid)) { goto fail; } // read the new register state, so we can see where the mmap went if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); return -1; } // this is the address of the memory we allocated void *mmap_memory = (void *)newregs.rax; if (mmap_memory == (void *)-1) { printf("failed to mmap\n"); goto fail; } printf("allocated memory at %p\n", mmap_memory); printf("executing jump to mmap region\n"); if (singlestep(pid)) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } if (newregs.rip == (long)mmap_memory) { printf("successfully jumped to mmap area\n"); } else { printf("unexpectedly jumped to %p\n", (void *)newregs.rip); goto fail; } // Calculate the position of the fprintf routine in the other process' // address // space. This is a little bit tricky because of ASLR on Linux. What we do // is // we find the offset in memory that libc has been loaded in their process, // and then we find the offset in memory that libc has been loaded in our // process. Then we take the delta betwen our fprintf and our libc start, // and // assume that the same delta will apply to the other process. // // For this mechanism to work, this program must be compiled with -fPIC to // ensure that our fprintf has an address relative to the one in libc. // // Additionally, this could fail if libc has been updated since the remote // process has been restarted. This is a pretty unlikely situation, but if // the // remote process has been running for a long time and you update libc, the // offset of the symbols could have changed slightly. void *their_libc = find_library(pid, libc_string); void *our_libc = find_library(getpid(), libc_string); void *their_fprintf = their_libc + ((void *)fprintf - our_libc); FILE *their_stderr = their_libc + ((void *)stderr - our_libc); printf("their libc %p\n", their_libc); printf("their fprintf %p\n", their_libc); printf("their stderr %p\n", their_stderr); // We want to make a call like: // // fprintf(stderr, "instruction pointer = %p\n", rip); // // To do this we're going to do the following: // // * put a CALL instruction into the mmap area that calls fprintf // * put a TRAP instruction right after the CALL // * put the format string right after the TRAP // * use the TRAP to restore the original text/program state // memory we are going to copy into our mmap area uint8_t new_text[32]; memset(new_text, 0, sizeof(new_text)); // insert a CALL instruction size_t offset = 0; new_text[offset++] = 0xe8; // CALL rel32 int32_t fprintf_delta = compute_jmp(mmap_memory, their_fprintf); memmove(new_text + offset, &fprintf_delta, sizeof(fprintf_delta)); offset += sizeof(fprintf_delta); // insert a TRAP instruction new_text[offset++] = 0xcc; // copy our fprintf format string right after the TRAP instruction memmove(new_text + offset, format, strlen(format)); // update the mmap area printf("inserting code/data into the mmap area at %p\n", mmap_memory); if (poke_text(pid, mmap_memory, new_text, NULL, sizeof(new_text))) { goto fail; } if (poke_text(pid, rip, new_word, NULL, sizeof(new_word))) { goto fail; } // set up our registers with the args to fprintf // memmove(&newregs, &oldregs, sizeof(newregs)); newregs.rax = 0; // no vector registers are used newregs.rdi = (long)their_stderr; // pointer to stderr in the caller newregs.rsi = (long)mmap_memory + offset; // pointer to the format string newregs.rdx = oldregs.rip; // the integer we want to print printf("setting the registers of the remote process\n"); if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } // continue the program, and wait for the trap printf("continuing execution\n"); ptrace(PTRACE_CONT, pid, NULL, NULL); if (do_wait("PTRACE_CONT")) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } newregs.rax = (long)rip; if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } new_word[0] = 0xff; // JMP %rax new_word[1] = 0xe0; // JMP %rax poke_text(pid, (void *)newregs.rip, new_word, NULL, sizeof(new_word)); printf("jumping back to original rip\n"); if (singlestep(pid)) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } if (newregs.rip == (long)rip) { printf("successfully jumped back to original %%rip at %p\n", rip); } else { printf("unexpectedly jumped to %p (expected to be at %p)\n", (void *)newregs.rip, rip); goto fail; } // unmap the memory we allocated newregs.rax = 11; // munmap newregs.rdi = (long)mmap_memory; // addr newregs.rsi = PAGE_SIZE; // size if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } // make the system call printf("making call to mmap\n"); if (singlestep(pid)) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } printf("munmap returned with status %llu\n", newregs.rax); printf("restoring old text at %p\n", rip); poke_text(pid, rip, old_word, NULL, sizeof(old_word)); printf("restoring old registers\n"); if (ptrace(PTRACE_SETREGS, pid, NULL, &oldregs)) { perror("PTRACE_SETREGS"); goto fail; } // detach the process printf("detaching\n"); if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) { perror("PTRACE_DETACH"); goto fail; } return 0; fail: poke_text(pid, rip, old_word, NULL, sizeof(old_word)); if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) { perror("PTRACE_DETACH"); } return 1; }
/** * find library module for provided driver in configuration file * if not found assume library name equals to module name */ static const char *find_library(sc_context_t *ctx, const char *name) { int i; const char *libname = NULL; scconf_block **blocks, *blk; for (i = 0; ctx->conf_blocks[i]; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_driver", name); if (!blocks) continue; blk = blocks[0]; free(blocks); if (blk == NULL) continue; libname = scconf_get_str(blk, "module", name); #ifdef _WIN32 if (libname && libname[0] != '\\' ) { #else if (libname && libname[0] != '/' ) { #endif sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: relative path to driver '%s' used", libname); } break; } return libname; } /** * load card/reader driver modules * Every module should contain a function " void * sc_module_init(char *) " * that returns a pointer to the function _sc_get_xxxx_driver() * used to initialize static modules * Also, an exported "char *sc_module_version" variable should exist in module */ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name) { const char *version, *libname; void *handle; void *(*modinit)(const char *) = NULL; void *(**tmodi)(const char *) = &modinit; const char *(*modversion)(void) = NULL; const char *(**tmodv)(void) = &modversion; if (name == NULL) { /* should not occurr, but... */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No module specified",name); return NULL; } libname = find_library(ctx, name); if (libname == NULL) return NULL; handle = sc_dlopen(libname); if (handle == NULL) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror()); return NULL; } /* verify correctness of module */ *(void **)tmodi = sc_dlsym(handle, "sc_module_init"); *(void **)tmodv = sc_dlsym(handle, "sc_driver_version"); if (modinit == NULL || modversion == NULL) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "dynamic library '%s' is not a OpenSC module",libname); sc_dlclose(handle); return NULL; } /* verify module version */ version = modversion(); /* XXX: We really need to have ABI version for each interface */ if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"dynamic library '%s': invalid module version",libname); sc_dlclose(handle); return NULL; } *dll = handle; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "successfully loaded card driver '%s'", name); return modinit(name); } static int load_card_driver_options(sc_context_t *ctx, struct sc_card_driver *driver) { scconf_block **blocks, *blk; int i; for (i = 0; ctx->conf_blocks[i]; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_driver", driver->short_name); if (!blocks) continue; blk = blocks[0]; free(blocks); if (blk == NULL) continue; /* no options at the moment */ } return SC_SUCCESS; }