, специально предназначенного для рекурсивной загрузки библиотек MFC
DLL. Хотя я успешно реализовал загрузку нескольких компонентов, таких как таблица перемещения, TLS
и таблица импорта, я сталкиваюсь с некоторыми проблемами, когда дело доходит до загрузки других разделов PE-файла, включая таблицу ресурсов.< /p>
Вот краткий обзор того, чего я достиг на данный момент:
Я могу успешно загрузить таблицу перемещений и применить необходимые перемещения.
Я реализовал загрузку TLS и могу получать доступ к локальным переменным потока и использовать их.
Я могу анализировать и загружать таблицу импорта, что позволяет мне разрешать зависимости.
Код: Выделить всё
struct ThreadInitializer {
static DWORD mainThreadId;
};
static ThreadInitializer initializer;
DWORD ThreadInitializer::mainThreadId = GetCurrentThreadId();
class MemoryPE {
std::string& fileName;
LPVOID fileImage;
DWORD fileSize;
PIMAGE_DOS_HEADER m_pDosHeader;
PIMAGE_NT_HEADERS m_pNtHeader;
PIMAGE_SECTION_HEADER m_pSectionHeader;
void* m_VirtualAddress;
INLINE unsigned int GetAlignedSize(unsigned int iOriginalData, unsigned int Alignment) //iOriginalData原始数据 iAlignment对齐边界
{
if (Alignment & (Alignment - 1)) return -1;
return (iOriginalData + Alignment - 1) & ~(Alignment - 1);
}
public:
MemoryPE(std::string _fileName, LPVOID _fileImage, DWORD _fileSize) :fileName(_fileName), fileImage(_fileImage), fileSize(_fileSize) {
m_pDosHeader = (PIMAGE_DOS_HEADER)fileImage;
m_pNtHeader = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(fileImage))[m_pDosHeader->e_lfanew];
m_pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)m_pNtHeader + sizeof(IMAGE_NT_HEADERS));
}
~MemoryPE() {}
INLINE int GetVirtualSize() {
int MemoryAlign = m_pNtHeader->OptionalHeader.SectionAlignment;
auto sectionsum = GetAlignedSize(m_pNtHeader->OptionalHeader.SizeOfHeaders, MemoryAlign);
auto pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)m_pNtHeader + sizeof(IMAGE_NT_HEADERS));
for (int i = 0; i < m_pNtHeader->FileHeader.NumberOfSections; ++i) {
int iTureCodeSize = pSectionHeader[i].Misc.VirtualSize;
int iFileAlignCodeSize = pSectionHeader[i].SizeOfRawData;
int iMaxSize = (iFileAlignCodeSize > iTureCodeSize) ? (iFileAlignCodeSize) : (iTureCodeSize);
int iSectionSize = GetAlignedSize(pSectionHeader[i].VirtualAddress + iMaxSize, MemoryAlign);
if (sectionsum < (unsigned int)iSectionSize) {
sectionsum = iSectionSize; //Use the Max
}
}
return sectionsum;
}
bool Run() {
AUTOLOG
auto& lasterror = LastError::GetInstance();
lasterror = ERROR_SUCCESS;
if (!IsDosHeaderValid()) {
lasterror = ERROR_DLL_MIGHT_BE_INCOMPATIBLE;
std::cerr OptionalHeader.ImageBase;
*Address += ulDelta;
#endif
}else if ((DWORD)(RelocationData[i] & 0xF000) == 0x00003000){
#ifndef _WIN64
DWORD* Address = (DWORD*)((PBYTE)ImageData + BaseRelocation->VirtualAddress + (RelocationData[i] & 0x0FFF));
DWORD dwDelta = (DWORD)ImageData - m_NtHeader->OptionalHeader.ImageBase;
*Address += dwDelta;
#endif
}
}
BaseRelocation = (PIMAGE_BASE_RELOCATION)((PBYTE)BaseRelocation + BaseRelocation->SizeOfBlock);
}
return true;
}
INLINE bool CopyDataSections(){
AUTOLOG
int HeaderLength = m_pNtHeader->OptionalHeader.SizeOfHeaders;
if(!HeaderLength) return false;
if (!m_VirtualAddress) return false;
memcpy(m_VirtualAddress, fileImage, HeaderLength);
for (int i = 0; i < m_pNtHeader->FileHeader.NumberOfSections; ++i){
if (m_pSectionHeader[i].VirtualAddress == 0 || m_pSectionHeader[i].SizeOfRawData == 0)continue;
auto SectionMemoryAddress = (VOID*)((PBYTE)m_VirtualAddress + m_pSectionHeader[i].VirtualAddress);
memcpy((VOID*)SectionMemoryAddress, (VOID*)((PBYTE)fileImage + m_pSectionHeader[i].PointerToRawData),
m_pSectionHeader[i].SizeOfRawData);
}
m_pDosHeader = (PIMAGE_DOS_HEADER)m_VirtualAddress;
m_pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)m_VirtualAddress + (m_pDosHeader->e_lfanew));
m_pSectionHeader = (PIMAGE_SECTION_HEADER)((PBYTE)m_pNtHeader + sizeof(IMAGE_NT_HEADERS));
return true;
}
INLINE bool Flush() {
AUTOLOG
ULONG ulOld;
if (m_VirtualAddress) {
VirtualProtect(m_VirtualAddress, GetVirtualSize(), PAGE_EXECUTE_READWRITE, &ulOld);
FlushInstructionCache(GetCurrentProcess(), m_VirtualAddress, GetVirtualSize());
return true;
}
return false;
}
INLINE bool FixTLSTable() {
AUTOLOG
auto TLSdirectory = (PIMAGE_DATA_DIRECTORY) & (m_pNtHeader)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
if (!CheckHeader(IMAGE_DIRECTORY_ENTRY_TLS)) return true;
auto tlsAddr = (PIMAGE_TLS_DIRECTORY)((PBYTE)m_VirtualAddress + TLSdirectory->VirtualAddress);
auto callback = (PIMAGE_TLS_CALLBACK*)tlsAddr->AddressOfCallBacks;
if (callback) {
while (*callback) {
(*callback)(m_VirtualAddress, DLL_PROCESS_ATTACH, NULL);
callback++;
}
}
return true;
}
BOOL UpdateImageBase(){
AUTOLOG
m_pNtHeader->OptionalHeader.ImageBase = (ULONG_PTR)m_VirtualAddress;
return TRUE;
}
PIMAGE_DATA_DIRECTORY GetHeader(DWORD dwindex) {
return &m_pNtHeader->OptionalHeader.DataDirectory[dwindex];
}
bool CheckHeader(DWORD nIndex) {
AUTOLOG
auto exportDir = GetHeader(nIndex);
return !(exportDir->Size == 0 || exportDir->VirtualAddress == 0);
}
bool HasExports() {
AUTOLOG
return CheckHeader(IMAGE_DIRECTORY_ENTRY_EXPORT);
}
INLINE bool ExecuteDLLMain() {
AUTOLOG
typedef BOOL(*ProcDllMain)(HINSTANCE, DWORD, LPVOID);
auto pDllMain = (ProcDllMain)(m_pNtHeader->OptionalHeader.AddressOfEntryPoint + (PBYTE)m_VirtualAddress);
if (pDllMain&&IsExecutableImage()) {
auto ExcuteDll = [=]()->bool {
if (pDllMain((HINSTANCE)m_VirtualAddress, DLL_PROCESS_ATTACH, 0) == FALSE) {
pDllMain((HINSTANCE)m_VirtualAddress, DLL_PROCESS_DETACH, 0);
return false;
}
return true;
};
if (GetCurrentThreadId() != ThreadInitializer::mainThreadId) {
return ExcuteDll();
}else {
std::thread(ExcuteDll).detach();
return true;
}
}
return true;
}
INLINE HMODULE GetModuleInstance() {
AUTOLOG
return (HMODULE)m_VirtualAddress;
}
};
Есть ли какие-либо конкретные шаги или соображения, которые следует учитывать при рекурсивной загрузке ресурсов? в библиотеках MFC DLL?
Можете ли вы предоставить какие-либо примеры или ссылки на ресурсы, касающиеся структуры таблицы ресурсов или способов обработки различных типов ресурсов?
Подробнее здесь: https://stackoverflow.com/questions/790 ... -with-load