@@ -859,7 +859,7 @@ void GetModuleInfo(MODINFO & Info, ULONG_PTR FileMapVA)
859859#undef GetUnsafeModuleInfo
860860}
861861
862- bool ModLoad (duint Base, duint Size, const char * FullPath, bool loadSymbols)
862+ bool ModLoad (duint Base, duint Size, const char * FullPath, bool loadSymbols, HANDLE hFile )
863863{
864864 // Handle a new module being loaded
865865 if (!Base || !Size || !FullPath)
@@ -928,25 +928,112 @@ bool ModLoad(duint Base, duint Size, const char* FullPath, bool loadSymbols)
928928 if (!info.isVirtual )
929929 {
930930 auto wszFullPath = StringUtils::Utf8ToUtf16 (FullPath);
931+ bool fileLoaded = false ;
931932
932- // Load the physical module from disk
933- if (StaticFileLoadW (wszFullPath.c_str (), UE_ACCESS_READ, false , &info.fileHandle , &info.loadedSize , &info.fileMap , &info.fileMapVA ))
933+ // 1. If we have a file handle from the debug event, try mapping from it first
934+ // https://github.com/x64dbg/x64dbg/issues/3756
935+ if (hFile)
936+ {
937+ DWORD fileSize = GetFileSize (hFile, nullptr );
938+ if (fileSize != INVALID_FILE_SIZE && fileSize > 0 )
939+ {
940+ HANDLE hMap = CreateFileMappingW (hFile, nullptr , PAGE_READONLY, 0 , 0 , nullptr );
941+ if (hMap)
942+ {
943+ LPVOID mapView = MapViewOfFile (hMap, FILE_MAP_READ, 0 , 0 , 0 );
944+ if (mapView)
945+ {
946+ info.fileHandle = (HANDLE)1 ; // Non-zero for TitanEngine compatibility
947+ info.loadedSize = fileSize;
948+ info.fileMap = hMap;
949+ info.fileMapVA = (ULONG_PTR)mapView;
950+ fileLoaded = true ;
951+ }
952+ else
953+ {
954+ CloseHandle (hMap);
955+ }
956+ }
957+ }
958+ }
959+
960+ // 2. If no file handle or mapping failed, try loading from disk path
961+ if (!fileLoaded && StaticFileLoadW (wszFullPath.c_str (), UE_ACCESS_READ, false , &info.fileHandle , &info.loadedSize , &info.fileMap , &info.fileMapVA ))
934962 {
935- // Fix an anti-debug trick, which opens exclusive access to the file
936963 CloseHandle (info.fileHandle );
937964 info.fileHandle = (HANDLE)1 ; // Set to non-zero for TitanEngine compatibility
965+ fileLoaded = true ;
966+ dprintf (QT_TRANSLATE_NOOP (" DBG" , " Module %s%s loaded from file handle (path inaccessible)\n " ), info.name , info.extension );
967+ }
938968
939- GetModuleInfo (info, info.fileMapVA );
969+ // 3. If both failed, try reading from process memory as last resort
970+ if (!fileLoaded)
971+ {
972+ // The Size parameter is unreliable here (all pass 1 as a placeholder).
973+ // This is consistent with steps 1 and 2 which also determine size from their source.
974+ duint actualSize = 0 ;
975+ unsigned char headerBuf[0x1000 ] = {0 };
976+ if (MemRead (Base, headerBuf, sizeof (headerBuf)))
977+ {
978+ PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)headerBuf;
979+ if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE &&
980+ dosHeader->e_lfanew > 0 &&
981+ dosHeader->e_lfanew < 0x1000 - sizeof (IMAGE_NT_HEADERS))
982+ {
983+ PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(headerBuf + dosHeader->e_lfanew );
984+ if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
985+ actualSize = HEADER_FIELD (ntHeaders, SizeOfImage);
986+ }
987+ }
940988
941- Size = HEADER_FIELD (info.headers , SizeOfImage);
942- info.size = Size;
989+ // fallback if PE header parsing failed
990+ if (actualSize == 0 )
991+ {
992+ MEMORY_BASIC_INFORMATION mbi;
993+ duint regionSize = 0 ;
994+ duint addr = Base;
995+ while (VirtualQueryEx (fdProcessInfo->hProcess , (LPCVOID)addr, &mbi, sizeof (mbi)))
996+ {
997+ if (mbi.AllocationBase != (PVOID)Base)
998+ break ;
999+ regionSize += mbi.RegionSize ;
1000+ addr += mbi.RegionSize ;
1001+ }
1002+ actualSize = regionSize;
1003+ }
1004+
1005+ if (actualSize > 0 )
1006+ {
1007+ info.mappedData .realloc (actualSize);
1008+ if (MemRead (Base, info.mappedData (), info.mappedData .size ()))
1009+ {
1010+ info.isVirtual = true ; // Process memory is SEC_IMAGE mapped
1011+ info.loadedSize = (DWORD)actualSize;
1012+ GetModuleInfo (info, (ULONG_PTR)info.mappedData ());
1013+ info.size = HEADER_FIELD (info.headers , SizeOfImage);
1014+ dprintf (QT_TRANSLATE_NOOP (" DBG" , " Module %s%s loaded from process memory (file inaccessible)\n " ), info.name , info.extension );
1015+ }
1016+ else
1017+ {
1018+ info.fileHandle = nullptr ;
1019+ info.loadedSize = 0 ;
1020+ info.fileMap = nullptr ;
1021+ info.fileMapVA = 0 ;
1022+ }
1023+ }
1024+ else
1025+ {
1026+ info.fileHandle = nullptr ;
1027+ info.loadedSize = 0 ;
1028+ info.fileMap = nullptr ;
1029+ info.fileMapVA = 0 ;
1030+ }
9431031 }
9441032 else
9451033 {
946- info.fileHandle = nullptr ;
947- info.loadedSize = 0 ;
948- info.fileMap = nullptr ;
949- info.fileMapVA = 0 ;
1034+ GetModuleInfo (info, info.fileMapVA );
1035+ Size = HEADER_FIELD (info.headers , SizeOfImage);
1036+ info.size = Size;
9501037 }
9511038 }
9521039 else
0 commit comments