void VDMInject32(HANDLE hProcess, unsigned int hwnd, const GUID* from) { TCHAR szPath[MAX_PATH] = {0}; GetPreferredModuleName(g_hModule, true, szPath); // construct arguments auto shared = VirtualAllocEx(hProcess, nullptr, sizeof(VDM::Shared32), MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, RVA(shared, AddressOf(VDM::Shared32, hwnd)), &hwnd, sizeof(HWND), nullptr); WriteProcessMemory(hProcess, RVA(shared, AddressOf(VDM::Shared32, guid)), from, sizeof(*from), nullptr); MODULEINFO kernel32; GetRemoteModuleInfo(hProcess, _T("kernel32.dll"), &kernel32, true); auto fnLoadLibrary = GetRemoteProcAddress(hProcess, (HMODULE)kernel32.lpBaseOfDll, "LoadLibraryW", true); auto remote = VirtualAllocEx(hProcess, nullptr, _countof(szPath), MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProcess, remote, szPath, _countof(szPath), nullptr); CallOnRemoteThread(hProcess, fnLoadLibrary, remote); MODULEINFO vdmhelper; GetRemoteModuleInfo(hProcess, _T("VDMHelper32.dll"), &vdmhelper, true); auto fnVDMProcess = GetRemoteProcAddress(hProcess, (HMODULE)vdmhelper.lpBaseOfDll, "VDMProcess", true); CallOnRemoteThread(hProcess, fnVDMProcess, shared); auto fnFreeLibrary = GetRemoteProcAddress(hProcess, (HMODULE)kernel32.lpBaseOfDll, "FreeLibrary", true); CallOnRemoteThread(hProcess, fnFreeLibrary, vdmhelper.lpBaseOfDll); VirtualFreeEx(hProcess, remote, 0, MEM_RELEASE); VirtualFreeEx(hProcess, shared, 0, MEM_RELEASE); }
NTSTATUS NTAPI LdrPEProcessImportDirectoryEntry(PVOID DriverBase, PLOADER_MODULE LoaderModule, PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory) { PVOID* ImportAddressList; PULONG FunctionNameList; if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0) { return STATUS_UNSUCCESSFUL; } /* Get the import address list. */ ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk); /* Get the list of functions to import. */ if (ImportModuleDirectory->OriginalFirstThunk != 0) { FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk); } else { FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk); } /* Walk through function list and fixup addresses. */ while (*FunctionNameList != 0L) { if ((*FunctionNameList) & 0x80000000) { DbgPrint("Failed to import ordinal from %s\n", LoaderModule->String); return STATUS_UNSUCCESSFUL; } else { IMAGE_IMPORT_BY_NAME *pe_name; pe_name = RVA(DriverBase, *FunctionNameList); *ImportAddressList = LdrPEGetExportByName((PVOID)LoaderModule->ModStart, pe_name->Name, pe_name->Hint); /* Fixup the address to be virtual */ *ImportAddressList = (PVOID)(ULONG_PTR)*ImportAddressList + (ULONG_PTR)KernelBase - (ULONG_PTR)KernelMemory; //DbgPrint("Looked for: %s and found: %x\n", pe_name->Name, *ImportAddressList); if ((*ImportAddressList) == NULL) { DbgPrint("Failed to import %s from %s\n", pe_name->Name, LoaderModule->String); return STATUS_UNSUCCESSFUL; } } ImportAddressList++; FunctionNameList++; } return STATUS_SUCCESS; }
void eterm_show(int m, cmulti **x, func_t *fF, int bmax, int kappa) { int kmax,k,db=64; int *b=NULL,tau; func_t *fJ=NULL; cmulti **y=NULL; rmulti **e=NULL,**eps=NULL,**em=NULL,**r=NULL,*rmax=NULL,**p=NULL; kmax=(bmax-64)/db; if(kmax<0){ kmax=2; } tau=cvec_get_exp_max(m,x); printf("tau=%d\n",tau); fJ=func_grad(func_retain(fF),func_var1_list(m)); CVA(y,m); RVA(e,kmax); RVA(eps,kmax); RVA(em,kmax); RVA(r,kmax); RVA(p,kmax); RA(rmax); b=ivec_allocate(kmax); b[0]=53; for(k=1; k<kmax; k++){ b[k]=(k-1)*db+64; } for(k=0; k<kmax; k++){ printf("b=%4d ",b[k]); set_default_prec(b[k]); rset_d(eps[k],1); rmul_2exp(eps[k],eps[k],-b[k]+tau); mpfr_printf("2^(-b+tau)=%8.1Re ",eps[k]); cvec_round(m,y,b[k]); csolve_newton_map(m,y,x,fF,fJ); csolve_newton_e_norm(e[k],m,y,x,fF,fJ,bmax*4); if(rgt(eps[k],e[k])){ printf("> "); }else{ printf("< "); } mpfr_printf("e=%8.1Re ",e[k]); rset_d(em[k],1); rmul_2exp(em[k],em[k],-b[k]+tau+kappa); if(rgt(e[k],em[k])){ printf("> "); }else{ printf("< "); } mpfr_printf("em=%8.1Re ",em[k]); rlog2(p[k],e[k]); rsub_d1(p[k],tau,p[k]); rsub_d1(p[k],b[k],p[k]); mpfr_printf("b-tau+log2(e)=%+6.2Rf ",p[k]); rlog2(r[k],e[k]); rsub_d1(r[k],tau,r[k]); rdiv_d2(r[k],r[k],b[k]); rsub_d1(r[k],1,r[k]); mpfr_printf("κ=1-(tau-log2(e))/b=%+.10Rf ",r[k]); printf("\n"); } rvec_max(rmax,kmax,p); mpfr_printf("cancel bits=%+.2Rf\n",rmax); rvec_max(rmax,kmax,r); mpfr_printf("κ_max=%+.10Rf\n",rmax); // done fJ=func_del(fJ); b=ivec_free(b); CVF(y,m); RVF(e,kmax); RVF(eps,kmax); RVF(em,kmax); RVF(r,kmax); RVF(p,kmax); RF(rmax); }
const char * PE_FindNearFunctionName( WINE_MODREF *wm, FARPROC funcAddr ) { unsigned short * ordinal; unsigned long * function; unsigned char ** name; const char *ename = NULL; int i, j; PE_MODREF *pem = &(wm->binfmt.pe); IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export; unsigned int load_addr = wm->module; unsigned long rva_start, rva_end, addr; char * forward; if (!exports) { /* Not a fatal problem, some apps do * GetProcAddress(0,"RegisterPenApp") which triggers this * case. */ WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem); return NULL; } ordinal= (unsigned short*) RVA(exports->AddressOfNameOrdinals); function= (unsigned long*) RVA(exports->AddressOfFunctions); name = (unsigned char **) RVA(exports->AddressOfNames); forward = NULL; rva_start = PE_HEADER(wm->module)->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; void *last_func = 0; for (j = 0; j < exports->NumberOfNames; j++) { int index = ordinal[j]; //printf("%p %p %s\n", function[index], funcAddr, RVA(name[j])); if(((void*)last_func >= funcAddr-load_addr ) && ((void*)function[index] < funcAddr-load_addr ) ) return (char*)RVA(name[j-1]); last_func = function[index]; } //printf("PE_FindFunctionName: could not resolve %p\n", funcAddr); return 0; }
static void dump_exports (HMODULE hModule) { #if 0 char *Module; int i, j; u_short *ordinal; u_long *function, *functions; u_char **name; unsigned int load_addr = hModule; DWORD rva_start = PE_HEADER (hModule)-> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; DWORD rva_end = rva_start + PE_HEADER (hModule)-> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY *) RVA (rva_start); Module = (char *) RVA (pe_exports->Name); TRACE ("*******EXPORT DATA*******\n"); TRACE ("Module name is %s, %ld functions, %ld names\n", Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames); ordinal = (u_short *) RVA (pe_exports->AddressOfNameOrdinals); functions = function = (u_long *) RVA (pe_exports->AddressOfFunctions); name = (u_char **) RVA (pe_exports->AddressOfNames); TRACE (" Ord RVA Addr Name\n"); for (i = 0; i < pe_exports->NumberOfFunctions; i++, function++) { if (!*function) continue; if (TRACE_ON (win32)) { DPRINTF ("%4ld %08lx %p", i + pe_exports->Base, *function, RVA (*function)); for (j = 0; j < pe_exports->NumberOfNames; j++) if (ordinal[j] == i) { DPRINTF (" %s", (char *) RVA (name[j])); break; } if ((*function >= rva_start) && (*function <= rva_end)) DPRINTF (" (forwarded -> %s)", (char *) RVA (*function)); DPRINTF ("\n"); } } #endif }
static const void *get_dir_and_size(unsigned int idx, unsigned int *size) { if(PE_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { const IMAGE_OPTIONAL_HEADER64 *opt = (const IMAGE_OPTIONAL_HEADER64*)&PE_nt_headers->OptionalHeader; if (idx >= opt->NumberOfRvaAndSizes) return NULL; if(size) *size = opt->DataDirectory[idx].Size; return RVA(opt->DataDirectory[idx].VirtualAddress, opt->DataDirectory[idx].Size); } else { const IMAGE_OPTIONAL_HEADER32 *opt = (const IMAGE_OPTIONAL_HEADER32*)&PE_nt_headers->OptionalHeader; if (idx >= opt->NumberOfRvaAndSizes) return NULL; if(size) *size = opt->DataDirectory[idx].Size; return RVA(opt->DataDirectory[idx].VirtualAddress, opt->DataDirectory[idx].Size); } }
static void do_relocations (unsigned int load_addr, IMAGE_BASE_RELOCATION * r) { int delta = load_addr - PE_HEADER (load_addr)->OptionalHeader.ImageBase; int hdelta = (delta >> 16) & 0xFFFF; int ldelta = delta & 0xFFFF; if (delta == 0) return; while (r->VirtualAddress) { char *page = (char *) RVA (r->VirtualAddress); int count = (r->SizeOfBlock - 8) / 2; int i; /* TRACE_(fixup)("%x relocations for page %lx\n", count, r->VirtualAddress); */ for (i = 0; i < count; i++) { int offset = r->TypeOffset[i] & 0xFFF; int type = r->TypeOffset[i] >> 12; //TRACE_(fixup)("patching %x type %x\n", offset, type); switch (type) { case IMAGE_REL_BASED_ABSOLUTE: break; case IMAGE_REL_BASED_HIGH: *(short *) (page + offset) += hdelta; break; case IMAGE_REL_BASED_LOW: *(short *) (page + offset) += ldelta; break; case IMAGE_REL_BASED_HIGHLOW: *(int *) (page + offset) += delta; break; case IMAGE_REL_BASED_HIGHADJ: FIXME ("Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n"); break; case IMAGE_REL_BASED_MIPS_JMPADDR: FIXME ("Is this a MIPS machine ???\n"); break; default: FIXME ("Unknown fixup type\n"); break; } } r = (IMAGE_BASE_RELOCATION *) ((char *) r + r->SizeOfBlock); } }
static tCLIFile* LoadPEFile(void *pData) { tCLIFile *pRet = TMALLOC(tCLIFile); unsigned char *pMSDOSHeader = (unsigned char*)&(((unsigned char*)pData)[0]); unsigned char *pPEHeader; unsigned char *pPEOptionalHeader; unsigned char *pPESectionHeaders; unsigned char *pCLIHeader; unsigned char *pRawMetaData; int i; unsigned int lfanew; unsigned short machine; int numSections; unsigned int imageBase; int fileAlignment; unsigned int cliHeaderRVA, cliHeaderSize; unsigned int metaDataRVA, metaDataSize; tMetaData *pMetaData; pRet->pRVA = RVA(); pRet->pMetaData = pMetaData = MetaData(); lfanew = *(unsigned int*)&(pMSDOSHeader[0x3c]); pPEHeader = pMSDOSHeader + lfanew + 4; pPEOptionalHeader = pPEHeader + 20; pPESectionHeaders = pPEOptionalHeader + 224; machine = *(unsigned short*)&(pPEHeader[0]); if (machine != DOT_NET_MACHINE) { return NULL; } numSections = *(unsigned short*)&(pPEHeader[2]); imageBase = *(unsigned int*)&(pPEOptionalHeader[28]); fileAlignment = *(int*)&(pPEOptionalHeader[36]); for (i=0; i<numSections; i++) { unsigned char *pSection = pPESectionHeaders + i * 40; RVA_Create(pRet->pRVA, pData, pSection); } cliHeaderRVA = *(unsigned int*)&(pPEOptionalHeader[208]); cliHeaderSize = *(unsigned int*)&(pPEOptionalHeader[212]); pCLIHeader = RVA_FindData(pRet->pRVA, cliHeaderRVA); metaDataRVA = *(unsigned int*)&(pCLIHeader[8]); metaDataSize = *(unsigned int*)&(pCLIHeader[12]); pRet->entryPoint = *(unsigned int*)&(pCLIHeader[20]); pRawMetaData = RVA_FindData(pRet->pRVA, metaDataRVA); // Load all metadata { unsigned int versionLen = *(unsigned int*)&(pRawMetaData[12]); unsigned int ofs, numberOfStreams; void *pTableStream = NULL; unsigned int tableStreamSize; pRet->pVersion = &(pRawMetaData[16]); log_f(1, "CLI version: %s\n", pRet->pVersion); ofs = 16 + versionLen; numberOfStreams = *(unsigned short*)&(pRawMetaData[ofs + 2]); ofs += 4; for (i=0; i<(signed)numberOfStreams; i++) { unsigned int streamOffset = *(unsigned int*)&pRawMetaData[ofs]; unsigned int streamSize = *(unsigned int*)&pRawMetaData[ofs+4]; unsigned char *pStreamName = &pRawMetaData[ofs+8]; void *pStream = pRawMetaData + streamOffset; ofs += (unsigned int)((strlen(pStreamName)+4) & (~0x3)) + 8; if (strcasecmp(pStreamName, "#Strings") == 0) { MetaData_LoadStrings(pMetaData, pStream, streamSize); } else if (strcasecmp(pStreamName, "#US") == 0) { MetaData_LoadUserStrings(pMetaData, pStream, streamSize); } else if (strcasecmp(pStreamName, "#Blob") == 0) { MetaData_LoadBlobs(pMetaData, pStream, streamSize); } else if (strcasecmp(pStreamName, "#GUID") == 0) { MetaData_LoadGUIDs(pMetaData, pStream, streamSize); } else if (strcasecmp(pStreamName, "#~") == 0) { pTableStream = pStream; tableStreamSize = streamSize; } } // Must load tables last if (pTableStream != NULL) { MetaData_LoadTables(pMetaData, pRet->pRVA, pTableStream, tableStreamSize); } } // Mark all generic definition types and methods as such for (i=pMetaData->tables.numRows[MD_TABLE_GENERICPARAM]; i>0; i--) { tMD_GenericParam *pGenericParam; IDX_TABLE ownerIdx; pGenericParam = (tMD_GenericParam*)MetaData_GetTableRow (pMetaData, MAKE_TABLE_INDEX(MD_TABLE_GENERICPARAM, i)); ownerIdx = pGenericParam->owner; switch (TABLE_ID(ownerIdx)) { case MD_TABLE_TYPEDEF: { tMD_TypeDef *pTypeDef = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, ownerIdx); pTypeDef->isGenericDefinition = 1; } break; case MD_TABLE_METHODDEF: { tMD_MethodDef *pMethodDef = (tMD_MethodDef*)MetaData_GetTableRow(pMetaData, ownerIdx); pMethodDef->isGenericDefinition = 1; } break; default: Crash("Wrong generic parameter owner: 0x%08x", ownerIdx); } } // Mark all nested classes as such for (i=pMetaData->tables.numRows[MD_TABLE_NESTEDCLASS]; i>0; i--) { tMD_NestedClass *pNested; tMD_TypeDef *pParent, *pChild; pNested = (tMD_NestedClass*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_NESTEDCLASS, i)); pParent = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, pNested->enclosingClass); pChild = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, pNested->nestedClass); pChild->pNestedIn = pParent; } return pRet; }
/*********************************************************************** * LoadLibraryExA (KERNEL32) */ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags) { WINE_MODREF *wm = 0; char* listpath[] = { "", "", "/usr/lib/win32", "/usr/local/lib/win32", 0 }; extern char* def_path; char path[512]; char checked[2000]; int i = -1; checked[0] = 0; if(!libname) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } wm=MODULE_FindModule(libname); if(wm) return wm->module; // if(fs_installed==0) // install_fs(); while (wm == 0 && listpath[++i]) { if (i < 2) { if (i == 0) /* check just original file name */ strncpy(path, libname, 511); else /* check default user path */ strncpy(path, def_path, 300); } else if (strcmp(def_path, listpath[i])) /* path from the list */ strncpy(path, listpath[i], 300); else continue; if (i > 0) { strcat(path, "/"); strncat(path, libname, 100); } path[511] = 0; wm = MODULE_LoadLibraryExA( path, hfile, flags ); if (!wm) { if (checked[0]) strcat(checked, ", "); strcat(checked, path); checked[1500] = 0; } } if ( wm ) { if ( !MODULE_DllProcessAttach( wm, NULL ) ) { WARN_(module)("Attach failed for module '%s', \n", libname); MODULE_FreeLibrary(wm); SetLastError(ERROR_DLL_INIT_FAILED); MODULE_RemoveFromList(wm); wm = NULL; } } if (!wm) printf("Win32 LoadLibrary failed to load: %s\n", checked); #define RVA(x) ((char *)wm->module+(unsigned int)(x)) if (strstr(libname,"vp31vfw.dll") && wm) { int i; // sse hack moved from patch dll into runtime patching if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==RVA(0x1000)) { fprintf(stderr, "VP3 DLL found\n"); for (i=0;i<18;i++) RVA(0x4bd6)[i]=0x90; } } // remove a few divs in the VP codecs that make trouble if (strstr(libname,"vp5vfw.dll") && wm) { int i; if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==RVA(0x3930)) { for (i=0;i<3;i++) RVA(0x4e86)[i]=0x90; for (i=0;i<3;i++) RVA(0x5a23)[i]=0x90; for (i=0;i<3;i++) RVA(0x5bff)[i]=0x90; } else { fprintf(stderr, "Unsupported VP5 version\n"); return 0; } } if (strstr(libname,"vp6vfw.dll") && wm) { int i; if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==RVA(0x3ef0)) { // looks like VP 6.1.0.2 for (i=0;i<6;i++) RVA(0x7268)[i]=0x90; for (i=0;i<6;i++) RVA(0x7e83)[i]=0x90; for (i=0;i<6;i++) RVA(0x806a)[i]=0x90; } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==RVA(0x4120)) { // looks like VP 6.2.0.10 for (i=0;i<6;i++) RVA(0x7688)[i]=0x90; for (i=0;i<6;i++) RVA(0x82c3)[i]=0x90; for (i=0;i<6;i++) RVA(0x84aa)[i]=0x90; for (i=0;i<6;i++) RVA(0x1d2cc)[i]=0x90; for (i=0;i<6;i++) RVA(0x2179d)[i]=0x90; for (i=0;i<6;i++) RVA(0x1977f)[i]=0x90; } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==RVA(0x3e70)) { // looks like VP 6.0.7.3 for (i=0;i<6;i++) RVA(0x7559)[i]=0x90; for (i=0;i<6;i++) RVA(0x81c3)[i]=0x90; for (i=0;i<6;i++) RVA(0x839e)[i]=0x90; } else { fprintf(stderr, "Unsupported VP6 version\n"); return 0; } } // Windows Media Video 9 Advanced if (strstr(libname,"wmvadvd.dll") && wm) { // The codec calls IsRectEmpty with coords 0,0,0,0 => result is 0 // but it really wants the rectangle to be not empty if (PE_FindExportedFunction(wm, "CreateInstance", TRUE)==RVA(0xb812)) { // Dll version is 10.0.0.3645 *RVA(0x8b0f)=0xeb; // Jump always, ignoring IsRectEmpty result } else { fprintf(stderr, "Unsupported WMVA version\n"); return 0; } } if (strstr(libname,"QuickTime.qts") && wm) { void** ptr; void *dispatch_addr; int i; // dispatch_addr = GetProcAddress(wm->module, "theQuickTimeDispatcher", TRUE); dispatch_addr = PE_FindExportedFunction(wm, "theQuickTimeDispatcher", TRUE); if (dispatch_addr == RVA(0x124c30)) { fprintf(stderr, "QuickTime5 DLLs found\n"); ptr = (void **)RVA(0x375ca4); // dispatch_ptr for (i=0;i<5;i++) RVA(0x19e842)[i]=0x90; // make_new_region ? for (i=0;i<28;i++) RVA(0x19e86d)[i]=0x90; // call__call_CreateCompatibleDC ? for (i=0;i<5;i++) RVA(0x19e898)[i]=0x90; // jmp_to_call_loadbitmap ? for (i=0;i<9;i++) RVA(0x19e8ac)[i]=0x90; // call__calls_OLE_shit ? for (i=0;i<106;i++) RVA(0x261b10)[i]=0x90; // disable threads #if 0 /* CreateThread callers */ for (i=0;i<5;i++) RVA(0x1487c5)[i]=0x90; for (i=0;i<5;i++) RVA(0x14b275)[i]=0x90; for (i=0;i<5;i++) RVA(0x1a24b1)[i]=0x90; for (i=0;i<5;i++) RVA(0x1afc5a)[i]=0x90; for (i=0;i<5;i++) RVA(0x2f799c)[i]=0x90; for (i=0;i<5;i++) RVA(0x2f7efe)[i]=0x90; for (i=0;i<5;i++) RVA(0x2fa33e)[i]=0x90; #endif #if 0 /* TerminateQTML fix */ for (i=0;i<47;i++) RVA(0x2fa3b8)[i]=0x90; // terminate thread for (i=0;i<47;i++) RVA(0x2f7f78)[i]=0x90; // terminate thread for (i=0;i<77;i++) RVA(0x1a13d5)[i]=0x90; RVA(0x08e0ae)[0] = 0xc3; // font/dc remover for (i=0;i<24;i++) RVA(0x07a1ad)[i]=0x90; // destroy window #endif } else if (dispatch_addr == RVA(0x13b330)) { fprintf(stderr, "QuickTime6 DLLs found\n"); ptr = (void **)RVA(0x3b9524); // dispatcher_ptr for (i=0;i<5;i++) RVA(0x2730cc)[i]=0x90; // make_new_region for (i=0;i<28;i++) RVA(0x2730f7)[i]=0x90; // call__call_CreateCompatibleDC for (i=0;i<5;i++) RVA(0x273122)[i]=0x90; // jmp_to_call_loadbitmap for (i=0;i<9;i++) RVA(0x273131)[i]=0x90; // call__calls_OLE_shit for (i=0;i<96;i++) RVA(0x2ac852)[i]=0x90; // disable threads } else if (dispatch_addr == RVA(0x13c3e0)) { fprintf(stderr, "QuickTime6.3 DLLs found\n"); ptr = (void **)RVA(0x3ca01c); // dispatcher_ptr for (i=0;i<5;i++) RVA(0x268f6c)[i]=0x90; // make_new_region for (i=0;i<28;i++) RVA(0x268f97)[i]=0x90; // call__call_CreateCompatibleDC for (i=0;i<5;i++) RVA(0x268fc2)[i]=0x90; // jmp_to_call_loadbitmap for (i=0;i<9;i++) RVA(0x268fd1)[i]=0x90; // call__calls_OLE_shit for (i=0;i<96;i++) RVA(0x2b4722)[i]=0x90; // disable threads } else { fprintf(stderr, "Unsupported QuickTime version (%p)\n", dispatch_addr); return 0; } fprintf(stderr,"QuickTime.qts patched!!! old entry=%p\n",ptr[0]); #ifdef EMU_QTX_API report_entry = report_func; report_ret = report_func_ret; wrapper_target=ptr[0]; ptr[0]=wrapper; #endif } #undef RVA return wm ? wm->module : 0; }
static BOOLEAN WinLdrpBindImportName(IN OUT PLIST_ENTRY ModuleListHead, IN PVOID DllBase, IN PVOID ImageBase, IN PIMAGE_THUNK_DATA ThunkData, IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, IN ULONG ExportSize, IN BOOLEAN ProcessForwards, IN PCSTR DirectoryPath) { ULONG Ordinal; PULONG NameTable, FunctionTable; PUSHORT OrdinalTable; LONG High, Low, Middle, Result; ULONG Hint; PIMAGE_IMPORT_BY_NAME ImportData; PCHAR ExportName, ForwarderName; BOOLEAN Success; //TRACE("WinLdrpBindImportName(): DllBase 0x%X, ImageBase 0x%X, ThunkData 0x%X, ExportDirectory 0x%X, ExportSize %d, ProcessForwards 0x%X\n", // DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, ProcessForwards); /* Check passed DllBase param */ if(DllBase == NULL) { WARN("DllBase == NULL!\n"); return FALSE; } /* Convert all non-critical pointers to PA from VA */ ThunkData = VaToPa(ThunkData); /* Is the reference by ordinal? */ if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal) && !ProcessForwards) { /* Yes, calculate the ordinal */ Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkData->u1.Ordinal) - (UINT32)ExportDirectory->Base); //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal); } else { /* It's reference by name, we have to look it up in the export directory */ if (!ProcessForwards) { /* AddressOfData in thunk entry will become a virtual address (from relative) */ //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData); ThunkData->u1.AddressOfData = (ULONG_PTR)RVA(ImageBase, ThunkData->u1.AddressOfData); //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData); } /* Get the import name */ ImportData = VaToPa((PVOID)ThunkData->u1.AddressOfData); /* Get pointers to Name and Ordinal tables (RVA -> VA) */ NameTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames)); OrdinalTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNameOrdinals)); //TRACE("NameTable 0x%X, OrdinalTable 0x%X, ED->AddressOfNames 0x%X, ED->AOFO 0x%X\n", // NameTable, OrdinalTable, ExportDirectory->AddressOfNames, ExportDirectory->AddressOfNameOrdinals); /* Get the hint, convert it to a physical pointer */ Hint = ((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Hint; //TRACE("HintIndex %d\n", Hint); /* Get the export name from the hint */ ExportName = VaToPa(RVA(DllBase, NameTable[Hint])); /* If Hint is less than total number of entries in the export directory, and import name == export name, then we can just get it from the OrdinalTable */ if ((Hint < ExportDirectory->NumberOfNames) && (strcmp(ExportName, (PCHAR)ImportData->Name) == 0)) { Ordinal = OrdinalTable[Hint]; //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal); } else { /* It's not the easy way, we have to lookup import name in the name table. Let's use a binary search for this task. */ //TRACE("WinLdrpBindImportName() looking up the import name using binary search...\n"); /* Low boundary is set to 0, and high boundary to the maximum index */ Low = 0; High = ExportDirectory->NumberOfNames - 1; /* Perform a binary-search loop */ while (High >= Low) { /* Divide by 2 by shifting to the right once */ Middle = (Low + High) / 2; /* Get the name from the name table */ ExportName = VaToPa(RVA(DllBase, NameTable[Middle])); /* Compare the names */ Result = strcmp(ExportName, (PCHAR)ImportData->Name); /*TRACE("Binary search: comparing Import '__', Export '%s'\n",*/ /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/ /*(PCHAR)VaToPa(RVA(DllBase, NameTable[Middle])));*/ /*TRACE("TE->u1.AOD %p, fulladdr %p\n", ThunkData->u1.AddressOfData, ((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name );*/ /* Depending on result of strcmp, perform different actions */ if (Result > 0) { /* Adjust top boundary */ High = Middle - 1; } else if (Result < 0) { /* Adjust bottom boundary */ Low = Middle + 1; } else { /* Yay, found it! */ break; } } /* If high boundary is less than low boundary, then no result found */ if (High < Low) { //Print(L"Error in binary search\n"); ERR("Did not find export '%s'!\n", (PCHAR)ImportData->Name); return FALSE; } /* Everything alright, get the ordinal */ Ordinal = OrdinalTable[Middle]; //TRACE("WinLdrpBindImportName() found Ordinal %d\n", Ordinal); } } /* Check ordinal number for validity! */ if (Ordinal >= ExportDirectory->NumberOfFunctions) { ERR("Ordinal number is invalid!\n"); return FALSE; } /* Get a pointer to the function table */ FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions)); /* Save a pointer to the function */ ThunkData->u1.Function = (ULONG_PTR)RVA(DllBase, FunctionTable[Ordinal]); /* Is it a forwarder? (function pointer is within the export directory) */ ForwarderName = (PCHAR)VaToPa((PVOID)ThunkData->u1.Function); if (((ULONG_PTR)ForwarderName > (ULONG_PTR)ExportDirectory) && ((ULONG_PTR)ForwarderName < ((ULONG_PTR)ExportDirectory + ExportSize))) { PLDR_DATA_TABLE_ENTRY DataTableEntry; CHAR ForwardDllName[255]; PIMAGE_EXPORT_DIRECTORY RefExportDirectory; ULONG RefExportSize; TRACE("WinLdrpBindImportName(): ForwarderName %s\n", ForwarderName); /* Save the name of the forward dll */ RtlCopyMemory(ForwardDllName, ForwarderName, sizeof(ForwardDllName)); /* Strip out the symbol name */ *strrchr(ForwardDllName,'.') = '\0'; /* Check if the target image is already loaded */ if (!WinLdrCheckForLoadedDll(ModuleListHead, ForwardDllName, &DataTableEntry)) { /* Check if the forward dll name has an extension */ if (strchr(ForwardDllName, '.') == NULL) { /* Name does not have an extension, append '.dll' */ strcat(ForwardDllName, ".dll"); } /* Now let's try to load it! */ Success = WinLdrpLoadAndScanReferencedDll(ModuleListHead, DirectoryPath, ForwardDllName, &DataTableEntry); if (!Success) { ERR("WinLdrpLoadAndScanReferencedDll() failed to load forwarder dll.\n"); return Success; } } /* Get pointer to the export directory of loaded DLL */ RefExportDirectory = (PIMAGE_EXPORT_DIRECTORY) RtlImageDirectoryEntryToData(VaToPa(DataTableEntry->DllBase), TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &RefExportSize); /* Fail if it's NULL */ if (RefExportDirectory) { UCHAR Buffer[128]; IMAGE_THUNK_DATA RefThunkData; PIMAGE_IMPORT_BY_NAME ImportByName; PCHAR ImportName; /* Get pointer to the import name */ ImportName = strrchr(ForwarderName, '.') + 1; /* Create a IMAGE_IMPORT_BY_NAME structure, pointing to the local Buffer */ ImportByName = (PIMAGE_IMPORT_BY_NAME)Buffer; /* Fill the name with the import name */ RtlCopyMemory(ImportByName->Name, ImportName, strlen(ImportName)+1); /* Set Hint to 0 */ ImportByName->Hint = 0; /* And finally point ThunkData's AddressOfData to that structure */ RefThunkData.u1.AddressOfData = (ULONG_PTR)ImportByName; /* And recursively call ourselves */ Success = WinLdrpBindImportName(ModuleListHead, DataTableEntry->DllBase, ImageBase, &RefThunkData, RefExportDirectory, RefExportSize, TRUE, DirectoryPath); /* Fill out the ThunkData with data from RefThunkData */ ThunkData->u1 = RefThunkData.u1; /* Return what we got from the recursive call */ return Success; } else { /* Fail if ExportDirectory is NULL */ return FALSE; } } /* Success! */ return TRUE; }
BOOLEAN WinLdrScanImportDescriptorTable(IN OUT PLIST_ENTRY ModuleListHead, IN PCCH DirectoryPath, IN PLDR_DATA_TABLE_ENTRY ScanDTE) { PLDR_DATA_TABLE_ENTRY DataTableEntry; PIMAGE_IMPORT_DESCRIPTOR ImportTable; ULONG ImportTableSize; PCH ImportName; BOOLEAN Success; /* Get a pointer to the import table of this image */ ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(ScanDTE->DllBase), TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize); { UNICODE_STRING BaseName; BaseName.Buffer = VaToPa(ScanDTE->BaseDllName.Buffer); BaseName.MaximumLength = ScanDTE->BaseDllName.MaximumLength; BaseName.Length = ScanDTE->BaseDllName.Length; TRACE("WinLdrScanImportDescriptorTable(): %wZ ImportTable = 0x%X\n", &BaseName, ImportTable); } /* If image doesn't have any import directory - just return success */ if (ImportTable == NULL) return TRUE; /* Loop through all entries */ for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++) { /* Get pointer to the name */ ImportName = (PCH)VaToPa(RVA(ScanDTE->DllBase, ImportTable->Name)); TRACE("WinLdrScanImportDescriptorTable(): Looking at %s\n", ImportName); /* In case we get a reference to ourselves - just skip it */ if (WinLdrpCompareDllName(ImportName, &ScanDTE->BaseDllName)) continue; /* Load the DLL if it is not already loaded */ if (!WinLdrCheckForLoadedDll(ModuleListHead, ImportName, &DataTableEntry)) { Success = WinLdrpLoadAndScanReferencedDll(ModuleListHead, DirectoryPath, ImportName, &DataTableEntry); if (!Success) { ERR("WinLdrpLoadAndScanReferencedDll() failed\n"); return Success; } } /* Scan its import address table */ Success = WinLdrpScanImportAddressTable(ModuleListHead, DataTableEntry->DllBase, ScanDTE->DllBase, (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk), DirectoryPath); if (!Success) { ERR("WinLdrpScanImportAddressTable() failed: ImportName = '%s', DirectoryPath = '%s'\n", ImportName, DirectoryPath); return Success; } } return TRUE; }
/********************************************************************** * PE_CreateModule * * Create WINE_MODREF structure for loaded HMODULE32, link it into * process modref_list, and fixup all imports. * * Note: hModule must point to a correctly allocated PE image, * with base relocations applied; the 16-bit dummy module * associated to hModule must already exist. * * Note: This routine must always be called in the context of the * process that is to own the module to be created. */ WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename, DWORD flags, WIN_BOOL builtin ) { DWORD load_addr = (DWORD)hModule; IMAGE_NT_HEADERS *nt = PE_HEADER(hModule); IMAGE_DATA_DIRECTORY *dir; IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL; IMAGE_EXPORT_DIRECTORY *pe_export = NULL; IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL; WINE_MODREF *wm; dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT; if (dir->Size) pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT; if (dir->Size) pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE; if (dir->Size) pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION; if (dir->Size) FIXME("Exception directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY; if (dir->Size) FIXME("Security directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG; if (dir->Size) TRACE("Debug directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT; if (dir->Size) FIXME("Copyright string ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR; if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG; if (dir->Size) FIXME("Load Configuration directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT; if (dir->Size) TRACE("Bound Import directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT; if (dir->Size) TRACE("Import Address Table directory ignored\n" ); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT; if (dir->Size) { TRACE("Delayed import, stub calls LoadLibrary\n" ); /* * Nothing to do here. */ #ifdef ImgDelayDescr /* * This code is useful to observe what the heck is going on. */ { ImgDelayDescr *pe_delay = NULL; pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress); TRACE_(delayhlp)("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs); TRACE_(delayhlp)("pe_delay->szName = %s\n", pe_delay->szName); TRACE_(delayhlp)("pe_delay->phmod = %08x\n", pe_delay->phmod); TRACE_(delayhlp)("pe_delay->pIAT = %08x\n", pe_delay->pIAT); TRACE_(delayhlp)("pe_delay->pINT = %08x\n", pe_delay->pINT); TRACE_(delayhlp)("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT); TRACE_(delayhlp)("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT); TRACE_(delayhlp)("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp); } #endif } dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR; if (dir->Size) FIXME("Unknown directory 14 ignored\n" ); dir = nt->OptionalHeader.DataDirectory+15; if (dir->Size) FIXME("Unknown directory 15 ignored\n" ); wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wm) ); wm->module = hModule; if ( builtin ) wm->flags |= WINE_MODREF_INTERNAL; if ( flags & DONT_RESOLVE_DLL_REFERENCES ) wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS; if ( flags & LOAD_LIBRARY_AS_DATAFILE ) wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE; wm->type = MODULE32_PE; wm->binfmt.pe.pe_export = pe_export; wm->binfmt.pe.pe_import = pe_import; wm->binfmt.pe.pe_resource = pe_resource; wm->binfmt.pe.tlsindex = -1; wm->filename = malloc(strlen(filename)+1); strcpy(wm->filename, filename ); wm->modname = strrchr( wm->filename, '\\' ); if (!wm->modname) wm->modname = wm->filename; else wm->modname++; if ( pe_export ) dump_exports( hModule ); /* Fixup Imports */ if ( pe_import && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) && fixup_imports( wm ) ) { /* remove entry from modref chain */ return NULL; } return wm; }
BOOLEAN WinLdrAllocateDataTableEntry(IN OUT PLIST_ENTRY ModuleListHead, IN PCCH BaseDllName, IN PCCH FullDllName, IN PVOID BasePA, OUT PLDR_DATA_TABLE_ENTRY *NewEntry) { PVOID BaseVA = PaToVa(BasePA); PWSTR Buffer; PLDR_DATA_TABLE_ENTRY DataTableEntry; PIMAGE_NT_HEADERS NtHeaders; USHORT Length; TRACE("WinLdrAllocateDataTableEntry(, '%s', '%s', %p)\n", BaseDllName, FullDllName, BasePA); /* Allocate memory for a data table entry, zero-initialize it */ DataTableEntry = (PLDR_DATA_TABLE_ENTRY)FrLdrHeapAlloc(sizeof(LDR_DATA_TABLE_ENTRY), TAG_WLDR_DTE); if (DataTableEntry == NULL) return FALSE; RtlZeroMemory(DataTableEntry, sizeof(LDR_DATA_TABLE_ENTRY)); /* Get NT headers from the image */ NtHeaders = RtlImageNtHeader(BasePA); /* Initialize corresponding fields of DTE based on NT headers value */ DataTableEntry->DllBase = BaseVA; DataTableEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage; DataTableEntry->EntryPoint = RVA(BaseVA, NtHeaders->OptionalHeader.AddressOfEntryPoint); DataTableEntry->SectionPointer = 0; DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum; /* Initialize BaseDllName field (UNICODE_STRING) from the Ansi BaseDllName by simple conversion - copying each character */ Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR)); Buffer = (PWSTR)FrLdrHeapAlloc(Length, TAG_WLDR_NAME); if (Buffer == NULL) { FrLdrHeapFree(DataTableEntry, TAG_WLDR_DTE); return FALSE; } RtlZeroMemory(Buffer, Length); DataTableEntry->BaseDllName.Length = Length; DataTableEntry->BaseDllName.MaximumLength = Length; DataTableEntry->BaseDllName.Buffer = PaToVa(Buffer); while (*BaseDllName != 0) { *Buffer++ = *BaseDllName++; } /* Initialize FullDllName field (UNICODE_STRING) from the Ansi FullDllName using the same method */ Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR)); Buffer = (PWSTR)FrLdrHeapAlloc(Length, TAG_WLDR_NAME); if (Buffer == NULL) { FrLdrHeapFree(DataTableEntry, TAG_WLDR_DTE); return FALSE; } RtlZeroMemory(Buffer, Length); DataTableEntry->FullDllName.Length = Length; DataTableEntry->FullDllName.MaximumLength = Length; DataTableEntry->FullDllName.Buffer = PaToVa(Buffer); while (*FullDllName != 0) { *Buffer++ = *FullDllName++; } /* Initialize what's left - LoadCount which is 1, and set Flags so that we know this entry is processed */ DataTableEntry->Flags = LDRP_ENTRY_PROCESSED; DataTableEntry->LoadCount = 1; /* Insert this DTE to a list in the LPB */ InsertTailList(ModuleListHead, &DataTableEntry->InLoadOrderLinks); TRACE("Inserting DTE %p, name='%.*S' DllBase=%p \n", DataTableEntry, DataTableEntry->BaseDllName.Length / 2, VaToPa(DataTableEntry->BaseDllName.Buffer), DataTableEntry->DllBase); /* Save pointer to a newly allocated and initialized entry */ *NewEntry = DataTableEntry; /* Return success */ return TRUE; }
static DWORD fixup_imports( WINE_MODREF *wm ) { IMAGE_IMPORT_DESCRIPTOR *pe_imp; PE_MODREF *pem; unsigned int load_addr = wm->module; int i,characteristics_detection=1; char *modname; assert(wm->type==MODULE32_PE); pem = &(wm->binfmt.pe); if (pem->pe_export) modname = (char*) RVA(pem->pe_export->Name); else modname = "<unknown>"; TRACE("Dumping imports list\n"); pe_imp = pem->pe_import; if (!pe_imp) return 0; /* We assume that we have at least one import with !0 characteristics and * detect broken imports with all characteristsics 0 (notably Borland) and * switch the detection off for them. */ for (i = 0; pe_imp->Name ; pe_imp++) { if (!i && !pe_imp->u.Characteristics) characteristics_detection = 0; if (characteristics_detection && !pe_imp->u.Characteristics) break; i++; } if (!i) return 0; wm->nDeps = i; wm->deps = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) ); /* load the imported modules. They are automatically * added to the modref list of the process. */ for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) { IMAGE_IMPORT_BY_NAME *pe_name; PIMAGE_THUNK_DATA import_list,thunk_list; char *name = (char *) RVA(pe_imp->Name); if (characteristics_detection && !pe_imp->u.Characteristics) break; /* FIXME: here we should fill imports */ TRACE("Loading imports for %s.dll\n", name); if (pe_imp->u.OriginalFirstThunk != 0) { TRACE("Microsoft style imports used\n"); import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk); thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk); while (import_list->u1.Ordinal) { if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) { int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal); // TRACE("--- Ordinal %s,%d\n", name, ordinal); thunk_list->u1.Function=LookupExternal(name, ordinal); } else { pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData); // TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint); thunk_list->u1.Function=LookupExternalByName(name, pe_name->Name); } import_list++; thunk_list++; } } else { TRACE("Borland style imports used\n"); thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk); while (thunk_list->u1.Ordinal) { if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) { int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal); TRACE("--- Ordinal %s.%d\n",name,ordinal); thunk_list->u1.Function=LookupExternal( name, ordinal); } else { pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData); TRACE("--- %s %s.%d\n", pe_name->Name,name,pe_name->Hint); thunk_list->u1.Function=LookupExternalByName( name, pe_name->Name); } thunk_list++; } } } return 0; }
/********************************************************************** * PE_LoadImage * Load one PE format DLL/EXE into memory * * Unluckily we can't just mmap the sections where we want them, for * (at least) Linux does only support offsets which are page-aligned. * * BUT we have to map the whole image anyway, for Win32 programs sometimes * want to access them. (HMODULE32 point to the start of it) */ HMODULE PE_LoadImage( int handle, LPCSTR filename, WORD *version ) { HMODULE hModule; HANDLE mapping; IMAGE_NT_HEADERS *nt; IMAGE_SECTION_HEADER *pe_sec; IMAGE_DATA_DIRECTORY *dir; // BY_HANDLE_FILE_INFORMATION bhfi; int i, rawsize, lowest_va, vma_size, file_size = 0; DWORD load_addr = 0, aoep, reloc = 0; // struct get_read_fd_request *req = get_req_buffer(); int unix_handle = handle; int page_size = getpagesize(); // if ( GetFileInformationByHandle( hFile, &bhfi ) ) // file_size = bhfi.nFileSizeLow; file_size=lseek(handle, 0, SEEK_END); lseek(handle, 0, SEEK_SET); // fix CreateFileMappingA mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL ); if (!mapping) { WARN("CreateFileMapping error %ld\n", GetLastError() ); return 0; } // hModule = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); hModule=(HMODULE)mapping; // CloseHandle( mapping ); if (!hModule) { WARN("MapViewOfFile error %ld\n", GetLastError() ); return 0; } if ( *(WORD*)hModule !=IMAGE_DOS_SIGNATURE) { WARN("%s image doesn't have DOS signature, but 0x%04x\n", filename,*(WORD*)hModule); goto error; } nt = PE_HEADER( hModule ); if ( nt->Signature != IMAGE_NT_SIGNATURE ) { WARN("%s image doesn't have PE signature, but 0x%08lx\n", filename, nt->Signature ); goto error; } if ( nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 ) { dbg_printf("Trying to load PE image for unsupported architecture ("); switch (nt->FileHeader.Machine) { case IMAGE_FILE_MACHINE_UNKNOWN: dbg_printf("Unknown"); break; case IMAGE_FILE_MACHINE_I860: dbg_printf("I860"); break; case IMAGE_FILE_MACHINE_R3000: dbg_printf("R3000"); break; case IMAGE_FILE_MACHINE_R4000: dbg_printf("R4000"); break; case IMAGE_FILE_MACHINE_R10000: dbg_printf("R10000"); break; case IMAGE_FILE_MACHINE_ALPHA: dbg_printf("Alpha"); break; case IMAGE_FILE_MACHINE_POWERPC: dbg_printf("PowerPC"); break; default: dbg_printf("Unknown-%04x", nt->FileHeader.Machine); break; } dbg_printf(")\n"); goto error; } pe_sec = PE_SECTIONS( hModule ); rawsize = 0; lowest_va = 0x10000; for (i = 0; i < nt->FileHeader.NumberOfSections; i++) { if (lowest_va > pe_sec[i].VirtualAddress) lowest_va = pe_sec[i].VirtualAddress; if (pe_sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) continue; if (pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData > rawsize) rawsize = pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData; } if ( file_size && file_size < rawsize ) { ERR("PE module is too small (header: %d, filesize: %d), " "probably truncated download?\n", rawsize, file_size ); goto error; } aoep = nt->OptionalHeader.AddressOfEntryPoint; if (aoep && (aoep < lowest_va)) FIXME("VIRUS WARNING: '%s' has an invalid entrypoint (0x%08lx) " "below the first virtual address (0x%08x) " "(possibly infected by Tchernobyl/SpaceFiller virus)!\n", filename, aoep, lowest_va ); /* FIXME: Hack! While we don't really support shared sections yet, * this checks for those special cases where the whole DLL * consists only of shared sections and is mapped into the * shared address space > 2GB. In this case, we assume that * the module got mapped at its base address. Thus we simply * check whether the module has actually been mapped there * and use it, if so. This is needed to get Win95 USER32.DLL * to work (until we support shared sections properly). */ if ( nt->OptionalHeader.ImageBase & 0x80000000 && !strstr(filename, "xanlib.dll")) { HMODULE sharedMod = (HMODULE)nt->OptionalHeader.ImageBase; IMAGE_NT_HEADERS *sharedNt = (PIMAGE_NT_HEADERS) ( (LPBYTE)sharedMod + ((LPBYTE)nt - (LPBYTE)hModule) ); /* Well, this check is not really comprehensive, but should be good enough for now ... */ if ( !IsBadReadPtr( (LPBYTE)sharedMod, sizeof(IMAGE_DOS_HEADER) ) && memcmp( (LPBYTE)sharedMod, (LPBYTE)hModule, sizeof(IMAGE_DOS_HEADER) ) == 0 && !IsBadReadPtr( sharedNt, sizeof(IMAGE_NT_HEADERS) ) && memcmp( sharedNt, nt, sizeof(IMAGE_NT_HEADERS) ) == 0 ) { UnmapViewOfFile( (LPVOID)hModule ); return sharedMod; } } load_addr = nt->OptionalHeader.ImageBase; vma_size = calc_vma_size( hModule ); load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if (load_addr == 0) { FIXME("We need to perform base relocations for %s\n", filename); dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC; if (dir->Size) reloc = dir->VirtualAddress; else { FIXME( "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\n", filename, (nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)? "stripped during link" : "unknown reason" ); goto error; } /* FIXME: If we need to relocate a system DLL (base > 2GB) we should * really make sure that the *new* base address is also > 2GB. * Some DLLs really check the MSB of the module handle :-/ */ if ( nt->OptionalHeader.ImageBase & 0x80000000 ) ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" ); load_addr = (DWORD)VirtualAlloc( NULL, vma_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if (!load_addr) { FIXME_(win32)( "FATAL: Couldn't load module %s (out of memory, %d needed)!\n", filename, vma_size); goto error; } } TRACE("Load addr is %lx (base %lx), range %x\n", load_addr, nt->OptionalHeader.ImageBase, vma_size ); TRACE_(segment)("Loading %s at %lx, range %x\n", filename, load_addr, vma_size ); #if 0 *(PIMAGE_DOS_HEADER)load_addr = *(PIMAGE_DOS_HEADER)hModule; *PE_HEADER( load_addr ) = *nt; memcpy( PE_SECTIONS(load_addr), PE_SECTIONS(hModule), sizeof(IMAGE_SECTION_HEADER) * nt->FileHeader.NumberOfSections ); memcpy( load_addr, hModule, lowest_fa ); #endif if ((void*)FILE_dommap( handle, (void *)load_addr, 0, nt->OptionalHeader.SizeOfHeaders, 0, 0, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_FIXED ) != (void*)load_addr) { ERR_(win32)( "Critical Error: failed to map PE header to necessary address.\n"); goto error; } pe_sec = PE_SECTIONS( hModule ); for (i = 0; i < nt->FileHeader.NumberOfSections; i++, pe_sec++) { if (!pe_sec->SizeOfRawData || !pe_sec->PointerToRawData) continue; TRACE("%s: mmaping section %s at %p off %lx size %lx/%lx\n", filename, pe_sec->Name, (void*)RVA(pe_sec->VirtualAddress), pe_sec->PointerToRawData, pe_sec->SizeOfRawData, pe_sec->Misc.VirtualSize ); if ((void*)FILE_dommap( unix_handle, (void*)RVA(pe_sec->VirtualAddress), 0, pe_sec->SizeOfRawData, 0, pe_sec->PointerToRawData, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_FIXED ) != (void*)RVA(pe_sec->VirtualAddress)) { ERR_(win32)( "Critical Error: failed to map PE section to necessary address.\n"); goto error; } if ((pe_sec->SizeOfRawData < pe_sec->Misc.VirtualSize) && (pe_sec->SizeOfRawData & (page_size-1))) { DWORD end = (pe_sec->SizeOfRawData & ~(page_size-1)) + page_size; if (end > pe_sec->Misc.VirtualSize) end = pe_sec->Misc.VirtualSize; TRACE("clearing %p - %p\n", RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, RVA(pe_sec->VirtualAddress) + end ); memset( (char*)RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, 0, end - pe_sec->SizeOfRawData ); } } if ( reloc ) do_relocations( load_addr, (IMAGE_BASE_RELOCATION *)RVA(reloc) ); *version = ( (nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) | (nt->OptionalHeader.MinorSubsystemVersion & 0xff); UnmapViewOfFile( (LPVOID)hModule ); return (HMODULE)load_addr; error: if (unix_handle != -1) close( unix_handle ); if (load_addr) VirtualFree( (LPVOID)load_addr, 0, MEM_RELEASE ); UnmapViewOfFile( (LPVOID)hModule ); return 0; }
/* Look up the specified function or ordinal in the exportlist: * If it is a string: * - look up the name in the Name list. * - look up the ordinal with that index. * - use the ordinal as offset into the functionlist * If it is a ordinal: * - use ordinal-pe_export->Base as offset into the functionlist */ FARPROC PE_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName, WIN_BOOL snoop ) { unsigned short * ordinals; unsigned long * function; unsigned char ** name; const char *ename = NULL; int i, ordinal; PE_MODREF *pem = &(wm->binfmt.pe); IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export; unsigned int load_addr = wm->module; unsigned long rva_start, rva_end, addr; char * forward; if (HIWORD(funcName)) TRACE("(%s)\n",funcName); else TRACE("(%d)\n",(int)funcName); if (!exports) { /* Not a fatal problem, some apps do * GetProcAddress(0,"RegisterPenApp") which triggers this * case. */ WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem); return NULL; } ordinals= (unsigned short*) RVA(exports->AddressOfNameOrdinals); function= (unsigned long*) RVA(exports->AddressOfFunctions); name = (unsigned char **) RVA(exports->AddressOfNames); forward = NULL; rva_start = PE_HEADER(wm->module)->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (HIWORD(funcName)) { int min = 0, max = exports->NumberOfNames - 1; while (min <= max) { int res, pos = (min + max) / 2; ename = (const char*) RVA(name[pos]); if (!(res = strcmp( ename, funcName ))) { ordinal = ordinals[pos]; goto found; } if (res > 0) max = pos - 1; else min = pos + 1; } for (i = 0; i < exports->NumberOfNames; i++) { ename = (const char*) RVA(name[i]); if (!strcmp( ename, funcName )) { ERR( "%s.%s required a linear search\n", wm->modname, funcName ); ordinal = ordinals[i]; goto found; } } return NULL; } else { ordinal = LOWORD(funcName) - exports->Base; if (snoop && name) { for (i = 0; i < exports->NumberOfNames; i++) if (ordinals[i] == ordinal) { ename = RVA(name[i]); break; } } } found: if (ordinal >= exports->NumberOfFunctions) { TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base ); return NULL; } addr = function[ordinal]; if (!addr) return NULL; if ((addr < rva_start) || (addr >= rva_end)) { FARPROC proc = RVA(addr); if (snoop) { if (!ename) ename = "@"; // proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc); TRACE("SNOOP_GetProcAddress n/a\n"); } return proc; } else { WINE_MODREF *wm; char *forward = RVA(addr); char module[256]; char *end = strchr(forward, '.'); if (!end) return NULL; if (end - forward >= sizeof(module)) return NULL; memcpy( module, forward, end - forward ); module[end-forward] = 0; if (!(wm = MODULE_FindModule( module ))) { ERR("module not found for forward '%s'\n", forward ); return NULL; } return MODULE_GetProcAddress( wm->module, end + 1, snoop ); } }
void AlignChimeLocal3(const string &Q3, const string &A3, const string &B3, const string &QLabel, const string &ALabel, const string &BLabel, ChimeHit2 &Hit) { Hit.Clear(); const byte *Q3Seq = (const byte *) Q3.c_str(); const byte *A3Seq = (const byte *) A3.c_str(); const byte *B3Seq = (const byte *) B3.c_str(); const unsigned ColCount = SIZE(Q3); asserta(SIZE(A3) == ColCount && SIZE(B3) == ColCount); vector<float> ColScoresA(ColCount, 0.0f); vector<float> ColScoresB(ColCount, 0.0f); float ScoreN = -(float) opt_xn; unsigned QL = 0; for (unsigned Col = 0; Col < ColCount; ++Col) { char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; if (!isgap(q)) ++QL; if (q == a && q == b && a == b) continue; if (isgap(q) || isgap(a) || isgap(b)) continue; if (Col > 0 && (isgap(Q3Seq[Col-1]) || isgap(A3Seq[Col-1]) || isgap(B3Seq[Col-1]))) continue; if (Col + 1 < ColCount && (isgap(Q3Seq[Col+1]) || isgap(A3Seq[Col+1]) || isgap(B3Seq[Col+1]))) continue; if (q == a && q != b) ColScoresA[Col] = 1; else ColScoresA[Col] = ScoreN; if (q == b && q != a) ColScoresB[Col] = 1; else ColScoresB[Col] = ScoreN; } vector<float> LVA(ColCount, 0.0f); vector<float> LVB(ColCount, 0.0f); LVA[0] = ColScoresA[0]; LVB[0] = ColScoresB[0]; for (unsigned Col = 1; Col < ColCount; ++Col) { LVA[Col] = max(LVA[Col-1], 0.0f) + ColScoresA[Col]; LVB[Col] = max(LVB[Col-1], 0.0f) + ColScoresB[Col]; } vector<float> RVA(ColCount, 0.0f); vector<float> RVB(ColCount, 0.0f); RVA[ColCount-1] = ColScoresA[ColCount-1]; RVB[ColCount-1] = ColScoresB[ColCount-1]; for (int Col = ColCount-2; Col >= 0; --Col) { RVA[Col] = max(RVA[Col+1], 0.0f) + ColScoresA[Col]; RVB[Col] = max(RVB[Col+1], 0.0f) + ColScoresB[Col]; } bool FirstA = true; float MaxSum = 0.0; unsigned ColX = UINT_MAX; for (unsigned Col = 1; Col < ColCount-1; ++Col) { float Sum = LVA[Col] + RVB[Col+1]; if (Sum > MaxSum) { FirstA = true; MaxSum = Sum; ColX = Col; } } for (unsigned Col = 1; Col < ColCount-1; ++Col) { float Sum = LVB[Col] + RVA[Col+1]; if (Sum > MaxSum) { FirstA = false; MaxSum = Sum; ColX = Col; } } if (ColX == UINT_MAX) return; unsigned ColLo = UINT_MAX; unsigned ColHi = UINT_MAX; if (FirstA) { float Sum = 0.0f; for (int Col = ColX; Col >= 0; --Col) { Sum += ColScoresA[Col]; if (Sum >= LVA[ColX]) { ColLo = Col; break; } } asserta(Sum >= LVA[ColX]); Sum = 0.0f; for (unsigned Col = ColX+1; Col < ColCount; ++Col) { Sum += ColScoresB[Col]; if (Sum >= RVB[ColX]) { ColHi = Col; break; } } asserta(Sum >= RVB[ColX]); } else { float Sum = 0.0f; for (int Col = ColX; Col >= 0; --Col) { Sum += ColScoresB[Col]; if (Sum >= LVB[ColX]) { ColLo = Col; break; } } asserta(Sum >= LVB[ColX]); Sum = 0.0f; for (unsigned Col = ColX+1; Col < ColCount; ++Col) { Sum += ColScoresA[Col]; if (Sum >= RVA[ColX]) { ColHi = Col; break; } } asserta(Sum >= RVA[ColX]); } unsigned ColXHi = ColX; for (unsigned Col = ColX + 1; Col < ColCount; ++Col) { char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; if (q == a && q == b && !isgap(q)) ColXHi = Col; else break; } unsigned ColXLo = ColX; for (int Col = (int) ColX - 1; Col >= 0; --Col) { char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; if (q == a && q == b && !isgap(q)) ColXLo = Col; else break; } unsigned IdQA = 0; unsigned IdQB = 0; unsigned IdAB = 0; unsigned NQA = 0; unsigned NQB = 0; unsigned NAB = 0; for (unsigned Col = 0; Col < ColCount; ++Col) { char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; if (!isgap(q) && !isgap(a)) { ++NQA; if (q == a) ++IdQA; } if (!isgap(q) && !isgap(b)) { ++NQB; if (q == b) ++IdQB; } if (!isgap(a) && !isgap(b)) { ++NAB; if (a == b) ++IdAB; } } Hit.PctIdQA = Pct(IdQA, NQA); Hit.PctIdQB = Pct(IdQB, NQB); Hit.PctIdAB = Pct(IdAB, NAB); unsigned LIdQA = 0; unsigned LIdQB = 0; for (unsigned Col = ColLo; Col < ColXLo; ++Col) { char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; if (!isgap(q) && !isgap(a)) { if (q == a) ++LIdQA; } if (!isgap(q) && !isgap(b)) { if (q == b) ++LIdQB; } } unsigned RIdQA = 0; unsigned RIdQB = 0; for (unsigned Col = ColXHi+1; Col <= ColHi; ++Col) { char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; if (!isgap(q) && !isgap(a)) { if (q == a) ++RIdQA; } if (!isgap(q) && !isgap(b)) { if (q == b) ++RIdQB; } } unsigned IdDiffL = max(LIdQA, LIdQB) - min(LIdQA, LIdQB); unsigned IdDiffR = max(RIdQA, RIdQB) - min(RIdQA, RIdQB); unsigned MinIdDiff = min(IdDiffL, IdDiffR); unsigned ColRange = ColHi - ColLo + 1; if (opt_queryfract > 0.0f && float(ColRange)/float(QL) < opt_queryfract) return; // double Div = Pct(MinIdDiff, QSD.L); #if TRACE { Log(" Col A Q B ScoreA ScoreB LVA LVB RVA RVB\n"); Log("----- - - - ------- ------- ------- ------- ------- -------\n"); for (unsigned Col = 0; Col < ColCount; ++Col) { if (ColScoresA[Col] == 0.0 && ColScoresB[Col] == 0.0) continue; char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; Log("%5u %c %c %c", Col, a, q, b); if (ColScoresA[Col] == 0.0) Log(" %7.7s", ""); else Log(" %7.1f", ColScoresA[Col]); if (ColScoresB[Col] == 0.0) Log(" %7.7s", ""); else Log(" %7.1f", ColScoresB[Col]); Log(" %7.1f %7.1f %7.1f %7.1f", LVA[Col], LVB[Col], RVA[Col], RVB[Col]); Log("\n"); } Log("\n"); Log("MaxSum %.1f, ColLo %u, ColXLo %u, ColX %u, ColXHi %u, ColHi %u, AF %c\n", MaxSum, ColLo, ColXLo, ColX, ColXHi, ColHi, tof(FirstA)); Log(" LIdQA %u, LIdQB %u, RIdQA %u, RIdQB %u\n", LIdQA, LIdQB, RIdQA, RIdQB); } #endif string Q3L; string A3L; string B3L; for (unsigned Col = ColLo; Col <= ColHi; ++Col) { char q = Q3[Col]; char a = A3[Col]; char b = B3[Col]; Q3L += q; A3L += a; B3L += b; } AlignChimeGlobal3(Q3L, A3L, B3L, QLabel, ALabel, BLabel, Hit); #if 0 // CS SNPs Hit.CS_LY = 0; Hit.CS_LN = 0; Hit.CS_RY = 0; Hit.CS_RN = 0; Hit.CS_LA = 0; Hit.CS_RA = 0; for (unsigned Col = ColLo; Col <= ColHi; ++Col) { char q = Q3Seq[Col]; char a = A3Seq[Col]; char b = B3Seq[Col]; if (q == a && q == b && a == b) continue; if (isgap(q) || isgap(a) || isgap(b)) continue; if (Col > 0 && (isgap(Q3Seq[Col-1]) || isgap(A3Seq[Col-1]) || isgap(B3Seq[Col-1]))) continue; if (Col + 1 < ColCount && (isgap(Q3Seq[Col+1]) || isgap(A3Seq[Col+1]) || isgap(B3Seq[Col+1]))) continue; if (!FirstA) swap(a, b); if (Col < ColXLo) { if (q == a && q != b) ++Hit.CS_LY; else if (q == b && q != a) ++Hit.CS_LN; else ++Hit.CS_LA; } else if (Col > ColXHi) { if (q == b && q != a) ++Hit.CS_RY; else if (q == a && q != b) ++Hit.CS_RN; else ++Hit.CS_RA; } } double ScoreL = GetScore2(Hit.CS_LY, Hit.CS_LN, Hit.CS_LA); double ScoreR = GetScore2(Hit.CS_RY, Hit.CS_RN, Hit.CS_RA); Hit.Score = ScoreL*ScoreR; //Hit.QSD = QSD; //if (FirstA) // { // Hit.ASD = ASD; // Hit.BSD = BSD; // Hit.PathQA = PathQA; // Hit.PathQB = PathQB; // } //else // { // Hit.ASD = BSD; // Hit.BSD = ASD; // } //Hit.ColLo = ColLo; //Hit.ColXLo = ColXLo; //Hit.ColXHi = ColXHi; //Hit.ColHi = ColHi; //Hit.Div = Div; // Hit.LogMe(); #endif }
FARPROC WINAPI __delayLoadHelper2( PCImgDelayDescr pidd, FARPROC * ppfnIATEntry ) { // Set up some data we use for the hook procs but also useful for // our own use // InternalImgDelayDescr idd = { pidd->grAttrs, PFromRva<LPCSTR>(pidd->rvaDLLName), PFromRva<HMODULE*>(pidd->rvaHmod), PFromRva<PImgThunkData>(pidd->rvaIAT), PFromRva<PCImgThunkData>(pidd->rvaINT), PFromRva<PCImgThunkData>(pidd->rvaBoundIAT), PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT), pidd->dwTimeStamp }; DelayLoadInfo dli = { sizeof DelayLoadInfo, pidd, ppfnIATEntry, idd.szName, { 0 }, 0, 0, 0 }; if (0 == (idd.grAttrs & dlattrRva)) { PDelayLoadInfo rgpdli[1] = { &dli }; RaiseException( VcppException(ERROR_SEVERITY_ERROR, ERROR_INVALID_PARAMETER), 0, 1, PULONG_PTR(rgpdli) ); return 0; } HMODULE hmod = *idd.phmod; // Calculate the index for the IAT entry in the import address table // N.B. The INT entries are ordered the same as the IAT entries so // the calculation can be done on the IAT side. // const unsigned iIAT = IndexFromPImgThunkData(PCImgThunkData(ppfnIATEntry), idd.pIAT); const unsigned iINT = iIAT; PCImgThunkData pitd = &(idd.pINT[iINT]); dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal); if (dli.dlp.fImportByName) { dli.dlp.szProcName = LPCSTR(PFromRva<PIMAGE_IMPORT_BY_NAME>(RVA(UINT_PTR(pitd->u1.AddressOfData)))->Name); } else { dli.dlp.dwOrdinal = DWORD(IMAGE_ORDINAL(pitd->u1.Ordinal)); } // Call the initial hook. If it exists and returns a function pointer, // abort the rest of the processing and just return it for the call. // FARPROC pfnRet = NULL; if (__pfnDliNotifyHook2) { pfnRet = ((*__pfnDliNotifyHook2)(dliStartProcessing, &dli)); if (pfnRet != NULL) { goto HookBypass; } } // Check to see if we need to try to load the library. // if (hmod == 0) { if (__pfnDliNotifyHook2) { hmod = HMODULE(((*__pfnDliNotifyHook2)(dliNotePreLoadLibrary, &dli))); } if (hmod == 0) { hmod = ::LoadLibraryEx(dli.szDll, NULL, 0); } if (hmod == 0) { dli.dwLastError = ::GetLastError(); if (__pfnDliFailureHook2) { // when the hook is called on LoadLibrary failure, it will // return 0 for failure and an hmod for the lib if it fixed // the problem. // hmod = HMODULE((*__pfnDliFailureHook2)(dliFailLoadLib, &dli)); } if (hmod == 0) { PDelayLoadInfo rgpdli[1] = { &dli }; RaiseException( VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND), 0, 1, PULONG_PTR(rgpdli) ); // If we get to here, we blindly assume that the handler of the exception // has magically fixed everything up and left the function pointer in // dli.pfnCur. // return dli.pfnCur; } } // Store the library handle. If it is already there, we infer // that another thread got there first, and we need to do a // FreeLibrary() to reduce the refcount // HMODULE hmodT = HMODULE(InterlockedExchangePointer((PVOID *) idd.phmod, PVOID(hmod))); if (hmodT == hmod) { ::FreeLibrary(hmod); } } // Go for the procedure now. // dli.hmodCur = hmod; if (__pfnDliNotifyHook2) { pfnRet = (*__pfnDliNotifyHook2)(dliNotePreGetProcAddress, &dli); } if (pfnRet == 0) { if (pidd->rvaBoundIAT && pidd->dwTimeStamp) { // bound imports exist...check the timestamp from the target image // PIMAGE_NT_HEADERS pinh(PinhFromImageBase(hmod)); if (pinh->Signature == IMAGE_NT_SIGNATURE && TimeStampOfImage(pinh) == idd.dwTimeStamp && FLoadedAtPreferredAddress(pinh, hmod)) { // Everything is good to go, if we have a decent address // in the bound IAT! // pfnRet = FARPROC(UINT_PTR(idd.pBoundIAT[iIAT].u1.Function)); if (pfnRet != 0) { goto SetEntryHookBypass; } } } pfnRet = ::GetProcAddress(hmod, dli.dlp.szProcName); } if (pfnRet == 0) { dli.dwLastError = ::GetLastError(); if (__pfnDliFailureHook2) { // when the hook is called on GetProcAddress failure, it will // return 0 on failure and a valid proc address on success // pfnRet = (*__pfnDliFailureHook2)(dliFailGetProc, &dli); } if (pfnRet == 0) { PDelayLoadInfo rgpdli[1] = { &dli }; RaiseException( VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND), 0, 1, PULONG_PTR(rgpdli) ); // If we get to here, we blindly assume that the handler of the exception // has magically fixed everything up and left the function pointer in // dli.pfnCur. // pfnRet = dli.pfnCur; } } SetEntryHookBypass: *ppfnIATEntry = pfnRet; HookBypass: if (__pfnDliNotifyHook2) { dli.dwLastError = 0; dli.hmodCur = hmod; dli.pfnCur = pfnRet; (*__pfnDliNotifyHook2)(dliNoteEndProcessing, &dli); } return pfnRet; }
MODULE_HEADERS * ExecPE(char *lpszName) { static void *BaseAddress; IMAGE_DOS_HEADER DosHeader; PIMAGE_SECTION_HEADER pSectionHeaders; PIMAGE_NT_HEADERS pNTHeader; static int nNTHeader; int i,len; int index = nNTHeader; char *bp; int ret; HFILE hFile; bp = lpszName; while(*bp) { *bp = tolower(*bp); bp++; } for(i=0;i<nNTHeader;i++) { if(strcmp(NTModules[i].modulename,lpszName) == 0) { return &NTModules[i]; } } hFile = _lopen(lpszName,READ); if(hFile == -1) { char lpszFileName[256]; strcpy(lpszFileName,dirname); strcat(lpszFileName,"/"); strcat(lpszFileName,lpszName); hFile = _lopen(lpszFileName,READ); if(hFile == -1) { logstr(LF_ERROR,"cannot open file %s\n",lpszFileName); return 0; } } /* read the dos image header first */ ret = _lread(hFile,&DosHeader,sizeof(IMAGE_DOS_HEADER)); if(DosHeader.e_magic == IMAGE_DOS_SIGNATURE) { /* now read in the nt header */ _llseek(hFile,DosHeader.e_lfanew,0); pNTHeader = &NTHeader[nNTHeader]; ret = _lread(hFile,pNTHeader, sizeof(IMAGE_NT_HEADERS)); /* yes, it is a win32 header */ if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) { _lclose(hFile); return 0; } bp = strrchr(lpszName,'/'); if(bp) bp++; else bp = lpszName; BaseAddress = VirtualAlloc( (void *) pNTHeader->OptionalHeader.ImageBase, pNTHeader->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE); logstr(lf_console,"Load File: %s %p\n",lpszName,BaseAddress); NTModules[nNTHeader].modulename = bp; NTModules[nNTHeader].pNTHeader = pNTHeader; NTModules[nNTHeader].BaseAddress = BaseAddress; nNTHeader++; if (nNTHeader == 1 && usebuiltins) { NTModules[nNTHeader++].modulename = "user32.dll"; NTModules[nNTHeader++].modulename = "gdi32.dll"; NTModules[nNTHeader++].modulename = "kernel32.dll"; NTModules[nNTHeader++].modulename = "shell32.dll"; NTModules[nNTHeader++].modulename = "comctl32.dll"; NTModules[nNTHeader++].modulename = "comdlg32.dll"; NTModules[nNTHeader++].modulename = "rpcrt4.dll"; NTModules[nNTHeader++].modulename = "advapi32.dll"; } /* show the NT header */ //if (index == 0) DumpHeader(&pNTHeader->FileHeader); /* show the Optional header */ //if (index == 0) DumpOptionalHeader((PIMAGE_OPTIONAL_HEADER) &pNTHeader->OptionalHeader); pSectionHeaders = (PIMAGE_SECTION_HEADER)((void *)BaseAddress + sizeof(IMAGE_NT_HEADERS)); /* now read the section headers */ ret = _lread( hFile, pSectionHeaders, sizeof(IMAGE_SECTION_HEADER)* pNTHeader->FileHeader.NumberOfSections); for(i=0; i < pNTHeader->FileHeader.NumberOfSections; i++) { void *LoadAddress; LoadAddress = RVA(BaseAddress,pSectionHeaders->VirtualAddress); //if (index == 0) { DumpSectionTable( LoadAddress,pSectionHeaders,i); } /* load only non-BSS segments */ if(!(pSectionHeaders->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) { _llseek(hFile,pSectionHeaders->PointerToRawData,SEEK_SET); len = _lread(hFile,(char*) LoadAddress, pSectionHeaders->SizeOfRawData); if( len != pSectionHeaders->SizeOfRawData) { logstr(LF_ERROR,"Failed to load section %x %x\n", i,len); exit(0); } pSectionHeaders++; } /* not needed, memory is zero */ if(strcmp(pSectionHeaders[i].Name, ".bss") == 0) memset((void *)LoadAddress, 0, pSectionHeaders[i].Misc.VirtualSize ? pSectionHeaders[i].Misc.VirtualSize : pSectionHeaders[i].SizeOfRawData); } _lclose(hFile); // we are dependent on other modules, go get and load those //if (index == 0) LoadImportsSection(BaseAddress, pNTHeader,lpszName); if (index == 0) { logstr(lf_header," %32s PE Header BaseAddress\n", "FileName"); for(i=0;i<nNTHeader;i++) { logstr(lf_header,"%.4d: %32s %p %p\n", i, NTModules[i].modulename, NTModules[i].pNTHeader, NTModules[i].BaseAddress); } } if (index == 0) LoadExportsTable(&NTModules[0],pNTHeader,lpszName); if (index == 0) ExecEntryPoint( NTModules[0].BaseAddress, NTModules[0].pNTHeader, lpszName); return &NTModules[index]; } return 0; }
PVOID NTAPI LdrPEGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint) { PIMAGE_EXPORT_DIRECTORY ExportDir; PULONG * ExFunctions; PULONG * ExNames; USHORT * ExOrdinals; PVOID ExName; ULONG Ordinal; PVOID Function; LONG minn, maxn, mid, res; ULONG ExportDirSize; /* HAL and NTOS use a virtual address, switch it to physical mode */ if ((ULONG_PTR)BaseAddress & 0x80000000) { BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - KSEG0_BASE + (ULONG)KernelMemory); } ExportDir = (PIMAGE_EXPORT_DIRECTORY) RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ExportDirSize); if (!ExportDir) { DbgPrint("LdrPEGetExportByName(): no export directory!\n"); return NULL; } /* The symbol names may be missing entirely */ if (!ExportDir->AddressOfNames) { DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n"); return NULL; } /* * Get header pointers */ ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames); ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions); /* * Check the hint first */ if (Hint < ExportDir->NumberOfNames) { ExName = RVA(BaseAddress, ExNames[Hint]); if (strcmp(ExName, (PCHAR)SymbolName) == 0) { Ordinal = ExOrdinals[Hint]; Function = RVA(BaseAddress, ExFunctions[Ordinal]); if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) { Function = LdrPEFixupForward((PCHAR)Function); if (Function == NULL) { DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function); } return Function; } if (Function != NULL) return Function; } } /* * Binary search */ minn = 0; maxn = ExportDir->NumberOfNames - 1; while (minn <= maxn) { mid = (minn + maxn) / 2; ExName = RVA(BaseAddress, ExNames[mid]); res = strcmp(ExName, (PCHAR)SymbolName); if (res == 0) { Ordinal = ExOrdinals[mid]; Function = RVA(BaseAddress, ExFunctions[Ordinal]); if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) { Function = LdrPEFixupForward((PCHAR)Function); if (Function == NULL) { DbgPrint("1: failed to find %s\n", Function); } return Function; } if (Function != NULL) { return Function; } } else if (res > 0) { maxn = mid - 1; } else { minn = mid + 1; } } /* Fall back on unsorted */ minn = 0; maxn = ExportDir->NumberOfNames - 1; while (minn <= maxn) { ExName = RVA(BaseAddress, ExNames[minn]); res = strcmp(ExName, (PCHAR)SymbolName); if (res == 0) { Ordinal = ExOrdinals[minn]; Function = RVA(BaseAddress, ExFunctions[Ordinal]); if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) { Function = LdrPEFixupForward((PCHAR)Function); if (Function == NULL) { DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName); } return Function; } if (Function != NULL) { return Function; } DbgPrint("Failed to get function %s\n", SymbolName); } minn++; } DbgPrint("2: failed to find %s\n",SymbolName); return (PVOID)NULL; }