bool GetExeInfo(LPCSTR fileName, ExeInfo&info) { LOADED_IMAGE loadedImage; if (!MapAndLoad(const_cast<PSTR>(fileName), nullptr, &loadedImage, FALSE, TRUE)) { return false; } info.managed = false; if (loadedImage.FileHeader->Signature == IMAGE_NT_SIGNATURE) { DWORD netHeaderAddress = loadedImage.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; if (netHeaderAddress) { info.managed = true; } } info.entryPoint = loadedImage.FileHeader->OptionalHeader.AddressOfEntryPoint; info.i386 = loadedImage.FileHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386; UnMapAndLoad(&loadedImage); return true; }
bool DebugFrontend::GetExeInfo(LPCSTR fileName, ExeInfo& info) const { LOADED_IMAGE loadedImage; if (!MapAndLoad(const_cast<PSTR>(fileName), NULL, &loadedImage, FALSE, TRUE)) { return false; } // Check if this is a managed application. // http://www.codeguru.com/cpp/w-p/system/misc/print.php/c14001 info.managed = false; if (loadedImage.FileHeader->Signature == IMAGE_NT_SIGNATURE) { DWORD netHeaderAddress = loadedImage.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; if (netHeaderAddress) { info.managed = true; } } info.entryPoint = loadedImage.FileHeader->OptionalHeader.AddressOfEntryPoint; info.i386 = loadedImage.FileHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386; UnMapAndLoad(&loadedImage); return true; }
void KImageModule::Unload(void) { SymUnloadModule(m_hProcess, m_symbolbase); SymCleanup(m_hProcess); if ( m_image.ModuleName ) UnMapAndLoad(& m_image); }
// Given the path to our python executable, load the binary and check // the processor architecture. If it's an x64 binary and our current // executable isn't, we'll return 0. static int is_valid(char* python) { char sPythonDir[MAX_PATH+1] = {0}; int result = 1; LOADED_IMAGE oImg; ZeroMemory(&oImg, sizeof(oImg)); if(!get_parent_dir(python, sPythonDir, MAX_PATH)) { debug("Could not get parent folder of %s..", python); return 0; } if(!MapAndLoad(PYTHON_EXE, sPythonDir, &oImg, 0, 1)) { debug("Could not MapAndLoad %s. Used folder: %s", PYTHON_EXE, sPythonDir); return 0; } switch(oImg.FileHeader->FileHeader.Machine) { case IMAGE_FILE_MACHINE_IA64: #ifdef _M_IA64 result = 1; #else result = 0; Platform_Mismatch("IA64"); #endif break; // AMD64 case IMAGE_FILE_MACHINE_AMD64: #ifdef _M_X64 result = 1; #else result = 0; Platform_Mismatch("X64"); #endif break; // X86 (32-bit) case IMAGE_FILE_MACHINE_I386: #ifdef _M_IX86 result = 1; #else result = 0; Platform_Mismatch("X86"); #endif break; // IA64 default: result = 0; Platform_Mismatch("Invalid"); break; } // This shouldn't happen, but you never know. if(!UnMapAndLoad(&oImg)) { debug("Could not unmap the python image."); return 0; } return result; }
int main(int argc, char *argv[]) { util_suppress_errmsg(); if (argc < 2) { fprintf(stderr, "usage: %s dllname\n", argv[0]); exit(1); } const char *dllname = argv[1]; LOADED_IMAGE img; if (MapAndLoad(dllname, NULL, &img, 1, 1) == FALSE) { fprintf(stderr, "cannot load DLL image\n"); exit(2); } IMAGE_EXPORT_DIRECTORY *dir; ULONG dirsize; dir = (IMAGE_EXPORT_DIRECTORY *)ImageDirectoryEntryToData( img.MappedAddress, 0 /* mapped as image */, IMAGE_DIRECTORY_ENTRY_EXPORT, &dirsize); if (dir == NULL) { fprintf(stderr, "cannot read image directory\n"); UnMapAndLoad(&img); exit(3); } DWORD *rva; rva = (DWORD *)ImageRvaToVa(img.FileHeader, img.MappedAddress, dir->AddressOfNames, NULL); for (DWORD i = 0; i < dir->NumberOfNames; i++) { char *name = (char *)ImageRvaToVa(img.FileHeader, img.MappedAddress, rva[i], NULL); printf("%s\n", name); } UnMapAndLoad(&img); return 0; }
BOOL TryMapAndLoad (PCSTR name, PCSTR path, PLOADED_IMAGE loadedImage, int requiredMachineType) { BOOL success = MapAndLoad (name, path, loadedImage, FALSE, TRUE); if (!success && GetLastError () == ERROR_FILE_NOT_FOUND) success = MapAndLoad (name, path, loadedImage, TRUE, TRUE); if (success && requiredMachineType != -1 && (int)loadedImage->FileHeader->FileHeader.Machine != requiredMachineType) { UnMapAndLoad (loadedImage); return FALSE; } return success; }
static BOOL PatchImports(char* name) { LOADED_IMAGE image; if (!MapAndLoad(name, NULL, &image, FALSE, FALSE)) { fprintf(stderr, "couldn't MapAndLoad '%s'\n", name); return FALSE; } if (image.FileHeader->OptionalHeader.NumberOfRvaAndSizes >= 2) { PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR) GetPtrFromRVA( image.FileHeader->OptionalHeader.DataDirectory[1].VirtualAddress, image.FileHeader, image.MappedAddress); while(1) { char *s; int len; // We've reached an empty IMAGE_IMPORT_DESCRIPTOR? if ((importDesc->TimeDateStamp == 0) && (importDesc->Name==0)) { break; } s = (char *) GetPtrFromRVA(importDesc->Name, image.FileHeader, image.MappedAddress); len = strlen(s); if (!strcasecmp(s, "kernel32.dll") || !strcasecmp(s, "msvcrt.dll") || !strcasecmp(s, "user32.dll") || !strcasecmp(s, "gdi32.dll") || !strcasecmp(s, "ole32.dll") || !strcasecmp(s, "advapi32.dll") || !strcasecmp(s, "comctl32.dll") || !strcasecmp(s, "ntdll.dll")) { printf("...patching %s ->", s); s[len - 5] = '_'; printf(" %s\n", s); } importDesc++; } } UnMapAndLoad(&image); return TRUE; }
static void load_and_analyze(void *dcontext, char *dllname) { LOADED_IMAGE img; BOOL res; res = MapAndLoad(dllname, NULL, &img, FALSE, TRUE); if (!res) { print("Error loading %s\n", dllname); return; } verbose_print("mapped at "PFX" (preferred "PFX")\n", img.MappedAddress, get_preferred_base(&img)); if (!list_usercalls) process_exports(dcontext, dllname, &img); if (list_syscalls || list_usercalls) process_symbols(dcontext, dllname, &img); UnMapAndLoad(&img); }
CAppProtector::CAppProtector(const char *lpszProtectedFileName,const char *lpszOriginalPEImageName, CAppSecureDlg* t) { ui=t; /* lpszProtectedFileName is the output filename, which is "SecureFile.EXE" by default lpszOriginalPEImageName is the PE File to protect. This file will NOT be modified in anyway. */ szProtectedFileName=new char[lstrlen(lpszProtectedFileName)+1]; lstrcpy(szProtectedFileName,lpszProtectedFileName); szMyFileName=new char[lstrlen(lpszOriginalPEImageName)+1]; lstrcpy(szMyFileName,lpszOriginalPEImageName); ///////////////////////////////////////////////////////////////////////// LOADED_IMAGE li; if(MapAndLoad(szMyFileName,0,&li,FALSE,TRUE)) RVAToFileOffset(li.FileHeader,li.FileHeader->OptionalHeader.AddressOfEntryPoint,li.FileHeader->FileHeader.NumberOfSections); else { AfxMessageBox("Load Failed !"); exit(1); } UnMapAndLoad(&li); ///////////////////////////////////////////////////////////////////////// }
/*********************************************************************** * BindImageEx (IMAGEHLP.@) * * Compute the virtual address of each function imported by a PE image * * PARAMS * * Flags [in] Bind options * ImageName [in] File name of the image to be bound * DllPath [in] Root of the fallback search path in case the ImageName file cannot be opened * SymbolPath [in] Symbol file root search path * StatusRoutine [in] Pointer to a status routine which will be called during the binding process * * RETURNS * Success: TRUE * Failure: FALSE * * NOTES * Binding is not implemented yet, so far this function only enumerates * all imported dlls/functions and returns TRUE. */ BOOL WINAPI BindImageEx( DWORD Flags, PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath, PIMAGEHLP_STATUS_ROUTINE StatusRoutine) { LOADED_IMAGE loaded_image; const IMAGE_IMPORT_DESCRIPTOR *import_desc; ULONG size; FIXME("(%d, %s, %s, %s, %p): semi-stub\n", Flags, debugstr_a(ImageName), debugstr_a(DllPath), debugstr_a(SymbolPath), StatusRoutine ); if (!(MapAndLoad(ImageName, DllPath, &loaded_image, TRUE, TRUE))) return FALSE; if (!(import_desc = RtlImageDirectoryEntryToData((HMODULE)loaded_image.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size))) { UnMapAndLoad(&loaded_image); return TRUE; /* No imported modules means nothing to bind, so we're done. */ } /* FIXME: Does native imagehlp support both 32-bit and 64-bit PE executables? */ #ifdef _WIN64 if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) #else if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) #endif { FIXME("Wrong architecture in PE header, unable to enumerate imports\n"); UnMapAndLoad(&loaded_image); return TRUE; } for (; import_desc->Name && import_desc->FirstThunk; ++import_desc) { IMAGE_THUNK_DATA *thunk; char dll_fullname[MAX_PATH]; const char *dll_name; if (!(dll_name = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, import_desc->Name, 0))) { UnMapAndLoad(&loaded_image); SetLastError(ERROR_INVALID_ACCESS); /* FIXME */ return FALSE; } if (StatusRoutine) StatusRoutine(BindImportModule, ImageName, dll_name, 0, 0); if (!SearchPathA(DllPath, dll_name, 0, sizeof(dll_fullname), dll_fullname, 0)) { UnMapAndLoad(&loaded_image); SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; } if (!(thunk = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, import_desc->OriginalFirstThunk ? import_desc->OriginalFirstThunk : import_desc->FirstThunk, 0))) { ERR("Can't grab thunk data of %s, going to next imported DLL\n", dll_name); continue; } for (; thunk->u1.Ordinal; ++thunk) { /* Ignoring ordinal imports for now */ if(!IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal)) { IMAGE_IMPORT_BY_NAME *iibn; if (!(iibn = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, thunk->u1.AddressOfData, 0))) { ERR("Can't grab import by name info, skipping to next ordinal\n"); continue; } if (StatusRoutine) StatusRoutine(BindImportProcedure, ImageName, dll_fullname, 0, (ULONG_PTR)iibn->Name); } } } UnMapAndLoad(&loaded_image); return TRUE; }
int BuildDepTree (BuildTreeConfig* cfg, char *name, struct DepTreeElement *root, struct DepTreeElement *self) { LOADED_IMAGE loaded_image; LOADED_IMAGE *img; IMAGE_DOS_HEADER *dos; HMODULE hmod; BOOL success; DWORD i, j; int soffs_len; soff_entry *soffs; if (self->flags & DEPTREE_PROCESSED) { return 0; } if (cfg->on_self) { char modpath[MAX_PATH]; success = GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, name, &hmod); if (!success) return 1; if (GetModuleFileNameA (hmod, modpath, MAX_PATH) == 0) return 1; if (self->resolved_module == NULL) self->resolved_module = strdup (modpath); dos = (IMAGE_DOS_HEADER *) hmod; loaded_image.FileHeader = (IMAGE_NT_HEADERS *) ((char *) hmod + dos->e_lfanew); loaded_image.Sections = (IMAGE_SECTION_HEADER *) ((char *) hmod + dos->e_lfanew + sizeof (IMAGE_NT_HEADERS)); loaded_image.NumberOfSections = loaded_image.FileHeader->FileHeader.NumberOfSections; loaded_image.MappedAddress = (void *) hmod; if (cfg->machineType != -1 && (int)loaded_image.FileHeader->FileHeader.Machine != cfg->machineType) return 1; } else { success = FALSE; for (i = 0; i < cfg->searchPaths->count && !success; ++i) { success = TryMapAndLoad (name, cfg->searchPaths->path[i], &loaded_image, cfg->machineType); } if (!success) success = TryMapAndLoad (name, NULL, &loaded_image, cfg->machineType); if (!success) { self->flags |= DEPTREE_UNRESOLVED; return 1; } if (self->resolved_module == NULL) self->resolved_module = strdup (loaded_image.ModuleName); } if (cfg->machineType == -1) cfg->machineType = (int)loaded_image.FileHeader->FileHeader.Machine; img = &loaded_image; PushStack (cfg->stack, cfg->stack_len, cfg->stack_size, name); self->mapped_address = loaded_image.MappedAddress; self->flags |= DEPTREE_PROCESSED; soffs_len = img->NumberOfSections; soffs = (soff_entry *) malloc (sizeof(soff_entry) * (soffs_len + 1)); for (i = 0; i < img->NumberOfSections; i++) { soffs[i].start = img->Sections[i].VirtualAddress; soffs[i].end = soffs[i].start + img->Sections[i].Misc.VirtualSize; if (cfg->on_self) soffs[i].off = img->MappedAddress/* + img->Sections[i].VirtualAddress*/; else if (img->Sections[i].PointerToRawData != 0) soffs[i].off = img->MappedAddress + img->Sections[i].PointerToRawData - img->Sections[i].VirtualAddress; else soffs[i].off = NULL; } soffs[img->NumberOfSections].start = 0; soffs[img->NumberOfSections].end = 0; soffs[img->NumberOfSections].off = 0; BuildDepTree32or64 (img, cfg, root, self, soffs, soffs_len); free (soffs); if (!cfg->on_self) UnMapAndLoad (&loaded_image); /* Not sure if a forwarded export warrants an import. If it doesn't, then the dll to which the export is forwarded will NOT * be among the dependencies of this dll and it will be necessary to do yet another ProcessDep... for (i = 0; i < self->exports_len; i++) { if (self->exports[i]->forward_str != NULL && self-.exports[i]->forward == NULL) { char *forward_str_copy = NULL, *export_name = NULL, *rdot = NULL; DWORD export_ordinal = 0; forward_str_copy = strdup (self->exports[i]->forward_str); rdot = strrchr (forward_str_copy, '.'); if (rdot != NULL && rdot[1] != 0) { rdot[0] = 0; export_name = &rdot[1]; if (export_name[0] == '#' && export_name[1] >= '0' && export_name[1] <= '9') { export_ordinal = strtol (&export_name[1], NULL, 10); export_name = NULL; } self->exports[i]->forward = FindExportForward (forward_str_copy, export_name, export_ordinal); } free (forward_str_copy); } } */ for (i = 0; i < self->imports_len; i++) { if (self->imports[i].mapped == NULL && self->imports[i].dll != NULL && (self->imports[i].name != NULL || self->imports[i].ordinal > 0)) { struct DepTreeElement *dll = self->imports[i].dll; for (j = 0; j < dll->exports_len; j++) { if ((self->imports[i].name != NULL && dll->exports[j].name != NULL && strcmp (self->imports[i].name, dll->exports[j].name) == 0) || (self->imports[i].ordinal > 0 && dll->exports[j].ordinal > 0 && self->imports[i].ordinal == dll->exports[j].ordinal)) { self->imports[i].mapped = &dll->exports[j]; break; } } /* if (self->imports[i].mapped == NULL) printf ("Could not match %s (%d) in %s to %s\n", self->imports[i].name, self->imports[i].ordinal, self->module, dll->module); */ } } /* By keeping items in the stack we turn it into a list of all * processed modules, this should be more effective at preventing * us from processing modules multiple times */ /*PopStack (stack, stack_len, stack_size, name);*/ return 0; }
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpOriginalCmdLine, int nCmdShow) { int i; LOADED_IMAGE oImg; LPWSTR lpCmdLine; wchar_t parentDir[MAX_PATH+1] = L"", exePath[MAX_PATH+1] = L""; size_t szParentDir, szExeStr, szCmdLine, szPlatExe; PROCESS_INFORMATION pi; STARTUPINFO si; LPWSTR *argv = __wargv; int argc = __argc; // Zero out our loaded image struct. ZeroMemory(&oImg, sizeof(oImg)); /* Make sure we have args. */ if(argc == 1) { Fatal(1L, L"No images specified."); } /* Get our exe's parent folder. */ if(!GetParentDir(parentDir, &szParentDir)) { Fatal(1L, L"Could not get parent folder of image, \"%s\". This should not happen ever.", argv[0]); } /* Iterate through our arguments */ for(i = 1; i < argc; i++) { /* Verify file exists. */ if(_waccess(argv[i], 00) == -1) { Fatal(1L, L"File does not exist.\nFile: %s", argv[i]); } /* Get the binary type. */ if(!MapAndLoadW(argv[i], &oImg)) { Fatal(1L, L"Unable to get binary type for image.\nImage: %s", argv[i]); } lstrcpyW(exePath, parentDir); switch(oImg.FileHeader->FileHeader.Machine) { case IMAGE_FILE_MACHINE_I386: lstrcatW(exePath, x86exe); szPlatExe = SZ_86_EXE; break; // TODO: Differentiate between x64 platforms. case IMAGE_FILE_MACHINE_AMD64: lstrcatW(exePath, amd64exe); szPlatExe = SZ_AMD_EXE; break; case IMAGE_FILE_MACHINE_IA64: lstrcatW(exePath, ia64exe); szPlatExe = SZ_IA_EXE; break; default: Fatal(1L, L"Unknown binary type returned for image.\nImage: %s\n\nBinary Type: %d", argv[i], oImg.FileHeader->FileHeader.Machine); } if(!UnMapAndLoad(&oImg)) { Fatal(1L, L"Failed to unload/unmap image.\nImage: %s", argv[i]); } /* Calculate the length of the eventual exe path with surrounding quotes. */ lstrcatW(exePath, depsexe); szExeStr = szParentDir + szPlatExe + 2; // +2 for the two "s surrounding the image path. /* Allocate our command line string. */ // szExeStr+ 1 +1+wcslen(argv)+1 // "(path)depends.exe" "argv" szCmdLine = szExeStr + lstrlenW(argv[i]) + 3; lpCmdLine = (LPWSTR)LocalAlloc(LPTR, sizeof(wchar_t) * (szCmdLine + 1)); if(lpCmdLine == NULL) { Fatal(1L, L"Could not allocate memory.\nMemory required (bytes): %d", sizeof(wchar_t) * (szCmdLine + 1)); } if(swprintf(lpCmdLine, szCmdLine+1, L"\"%s\" \"%s\"", exePath, argv[i]) == -1) { LocalFree(lpCmdLine); FatalCall(L"swprintf"); } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); /* Depends launching. */ if (!CreateProcessW( NULL, /* No module name (use command line) */ lpCmdLine, /* Command line */ NULL, /* Process handle not inheritable */ NULL, /* Thread handle not inheritable */ FALSE, /* Set handle inheritance to FALSE */ 0, /* No creation flags */ NULL, /* Use parent's environment block */ NULL, /* Use parent's starting directory */ &si, /* Pointer to STARTUPINFO structure */ &pi /* Pointer to PROCESS_INFORMATION structure */ )) { // len("CreateProcessW") + len(" - ") + len(cmdline) szCmdLine += 17; LocalFree(lpCmdLine); lpCmdLine = (LPWSTR)LocalAlloc(LPTR, sizeof(wchar_t) * (szCmdLine + 1)); swprintf(lpCmdLine, szCmdLine+1, L"CreateProcessW - \"%s\" \"%s\"", exePath, argv[i]); FatalCall(lpCmdLine); } LocalFree(lpCmdLine); } return 0; }
static void process_exports(void *dcontext, char *dllname) { LOADED_IMAGE img; IMAGE_EXPORT_DIRECTORY *dir; IMAGE_SECTION_HEADER *sec; DWORD *name, *code; WORD *ordinal; const char *string; uint size; BOOL res; uint i; byte *addr, *start_exports, *end_exports; verbose_print("Processing exports of \"%s\"\n", dllname); res = MapAndLoad(dllname, NULL, &img, FALSE, TRUE); if (!res) { print("Error loading %s\n", dllname); return; } dir = (IMAGE_EXPORT_DIRECTORY *) ImageDirectoryEntryToData(img.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size); verbose_print("mapped at 0x%08x, exports is at 0x%08x, size is 0x%x\n", img.MappedAddress, dir, size); start_exports = (byte *) dir; end_exports = start_exports + size; verbose_print("name=%s, ord base=0x%08x, names=%d 0x%08x\n", (char *) ImageRvaToVa(img.FileHeader, img.MappedAddress, dir->Name, NULL), dir->Base, dir->NumberOfNames, dir->AddressOfNames); /* don't limit functions to lie in .text -- * for ntdll, some exported routines have their code after .text, inside * ECODE section! */ sec = img.Sections; for (i = 0; i < img.NumberOfSections; i++) { verbose_print("Section %d %s: 0x%x + 0x%x == 0x%08x through 0x%08x\n", i, sec->Name, sec->VirtualAddress, sec->SizeOfRawData, ImageRvaToVa(img.FileHeader, img.MappedAddress, sec->VirtualAddress, NULL), (uint) ImageRvaToVa(img.FileHeader, img.MappedAddress, sec->VirtualAddress, NULL) + sec->SizeOfRawData); sec++; } name = (DWORD *) ImageRvaToVa(img.FileHeader, img.MappedAddress, dir->AddressOfNames, NULL); code = (DWORD *) ImageRvaToVa(img.FileHeader, img.MappedAddress, dir->AddressOfFunctions, NULL); ordinal = (WORD *) ImageRvaToVa(img.FileHeader, img.MappedAddress, dir->AddressOfNameOrdinals, NULL); verbose_print("names: from 0x%08x to 0x%08x\n", ImageRvaToVa(img.FileHeader, img.MappedAddress, name[0], NULL), ImageRvaToVa(img.FileHeader, img.MappedAddress, name[dir->NumberOfNames-1], NULL)); for (i = 0; i < dir->NumberOfNames; i++) { string = (char *) ImageRvaToVa(img.FileHeader, img.MappedAddress, name[i], NULL); /* ordinal is biased (dir->Base), but don't add base when using as index */ assert(dir->NumberOfFunctions > ordinal[i]); /* I don't understand why have to do RVA to VA here, when dumpbin /exports * seems to give the same offsets but by simply adding them to base we * get the appropriate code location -- but that doesn't work here... */ addr = ImageRvaToVa(img.FileHeader, img.MappedAddress, code[ordinal[i]], NULL); verbose_print("name=%s 0x%08x, ord=%d, code=0x%x -> 0x%08x\n", string, string, ordinal[i], code[ordinal[i]], addr); if (list_exports) { print("ord %3d offs 0x%08x %s\n", ordinal[i], addr - img.MappedAddress, string); } if (list_Ki && string[0] == 'K' && string[1] == 'i') { print("\n==================================================\n"); print("%s\n\n", string); check_Ki(string); print("\ndisassembly:\n"); decode_function(dcontext, addr); print( "==================================================\n"); } /* forwarded export points inside exports section */ if (addr >= start_exports && addr < end_exports) { if (list_forwards || verbose) { /* I've had issues w/ forwards before, so avoid printing crap */ if (addr[0] > 0 && addr[0] < 127) print("%s is forwarded to %.128s\n", string, addr); else print("ERROR identifying forwarded entry for %s\n", string); } } else if (list_syscalls) { process_syscall_wrapper(dcontext, addr, string, "export"); } } if (list_syscalls) process_symbols(dcontext, dllname, &img); UnMapAndLoad(&img); }