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; }
bool KImageModule::Load(char * filename, char *sympath) { _tcscpy(m_modulename, filename); memset(& m_image, 0, sizeof(m_image)); m_imagebase_loaded = (DWORD) GetModuleHandle(filename); if ( m_imagebase_loaded ) // module is already loaded, for example GDI32.DLL { m_imagebase_default = m_imagebase_loaded; m_bLoaded = false; PIMAGE_NT_HEADERS pNTHeader = ImageNtHeader((void *)m_imagebase_loaded); Output("%s already loaded at 0x%x %s\n", filename, m_imagebase_loaded, ctime( (time_t *) & pNTHeader->FileHeader.TimeDateStamp)); } else { if ( MapAndLoad(filename, NULL, & m_image, FALSE, TRUE) ) Output("%s loaded at 0x%x %s\n", m_image.ModuleName, m_image.MappedAddress, ctime( (time_t *) & m_image.FileHeader->FileHeader.TimeDateStamp)); else { Output("Unable to load %s\n", filename); return false; } m_imagebase_loaded = (DWORD) m_image.MappedAddress; m_imagebase_default = m_image.FileHeader->OptionalHeader.ImageBase; m_bLoaded = true; } if ( !SymInitialize(m_hProcess, sympath, FALSE) ) { Output("SymInitialize failed\n\n"); return false; } m_symbolbase = SymLoadModule(m_hProcess, NULL, filename, 0, m_imagebase_loaded, 0 ); if ( m_symbolbase==0 ) { Output("SymLoadModule failed\n\n"); return false; } IMAGEHLP_MODULE im; im.SizeOfStruct = sizeof(im); SymGetModuleInfo( m_hProcess, m_symbolbase, &im ); Output("""%s"" loaded. %s\n", im.LoadedImageName, ctime((time_t *) & im.TimeDateStamp)); return true; }
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; }
// 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; }
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; }
BOOL MapAndLoadW(LPWSTR imgPath, PLOADED_IMAGE lpImg) { wchar_t lpImgPathW[MAX_PATH+1] = L""; char lpImgPathA[MAX_PATH+1] = "", lpImgNameA[MAX_PATH+1] = "", lpImgDirA[MAX_PATH+1] = ""; size_t szDllPathW; if(_wfullpath(lpImgPathW, (LPCWSTR)imgPath, MAX_PATH) == NULL) return FALSE; if((szDllPathW = wcslen(lpImgPathW)) == 0) return FALSE; if(wcstombs(lpImgPathA, (LPCWSTR)lpImgPathW, szDllPathW) == -1) return FALSE; strcpy(lpImgNameA ,(LPCSTR)(strrchr(lpImgPathA, '\\') + 1)); *(strrchr(lpImgPathA, '\\')) = '\0'; strcpy(lpImgDirA, (LPCSTR)lpImgPathA); return MapAndLoad(lpImgNameA, lpImgDirA, lpImg, FALSE, TRUE); }
void initializeFSM() { LOADED_IMAGE image; PSTR imageFilename; //imageFilename = argv[1]; //imageFilename = "test_short_instruction.exe"; //imageFilename = "test_prefix.exe"; //imageFilename = "prefix_4_opcode_1.exe"; imageFilename = "prefix_2_opcode_1_modRM_SIB_imm.exe"; //imageFilename = "opcode_1_modRM_SIB_imm.exe"; if (!MapAndLoad(imageFilename, NULL, &image, FALSE, TRUE)) { PRINT_ERROR("MapAndLoad", __FILE__, __LINE__); return; } g_va = ImageRvaToVa(image.FileHeader, image.MappedAddress, image.FileHeader->OptionalHeader.BaseOfCode, NULL); }
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); }
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; }
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; }
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); }