mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
CModule and CMemory class improvements
This commit significantly reduces output code size, and a noticeable increase in performance. Changes are: - Removed all extraneous std::string and std::vector copy constructions; use raw pointers instead to boost performance. - Marked simple getters in CModule inline. - Marked several functions in CModule const. - Slightly reordered CModule class. - 'CMemory::CheckOpCodes' and 'CMemory::Patch' now take a const reference.
This commit is contained in:
parent
c874b7c4d8
commit
975c40876a
@ -85,7 +85,7 @@ typedef int32 DWORD;
|
||||
typedef int32 LONG;
|
||||
typedef int BOOL; // uppercase BOOL is usually 4 bytes
|
||||
#endif
|
||||
typedef int64 QWORD;
|
||||
//typedef int64 QWORD;
|
||||
#ifndef __cplusplus
|
||||
typedef int bool; // we want to use bool in our C programs
|
||||
#endif
|
||||
|
@ -54,7 +54,7 @@ bool CPluginSystem::LoadPluginInstance(PluginInstance_t& pluginInst)
|
||||
if (loadedPlugin == INVALID_HANDLE_VALUE || loadedPlugin == 0)
|
||||
return false;
|
||||
|
||||
CModule pluginModule = CModule(pluginInst.m_svPluginName);
|
||||
CModule pluginModule = CModule(pluginInst.m_svPluginName.c_str());
|
||||
|
||||
// Pass selfModule here on load function, we have to do this because local listen/dedi/client dll's are called different, refer to a comment on the pluginsdk.
|
||||
auto onLoadFn = pluginModule.GetExportedFunction("PluginInstance_OnLoad").RCast<PluginInstance_t::OnLoad>();
|
||||
|
@ -115,17 +115,21 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CheckOpCodes(const vector<uint8_t> vOpcodeArray) const;
|
||||
void Patch(const vector<uint8_t> vOpcodeArray) const;
|
||||
void PatchString(const string& svString) const;
|
||||
CMemory FindPattern(const string& svPattern, const Direction searchDirect = Direction::DOWN, const int opCodesToScan = 512, const ptrdiff_t occurrence = 1) const;
|
||||
CMemory FindPatternSelf(const string& svPattern, const Direction searchDirect = Direction::DOWN, const int opCodesToScan = 512, const ptrdiff_t occurrence = 1);
|
||||
bool CheckOpCodes(const vector<uint8_t>& vOpcodeArray) const;
|
||||
void Patch(const vector<uint8_t>& vOpcodeArray) const;
|
||||
void PatchString(const char* szString) const;
|
||||
|
||||
CMemory FindPattern(const char* szPattern, const Direction searchDirect = Direction::DOWN, const int opCodesToScan = 512, const ptrdiff_t occurrence = 1) const;
|
||||
CMemory FindPatternSelf(const char* szPattern, const Direction searchDirect = Direction::DOWN, const int opCodesToScan = 512, const ptrdiff_t occurrence = 1);
|
||||
vector<CMemory> FindAllCallReferences(const uintptr_t sectionBase, const size_t sectionSize);
|
||||
|
||||
CMemory FollowNearCall(const ptrdiff_t opcodeOffset = 0x1, const ptrdiff_t nextInstructionOffset = 0x5) const;
|
||||
CMemory FollowNearCallSelf(const ptrdiff_t opcodeOffset = 0x1, const ptrdiff_t nextInstructionOffset = 0x5);
|
||||
CMemory ResolveRelativeAddress(const ptrdiff_t registerOffset = 0x0, const ptrdiff_t nextInstructionOffset = 0x4) const;
|
||||
CMemory ResolveRelativeAddressSelf(const ptrdiff_t registerOffset = 0x0, const ptrdiff_t nextInstructionOffset = 0x4);
|
||||
vector<CMemory> FindAllCallReferences(const uintptr_t sectionBase, const size_t sectionSize);
|
||||
|
||||
static void HookVirtualMethod(const uintptr_t virtualTable, const void* pHookMethod, const ptrdiff_t methodIndex, void** ppOriginalMethod);
|
||||
static void HookImportedFunction(const uintptr_t pImportedMethod, const void* pHookMethod, void** ppOriginalMethod);
|
||||
|
||||
private:
|
||||
uintptr_t ptr = 0;
|
||||
|
@ -7,42 +7,44 @@ public:
|
||||
struct ModuleSections_t
|
||||
{
|
||||
ModuleSections_t(void) = default;
|
||||
ModuleSections_t(const string& svSectionName, uintptr_t pSectionBase, size_t nSectionSize) :
|
||||
m_svSectionName(svSectionName), m_pSectionBase(pSectionBase), m_nSectionSize(nSectionSize) {}
|
||||
ModuleSections_t(const char* sectionName, uintptr_t pSectionBase, size_t nSectionSize) :
|
||||
m_SectionName(sectionName), m_pSectionBase(pSectionBase), m_nSectionSize(nSectionSize) {}
|
||||
|
||||
bool IsSectionValid(void) const
|
||||
{
|
||||
return m_nSectionSize != 0;
|
||||
}
|
||||
inline bool IsSectionValid(void) const { return m_nSectionSize != 0; }
|
||||
|
||||
string m_svSectionName; // Name of section.
|
||||
uintptr_t m_pSectionBase{}; // Start address of section.
|
||||
size_t m_nSectionSize{}; // Size of section.
|
||||
string m_SectionName; // Name of section.
|
||||
uintptr_t m_pSectionBase; // Start address of section.
|
||||
size_t m_nSectionSize; // Size of section.
|
||||
};
|
||||
|
||||
CModule(void) = default;
|
||||
CModule(const string& moduleName);
|
||||
CModule(const uintptr_t nModuleBase, const string& svModuleName);
|
||||
CModule(const char* szModuleName);
|
||||
CModule(const char* szModuleName, const uintptr_t nModuleBase);
|
||||
|
||||
void Init();
|
||||
void LoadSections();
|
||||
#ifndef PLUGINSDK
|
||||
CMemory FindPatternSIMD(const string& svPattern, const ModuleSections_t* moduleSection = nullptr) const;
|
||||
CMemory FindString(const string& string, const ptrdiff_t occurrence = 1, bool nullTerminator = false) const;
|
||||
CMemory FindStringReadOnly(const string& svString, bool nullTerminator) const;
|
||||
CMemory FindPatternSIMD(const char* szPattern, const ModuleSections_t* moduleSection = nullptr) const;
|
||||
CMemory FindString(const char* szString, const ptrdiff_t occurrence = 1, bool nullTerminator = false) const;
|
||||
CMemory FindStringReadOnly(const char* szString, bool nullTerminator) const;
|
||||
CMemory FindFreeDataPage(const size_t nSize) const;
|
||||
|
||||
CMemory GetVirtualMethodTable(const string& svTableName, const size_t nRefIndex = 0);
|
||||
CMemory GetVirtualMethodTable(const char* szTableName, const size_t nRefIndex = 0);
|
||||
#endif // !PLUGINSDK
|
||||
CMemory GetImportedFunction(const string& svModuleName, const string& svFunctionName, const bool bGetFunctionReference) const;
|
||||
CMemory GetExportedFunction(const string& svFunctionName) const;
|
||||
ModuleSections_t GetSectionByName(const string& svSectionName) const;
|
||||
uintptr_t GetModuleBase(void) const;
|
||||
DWORD GetModuleSize(void) const;
|
||||
string GetModuleName(void) const;
|
||||
uintptr_t GetRVA(const uintptr_t nAddress) const;
|
||||
CMemory GetImportedFunction(const char* szModuleName, const char* szFunctionName, const bool bGetFunctionReference) const;
|
||||
CMemory GetExportedFunction(const char* szFunctionName) const;
|
||||
ModuleSections_t GetSectionByName(const char* szSectionName) const;
|
||||
|
||||
IMAGE_NT_HEADERS64* m_pNTHeaders = nullptr;
|
||||
IMAGE_DOS_HEADER* m_pDOSHeader = nullptr;
|
||||
inline const vector<CModule::ModuleSections_t>& GetSections() const { return m_ModuleSections; }
|
||||
inline uintptr_t GetModuleBase(void) const { return m_pModuleBase; }
|
||||
inline DWORD GetModuleSize(void) const { return m_nModuleSize; }
|
||||
inline const string& GetModuleName(void) const { return m_ModuleName; }
|
||||
inline uintptr_t GetRVA(const uintptr_t nAddress) const { return (nAddress - GetModuleBase()); }
|
||||
|
||||
void UnlinkFromPEB(void) const;
|
||||
|
||||
IMAGE_NT_HEADERS64* m_pNTHeaders;
|
||||
IMAGE_DOS_HEADER* m_pDOSHeader;
|
||||
|
||||
ModuleSections_t m_ExecutableCode;
|
||||
ModuleSections_t m_ExceptionTable;
|
||||
@ -50,12 +52,13 @@ public:
|
||||
ModuleSections_t m_ReadOnlyData;
|
||||
|
||||
private:
|
||||
CMemory FindPatternSIMD(const uint8_t* szPattern, const char* szMask, const ModuleSections_t* moduleSection = nullptr, const size_t nOccurrence = 0) const;
|
||||
CMemory FindPatternSIMD(const uint8_t* pPattern, const char* szMask,
|
||||
const ModuleSections_t* moduleSection = nullptr, const size_t nOccurrence = 0) const;
|
||||
|
||||
string m_svModuleName;
|
||||
uintptr_t m_pModuleBase{};
|
||||
DWORD m_nModuleSize{};
|
||||
vector<ModuleSections_t> m_vModuleSections;
|
||||
string m_ModuleName;
|
||||
uintptr_t m_pModuleBase;
|
||||
DWORD m_nModuleSize;
|
||||
vector<ModuleSections_t> m_ModuleSections;
|
||||
};
|
||||
|
||||
#endif // MODULE_H
|
@ -26,8 +26,8 @@ public:
|
||||
void SetDisabled(const bool bDisabled);
|
||||
void InvalidateMap();
|
||||
|
||||
void AddEntry(const string& svPattern, const uint64_t nRVA);
|
||||
bool FindEntry(const string& svPattern, uint64_t& nRVA) const;
|
||||
void AddEntry(const char* szPattern, const uint64_t nRVA);
|
||||
bool FindEntry(const char* szPattern, uint64_t& nRVA);
|
||||
|
||||
bool LoadCache(const string& svCacheFile);
|
||||
bool WriteCache(const string& svCacheFile) const;
|
||||
|
@ -66,10 +66,10 @@ string FourCCToString(int n);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Bytes
|
||||
vector<int> StringToBytes(const string& svInput, bool bNullTerminator);
|
||||
pair<vector<uint8_t>, string> StringToMaskedBytes(const string& svInput, bool bNullTerminator);
|
||||
vector<int> PatternToBytes(const string& svInput);
|
||||
pair<vector<uint8_t>, string> PatternToMaskedBytes(const string& svInput);
|
||||
vector<int> StringToBytes(const char* szInput, bool bNullTerminator);
|
||||
pair<vector<uint8_t>, string> StringToMaskedBytes(const char* szInput, bool bNullTerminator);
|
||||
vector<int> PatternToBytes(const char* szInput);
|
||||
pair<vector<uint8_t>, string> PatternToMaskedBytes(const char* szInput);
|
||||
vector<int> IntToDigits(int iValue);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -5,9 +5,9 @@ class CVTableHelper
|
||||
public:
|
||||
|
||||
CVTableHelper(void) = default;
|
||||
CVTableHelper(CModule* module, const string& tableName = "", uint32_t refIndex = 0);
|
||||
CVTableHelper(uintptr_t virtualTable, const string& tableName = "");
|
||||
CVTableHelper(void* virtualTable, const string& tableName = "");
|
||||
CVTableHelper(CModule* module, const char* tableName = "", uint32_t refIndex = 0);
|
||||
CVTableHelper(uintptr_t virtualTable, const char* tableName = "");
|
||||
CVTableHelper(void* virtualTable, const char* tableName = "");
|
||||
|
||||
inline operator uintptr_t(void) const
|
||||
{
|
||||
|
@ -34,6 +34,10 @@ add_sources( SOURCE_GROUP "Runtime"
|
||||
"binstream.cpp"
|
||||
)
|
||||
|
||||
add_sources( SOURCE_GROUP "Windows"
|
||||
"${ENGINE_SOURCE_DIR}/windows/tebpeb64.h"
|
||||
)
|
||||
|
||||
file( GLOB TIER0_PUBLIC_HEADERS
|
||||
"${ENGINE_SOURCE_DIR}/public/tier0/*"
|
||||
)
|
||||
|
@ -7,10 +7,10 @@
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: check array of opcodes starting from current address
|
||||
// Input : vOpcodeArray -
|
||||
// Input : &vOpcodeArray -
|
||||
// Output : true if equal, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMemory::CheckOpCodes(const vector<uint8_t> vOpcodeArray) const
|
||||
bool CMemory::CheckOpCodes(const vector<uint8_t>& vOpcodeArray) const
|
||||
{
|
||||
uintptr_t ref = ptr;
|
||||
|
||||
@ -29,9 +29,9 @@ bool CMemory::CheckOpCodes(const vector<uint8_t> vOpcodeArray) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: patch array of opcodes starting from current address
|
||||
// Input : vOpcodeArray -
|
||||
// Input : &vOpcodeArray -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemory::Patch(const vector<uint8_t> vOpcodeArray) const
|
||||
void CMemory::Patch(const vector<uint8_t>& vOpcodeArray) const
|
||||
{
|
||||
DWORD oldProt = NULL;
|
||||
|
||||
@ -49,23 +49,20 @@ void CMemory::Patch(const vector<uint8_t> vOpcodeArray) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: patch string constant at current address
|
||||
// Input : &svString -
|
||||
// Input : *szString -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemory::PatchString(const string& svString) const
|
||||
void CMemory::PatchString(const char* szString) const
|
||||
{
|
||||
DWORD oldProt = NULL;
|
||||
|
||||
SIZE_T dwSize = svString.size();
|
||||
const vector<char> bytes(svString.begin(), svString.end());
|
||||
SIZE_T dwSize = strlen(szString);
|
||||
|
||||
VirtualProtect(reinterpret_cast<void*>(ptr), dwSize, PAGE_EXECUTE_READWRITE, &oldProt); // Patch page to be able to read and write to it.
|
||||
|
||||
for (size_t i = 0; i < svString.size(); i++)
|
||||
for (size_t i = 0; i < dwSize; i++)
|
||||
{
|
||||
*reinterpret_cast<uint8_t*>(ptr + i) = bytes[i]; // Write string to Address.
|
||||
*reinterpret_cast<uint8_t*>(ptr + i) = szString[i]; // Write string to Address.
|
||||
}
|
||||
|
||||
dwSize = svString.size();
|
||||
VirtualProtect(reinterpret_cast<void*>(ptr), dwSize, oldProt, &oldProt); // Restore protection.
|
||||
}
|
||||
|
||||
@ -77,11 +74,11 @@ void CMemory::PatchString(const string& svString) const
|
||||
// occurrence -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CMemory::FindPattern(const string& svPattern, const Direction searchDirect, const int opCodesToScan, const ptrdiff_t occurrence) const
|
||||
CMemory CMemory::FindPattern(const char* szPattern, const Direction searchDirect, const int opCodesToScan, const ptrdiff_t occurrence) const
|
||||
{
|
||||
uint8_t* pScanBytes = reinterpret_cast<uint8_t*>(ptr); // Get the base of the module.
|
||||
|
||||
const vector<int> PatternBytes = PatternToBytes(svPattern); // Convert our pattern to a byte array.
|
||||
const vector<int> PatternBytes = PatternToBytes(szPattern); // Convert our pattern to a byte array.
|
||||
const pair<size_t, const int*> bytesInfo = std::make_pair<size_t, const int*>(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
|
||||
ptrdiff_t occurrences = 0;
|
||||
|
||||
@ -124,11 +121,11 @@ CMemory CMemory::FindPattern(const string& svPattern, const Direction searchDire
|
||||
// occurrence -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CMemory::FindPatternSelf(const string& svPattern, const Direction searchDirect, const int opCodesToScan, const ptrdiff_t occurrence)
|
||||
CMemory CMemory::FindPatternSelf(const char* szPattern, const Direction searchDirect, const int opCodesToScan, const ptrdiff_t occurrence)
|
||||
{
|
||||
uint8_t* pScanBytes = reinterpret_cast<uint8_t*>(ptr); // Get the base of the module.
|
||||
|
||||
const vector<int> PatternBytes = PatternToBytes(svPattern); // Convert our pattern to a byte array.
|
||||
const vector<int> PatternBytes = PatternToBytes(szPattern); // Convert our pattern to a byte array.
|
||||
const pair<size_t, const int*> bytesInfo = std::make_pair<size_t, const int*>(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
|
||||
ptrdiff_t occurrences = 0;
|
||||
|
||||
@ -165,6 +162,34 @@ CMemory CMemory::FindPatternSelf(const string& svPattern, const Direction search
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: resolve all 'call' references to ptr
|
||||
// (This is very slow only use for mass patching.)
|
||||
// Input : sectionBase -
|
||||
// sectionSize -
|
||||
// Output : vector<CMemory>
|
||||
//-----------------------------------------------------------------------------
|
||||
vector<CMemory> CMemory::FindAllCallReferences(const uintptr_t sectionBase, const size_t sectionSize)
|
||||
{
|
||||
vector <CMemory> referencesInfo = {};
|
||||
|
||||
uint8_t* pTextStart = reinterpret_cast<uint8_t*>(sectionBase);
|
||||
for (size_t i = 0ull; i < sectionSize - 0x5; i++, _mm_prefetch(reinterpret_cast<const char*>(pTextStart + 64), _MM_HINT_NTA))
|
||||
{
|
||||
if (pTextStart[i] == CALL)
|
||||
{
|
||||
CMemory memAddr = CMemory(&pTextStart[i]);
|
||||
if (!memAddr.Offset(0x1).CheckOpCodes({ 0x00, 0x00, 0x00, 0x00 })) // Check if its not a dynamic resolved call.
|
||||
{
|
||||
if (memAddr.FollowNearCall() == *this)
|
||||
referencesInfo.push_back(memAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return referencesInfo;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: ResolveRelativeAddress wrapper
|
||||
// Input : opcodeOffset -
|
||||
@ -230,40 +255,12 @@ CMemory CMemory::ResolveRelativeAddressSelf(const ptrdiff_t registerOffset, cons
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: resolve all 'call' references to ptr
|
||||
// (This is very slow only use for mass patching.)
|
||||
// Input : sectionBase -
|
||||
// sectionSize -
|
||||
// Output : vector<CMemory>
|
||||
//-----------------------------------------------------------------------------
|
||||
vector<CMemory> CMemory::FindAllCallReferences(const uintptr_t sectionBase, const size_t sectionSize)
|
||||
{
|
||||
vector <CMemory> referencesInfo = {};
|
||||
|
||||
uint8_t* pTextStart = reinterpret_cast<uint8_t*>(sectionBase);
|
||||
for (size_t i = 0ull; i < sectionSize - 0x5; i++, _mm_prefetch(reinterpret_cast<const char*>(pTextStart + 64), _MM_HINT_NTA))
|
||||
{
|
||||
if (pTextStart[i] == CALL)
|
||||
{
|
||||
CMemory memAddr = CMemory(&pTextStart[i]);
|
||||
if (!memAddr.Offset(0x1).CheckOpCodes({ 0x00, 0x00, 0x00, 0x00 })) // Check if its not a dynamic resolved call.
|
||||
{
|
||||
if (memAddr.FollowNearCall() == *this)
|
||||
referencesInfo.push_back(memAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return referencesInfo;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: patch virtual method to point to a user set function
|
||||
// Input : virtualTable -
|
||||
// pHookMethod -
|
||||
// methodIndex -
|
||||
// pOriginalMethod -
|
||||
// Input : virtualTable -
|
||||
// *pHookMethod -
|
||||
// methodIndex -
|
||||
// **pOriginalMethod -
|
||||
// Output : void** via pOriginalMethod
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemory::HookVirtualMethod(const uintptr_t virtualTable, const void* pHookMethod, const ptrdiff_t methodIndex, void** ppOriginalMethod)
|
||||
@ -285,6 +282,33 @@ void CMemory::HookVirtualMethod(const uintptr_t virtualTable, const void* pHookM
|
||||
// Restore original page.
|
||||
VirtualProtect(reinterpret_cast<void*>(virtualMethod), sizeof(virtualMethod), oldProt, &oldProt);
|
||||
|
||||
// Move original function into argument.
|
||||
*ppOriginalMethod = reinterpret_cast<void*>(originalFunction);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: patch iat entry to point to a user set function
|
||||
// Input : pImportedMethod -
|
||||
// pHookMethod -
|
||||
// ppOriginalMethod -
|
||||
// Output : void** via ppOriginalMethod
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMemory::HookImportedFunction(const uintptr_t pImportedMethod, const void* pHookMethod, void** ppOriginalMethod)
|
||||
{
|
||||
DWORD oldProt = NULL;
|
||||
|
||||
// Preserve original function.
|
||||
const uintptr_t originalFunction = *reinterpret_cast<uintptr_t*>(pImportedMethod);
|
||||
|
||||
// Set page for current iat entry to execute n read n write.
|
||||
VirtualProtect(reinterpret_cast<void*>(pImportedMethod), sizeof(void*), PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
|
||||
// Set method to our hook.
|
||||
*reinterpret_cast<uintptr_t*>(pImportedMethod) = reinterpret_cast<uintptr_t>(pHookMethod);
|
||||
|
||||
// Restore original page.
|
||||
VirtualProtect(reinterpret_cast<void*>(pImportedMethod), sizeof(void*), oldProt, &oldProt);
|
||||
|
||||
// Move original function into argument.
|
||||
*ppOriginalMethod = reinterpret_cast<void*>(originalFunction);
|
||||
}
|
@ -5,15 +5,16 @@
|
||||
//===========================================================================//
|
||||
#include "tier0/memaddr.h"
|
||||
#include "tier0/sigcache.h"
|
||||
#include "windows/tebpeb64.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor
|
||||
// Input : *svModuleName
|
||||
// Input : *szModuleName -
|
||||
//-----------------------------------------------------------------------------
|
||||
CModule::CModule(const string& svModuleName)
|
||||
: m_svModuleName(svModuleName)
|
||||
CModule::CModule(const char* szModuleName)
|
||||
: m_ModuleName(szModuleName)
|
||||
{
|
||||
m_pModuleBase = reinterpret_cast<uintptr_t>(GetModuleHandleA(svModuleName.c_str()));
|
||||
m_pModuleBase = reinterpret_cast<uintptr_t>(GetModuleHandleA(szModuleName));
|
||||
|
||||
Init();
|
||||
LoadSections();
|
||||
@ -21,10 +22,11 @@ CModule::CModule(const string& svModuleName)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor
|
||||
// Input : nModuleBase
|
||||
// Input : *szModuleName -
|
||||
// nModuleBase -
|
||||
//-----------------------------------------------------------------------------
|
||||
CModule::CModule(const uintptr_t nModuleBase, const string& svModuleName)
|
||||
: m_svModuleName(svModuleName)
|
||||
CModule::CModule(const char* szModuleName, const uintptr_t nModuleBase)
|
||||
: m_ModuleName(szModuleName)
|
||||
, m_pModuleBase(nModuleBase)
|
||||
{
|
||||
Init();
|
||||
@ -45,7 +47,7 @@ void CModule::Init()
|
||||
for (WORD i = 0; i < m_pNTHeaders->FileHeader.NumberOfSections; i++) // Loop through the sections.
|
||||
{
|
||||
const IMAGE_SECTION_HEADER& hCurrentSection = hSection[i]; // Get current section.
|
||||
m_vModuleSections.push_back(ModuleSections_t(reinterpret_cast<const char*>(hCurrentSection.Name),
|
||||
m_ModuleSections.push_back(ModuleSections_t(reinterpret_cast<const char*>(hCurrentSection.Name),
|
||||
static_cast<uintptr_t>(m_pModuleBase + hCurrentSection.VirtualAddress), hCurrentSection.SizeOfRawData)); // Push back a struct with the section data.
|
||||
}
|
||||
}
|
||||
@ -64,11 +66,14 @@ void CModule::LoadSections()
|
||||
#ifndef PLUGINSDK
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: find array of bytes in process memory using SIMD instructions
|
||||
// Input : *szPattern -
|
||||
// *szMask -
|
||||
// Input : *pPattern -
|
||||
// *szMask -
|
||||
// *moduleSection -
|
||||
// nOccurrence -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, const ModuleSections_t* moduleSection, const size_t nOccurrence) const
|
||||
CMemory CModule::FindPatternSIMD(const uint8_t* pPattern, const char* szMask,
|
||||
const ModuleSections_t* moduleSection, const size_t nOccurrence) const
|
||||
{
|
||||
if (!m_ExecutableCode.IsSectionValid())
|
||||
return CMemory();
|
||||
@ -97,11 +102,11 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, c
|
||||
}
|
||||
}
|
||||
}
|
||||
const __m128i xmm1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(szPattern));
|
||||
const __m128i xmm1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pPattern));
|
||||
__m128i xmm2, xmm3, msks;
|
||||
for (; pData != pEnd; _mm_prefetch(reinterpret_cast<const char*>(++pData + 64), _MM_HINT_NTA))
|
||||
{
|
||||
if (szPattern[0] == pData[0])
|
||||
if (pPattern[0] == pData[0])
|
||||
{
|
||||
xmm2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pData));
|
||||
msks = _mm_cmpeq_epi8(xmm1, xmm2);
|
||||
@ -110,7 +115,7 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, c
|
||||
for (uintptr_t i = 1; i < static_cast<uintptr_t>(iNumMasks); ++i)
|
||||
{
|
||||
xmm2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((pData + i * 16)));
|
||||
xmm3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((szPattern + i * 16)));
|
||||
xmm3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>((pPattern + i * 16)));
|
||||
msks = _mm_cmpeq_epi8(xmm2, xmm3);
|
||||
if ((_mm_movemask_epi8(msks) & nMasks[i]) == nMasks[i])
|
||||
{
|
||||
@ -139,97 +144,47 @@ CMemory CModule::FindPatternSIMD(const uint8_t* szPattern, const char* szMask, c
|
||||
return CMemory();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: find a string pattern in process memory using SIMD instructions
|
||||
// Input : &svPattern
|
||||
// &moduleSection
|
||||
// Input : *szPattern -
|
||||
// *moduleSection -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::FindPatternSIMD(const string& svPattern, const ModuleSections_t* moduleSection) const
|
||||
CMemory CModule::FindPatternSIMD(const char* szPattern, const ModuleSections_t* moduleSection) const
|
||||
{
|
||||
uint64_t nRVA;
|
||||
if (g_SigCache.FindEntry(svPattern, nRVA))
|
||||
if (g_SigCache.FindEntry(szPattern, nRVA))
|
||||
{
|
||||
return CMemory(nRVA + GetModuleBase());
|
||||
}
|
||||
|
||||
const pair<vector<uint8_t>, string> patternInfo = PatternToMaskedBytes(svPattern);
|
||||
const pair<vector<uint8_t>, string> patternInfo = PatternToMaskedBytes(szPattern);
|
||||
const CMemory memory = FindPatternSIMD(patternInfo.first.data(), patternInfo.second.c_str(), moduleSection);
|
||||
|
||||
g_SigCache.AddEntry(svPattern, GetRVA(memory.GetPtr()));
|
||||
g_SigCache.AddEntry(szPattern, GetRVA(memory.GetPtr()));
|
||||
return memory;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: find address of input string constant in read only memory
|
||||
// Input : *svString -
|
||||
// bNullTerminator -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::FindStringReadOnly(const string& svString, bool bNullTerminator) const
|
||||
{
|
||||
if (!m_ReadOnlyData.IsSectionValid())
|
||||
return CMemory();
|
||||
|
||||
uint64_t nRVA;
|
||||
if (g_SigCache.FindEntry(svString, nRVA))
|
||||
{
|
||||
return CMemory(nRVA + GetModuleBase());
|
||||
}
|
||||
|
||||
const vector<int> vBytes = StringToBytes(svString, bNullTerminator); // Convert our string to a byte array.
|
||||
const pair<size_t, const int*> bytesInfo = std::make_pair<size_t, const int*>(vBytes.size(), vBytes.data()); // Get the size and data of our bytes.
|
||||
|
||||
const uint8_t* pBase = reinterpret_cast<uint8_t*>(m_ReadOnlyData.m_pSectionBase); // Get start of .rdata section.
|
||||
|
||||
for (size_t i = 0ull; i < m_ReadOnlyData.m_nSectionSize - bytesInfo.first; i++)
|
||||
{
|
||||
bool bFound = true;
|
||||
|
||||
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
|
||||
// our if clause will be false.
|
||||
for (size_t j = 0ull; j < bytesInfo.first; j++)
|
||||
{
|
||||
if (pBase[i + j] != bytesInfo.second[j] && bytesInfo.second[j] != -1)
|
||||
{
|
||||
bFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFound)
|
||||
{
|
||||
CMemory result = CMemory(&pBase[i]);
|
||||
g_SigCache.AddEntry(svString, GetRVA(result.GetPtr()));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return CMemory();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: find address of reference to string constant in executable memory
|
||||
// Input : *svString -
|
||||
// Input : *szString -
|
||||
// bNullTerminator -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::FindString(const string& svString, const ptrdiff_t nOccurrence, bool bNullTerminator) const
|
||||
CMemory CModule::FindString(const char* szString, const ptrdiff_t nOccurrence, bool bNullTerminator) const
|
||||
{
|
||||
if (!m_ExecutableCode.IsSectionValid())
|
||||
return CMemory();
|
||||
|
||||
uint64_t nRVA;
|
||||
string svPackedString = svString + std::to_string(nOccurrence);
|
||||
string svPackedString = szString + std::to_string(nOccurrence);
|
||||
|
||||
if (g_SigCache.FindEntry(svPackedString, nRVA))
|
||||
if (g_SigCache.FindEntry(svPackedString.c_str(), nRVA))
|
||||
{
|
||||
return CMemory(nRVA + GetModuleBase());
|
||||
}
|
||||
|
||||
const CMemory stringAddress = FindStringReadOnly(svString, bNullTerminator); // Get Address for the string in the .rdata section.
|
||||
const CMemory stringAddress = FindStringReadOnly(szString, bNullTerminator); // Get Address for the string in the .rdata section.
|
||||
|
||||
if (!stringAddress)
|
||||
return CMemory();
|
||||
@ -255,7 +210,7 @@ CMemory CModule::FindString(const string& svString, const ptrdiff_t nOccurrence,
|
||||
if (nOccurrence == dOccurrencesFound)
|
||||
{
|
||||
resultAddress = CMemory(&pTextStart[i]);
|
||||
g_SigCache.AddEntry(svPackedString, GetRVA(resultAddress.GetPtr()));
|
||||
g_SigCache.AddEntry(svPackedString.c_str(), GetRVA(resultAddress.GetPtr()));
|
||||
|
||||
return resultAddress;
|
||||
}
|
||||
@ -266,30 +221,127 @@ CMemory CModule::FindString(const string& svString, const ptrdiff_t nOccurrence,
|
||||
}
|
||||
|
||||
resultAddress = CMemory(pLatestOccurrence);
|
||||
g_SigCache.AddEntry(svPackedString, GetRVA(resultAddress.GetPtr()));
|
||||
g_SigCache.AddEntry(svPackedString.c_str(), GetRVA(resultAddress.GetPtr()));
|
||||
|
||||
return resultAddress;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get address of a virtual method table by rtti type descriptor name.
|
||||
// Input : *svTableName -
|
||||
// nRefIndex -
|
||||
// Output : address of virtual method table, null if not found.
|
||||
// Purpose: find address of input string constant in read only memory
|
||||
// Input : *szString -
|
||||
// bNullTerminator -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::GetVirtualMethodTable(const string& svTableName, const size_t nRefIndex)
|
||||
CMemory CModule::FindStringReadOnly(const char* szString, bool bNullTerminator) const
|
||||
{
|
||||
uint64_t nRVA; // Packed together as we can have multiple VFTable searches, but with different ref indexes.
|
||||
string svPackedTableName = svTableName + std::to_string(nRefIndex);
|
||||
if (!m_ReadOnlyData.IsSectionValid())
|
||||
return CMemory();
|
||||
|
||||
if (g_SigCache.FindEntry(svPackedTableName, nRVA))
|
||||
uint64_t nRVA;
|
||||
if (g_SigCache.FindEntry(szString, nRVA))
|
||||
{
|
||||
return CMemory(nRVA + GetModuleBase());
|
||||
}
|
||||
|
||||
ModuleSections_t moduleSection = { ".data", m_RunTimeData.m_pSectionBase, m_RunTimeData.m_nSectionSize };
|
||||
const vector<int> vBytes = StringToBytes(szString, bNullTerminator); // Convert our string to a byte array.
|
||||
const pair<size_t, const int*> bytesInfo = std::make_pair<size_t, const int*>(vBytes.size(), vBytes.data()); // Get the size and data of our bytes.
|
||||
|
||||
const auto tableNameInfo = StringToMaskedBytes(svTableName, false);
|
||||
const uint8_t* pBase = reinterpret_cast<uint8_t*>(m_ReadOnlyData.m_pSectionBase); // Get start of .rdata section.
|
||||
|
||||
for (size_t i = 0ull; i < m_ReadOnlyData.m_nSectionSize - bytesInfo.first; i++)
|
||||
{
|
||||
bool bFound = true;
|
||||
|
||||
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
|
||||
// our if clause will be false.
|
||||
for (size_t j = 0ull; j < bytesInfo.first; j++)
|
||||
{
|
||||
if (pBase[i + j] != bytesInfo.second[j] && bytesInfo.second[j] != -1)
|
||||
{
|
||||
bFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFound)
|
||||
{
|
||||
CMemory result = CMemory(&pBase[i]);
|
||||
g_SigCache.AddEntry(szString, GetRVA(result.GetPtr()));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return CMemory();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: find 'free' page in r/w/x sections
|
||||
// Input : nSize -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::FindFreeDataPage(const size_t nSize) const
|
||||
{
|
||||
auto checkDataSection = [](const void* address, const std::size_t size)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION membInfo = { 0 };
|
||||
|
||||
VirtualQuery(address, &membInfo, sizeof(membInfo));
|
||||
|
||||
if (membInfo.AllocationBase && membInfo.BaseAddress && membInfo.State == MEM_COMMIT && !(membInfo.Protect & PAGE_GUARD) && membInfo.Protect != PAGE_NOACCESS)
|
||||
{
|
||||
if ((membInfo.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)) && membInfo.RegionSize >= size)
|
||||
{
|
||||
return ((membInfo.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)) && membInfo.RegionSize >= size) ? true : false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// This is very unstable, this doesn't check for the actual 'page' sizes.
|
||||
// Also can be optimized to search per 'section'.
|
||||
const uintptr_t endOfModule = m_pModuleBase + m_pNTHeaders->OptionalHeader.SizeOfImage - sizeof(uintptr_t);
|
||||
for (uintptr_t currAddr = endOfModule; m_pModuleBase < currAddr; currAddr -= sizeof(uintptr_t))
|
||||
{
|
||||
if (*reinterpret_cast<uintptr_t*>(currAddr) == 0 && checkDataSection(reinterpret_cast<void*>(currAddr), nSize))
|
||||
{
|
||||
bool bIsGoodPage = true;
|
||||
uint32_t nPageCount = 0;
|
||||
|
||||
for (; nPageCount < nSize && bIsGoodPage; nPageCount += sizeof(uintptr_t))
|
||||
{
|
||||
const uintptr_t pageData = *reinterpret_cast<std::uintptr_t*>(currAddr + nPageCount);
|
||||
if (pageData != 0)
|
||||
bIsGoodPage = false;
|
||||
}
|
||||
|
||||
if (bIsGoodPage && nPageCount >= nSize)
|
||||
return currAddr;
|
||||
}
|
||||
}
|
||||
|
||||
return CMemory();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get address of a virtual method table by rtti type descriptor name.
|
||||
// Input : *szTableName -
|
||||
// nRefIndex -
|
||||
// Output : address of virtual method table, null if not found.
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::GetVirtualMethodTable(const char* szTableName, const size_t nRefIndex)
|
||||
{
|
||||
uint64_t nRVA; // Packed together as we can have multiple VFTable searches, but with different ref indexes.
|
||||
string svPackedTableName = szTableName + std::to_string(nRefIndex);
|
||||
|
||||
if (g_SigCache.FindEntry(svPackedTableName.c_str(), nRVA))
|
||||
{
|
||||
return CMemory(nRVA + GetModuleBase());
|
||||
}
|
||||
|
||||
ModuleSections_t moduleSection(".data", m_RunTimeData.m_pSectionBase, m_RunTimeData.m_nSectionSize);
|
||||
|
||||
const auto tableNameInfo = StringToMaskedBytes(szTableName, false);
|
||||
CMemory rttiTypeDescriptor = FindPatternSIMD(tableNameInfo.first.data(), tableNameInfo.second.c_str(), &moduleSection).OffsetSelf(-0x10);
|
||||
if (!rttiTypeDescriptor)
|
||||
return CMemory();
|
||||
@ -314,7 +366,7 @@ CMemory CModule::GetVirtualMethodTable(const string& svTableName, const size_t n
|
||||
|
||||
moduleSection = { ".rdata", m_ReadOnlyData.m_pSectionBase, m_ReadOnlyData.m_nSectionSize };
|
||||
CMemory vfTable = FindPatternSIMD(reinterpret_cast<rsig_t>(&referenceOffset), "xxxxxxxx", &moduleSection).OffsetSelf(0x8);
|
||||
g_SigCache.AddEntry(svPackedTableName, GetRVA(vfTable.GetPtr()));
|
||||
g_SigCache.AddEntry(svPackedTableName.c_str(), GetRVA(vfTable.GetPtr()));
|
||||
|
||||
return vfTable;
|
||||
}
|
||||
@ -323,7 +375,14 @@ CMemory CModule::GetVirtualMethodTable(const string& svTableName, const size_t n
|
||||
}
|
||||
#endif // !PLUGINSDK
|
||||
|
||||
CMemory CModule::GetImportedFunction(const string& svModuleName, const string& svFunctionName, const bool bGetFunctionReference) const
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get address of imported function in target module
|
||||
// Input : *szModuleName -
|
||||
// *szFunctionName -
|
||||
// bGetFunctionReference -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::GetImportedFunction(const char* szModuleName, const char* szFunctionName, const bool bGetFunctionReference) const
|
||||
{
|
||||
if (!m_pDOSHeader || m_pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) // Is dosHeader valid?
|
||||
return CMemory();
|
||||
@ -339,9 +398,9 @@ CMemory CModule::GetImportedFunction(const string& svModuleName, const string& s
|
||||
for (IMAGE_IMPORT_DESCRIPTOR* pIID = pImageImportDescriptors; pIID->Name != 0; pIID++)
|
||||
{
|
||||
// Get virtual relative Address of the imported module name. Then add module base Address to get the actual location.
|
||||
string svImportedModuleName = reinterpret_cast<char*>(reinterpret_cast<DWORD*>(m_pModuleBase + pIID->Name));
|
||||
const char* szImportedModuleName = reinterpret_cast<char*>(reinterpret_cast<DWORD*>(m_pModuleBase + pIID->Name));
|
||||
|
||||
if (IsEqualNoCase(svImportedModuleName, svModuleName)) // Is this our wanted imported module?.
|
||||
if (stricmp(szImportedModuleName, szModuleName) == 0) // Is this our wanted imported module?.
|
||||
{
|
||||
// Original First Thunk to get function name.
|
||||
IMAGE_THUNK_DATA* pOgFirstThunk = reinterpret_cast<IMAGE_THUNK_DATA*>(m_pModuleBase + pIID->OriginalFirstThunk);
|
||||
@ -353,9 +412,7 @@ CMemory CModule::GetImportedFunction(const string& svModuleName, const string& s
|
||||
// Get image import by name.
|
||||
const IMAGE_IMPORT_BY_NAME* pImageImportByName = reinterpret_cast<IMAGE_IMPORT_BY_NAME*>(m_pModuleBase + pOgFirstThunk->u1.AddressOfData);
|
||||
|
||||
// Get import function name.
|
||||
const string svImportedFunctionName = pImageImportByName->Name;
|
||||
if (svImportedFunctionName.compare(svFunctionName) == 0) // Is this our wanted imported function?
|
||||
if (strcmp(pImageImportByName->Name, szFunctionName) == 0) // Is this our wanted imported function?
|
||||
{
|
||||
// Grab function address from firstThunk.
|
||||
uintptr_t* pFunctionAddress = &pFirstThunk->u1.Function;
|
||||
@ -371,11 +428,11 @@ CMemory CModule::GetImportedFunction(const string& svModuleName, const string& s
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get address of exported function in this module
|
||||
// Input : *svFunctionName -
|
||||
// Input : *szFunctionName -
|
||||
// bNullTerminator -
|
||||
// Output : CMemory
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemory CModule::GetExportedFunction(const string& svFunctionName) const
|
||||
CMemory CModule::GetExportedFunction(const char* szFunctionName) const
|
||||
{
|
||||
if (!m_pDOSHeader || m_pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) // Is dosHeader valid?
|
||||
return CMemory();
|
||||
@ -410,9 +467,9 @@ CMemory CModule::GetExportedFunction(const string& svFunctionName) const
|
||||
for (DWORD i = 0; i < pImageExportDirectory->NumberOfFunctions; i++) // Iterate through all the functions.
|
||||
{
|
||||
// Get virtual relative Address of the function name. Then add module base Address to get the actual location.
|
||||
string ExportFunctionName = reinterpret_cast<char*>(reinterpret_cast<DWORD*>(m_pModuleBase + pAddressOfName[i]));
|
||||
const char* ExportFunctionName = reinterpret_cast<char*>(reinterpret_cast<DWORD*>(m_pModuleBase + pAddressOfName[i]));
|
||||
|
||||
if (ExportFunctionName.compare(svFunctionName) == 0) // Is this our wanted exported function?
|
||||
if (strcmp(ExportFunctionName, szFunctionName) == 0) // Is this our wanted exported function?
|
||||
{
|
||||
// Get the function ordinal. Then grab the relative virtual address of our wanted function. Then add module base address so we get the actual location.
|
||||
return CMemory(m_pModuleBase + pAddressOfFunctions[reinterpret_cast<WORD*>(pAddressOfOrdinals)[i]]); // Return as CMemory class.
|
||||
@ -423,14 +480,14 @@ CMemory CModule::GetExportedFunction(const string& svFunctionName) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: get the module section by name (example: '.rdata', '.text')
|
||||
// Input : *svModuleName -
|
||||
// Input : *szSectionName -
|
||||
// Output : ModuleSections_t
|
||||
//-----------------------------------------------------------------------------
|
||||
CModule::ModuleSections_t CModule::GetSectionByName(const string& svSectionName) const
|
||||
CModule::ModuleSections_t CModule::GetSectionByName(const char* szSectionName) const
|
||||
{
|
||||
for (const ModuleSections_t& section : m_vModuleSections)
|
||||
for (const ModuleSections_t& section : m_ModuleSections)
|
||||
{
|
||||
if (section.m_svSectionName == svSectionName)
|
||||
if (section.m_SectionName.compare(szSectionName) == 0)
|
||||
return section;
|
||||
}
|
||||
|
||||
@ -438,33 +495,29 @@ CModule::ModuleSections_t CModule::GetSectionByName(const string& svSectionName)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the module base
|
||||
// Purpose: unlink module from peb
|
||||
//-----------------------------------------------------------------------------
|
||||
uintptr_t CModule::GetModuleBase(void) const
|
||||
void CModule::UnlinkFromPEB() const // Disclaimer: This does not bypass GetMappedFileName. That function calls NtQueryVirtualMemory which does a syscall to ntoskrnl for getting info on a section.
|
||||
{
|
||||
return m_pModuleBase;
|
||||
}
|
||||
#define UNLINK_FROM_PEB(entry) \
|
||||
(entry).Flink->Blink = (entry).Blink; \
|
||||
(entry).Blink->Flink = (entry).Flink;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the module size
|
||||
//-----------------------------------------------------------------------------
|
||||
DWORD CModule::GetModuleSize(void) const
|
||||
{
|
||||
return m_nModuleSize;
|
||||
}
|
||||
const PEB64* processEnvBlock = reinterpret_cast<PEB64*>(__readgsqword(0x60)); // https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
|
||||
const LIST_ENTRY* inLoadOrderList = &processEnvBlock->Ldr->InLoadOrderModuleList;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the module name
|
||||
//-----------------------------------------------------------------------------
|
||||
string CModule::GetModuleName(void) const
|
||||
{
|
||||
return m_svModuleName;
|
||||
}
|
||||
for (LIST_ENTRY* entry = inLoadOrderList->Flink; entry != inLoadOrderList; entry = entry->Flink)
|
||||
{
|
||||
const PLDR_DATA_TABLE_ENTRY pldrEntry = reinterpret_cast<PLDR_DATA_TABLE_ENTRY>(entry->Flink);
|
||||
const std::uintptr_t baseAddr = reinterpret_cast<std::uintptr_t>(pldrEntry->DllBase);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the RVA of given address
|
||||
//-----------------------------------------------------------------------------
|
||||
uintptr_t CModule::GetRVA(const uintptr_t nAddress) const
|
||||
{
|
||||
return (nAddress - GetModuleBase());
|
||||
if (baseAddr != m_pModuleBase)
|
||||
continue;
|
||||
|
||||
UNLINK_FROM_PEB(pldrEntry->InInitializationOrderLinks);
|
||||
UNLINK_FROM_PEB(pldrEntry->InMemoryOrderLinks);
|
||||
UNLINK_FROM_PEB(pldrEntry->InLoadOrderLinks);
|
||||
break;
|
||||
}
|
||||
#undef UNLINK_FROM_PEB
|
||||
}
|
||||
|
@ -38,38 +38,38 @@ void CSigCache::InvalidateMap()
|
||||
return;
|
||||
}
|
||||
|
||||
(*m_Cache.mutable_smap()).clear();
|
||||
m_Cache.mutable_smap()->clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: creates a map of a pattern and relative virtual address
|
||||
// Input : &svPattern - (key)
|
||||
// nRVA - (value)
|
||||
// Input : *szPattern - (key)
|
||||
// nRVA - (value)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSigCache::AddEntry(const string& svPattern, const uint64_t nRVA)
|
||||
void CSigCache::AddEntry(const char* szPattern, const uint64_t nRVA)
|
||||
{
|
||||
if (m_bDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
(*m_Cache.mutable_smap())[svPattern] = nRVA;
|
||||
(*m_Cache.mutable_smap())[szPattern] = nRVA;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: finds a pattern key in the cache map and sets its value to nRVA
|
||||
// Input : &svPattern -
|
||||
// &nRVA -
|
||||
// Input : &szPattern -
|
||||
// &nRVA -
|
||||
// Output : true if key is found, false otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSigCache::FindEntry(const string& svPattern, uint64_t& nRVA) const
|
||||
bool CSigCache::FindEntry(const char* szPattern, uint64_t& nRVA)
|
||||
{
|
||||
if (!m_bDisabled && m_bInitialized)
|
||||
{
|
||||
google::protobuf::Map<string, uint64_t> sMap = m_Cache.smap();
|
||||
auto p = sMap.find(svPattern);
|
||||
google::protobuf::Map<string, uint64_t>* sMap = m_Cache.mutable_smap();
|
||||
auto p = sMap->find(szPattern);
|
||||
|
||||
if (p != sMap.end())
|
||||
if (p != sMap->end())
|
||||
{
|
||||
nRVA = p->second;
|
||||
return true;
|
||||
|
@ -864,13 +864,13 @@ string& StringTrim(string& svInput, const char* pszToTrim, bool bTrimAll)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For converting a string to an array of bytes.
|
||||
vector<int> StringToBytes(const string& svInput, bool bNullTerminator)
|
||||
vector<int> StringToBytes(const char* szInput, bool bNullTerminator)
|
||||
{
|
||||
char* pszStringStart = const_cast<char*>(svInput.c_str());
|
||||
char* pszStringEnd = pszStringStart + strlen(svInput.c_str());
|
||||
vector<int> vBytes = vector<int>{ };
|
||||
const char* pszStringStart = const_cast<char*>(szInput);
|
||||
const char* pszStringEnd = pszStringStart + strlen(szInput);
|
||||
vector<int> vBytes;
|
||||
|
||||
for (char* pszCurrentByte = pszStringStart; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
|
||||
for (const char* pszCurrentByte = pszStringStart; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
|
||||
{
|
||||
// Dereference character and push back the byte.
|
||||
vBytes.push_back(*pszCurrentByte);
|
||||
@ -885,14 +885,14 @@ vector<int> StringToBytes(const string& svInput, bool bNullTerminator)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For converting a string to an array of bytes.
|
||||
pair<vector<uint8_t>, string> StringToMaskedBytes(const string& svInput, bool bNullTerminator)
|
||||
pair<vector<uint8_t>, string> StringToMaskedBytes(const char* szInput, bool bNullTerminator)
|
||||
{
|
||||
char* pszStringStart = const_cast<char*>(svInput.c_str());
|
||||
char* pszStringEnd = pszStringStart + strlen(svInput.c_str());
|
||||
vector<uint8_t> vBytes = vector<uint8_t>{ };
|
||||
string svMask = string();
|
||||
const char* pszStringStart = const_cast<char*>(szInput);
|
||||
const char* pszStringEnd = pszStringStart + strlen(szInput);
|
||||
vector<uint8_t> vBytes;
|
||||
string svMask;
|
||||
|
||||
for (char* pszCurrentByte = pszStringStart; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
|
||||
for (const char* pszCurrentByte = pszStringStart; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
|
||||
{
|
||||
// Dereference character and push back the byte.
|
||||
vBytes.push_back(*pszCurrentByte);
|
||||
@ -921,13 +921,13 @@ string FourCCToString(int n)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For converting a string pattern with wildcards to an array of bytes.
|
||||
vector<int> PatternToBytes(const string& svInput)
|
||||
vector<int> PatternToBytes(const char* szInput)
|
||||
{
|
||||
char* pszPatternStart = const_cast<char*>(svInput.c_str());
|
||||
char* pszPatternEnd = pszPatternStart + strlen(svInput.c_str());
|
||||
vector<int> vBytes = vector<int>{ };
|
||||
const char* pszPatternStart = const_cast<char*>(szInput);
|
||||
const char* pszPatternEnd = pszPatternStart + strlen(szInput);
|
||||
vector<int> vBytes;
|
||||
|
||||
for (char* pszCurrentByte = pszPatternStart; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
|
||||
for (const char* pszCurrentByte = pszPatternStart; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
|
||||
{
|
||||
if (*pszCurrentByte == '?')
|
||||
{
|
||||
@ -940,7 +940,7 @@ vector<int> PatternToBytes(const string& svInput)
|
||||
}
|
||||
else
|
||||
{
|
||||
vBytes.push_back(strtoul(pszCurrentByte, &pszCurrentByte, 16));
|
||||
vBytes.push_back(strtoul(pszCurrentByte, const_cast<char**>(&pszCurrentByte), 16));
|
||||
}
|
||||
}
|
||||
return vBytes;
|
||||
@ -948,14 +948,15 @@ vector<int> PatternToBytes(const string& svInput)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For converting a string pattern with wildcards to an array of bytes and mask.
|
||||
pair<vector<uint8_t>, string> PatternToMaskedBytes(const string& svInput)
|
||||
pair<vector<uint8_t>, string> PatternToMaskedBytes(const char* szInput)
|
||||
{
|
||||
char* pszPatternStart = const_cast<char*>(svInput.c_str());
|
||||
char* pszPatternEnd = pszPatternStart + strlen(svInput.c_str());
|
||||
vector<uint8_t> vBytes = vector<uint8_t>{ };
|
||||
string svMask = string();
|
||||
const char* pszPatternStart = const_cast<char*>(szInput);
|
||||
const char* pszPatternEnd = pszPatternStart + strlen(szInput);
|
||||
|
||||
for (char* pszCurrentByte = pszPatternStart; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
|
||||
vector<uint8_t> vBytes;
|
||||
string svMask;
|
||||
|
||||
for (const char* pszCurrentByte = pszPatternStart; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
|
||||
{
|
||||
if (*pszCurrentByte == '?')
|
||||
{
|
||||
@ -969,7 +970,7 @@ pair<vector<uint8_t>, string> PatternToMaskedBytes(const string& svInput)
|
||||
}
|
||||
else
|
||||
{
|
||||
vBytes.push_back(uint8_t(strtoul(pszCurrentByte, &pszCurrentByte, 16)));
|
||||
vBytes.push_back(uint8_t(strtoul(pszCurrentByte, const_cast<char**>(&pszCurrentByte), 16)));
|
||||
svMask += 'x';
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,8 @@
|
||||
// const std::string& -
|
||||
// uint32_t
|
||||
//-----------------------------------------------------------------------------
|
||||
CVTableHelper::CVTableHelper(CModule* module, const string& tableName, uint32_t refIndex) : m_svVirtualTableName(tableName)
|
||||
CVTableHelper::CVTableHelper(CModule* module, const char* tableName, uint32_t refIndex)
|
||||
: m_svVirtualTableName(tableName)
|
||||
{
|
||||
m_pVirtualTable = module->GetVirtualMethodTable(tableName, refIndex);
|
||||
m_nVirtualFunctionCount = GetVTableLength();
|
||||
@ -26,7 +27,8 @@ CVTableHelper::CVTableHelper(CModule* module, const string& tableName, uint32_t
|
||||
// Input : uintptr_t -
|
||||
// const std::string& -
|
||||
//-----------------------------------------------------------------------------
|
||||
CVTableHelper::CVTableHelper(uintptr_t virtualTable, const string& tableName) : m_pVirtualTable(virtualTable), m_svVirtualTableName(tableName)
|
||||
CVTableHelper::CVTableHelper(uintptr_t virtualTable, const char* tableName)
|
||||
: m_pVirtualTable(virtualTable), m_svVirtualTableName(tableName)
|
||||
{
|
||||
m_nVirtualFunctionCount = GetVTableLength();
|
||||
GetAllVTableFunctions();
|
||||
@ -38,7 +40,8 @@ CVTableHelper::CVTableHelper(uintptr_t virtualTable, const string& tableName) :
|
||||
// Input : void* -
|
||||
// const std::string& -
|
||||
//-----------------------------------------------------------------------------
|
||||
CVTableHelper::CVTableHelper(void* virtualTable, const string& tableName) : m_pVirtualTable(uintptr_t(virtualTable)), m_svVirtualTableName(tableName)
|
||||
CVTableHelper::CVTableHelper(void* virtualTable, const char* tableName)
|
||||
: m_pVirtualTable(uintptr_t(virtualTable)), m_svVirtualTableName(tableName)
|
||||
{
|
||||
m_nVirtualFunctionCount = GetVTableLength();
|
||||
GetAllVTableFunctions();
|
||||
|
267
r5dev/windows/tebpeb64.h
Normal file
267
r5dev/windows/tebpeb64.h
Normal file
@ -0,0 +1,267 @@
|
||||
//
|
||||
// [TEB/PEB UNDER 64-BIT WINDOWS]
|
||||
// This file represents the 64-bit PEB and associated data structures for 64-bit Windows
|
||||
// This PEB is allegedly valid between XP thru [at least] Windows 8
|
||||
//
|
||||
// [REFERENCES]
|
||||
// http://terminus.rewolf.pl/terminus/structures/ntdll/_PEB_x64.html
|
||||
// http://terminus.rewolf.pl/terminus/structures/ntdll/_TEB64_x86.html
|
||||
// https://github.com/giampaolo/psutil/commit/babd2b73538fcb6f3931f0ab6d9c100df6f37bcb (RTL_USER_PROCESS_PARAMETERS)
|
||||
// https://redplait.blogspot.com/2011/09/w8-64bit-teb-peb.html (TEB)
|
||||
//
|
||||
// [CHANGELIST]
|
||||
// 2018-05-02: -now can be compiled alongside windows.h (without changes) or by defining WANT_ALL_WINDOWS_H_DEFINITIONS so this file can be used standalone
|
||||
// -this file may also be included alongside tebpeb32.h which can be found at http://bytepointer.com/resources/tebpeb32.h
|
||||
// -64-bit types no longer clash with the 32-bit ones; e.g. UNICODE_STRING64, RTL_USER_PROCESS_PARAMETERS64, PEB64 (same result whether 32 or 64-bit compiler is used)
|
||||
// -added more QWORD aliases (i.e. HANDLE64 and PTR64) so underlying types are clearer, however most PEB members remain generic QWORD placeholders for now
|
||||
// -fixed missing semicolon bug in UNICODE_STRING64
|
||||
// -added prliminary RTL_USER_PROCESS_PARAMETERS64 and TEB64 with offsets
|
||||
// -included byte offsets for PEB64
|
||||
//
|
||||
// 2017-08-25: initial public release
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// base types
|
||||
//
|
||||
|
||||
#include "Windows.h"
|
||||
|
||||
typedef struct _PEB_LDR_DATA
|
||||
{
|
||||
ULONG Length;
|
||||
BOOLEAN Initialized;
|
||||
HANDLE SsHandle;
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
PVOID EntryInProgress;
|
||||
BOOLEAN ShutdownInProgress;
|
||||
HANDLE ShutdownThreadId;
|
||||
} PEB_LDR_DATA, * PPEB_LDR_DATA;
|
||||
|
||||
//always declare 64-bit types
|
||||
#ifdef _MSC_VER
|
||||
//Visual C++
|
||||
typedef unsigned __int64 QWORD;
|
||||
typedef __int64 INT64;
|
||||
#else
|
||||
//GCC
|
||||
typedef unsigned long long QWORD;
|
||||
typedef long long INT64;
|
||||
#endif
|
||||
typedef QWORD PTR64;
|
||||
|
||||
//UNCOMMENT line below if you are not including windows.h
|
||||
//#define WANT_ALL_WINDOWS_H_DEFINITIONS
|
||||
#ifdef WANT_ALL_WINDOWS_H_DEFINITIONS
|
||||
|
||||
//base types
|
||||
typedef unsigned char BYTE;
|
||||
typedef char CHAR;
|
||||
typedef unsigned short WORD;
|
||||
typedef short INT16;
|
||||
typedef unsigned long DWORD;
|
||||
typedef long INT32;
|
||||
typedef unsigned __int64 QWORD;
|
||||
typedef __int64 INT64;
|
||||
typedef void* HANDLE;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
//base structures
|
||||
union LARGE_INTEGER
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD LowPart;
|
||||
INT32 HighPart;
|
||||
} u;
|
||||
INT64 QuadPart;
|
||||
};
|
||||
|
||||
union ULARGE_INTEGER
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD LowPart;
|
||||
DWORD HighPart;
|
||||
} u;
|
||||
QWORD QuadPart;
|
||||
};
|
||||
|
||||
#endif //#ifdef WANT_ALL_WINDOWS_H_DEFINITIONS
|
||||
|
||||
struct UNICODE_STRING64
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
WORD Length;
|
||||
WORD MaximumLength;
|
||||
} u;
|
||||
QWORD dummyalign;
|
||||
};
|
||||
QWORD Buffer;
|
||||
};
|
||||
|
||||
typedef struct _CLIENT_ID64
|
||||
{
|
||||
QWORD ProcessId;
|
||||
QWORD ThreadId;
|
||||
} CLIENT_ID64;
|
||||
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY
|
||||
{
|
||||
LIST_ENTRY InLoadOrderLinks;
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
union
|
||||
{
|
||||
LIST_ENTRY InInitializationOrderLinks;
|
||||
LIST_ENTRY InProgressLinks;
|
||||
};
|
||||
PVOID DllBase;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STRING64 FullDllName;
|
||||
UNICODE_STRING64 BaseDllName;
|
||||
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;// [ PIXIE ]: Narrowed down version, don't need full.
|
||||
|
||||
//NOTE: the members of this structure are not yet complete
|
||||
typedef struct _RTL_USER_PROCESS_PARAMETERS64
|
||||
{
|
||||
BYTE Reserved1[16]; //0x00
|
||||
QWORD Reserved2[5]; //0x10
|
||||
UNICODE_STRING64 CurrentDirectoryPath; //0x38
|
||||
QWORD CurrentDirectoryHandle; //0x48
|
||||
UNICODE_STRING64 DllPath; //0x50
|
||||
UNICODE_STRING64 ImagePathName; //0x60
|
||||
UNICODE_STRING64 CommandLine; //0x70
|
||||
PTR64 Environment; //0x80
|
||||
} RTL_USER_PROCESS_PARAMETERS64;
|
||||
|
||||
//
|
||||
// PEB64 structure - TODO: comb more through http://terminus.rewolf.pl/terminus/structures/ntdll/_PEB_x64.html and add OS delineations and Windows 10 updates
|
||||
//
|
||||
// The structure represented here is a work-in-progress as only members thru offset 0x320 are listed; the actual sizes per OS are:
|
||||
// 0x0358 XP/WS03
|
||||
// 0x0368 Vista
|
||||
// 0x037C Windows 7
|
||||
// 0x0388 Windows 8
|
||||
// 0x07A0 Windows 10
|
||||
//
|
||||
struct PEB64
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE InheritedAddressSpace; //0x000
|
||||
BYTE ReadImageFileExecOptions; //0x001
|
||||
BYTE BeingDebugged; //0x002
|
||||
BYTE _SYSTEM_DEPENDENT_01; //0x003
|
||||
} flags;
|
||||
QWORD dummyalign;
|
||||
} dword0;
|
||||
QWORD Mutant; //0x0008
|
||||
QWORD ImageBaseAddress; //0x0010
|
||||
PPEB_LDR_DATA Ldr; //0x0018
|
||||
PTR64 ProcessParameters; //0x0020 / pointer to RTL_USER_PROCESS_PARAMETERS64
|
||||
QWORD SubSystemData; //0x0028
|
||||
QWORD ProcessHeap; //0x0030
|
||||
QWORD FastPebLock; //0x0038
|
||||
QWORD _SYSTEM_DEPENDENT_02; //0x0040
|
||||
QWORD _SYSTEM_DEPENDENT_03; //0x0048
|
||||
QWORD _SYSTEM_DEPENDENT_04; //0x0050
|
||||
union
|
||||
{
|
||||
QWORD KernelCallbackTable; //0x0058
|
||||
QWORD UserSharedInfoPtr; //0x0058
|
||||
};
|
||||
DWORD SystemReserved; //0x0060
|
||||
DWORD _SYSTEM_DEPENDENT_05; //0x0064
|
||||
QWORD _SYSTEM_DEPENDENT_06; //0x0068
|
||||
QWORD TlsExpansionCounter; //0x0070
|
||||
QWORD TlsBitmap; //0x0078
|
||||
DWORD TlsBitmapBits[2]; //0x0080
|
||||
QWORD ReadOnlySharedMemoryBase; //0x0088
|
||||
QWORD _SYSTEM_DEPENDENT_07; //0x0090
|
||||
QWORD ReadOnlyStaticServerData; //0x0098
|
||||
QWORD AnsiCodePageData; //0x00A0
|
||||
QWORD OemCodePageData; //0x00A8
|
||||
QWORD UnicodeCaseTableData; //0x00B0
|
||||
DWORD NumberOfProcessors; //0x00B8
|
||||
union
|
||||
{
|
||||
DWORD NtGlobalFlag; //0x00BC
|
||||
DWORD dummy02; //0x00BC
|
||||
};
|
||||
LARGE_INTEGER CriticalSectionTimeout; //0x00C0
|
||||
QWORD HeapSegmentReserve; //0x00C8
|
||||
QWORD HeapSegmentCommit; //0x00D0
|
||||
QWORD HeapDeCommitTotalFreeThreshold; //0x00D8
|
||||
QWORD HeapDeCommitFreeBlockThreshold; //0x00E0
|
||||
DWORD NumberOfHeaps; //0x00E8
|
||||
DWORD MaximumNumberOfHeaps; //0x00EC
|
||||
QWORD ProcessHeaps; //0x00F0
|
||||
QWORD GdiSharedHandleTable; //0x00F8
|
||||
QWORD ProcessStarterHelper; //0x0100
|
||||
QWORD GdiDCAttributeList; //0x0108
|
||||
QWORD LoaderLock; //0x0110
|
||||
DWORD OSMajorVersion; //0x0118
|
||||
DWORD OSMinorVersion; //0x011C
|
||||
WORD OSBuildNumber; //0x0120
|
||||
WORD OSCSDVersion; //0x0122
|
||||
DWORD OSPlatformId; //0x0124
|
||||
DWORD ImageSubsystem; //0x0128
|
||||
DWORD ImageSubsystemMajorVersion; //0x012C
|
||||
QWORD ImageSubsystemMinorVersion; //0x0130
|
||||
union
|
||||
{
|
||||
QWORD ImageProcessAffinityMask; //0x0138
|
||||
QWORD ActiveProcessAffinityMask; //0x0138
|
||||
};
|
||||
QWORD GdiHandleBuffer[30]; //0x0140
|
||||
QWORD PostProcessInitRoutine; //0x0230
|
||||
QWORD TlsExpansionBitmap; //0x0238
|
||||
DWORD TlsExpansionBitmapBits[32]; //0x0240
|
||||
QWORD SessionId; //0x02C0
|
||||
ULARGE_INTEGER AppCompatFlags; //0x02C8
|
||||
ULARGE_INTEGER AppCompatFlagsUser; //0x02D0
|
||||
QWORD pShimData; //0x02D8
|
||||
QWORD AppCompatInfo; //0x02E0
|
||||
UNICODE_STRING64 CSDVersion; //0x02E8
|
||||
QWORD ActivationContextData; //0x02F8
|
||||
QWORD ProcessAssemblyStorageMap; //0x0300
|
||||
QWORD SystemDefaultActivationContextData; //0x0308
|
||||
QWORD SystemAssemblyStorageMap; //0x0310
|
||||
QWORD MinimumStackCommit; //0x0318
|
||||
|
||||
}; //struct PEB64
|
||||
|
||||
//
|
||||
// TEB64 structure - preliminary structure; the portion listed current at least as of Windows 8
|
||||
//
|
||||
struct TEB64
|
||||
{
|
||||
BYTE NtTib[56]; //0x0000 / NT_TIB64 structure
|
||||
PTR64 EnvironmentPointer; //0x0038
|
||||
CLIENT_ID64 ClientId; //0x0040
|
||||
PTR64 ActiveRpcHandle; //0x0050
|
||||
PTR64 ThreadLocalStoragePointer; //0x0058
|
||||
PTR64 ProcessEnvironmentBlock; //0x0060 / ptr to PEB64
|
||||
DWORD LastErrorValue; //0x0068
|
||||
DWORD CountOfOwnedCriticalSections; //0x006C
|
||||
PTR64 CsrClientThread; //0x0070
|
||||
PTR64 Win32ThreadInfo; //0x0078
|
||||
DWORD User32Reserved[26]; //0x0080
|
||||
DWORD UserReserved[6]; //0x00E8
|
||||
PTR64 WOW32Reserved; //0x0100
|
||||
DWORD CurrentLocale; //0x0108
|
||||
DWORD FpSoftwareStatusRegister; //0x010C
|
||||
PTR64 SystemReserved1[54]; //0x0110
|
||||
DWORD ExceptionCode; //0x02C0
|
||||
PTR64 ActivationContextStackPointer; //0x02C8
|
||||
|
||||
}; //struct TEB64
|
Loading…
x
Reference in New Issue
Block a user