FunctionPass::FunctionPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks) : AnalysisPass(VirtualStart, VirtualEnd, MainBlocks) { // Zero values m_FunctionInfo = nullptr; m_FunctionInfoSize = 0; // This will only be valid if the address range is within a loaded module m_ModuleStart = ModBaseFromAddr(VirtualStart); if(m_ModuleStart != 0) { char modulePath[MAX_PATH]; memset(modulePath, 0, sizeof(modulePath)); ModPathFromAddr(m_ModuleStart, modulePath, ARRAYSIZE(modulePath)); HANDLE fileHandle; DWORD fileSize; HANDLE fileMapHandle; ULONG_PTR fileMapVa; if(StaticFileLoadW( StringUtils::Utf8ToUtf16(modulePath).c_str(), UE_ACCESS_READ, false, &fileHandle, &fileSize, &fileMapHandle, &fileMapVa)) { // Find a pointer to IMAGE_DIRECTORY_ENTRY_EXCEPTION for later use ULONG_PTR virtualOffset = GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALOFFSET); m_FunctionInfoSize = (ULONG)GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALSIZE); // Unload the file StaticFileUnloadW(nullptr, false, fileHandle, fileSize, fileMapHandle, fileMapVa); // Get a copy of the function table if(virtualOffset) { // Read the table into a buffer m_FunctionInfo = BridgeAlloc(m_FunctionInfoSize); if(m_FunctionInfo) MemRead(virtualOffset + m_ModuleStart, m_FunctionInfo, m_FunctionInfoSize); } } } }
ControlFlowAnalysis::ControlFlowAnalysis(uint base, uint size, bool exceptionDirectory) : Analysis(base, size) { _functionInfoData = nullptr; #ifdef _WIN64 // This will only be valid if the address range is within a loaded module _moduleBase = ModBaseFromAddr(base); if(exceptionDirectory && _moduleBase != 0) { char modulePath[MAX_PATH]; memset(modulePath, 0, sizeof(modulePath)); ModPathFromAddr(_moduleBase, modulePath, ARRAYSIZE(modulePath)); HANDLE fileHandle; DWORD fileSize; HANDLE fileMapHandle; ULONG_PTR fileMapVa; if(StaticFileLoadW( StringUtils::Utf8ToUtf16(modulePath).c_str(), UE_ACCESS_READ, false, &fileHandle, &fileSize, &fileMapHandle, &fileMapVa)) { // Find a pointer to IMAGE_DIRECTORY_ENTRY_EXCEPTION for later use ULONG_PTR virtualOffset = GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALOFFSET); _functionInfoSize = (uint)GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALSIZE); // Unload the file StaticFileUnloadW(nullptr, false, fileHandle, fileSize, fileMapHandle, fileMapVa); // Get a copy of the function table if(virtualOffset) { // Read the table into a buffer _functionInfoData = emalloc(_functionInfoSize); if(_functionInfoData) MemRead(virtualOffset + _moduleBase, _functionInfoData, _functionInfoSize); } } } #endif //_WIN64 }
bool ModUnload(uint Base) { EXCLUSIVE_ACQUIRE(LockModules); // Find the iterator index const auto found = modinfo.find(Range(Base, Base)); if(found == modinfo.end()) return false; // Unload everything from TitanEngine StaticFileUnloadW(nullptr, false, found->second.Handle, found->second.FileMapSize, found->second.MapHandle, found->second.FileMapVA); // Remove it from the list modinfo.erase(found); EXCLUSIVE_RELEASE(); // Update symbols SymUpdateModuleList(); return true; }
int PatchFile(const PATCHINFO* List, int Count, const char* FileName, char* Error) { // // This function returns an int based on the number // of patches applied. -1 indicates a failure. // if(Count <= 0) { // Notify the user of the error if(Error) strcpy_s(Error, MAX_ERROR_SIZE, "No patches to apply"); return -1; } // Get a copy of the first module name in the array char moduleName[MAX_MODULE_SIZE]; strcpy_s(moduleName, List[0].mod); // Check if all patches are in the same module for(int i = 0; i < Count; i++) { if(_stricmp(List[i].mod, moduleName)) { if(Error) sprintf_s(Error, MAX_ERROR_SIZE, "Not all patches are in module %s", moduleName); return -1; } } // See if the module was loaded duint moduleBase = ModBaseFromName(moduleName); if(!moduleBase) { if(Error) sprintf_s(Error, MAX_ERROR_SIZE, "Failed to get base of module %s", moduleName); return -1; } // Get the unicode version of the module's path wchar_t originalName[MAX_PATH]; if(!GetModuleFileNameExW(fdProcessInfo->hProcess, (HMODULE)moduleBase, originalName, ARRAYSIZE(originalName))) { if(Error) sprintf_s(Error, MAX_ERROR_SIZE, "Failed to get module path of module %s", moduleName); return -1; } // Create a temporary backup file if(!CopyFileW(originalName, StringUtils::Utf8ToUtf16(FileName).c_str(), false)) { if(Error) strcpy_s(Error, MAX_ERROR_SIZE, "Failed to make a copy of the original file (patch target is in use?)"); return -1; } HANDLE fileHandle; DWORD loadedSize; HANDLE fileMap; ULONG_PTR fileMapVa; if(!StaticFileLoadW(StringUtils::Utf8ToUtf16(FileName).c_str(), UE_ACCESS_ALL, false, &fileHandle, &loadedSize, &fileMap, &fileMapVa)) { strcpy_s(Error, MAX_ERROR_SIZE, "StaticFileLoad failed"); return -1; } // Begin iterating all patches, applying them to a file int patchCount = 0; for(int i = 0; i < Count; i++) { // Convert the virtual address to an offset within disk file data unsigned char* ptr = (unsigned char*)ConvertVAtoFileOffsetEx(fileMapVa, loadedSize, moduleBase, List[i].addr, false, true); // Skip patches that do not have a raw address if(!ptr) continue; *ptr = List[i].newbyte; patchCount++; } // Unload the file from memory and commit changes to disk if(!StaticFileUnloadW(StringUtils::Utf8ToUtf16(FileName).c_str(), true, fileHandle, loadedSize, fileMap, fileMapVa)) { if(Error) strcpy_s(Error, MAX_ERROR_SIZE, "StaticFileUnload failed"); return -1; } // Zero the error message and return count if(Error) memset(Error, 0, MAX_ERROR_SIZE * sizeof(char)); return patchCount; }