diff --git a/PortableExecutable.cpp b/PortableExecutable.cpp index 2d15158..8d96b63 100644 --- a/PortableExecutable.cpp +++ b/PortableExecutable.cpp @@ -1,4 +1,4 @@ -#include "PortableExecutable.h" +#include "PortableExecutable.h" #include "Log.h" @@ -173,3 +173,70 @@ IMAGE_SECTION_HEADER const* PortableExecutable::FindSection( return &(*found); } } + + +std::unordered_map PortableExecutable::GetExportSymbols() const noexcept +{ + std::unordered_map exportSymbols; + + IMAGE_DATA_DIRECTORY const& exportTable = uPEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + if (exportTable.Size == 0) { + return exportSymbols; + } + DWORD rawExportAddress = VirtualToRaw(exportTable.VirtualAddress); + if (rawExportAddress == 0) { + return exportSymbols; + } + IMAGE_EXPORT_DIRECTORY exportDir; + if (!ReadBytes(rawExportAddress, sizeof(IMAGE_EXPORT_DIRECTORY), &exportDir)) { + return exportSymbols; + } + std::string moduleName; + if (!ReadCString(VirtualToRaw(exportDir.Name), moduleName)) + { + moduleName = ""; + } + + std::vector addressOfFunctions; + size_t funcCount = exportDir.NumberOfFunctions; + addressOfFunctions.resize(funcCount); + if (!ReadBytes(VirtualToRaw(exportDir.AddressOfFunctions), sizeof(DWORD) * funcCount, addressOfFunctions.data())) { + return exportSymbols; + } + + std::vector addressOfNames; + size_t nameCount = exportDir.NumberOfNames; + addressOfNames.resize(nameCount); + if (!ReadBytes(VirtualToRaw(exportDir.AddressOfNames), sizeof(DWORD) * nameCount, addressOfNames.data())) { + return exportSymbols; + } + + std::vector addressOfNameOrdinals; + addressOfNameOrdinals.resize(nameCount); + if (!ReadBytes(VirtualToRaw(exportDir.AddressOfNameOrdinals), sizeof(WORD) * nameCount, addressOfNameOrdinals.data())) { + return exportSymbols; + } + + for (size_t i = 0; i < nameCount; ++i) { + DWORD nameRVA = addressOfNames[i]; + DWORD rawNameAddress = VirtualToRaw(nameRVA); + if (rawNameAddress == 0) { + continue; + } + + std::string nameANSI; + if (!ReadCString(rawNameAddress, nameANSI)) { + continue; + } + + WORD ordinal = addressOfNameOrdinals[i]; + if (ordinal >= funcCount) { + continue; // 无效序号 + } + + DWORD functionRVA = addressOfFunctions[ordinal]; + exportSymbols[nameANSI] = functionRVA; + } + + return exportSymbols; +} \ No newline at end of file diff --git a/PortableExecutable.h b/PortableExecutable.h index e22acca..0e75942 100644 --- a/PortableExecutable.h +++ b/PortableExecutable.h @@ -1,4 +1,4 @@ -// A class to parse PE files +// A class to parse PE files #pragma once #define WIN32_LEAN_AND_MEAN @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -109,6 +110,8 @@ class PortableExecutable IMAGE_SECTION_HEADER const* FindSection( std::string_view name) const noexcept; + std::unordered_map GetExportSymbols() const noexcept; + private: bool ReadFile(); }; diff --git a/SyringeDebugger.cpp b/SyringeDebugger.cpp index 5715a6f..a0185c6 100644 --- a/SyringeDebugger.cpp +++ b/SyringeDebugger.cpp @@ -1,4 +1,4 @@ -#include "SyringeDebugger.h" +#include "SyringeDebugger.h" #include "CRC32.h" #include "FindFile.h" @@ -1053,6 +1053,10 @@ void SyringeDebugger::FindDLLs() PortableExecutable const DLL{ fn }; HookBuffer buffer; + auto AlwaysLoad = false; + auto Export = DLL.GetExportSymbols(); + if (Export.count("SyringeForceLoad"))AlwaysLoad = true; + auto canLoad = false; if (auto const hooks = DLL.FindSection(".syhks00")) { @@ -1063,6 +1067,8 @@ void SyringeDebugger::FindDLLs() canLoad = ParseInjFileHooks(fn, buffer); } + if (AlwaysLoad)canLoad = true; + if (canLoad) { Log::WriteLine(__FUNCTION__ ": Recognized DLL: \"%.*s\"", printable(fn));