mirror of
https://github.com/ptitSeb/box64.git
synced 2025-05-07 15:36:41 +08:00
Added a simple PE loaded dedicated for volatileMetadata (#2607)
This commit is contained in:
parent
11563f3b62
commit
8d7db7f1fb
@ -403,6 +403,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/tools/rbtree.c"
|
||||
"${BOX64_ROOT}/src/tools/env.c"
|
||||
"${BOX64_ROOT}/src/tools/wine_tools.c"
|
||||
"${BOX64_ROOT}/src/tools/pe_tools.c"
|
||||
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
|
||||
)
|
||||
if(NOT STATICBUILD)
|
||||
|
7
src/include/pe_tools.h
Normal file
7
src/include/pe_tools.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __PE_TOOLS_H__
|
||||
#define __PE_TOOLS_H__
|
||||
|
||||
|
||||
void ParseVolatileMetadata(char* filename, void* addr);
|
||||
|
||||
#endif // __PE_TOOLS_H__
|
@ -10,6 +10,6 @@ void* get_wine_prereserve(void);
|
||||
void dynarec_wine_prereserve(void);
|
||||
#endif
|
||||
|
||||
void DetectUnityPlayer(int fd);
|
||||
void DetectUnityPlayer(char* filename);
|
||||
|
||||
#endif //__WINE_TOOLS_H__
|
||||
|
316
src/tools/pe_tools.c
Normal file
316
src/tools/pe_tools.c
Normal file
@ -0,0 +1,316 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t WORD;
|
||||
typedef uint32_t DWORD;
|
||||
typedef int32_t LONG;
|
||||
typedef uint32_t ULONG;
|
||||
typedef uint64_t ULONGLONG;
|
||||
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550
|
||||
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
|
||||
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10B
|
||||
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20B
|
||||
|
||||
typedef struct _IMAGE_DOS_HEADER {
|
||||
WORD e_magic;
|
||||
WORD e_cblp;
|
||||
WORD e_cp;
|
||||
WORD e_crlc;
|
||||
WORD e_cparhdr;
|
||||
WORD e_minalloc;
|
||||
WORD e_maxalloc;
|
||||
WORD e_ss;
|
||||
WORD e_sp;
|
||||
WORD e_csum;
|
||||
WORD e_ip;
|
||||
WORD e_cs;
|
||||
WORD e_lfarlc;
|
||||
WORD e_ovno;
|
||||
WORD e_res[4];
|
||||
WORD e_oemid;
|
||||
WORD e_oeminfo;
|
||||
WORD e_res2[10];
|
||||
LONG e_lfanew;
|
||||
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
|
||||
|
||||
typedef struct _IMAGE_FILE_HEADER {
|
||||
WORD Machine;
|
||||
WORD NumberOfSections;
|
||||
DWORD TimeDateStamp;
|
||||
DWORD PointerToSymbolTable;
|
||||
DWORD NumberOfSymbols;
|
||||
WORD SizeOfOptionalHeader;
|
||||
WORD Characteristics;
|
||||
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
|
||||
|
||||
typedef struct _IMAGE_DATA_DIRECTORY {
|
||||
DWORD VirtualAddress;
|
||||
DWORD Size;
|
||||
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
|
||||
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER64 {
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
ULONGLONG ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Win32VersionValue;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
ULONGLONG SizeOfStackReserve;
|
||||
ULONGLONG SizeOfStackCommit;
|
||||
ULONGLONG SizeOfHeapReserve;
|
||||
ULONGLONG SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[16];
|
||||
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
|
||||
|
||||
typedef struct _IMAGE_NT_HEADERS64 {
|
||||
DWORD Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
|
||||
|
||||
typedef struct _IMAGE_SECTION_HEADER {
|
||||
BYTE Name[8];
|
||||
union {
|
||||
DWORD PhysicalAddress;
|
||||
DWORD VirtualSize;
|
||||
} Misc;
|
||||
DWORD VirtualAddress;
|
||||
DWORD SizeOfRawData;
|
||||
DWORD PointerToRawData;
|
||||
DWORD PointerToRelocations;
|
||||
DWORD PointerToLinenumbers;
|
||||
WORD NumberOfRelocations;
|
||||
WORD NumberOfLinenumbers;
|
||||
DWORD Characteristics;
|
||||
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
|
||||
|
||||
typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64 {
|
||||
DWORD Size;
|
||||
DWORD TimeDateStamp;
|
||||
WORD MajorVersion;
|
||||
WORD MinorVersion;
|
||||
DWORD GlobalFlagsClear;
|
||||
DWORD GlobalFlagsSet;
|
||||
DWORD CriticalSectionDefaultTimeout;
|
||||
ULONGLONG DeCommitFreeBlockThreshold;
|
||||
ULONGLONG DeCommitTotalFreeThreshold;
|
||||
ULONGLONG LockPrefixTable;
|
||||
ULONGLONG MaximumAllocationSize;
|
||||
ULONGLONG VirtualMemoryThreshold;
|
||||
ULONGLONG ProcessAffinityMask;
|
||||
DWORD ProcessHeapFlags;
|
||||
WORD CSDVersion;
|
||||
WORD DependentLoadFlags;
|
||||
ULONGLONG EditList;
|
||||
ULONGLONG SecurityCookie;
|
||||
ULONGLONG SEHandlerTable;
|
||||
ULONGLONG SEHandlerCount;
|
||||
ULONGLONG GuardCFCheckFunctionPointer;
|
||||
ULONGLONG GuardCFDispatchFunctionPointer;
|
||||
ULONGLONG GuardCFFunctionTable;
|
||||
ULONGLONG GuardCFFunctionCount;
|
||||
DWORD GuardFlags;
|
||||
ULONGLONG CodeIntegrity;
|
||||
ULONGLONG GuardAddressTakenIatEntryTable;
|
||||
ULONGLONG GuardAddressTakenIatEntryCount;
|
||||
ULONGLONG GuardLongJumpTargetTable;
|
||||
ULONGLONG GuardLongJumpTargetCount;
|
||||
ULONGLONG DynamicValueRelocTable;
|
||||
ULONGLONG CHPEMetadataPointer;
|
||||
ULONGLONG GuardRFFailureRoutine;
|
||||
ULONGLONG GuardRFFailureRoutineFunctionPointer;
|
||||
DWORD DynamicValueRelocTableOffset;
|
||||
WORD DynamicValueRelocTableSection;
|
||||
WORD Reserved2;
|
||||
ULONGLONG GuardRFVerifyStackPointerFunctionPointer;
|
||||
DWORD HotPatchTableOffset;
|
||||
DWORD Reserved3;
|
||||
ULONGLONG EnclaveConfigurationPointer;
|
||||
ULONGLONG VolatileMetadataPointer;
|
||||
ULONGLONG GuardEHContinuationTable;
|
||||
ULONGLONG GuardEHContinuationCount;
|
||||
ULONGLONG GuardXFGCheckFunctionPointer;
|
||||
ULONGLONG GuardXFGDispatchFunctionPointer;
|
||||
ULONGLONG GuardXFGTableDispatchFunctionPointer;
|
||||
ULONGLONG CastGuardOsDeterminedFailureMode;
|
||||
ULONGLONG GuardMemcpyFunctionPointer;
|
||||
} IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64;
|
||||
|
||||
typedef struct _IMAGE_VOLATILE_METADATA {
|
||||
DWORD Size;
|
||||
DWORD Version;
|
||||
DWORD VolatileAccessTable;
|
||||
DWORD VolatileAccessTableSize;
|
||||
DWORD VolatileInfoRangeTable;
|
||||
DWORD VolatileInfoRangeTableSize;
|
||||
} IMAGE_VOLATILE_METADATA, *PIMAGE_VOLATILE_METADATA;
|
||||
|
||||
typedef struct _IMAGE_VOLATILE_RVA_METADATA {
|
||||
ULONG Rva;
|
||||
} IMAGE_VOLATILE_RVA_METADATA, *PIMAGE_VOLATILE_RVA_METADATA;
|
||||
|
||||
typedef struct _IMAGE_VOLATILE_RANGE_METADATA {
|
||||
ULONG Rva;
|
||||
ULONG Size;
|
||||
} IMAGE_VOLATILE_RANGE_METADATA, *PIMAGE_VOLATILE_RANGE_METADATA;
|
||||
|
||||
static int HasSuffix(const char* str, const char* suffix)
|
||||
{
|
||||
size_t lenstr = strlen(str);
|
||||
size_t lensuffix = strlen(suffix);
|
||||
if (lensuffix > lenstr) return 0;
|
||||
return strcmp(str + lenstr - lensuffix, suffix) == 0;
|
||||
}
|
||||
|
||||
DWORD RVAToFileOffset(PIMAGE_SECTION_HEADER sections, DWORD numberOfSections, DWORD rva, BYTE* fileBuffer, size_t fileSize)
|
||||
{
|
||||
for (DWORD i = 0; i < numberOfSections; i++) {
|
||||
PIMAGE_SECTION_HEADER section = §ions[i];
|
||||
if (rva >= section->VirtualAddress && rva < section->VirtualAddress + section->SizeOfRawData) {
|
||||
DWORD offset = rva - section->VirtualAddress + section->PointerToRawData;
|
||||
if (offset < fileSize) {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ParseVolatileMetadata(char* filename, void* addr)
|
||||
{
|
||||
if (!filename) return;
|
||||
if (!HasSuffix(filename, ".dll")) {
|
||||
return;
|
||||
}
|
||||
|
||||
FILE* file = fopen(filename, "rb");
|
||||
if (!file) return;
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
char* buffer = (char*)malloc(size);
|
||||
if (!buffer) {
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fread(buffer, 1, size, file) != size) {
|
||||
free(buffer);
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)buffer;
|
||||
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
PIMAGE_NT_HEADERS64 ntHeaders64 = (PIMAGE_NT_HEADERS64)(buffer + dosHeader->e_lfanew);
|
||||
if (ntHeaders64->Signature != IMAGE_NT_SIGNATURE || ntHeaders64->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
int numberOfSections = ntHeaders64->FileHeader.NumberOfSections;
|
||||
if (numberOfSections <= 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
IMAGE_DATA_DIRECTORY loadConfigDir = ntHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
|
||||
if (loadConfigDir.VirtualAddress == 0 || loadConfigDir.Size == 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
PIMAGE_SECTION_HEADER sectionHeaders = (PIMAGE_SECTION_HEADER)((void*)ntHeaders64 + sizeof(IMAGE_NT_HEADERS64)); // immediately follows the optional header, if any.
|
||||
DWORD loadConfigOffset = RVAToFileOffset(sectionHeaders, numberOfSections, loadConfigDir.VirtualAddress, (BYTE*)buffer, ntHeaders64->OptionalHeader.SizeOfImage);
|
||||
if (loadConfigOffset == 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
PIMAGE_LOAD_CONFIG_DIRECTORY64 loadConfig = (PIMAGE_LOAD_CONFIG_DIRECTORY64)(buffer + loadConfigOffset);
|
||||
if (loadConfig->Size < offsetof(IMAGE_LOAD_CONFIG_DIRECTORY64, VolatileMetadataPointer) + sizeof(ULONGLONG)) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
DWORD volatileMetadataPointer = (DWORD)(loadConfig->VolatileMetadataPointer - ntHeaders64->OptionalHeader.ImageBase);
|
||||
if (volatileMetadataPointer == 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD volatileMetadataOffset = RVAToFileOffset(sectionHeaders, numberOfSections, volatileMetadataPointer, (BYTE*)buffer, ntHeaders64->OptionalHeader.SizeOfImage);
|
||||
if (volatileMetadataOffset == 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
PIMAGE_VOLATILE_METADATA volatileMetadata = (PIMAGE_VOLATILE_METADATA)(buffer + volatileMetadataOffset);
|
||||
if (volatileMetadata->VolatileAccessTable && volatileMetadata->VolatileAccessTableSize) {
|
||||
printf_log(LOG_INFO, "Parsing volatile metadata of file: %s\n", filename);
|
||||
|
||||
DWORD volatileAccessTableOffset = RVAToFileOffset(sectionHeaders, numberOfSections, volatileMetadata->VolatileAccessTable, (BYTE*)buffer, ntHeaders64->OptionalHeader.SizeOfImage);
|
||||
if (volatileAccessTableOffset == 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD numEntries = volatileMetadata->VolatileAccessTableSize / sizeof(IMAGE_VOLATILE_RVA_METADATA);
|
||||
PIMAGE_VOLATILE_RVA_METADATA volatileAccessTable = (PIMAGE_VOLATILE_RVA_METADATA)(buffer + volatileAccessTableOffset);
|
||||
|
||||
for (DWORD i = 0; i < numEntries; i++) {
|
||||
ULONG entry = volatileAccessTable[i].Rva;
|
||||
printf_log(LOG_INFO, "Volatile Access Table Entry %d: %08X\n", i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (volatileMetadata->VolatileInfoRangeTable && volatileMetadata->VolatileInfoRangeTableSize) {
|
||||
DWORD volatileInfoRangeTableOffset = RVAToFileOffset(sectionHeaders, numberOfSections, volatileMetadata->VolatileInfoRangeTable, (BYTE*)buffer, ntHeaders64->OptionalHeader.SizeOfImage);
|
||||
if (volatileInfoRangeTableOffset == 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD numEntries = volatileMetadata->VolatileInfoRangeTableSize / sizeof(IMAGE_VOLATILE_RANGE_METADATA);
|
||||
PIMAGE_VOLATILE_RANGE_METADATA volatileRangeMetadata = (PIMAGE_VOLATILE_RANGE_METADATA)(buffer + volatileInfoRangeTableOffset);
|
||||
|
||||
for (DWORD i = 0; i < numEntries; i++) {
|
||||
ULONG Rva = volatileRangeMetadata[i].Rva;
|
||||
ULONG Size = volatileRangeMetadata[i].Size;
|
||||
printf_log(LOG_INFO, "Volatile Range Metadata Entry %d: %08X Size: %08X\n", i, Rva, Size);
|
||||
}
|
||||
}
|
||||
}
|
@ -136,16 +136,11 @@ void dynarec_wine_prereserve()
|
||||
}
|
||||
#endif
|
||||
|
||||
void DetectUnityPlayer(int fd)
|
||||
void DetectUnityPlayer(char* filename)
|
||||
{
|
||||
static int unityplayer_detected = 0;
|
||||
if (fd > 0 && BOX64ENV(unityplayer) && !unityplayer_detected) {
|
||||
char filename[4096];
|
||||
char buf[128];
|
||||
sprintf(buf, "/proc/self/fd/%d", fd);
|
||||
ssize_t r = readlink(buf, filename, sizeof(filename) - 1);
|
||||
if (r != -1) filename[r] = 0;
|
||||
if (r > 0 && strlen(filename) > strlen("UnityPlayer.dll") && !strcasecmp(filename + strlen(filename) - strlen("UnityPlayer.dll"), "UnityPlayer.dll")) {
|
||||
if (!filename && BOX64ENV(unityplayer) && !unityplayer_detected) {
|
||||
if (strlen(filename) > strlen("UnityPlayer.dll") && !strcasecmp(filename + strlen(filename) - strlen("UnityPlayer.dll"), "UnityPlayer.dll")) {
|
||||
printf_log(LOG_NONE, "Detected UnityPlayer.dll\n");
|
||||
#ifdef DYNAREC
|
||||
if (!BOX64ENV(dynarec_strongmem)) {
|
||||
@ -156,4 +151,4 @@ void DetectUnityPlayer(int fd)
|
||||
unityplayer_detected = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "globalsymbols.h"
|
||||
#include "env.h"
|
||||
#include "wine_tools.h"
|
||||
#include "pe_tools.h"
|
||||
#include "cleanup.h"
|
||||
#ifndef LOG_INFO
|
||||
#define LOG_INFO 1
|
||||
@ -3032,7 +3033,14 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, size_t length, int prot, int f
|
||||
#endif
|
||||
if(ret!=MAP_FAILED) {
|
||||
if(emu && !(flags&MAP_ANONYMOUS) && (fd>0)) {
|
||||
DetectUnityPlayer(fd);
|
||||
char filename[4096];
|
||||
char buf[128];
|
||||
sprintf(buf, "/proc/self/fd/%d", fd);
|
||||
ssize_t r = readlink(buf, filename, sizeof(filename) - 1);
|
||||
if (r != -1) filename[r] = 0;
|
||||
|
||||
DetectUnityPlayer(filename);
|
||||
// ParseVolatileMetadata(filename, addr);
|
||||
// the last_mmap will allow mmap created by wine, even those that have hole, to be fully tracked as one single mmap
|
||||
if((ret>=last_mmap_addr[0]) && ret+length<(last_mmap_addr[0]+last_mmap_len[0]))
|
||||
RecordEnvMappings((uintptr_t)last_mmap_addr[0], last_mmap_len[0], fd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user