mirror of
https://github.com/BeneficialCode/WinArk
synced 2026-08-09 12:00:31 +00:00
fix the inline hook scan bug
This commit is contained in:
+73
-80
@@ -45,9 +45,10 @@ PEParser::PEParser(const wchar_t* path, bool isScylla) :_path(path) {
|
||||
}
|
||||
}
|
||||
|
||||
PEParser::PEParser(void* base) {
|
||||
PEParser::PEParser(void* base, SIZE_T mappedSize) {
|
||||
_address = reinterpret_cast<PUCHAR>(base);
|
||||
_moduleBase = (DWORD_PTR)base;
|
||||
_fileSize.QuadPart = static_cast<LONGLONG>(mappedSize);
|
||||
_isFileMap = false;
|
||||
CheckValidity();
|
||||
if (IsValid()) {
|
||||
@@ -56,13 +57,13 @@ PEParser::PEParser(void* base) {
|
||||
}
|
||||
|
||||
void PEParser::GetSectionHeaders() {
|
||||
ReleaseSectionData();
|
||||
_PESections.clear();
|
||||
int count = GetSectionCount();
|
||||
_PESections.reserve(count);
|
||||
|
||||
PEFileSection peFileSection;
|
||||
|
||||
for (WORD i = 0; i < count; i++) {
|
||||
PEFileSection peFileSection;
|
||||
memcpy_s(&peFileSection._sectionHeader, sizeof(IMAGE_SECTION_HEADER), &_sections[i], sizeof(IMAGE_SECTION_HEADER));
|
||||
_PESections.push_back(peFileSection);
|
||||
}
|
||||
@@ -73,10 +74,13 @@ HANDLE PEParser::GetFileHandle() {
|
||||
}
|
||||
|
||||
PEParser::~PEParser() {
|
||||
ReleaseSectionData();
|
||||
if (_resModule)
|
||||
::FreeLibrary(_resModule);
|
||||
if (_hMemMap) {
|
||||
::UnmapViewOfFile(_address);
|
||||
if (_address) {
|
||||
::UnmapViewOfFile(_address);
|
||||
}
|
||||
::CloseHandle(_hMemMap);
|
||||
}
|
||||
if (_hFile != INVALID_HANDLE_VALUE)
|
||||
@@ -440,6 +444,15 @@ void PEParser::CheckValidity() {
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void PEParser::ReleaseSectionData() {
|
||||
for (auto& section : _PESections) {
|
||||
delete[] section._pData;
|
||||
section._pData = nullptr;
|
||||
section._dataSize = 0;
|
||||
section._normalSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned PEParser::RvaToFileOffset(unsigned rva) const {
|
||||
for (int i = 0; i < GetSectionCount(); ++i) {
|
||||
if (rva >= _PESections[i]._sectionHeader.VirtualAddress && rva <
|
||||
@@ -886,12 +899,20 @@ bool PEParser::DumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR*
|
||||
}
|
||||
|
||||
void PEParser::GetPESections() {
|
||||
DWORD_PTR offset = 0;
|
||||
const int count = GetSectionCount();
|
||||
if (count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int count = GetSectionCount();
|
||||
_PESections.reserve(count);
|
||||
if (static_cast<int>(_PESections.size()) != count) {
|
||||
GetSectionHeaders();
|
||||
}
|
||||
else {
|
||||
ReleaseSectionData();
|
||||
}
|
||||
|
||||
for (WORD i = 0; i < count; i++) {
|
||||
DWORD_PTR offset = 0;
|
||||
if (_isFileMap) {
|
||||
_PESections[i]._normalSize = _sections[i].SizeOfRawData;
|
||||
_PESections[i]._dataSize = _sections[i].SizeOfRawData;
|
||||
@@ -919,63 +940,28 @@ DWORD PEParser::IsMemoryNotNull(BYTE* pData, int dataSize) {
|
||||
}
|
||||
|
||||
void PEParser::GetPESectionData(DWORD_PTR offset, PEFileSection& peFileSection) {
|
||||
const DWORD maxReadSize = 100;
|
||||
DWORD currentReadSize;
|
||||
DWORD valuesFound = 0;
|
||||
DWORD readSize = 0;
|
||||
DWORD_PTR currentOffset = 0;
|
||||
BYTE data[maxReadSize] = { 0 };
|
||||
|
||||
peFileSection._dataSize = 0;
|
||||
peFileSection._pData = nullptr;
|
||||
readSize = peFileSection._normalSize;
|
||||
const DWORD readSize = peFileSection._normalSize;
|
||||
if (!readSize || !offset) {
|
||||
// section without data is valid
|
||||
return;
|
||||
}
|
||||
|
||||
if (readSize <= maxReadSize) {
|
||||
peFileSection._dataSize = readSize;
|
||||
peFileSection._normalSize = readSize;
|
||||
peFileSection._pData = new BYTE[peFileSection._dataSize];
|
||||
memcpy(peFileSection._pData, _address + offset, peFileSection._dataSize);
|
||||
const BYTE* sectionData = _address + offset;
|
||||
DWORD lastNonZero = readSize;
|
||||
while (lastNonZero > 0 && sectionData[lastNonZero - 1] == 0) {
|
||||
--lastNonZero;
|
||||
}
|
||||
|
||||
if (!lastNonZero) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentReadSize = readSize % maxReadSize;
|
||||
if (!currentReadSize) {
|
||||
currentReadSize = maxReadSize;
|
||||
}
|
||||
currentOffset = offset + readSize - currentReadSize;
|
||||
|
||||
while (currentOffset >= offset) {
|
||||
ZeroMemory(data, currentReadSize);
|
||||
memcpy(data, _address + currentOffset, currentReadSize);
|
||||
valuesFound = IsMemoryNotNull(data, currentReadSize);
|
||||
if (valuesFound) {
|
||||
// found some real code
|
||||
currentOffset += valuesFound;
|
||||
if (offset < currentOffset) {
|
||||
// real size
|
||||
peFileSection._dataSize = (DWORD)(currentOffset - offset);
|
||||
|
||||
peFileSection._dataSize += sizeof(DWORD);
|
||||
|
||||
if (peFileSection._normalSize < peFileSection._dataSize) {
|
||||
peFileSection._dataSize = peFileSection._normalSize;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
currentReadSize = maxReadSize;
|
||||
currentOffset -= currentReadSize;
|
||||
}
|
||||
|
||||
if (peFileSection._dataSize) {
|
||||
peFileSection._pData = new BYTE[peFileSection._dataSize];
|
||||
memcpy(peFileSection._pData, _address + offset, peFileSection._dataSize);
|
||||
peFileSection._dataSize = (std::min)(readSize, lastNonZero + static_cast<DWORD>(sizeof(DWORD)));
|
||||
peFileSection._pData = new BYTE[peFileSection._dataSize];
|
||||
if (peFileSection._pData) {
|
||||
memcpy(peFileSection._pData, sectionData, peFileSection._dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1011,16 +997,20 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
bool ret = true;
|
||||
|
||||
DWORD fileOffset = 0, writeSize = 0;
|
||||
HANDLE outputFile = INVALID_HANDLE_VALUE;
|
||||
const WORD sectionCount = static_cast<WORD>(GetSectionCount());
|
||||
|
||||
do
|
||||
{
|
||||
ret = OpenWriteFileHandle(pNewFile);
|
||||
if (!ret)
|
||||
outputFile = pNewFile ? ::CreateFile(pNewFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0) : _hFile;
|
||||
ret = outputFile != INVALID_HANDLE_VALUE;
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
|
||||
writeSize = sizeof(IMAGE_DOS_HEADER);
|
||||
|
||||
if (!WriteMemoryToFile(_hFile, fileOffset, writeSize, GetBaseAddress())) {
|
||||
if (!WriteMemoryToFile(outputFile, fileOffset, writeSize, GetBaseAddress())) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -1035,7 +1025,7 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
BYTE* pDosStub = GetDosStub();
|
||||
if (pDosStub) {
|
||||
writeSize = dosStubSize;
|
||||
if (!WriteMemoryToFile(_hFile, fileOffset, writeSize, pDosStub)) {
|
||||
if (!WriteMemoryToFile(outputFile, fileOffset, writeSize, pDosStub)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -1045,14 +1035,14 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
|
||||
if (!IsPe64()) {
|
||||
writeSize = sizeof(IMAGE_NT_HEADERS32);
|
||||
if (!WriteMemoryToFile(_hFile, fileOffset, writeSize, &_ntHeader32Copy)) {
|
||||
if (!WriteMemoryToFile(outputFile, fileOffset, writeSize, &_ntHeader32Copy)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
writeSize = sizeof(IMAGE_NT_HEADERS64);
|
||||
if (!WriteMemoryToFile(_hFile, fileOffset, writeSize, &_ntHeader64Copy)) {
|
||||
if (!WriteMemoryToFile(outputFile, fileOffset, writeSize, &_ntHeader64Copy)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -1063,8 +1053,8 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
|
||||
writeSize = sizeof(IMAGE_SECTION_HEADER);
|
||||
|
||||
for (WORD i = 0; i < GetSectionCount(); i++) {
|
||||
if (!WriteMemoryToFile(_hFile, fileOffset, writeSize, &_PESections[i]._sectionHeader)) {
|
||||
for (WORD i = 0; i < sectionCount; i++) {
|
||||
if (!WriteMemoryToFile(outputFile, fileOffset, writeSize, &_PESections[i]._sectionHeader)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -1072,7 +1062,7 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
}
|
||||
|
||||
|
||||
for (WORD i = 0; i < GetSectionCount(); i++) {
|
||||
for (WORD i = 0; i < sectionCount; i++) {
|
||||
if (!_PESections[i]._sectionHeader.PointerToRawData)
|
||||
continue;
|
||||
|
||||
@@ -1080,7 +1070,7 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
// padding
|
||||
writeSize = _PESections[i]._sectionHeader.PointerToRawData - fileOffset;
|
||||
|
||||
if (!WriteZeroMemoryToFile(_hFile, fileOffset, writeSize)) {
|
||||
if (!WriteZeroMemoryToFile(outputFile, fileOffset, writeSize)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -1090,7 +1080,7 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
writeSize = _PESections[i]._dataSize;
|
||||
|
||||
if (writeSize) {
|
||||
if (!WriteMemoryToFile(_hFile, _PESections[i]._sectionHeader.PointerToRawData,
|
||||
if (!WriteMemoryToFile(outputFile, _PESections[i]._sectionHeader.PointerToRawData,
|
||||
writeSize, _PESections[i]._pData)) {
|
||||
ret = false;
|
||||
break;
|
||||
@@ -1100,7 +1090,7 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
if (_PESections[i]._dataSize < _PESections[i]._sectionHeader.SizeOfRawData) {
|
||||
// padding
|
||||
writeSize = _PESections[i]._sectionHeader.SizeOfRawData - _PESections[i]._dataSize;
|
||||
if (!WriteZeroMemoryToFile(_hFile, fileOffset, writeSize)) {
|
||||
if (!WriteZeroMemoryToFile(outputFile, fileOffset, writeSize)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -1112,13 +1102,13 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
DWORD overlayOffset = GetSectionHeaderBasedFileSize();
|
||||
|
||||
LARGE_INTEGER fileSize = GetFileSize();
|
||||
if (fileSize.QuadPart > 0) {
|
||||
DWORD overlaySize = fileSize.QuadPart - overlayOffset;
|
||||
if (_isFileMap && fileSize.QuadPart > overlayOffset) {
|
||||
DWORD overlaySize = static_cast<DWORD>(fileSize.QuadPart - overlayOffset);
|
||||
|
||||
if (overlaySize) {
|
||||
writeSize = overlaySize;
|
||||
BYTE* pOverlayData = GetFileAddress(overlayOffset);
|
||||
if (!WriteMemoryToFile(_hFile, fileOffset, writeSize, pOverlayData)) {
|
||||
if (!WriteMemoryToFile(outputFile, fileOffset, writeSize, pOverlayData)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -1126,26 +1116,29 @@ bool PEParser::SavePEFileToDisk(const WCHAR* pNewFile) {
|
||||
}
|
||||
}
|
||||
|
||||
SetEndOfFile(_hFile);
|
||||
SetEndOfFile(outputFile);
|
||||
} while (false);
|
||||
|
||||
|
||||
if (_hFile != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(_hFile);
|
||||
_hFile = INVALID_HANDLE_VALUE;
|
||||
if (outputFile != INVALID_HANDLE_VALUE && outputFile != _hFile) {
|
||||
CloseHandle(outputFile);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PEParser::WriteZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size) {
|
||||
bool ret = false;
|
||||
PVOID pZeroMemory = calloc(size, 1);
|
||||
constexpr DWORD kZeroChunkSize = 64 * 1024;
|
||||
BYTE zeroBuffer[kZeroChunkSize] = {};
|
||||
|
||||
if (pZeroMemory) {
|
||||
ret = WriteMemoryToFile(hFile, fileOffset, size, pZeroMemory);
|
||||
free(pZeroMemory);
|
||||
while (size) {
|
||||
const DWORD chunkSize = (std::min)(size, kZeroChunkSize);
|
||||
if (!WriteMemoryToFile(hFile, fileOffset, chunkSize, zeroBuffer)) {
|
||||
return false;
|
||||
}
|
||||
fileOffset += chunkSize;
|
||||
size -= chunkSize;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-2
@@ -168,7 +168,7 @@ class PEParser {
|
||||
public:
|
||||
explicit PEParser(const wchar_t* path,bool isScylla = false);
|
||||
~PEParser();
|
||||
PEParser(void* base);
|
||||
PEParser(void* base, SIZE_T mappedSize = 0);
|
||||
|
||||
bool IsValid() const;
|
||||
bool IsPe64() const;
|
||||
@@ -278,6 +278,7 @@ protected:
|
||||
private:
|
||||
bool IsObjectPe64() const;
|
||||
void CheckValidity();
|
||||
void ReleaseSectionData();
|
||||
|
||||
|
||||
//CString GetResourceName(void* data) const;
|
||||
@@ -304,4 +305,4 @@ private:
|
||||
bool _valid = false;
|
||||
bool _importLib = false, _objectFile = false;
|
||||
bool _isFileMap = true;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -64,15 +64,21 @@ ImagehlpSymbol::~ImagehlpSymbol() {
|
||||
|
||||
SymbolHandler::SymbolHandler(HANDLE hProcess, PCSTR searchPath,DWORD symOptions){
|
||||
m_hProcess = hProcess;
|
||||
if (m_hProcess != INVALID_HANDLE_VALUE && m_hProcess != ::GetCurrentProcess()) {
|
||||
::SymSetOptions(symOptions);
|
||||
_initialized = ::SymInitialize(m_hProcess, searchPath, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
SymbolHandler::~SymbolHandler() {
|
||||
if (_initialized)
|
||||
::SymCleanup(m_hProcess);
|
||||
if (m_hProcess != ::GetCurrentProcess())
|
||||
::CloseHandle(m_hProcess);
|
||||
}
|
||||
|
||||
ULONG64 SymbolHandler::LoadSymbolsForModule(PCSTR imageName, PCSTR moduleName, DWORD64 baseAddress,DWORD dllSize) {
|
||||
_address = SymLoadModuleEx(m_hProcess, nullptr, imageName, nullptr, baseAddress, dllSize, nullptr, 0);
|
||||
_address = SymLoadModuleEx(m_hProcess, nullptr, imageName, moduleName, baseAddress, dllSize, nullptr, 0);
|
||||
return _address;
|
||||
}
|
||||
|
||||
@@ -219,10 +225,13 @@ BOOL SymbolHandler::Callback(ULONG code, ULONG64 data) {
|
||||
}
|
||||
|
||||
std::unique_ptr<SymbolHandler> SymbolHandler::CreateForProcess(DWORD pid, PCSTR searchPath) {
|
||||
auto hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, pid);
|
||||
auto hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, FALSE, pid);
|
||||
if (!hProcess)
|
||||
return nullptr;
|
||||
return std::make_unique<SymbolHandler>(hProcess, searchPath);
|
||||
auto handler = std::make_unique<SymbolHandler>(hProcess, searchPath);
|
||||
if (!handler->_initialized)
|
||||
return nullptr;
|
||||
return handler;
|
||||
}
|
||||
|
||||
ULONG SymbolHandler::GetStructSize(std::string name) {
|
||||
@@ -292,4 +301,4 @@ DWORD SymbolHandler::GetBitFieldPos(std::string name, std::string fieldName) {
|
||||
free(childrenParams);
|
||||
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,5 +213,6 @@ private:
|
||||
|
||||
HANDLE m_hProcess{ INVALID_HANDLE_VALUE };
|
||||
DWORD64 _address{ 0 };
|
||||
bool _initialized{ false };
|
||||
static inline bool _first = false;
|
||||
};
|
||||
};
|
||||
|
||||
+127
-130
@@ -3,6 +3,31 @@
|
||||
#include <PEParser.h>
|
||||
#include "Helpers.h"
|
||||
|
||||
namespace {
|
||||
DWORD_PTR GetPageSizeCached() {
|
||||
static DWORD_PTR s_pageSize = [] {
|
||||
SYSTEM_INFO si = {};
|
||||
::GetSystemInfo(&si);
|
||||
return static_cast<DWORD_PTR>(si.dwPageSize);
|
||||
}();
|
||||
return s_pageSize;
|
||||
}
|
||||
|
||||
DWORD_PTR GetPageBaseCached(DWORD_PTR address) {
|
||||
const auto pageSize = GetPageSizeCached();
|
||||
return address & ~(pageSize - 1);
|
||||
}
|
||||
|
||||
ImportModuleThunk* FindModuleThunkByRva(std::map<DWORD_PTR, ImportModuleThunk>& moduleMap, DWORD_PTR rva) {
|
||||
auto it = moduleMap.upper_bound(rva);
|
||||
if (it == moduleMap.begin()) {
|
||||
return nullptr;
|
||||
}
|
||||
--it;
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void ApiReader::ReadApisFromModuleList() {
|
||||
for (unsigned int i = 0; i < _moduleList.size(); i++) {
|
||||
SetModulePriority(&_moduleList[i]);
|
||||
@@ -319,34 +344,7 @@ bool ApiReader::AddFunctionToModuleList(ApiInfo* pApiFound, DWORD_PTR va, DWORD_
|
||||
WORD ordinal, bool valid, bool suspect)
|
||||
{
|
||||
ImportThunk thunk;
|
||||
ImportModuleThunk* pModuleThunk = nullptr;
|
||||
std::map<DWORD_PTR, ImportModuleThunk>::iterator iter;
|
||||
|
||||
if (_moduleThunkMap->size() > 1) {
|
||||
iter = _moduleThunkMap->begin();
|
||||
while (iter != _moduleThunkMap->end()) {
|
||||
if (rva >= iter->second.m_FirstThunk) {
|
||||
iter++;
|
||||
if (iter == _moduleThunkMap->end()) {
|
||||
iter--;
|
||||
pModuleThunk = &iter->second;
|
||||
break;
|
||||
}
|
||||
else if (rva < iter->second.m_FirstThunk) {
|
||||
iter--;
|
||||
pModuleThunk = &iter->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
iter = _moduleThunkMap->begin();
|
||||
pModuleThunk = &iter->second;
|
||||
}
|
||||
ImportModuleThunk* pModuleThunk = FindModuleThunkByRva(*_moduleThunkMap, rva);
|
||||
|
||||
if (!pModuleThunk) {
|
||||
return false;
|
||||
@@ -370,41 +368,37 @@ bool ApiReader::AddFunctionToModuleList(ApiInfo* pApiFound, DWORD_PTR va, DWORD_
|
||||
bool ApiReader::AddNotFoundApiToModuleList(DWORD_PTR iat, DWORD_PTR apiAddress)
|
||||
{
|
||||
ImportThunk thunk;
|
||||
ImportModuleThunk* pModuleThunk = nullptr;
|
||||
std::map<DWORD_PTR, ImportModuleThunk>::iterator iter;
|
||||
DWORD_PTR rva = iat - _targetImageBase;
|
||||
ImportModuleThunk* pModuleThunk = nullptr;
|
||||
auto next = _moduleThunkMap->upper_bound(rva);
|
||||
|
||||
if (_moduleThunkMap->size() > 0) {
|
||||
iter = _moduleThunkMap->begin();
|
||||
while (iter != _moduleThunkMap->end()) {
|
||||
if (rva >= iter->second.m_FirstThunk) {
|
||||
iter++;
|
||||
if (iter == _moduleThunkMap->end()) {
|
||||
iter--;
|
||||
if (iter->second.m_ModuleName[0] == L'?') {
|
||||
pModuleThunk = &iter->second;
|
||||
}
|
||||
else {
|
||||
AddUnknownModuleToModuleList(rva);
|
||||
pModuleThunk = &(_moduleThunkMap->find(rva)->second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (rva < iter->second.m_FirstThunk) {
|
||||
iter--;
|
||||
pModuleThunk = &iter->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (next == _moduleThunkMap->begin()) {
|
||||
AddUnknownModuleToModuleList(rva);
|
||||
pModuleThunk = &(_moduleThunkMap->find(rva)->second);
|
||||
}
|
||||
else {
|
||||
auto prev = next;
|
||||
--prev;
|
||||
if (next == _moduleThunkMap->end()) {
|
||||
if (prev->second.m_ModuleName[0] == L'?') {
|
||||
pModuleThunk = &prev->second;
|
||||
}
|
||||
else {
|
||||
AddUnknownModuleToModuleList(rva);
|
||||
pModuleThunk = &(_moduleThunkMap->find(rva)->second);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pModuleThunk = &prev->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pModuleThunk) {
|
||||
if (_moduleThunkMap->empty()) {
|
||||
AddUnknownModuleToModuleList(rva);
|
||||
pModuleThunk = &(_moduleThunkMap->find(rva)->second);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pModuleThunk) {
|
||||
return false;
|
||||
@@ -627,12 +621,10 @@ ApiInfo* ApiReader::GetApiByVirtualAddress(DWORD_PTR virtualAddress, bool* pIsSu
|
||||
void ApiReader::ReadAndParseIAT(DWORD_PTR iat, DWORD size, std::map<DWORD_PTR, ImportModuleThunk>& moduleListNew)
|
||||
{
|
||||
_moduleThunkMap = &moduleListNew;
|
||||
BYTE* pIAT = new BYTE[size];
|
||||
if (ReadMemoryFromProcess(iat, size, pIAT)) {
|
||||
ParseIAT(iat, pIAT, size);
|
||||
std::unique_ptr<BYTE[]> pIAT(new BYTE[size]);
|
||||
if (ReadMemoryFromProcess(iat, size, pIAT.get())) {
|
||||
ParseIAT(iat, pIAT.get(), size);
|
||||
}
|
||||
|
||||
delete[] pIAT;
|
||||
}
|
||||
|
||||
void ApiReader::AddFoundApiToModuleList(DWORD_PTR iat, ApiInfo* pApiFound, bool isNewModule, bool isSuspect)
|
||||
@@ -675,76 +667,81 @@ bool ApiReader::IsInvalidMemoryForIAT(DWORD_PTR address)
|
||||
}
|
||||
|
||||
void ApiReader::ParseIAT(DWORD_PTR iat, BYTE* pIAT, SIZE_T size) {
|
||||
ApiInfo* pApiFound = nullptr;
|
||||
ModuleInfo* pModule = nullptr;
|
||||
bool isSuspect = false;
|
||||
int countApiFound = 0, countApiNotFound = 0;
|
||||
DWORD_PTR* p64 = (DWORD_PTR*)pIAT;
|
||||
DWORD* p32 = reinterpret_cast<DWORD*>(pIAT);
|
||||
SIZE_T iatSize = 0;
|
||||
DWORD pointerSize = 0;
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
if (isWow64) {
|
||||
pointerSize = 4;
|
||||
iatSize = size / pointerSize;
|
||||
for (SIZE_T i = 0; i < iatSize; i++) {
|
||||
if (!IsInvalidMemoryForIAT(p32[i])) {
|
||||
if (p32[i] > _minApiAddress && p32[i] < _maxApiAddress) {
|
||||
pApiFound = GetApiByVirtualAddress(p32[i], &isSuspect);
|
||||
if (pApiFound != nullptr) {
|
||||
countApiFound++;
|
||||
if (pModule != pApiFound->pModule) {
|
||||
pModule = pApiFound->pModule;
|
||||
AddFoundApiToModuleList(iat + (DWORD_PTR)&p32[i] - (DWORD_PTR)pIAT, pApiFound, true, isSuspect);
|
||||
}
|
||||
else {
|
||||
AddFoundApiToModuleList(iat + (DWORD_PTR)&p32[i] - (DWORD_PTR)pIAT, pApiFound, false, isSuspect);
|
||||
}
|
||||
}
|
||||
else {
|
||||
countApiNotFound++;
|
||||
AddNotFoundApiToModuleList(iat + (DWORD_PTR)&p32[i] - (DWORD_PTR)pIAT, p32[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
countApiNotFound++;
|
||||
AddNotFoundApiToModuleList(iat + (DWORD_PTR)&p32[i] - (DWORD_PTR)pIAT, p32[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
pointerSize = 8;
|
||||
iatSize = size / pointerSize;
|
||||
for (SIZE_T i = 0; i < iatSize; i++) {
|
||||
if (!IsInvalidMemoryForIAT(p64[i])) {
|
||||
if (p64[i] > _minApiAddress && p64[i] < _maxApiAddress) {
|
||||
pApiFound = GetApiByVirtualAddress(p64[i], &isSuspect);
|
||||
if (pApiFound != nullptr) {
|
||||
countApiFound++;
|
||||
if (pModule != pApiFound->pModule) {
|
||||
pModule = pApiFound->pModule;
|
||||
AddFoundApiToModuleList(iat + (DWORD_PTR)&p64[i] - (DWORD_PTR)pIAT, pApiFound, true, isSuspect);
|
||||
}
|
||||
else {
|
||||
AddFoundApiToModuleList(iat + (DWORD_PTR)&p64[i] - (DWORD_PTR)pIAT, pApiFound, false, isSuspect);
|
||||
}
|
||||
}
|
||||
else {
|
||||
countApiNotFound++;
|
||||
AddNotFoundApiToModuleList(iat + (DWORD_PTR)&p64[i] - (DWORD_PTR)pIAT, p64[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
countApiNotFound++;
|
||||
AddNotFoundApiToModuleList(iat + (DWORD_PTR)&p64[i] - (DWORD_PTR)pIAT, p64[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const DWORD pointerSize = isWow64 ? sizeof(DWORD) : sizeof(DWORD_PTR);
|
||||
const SIZE_T iatSize = size / pointerSize;
|
||||
std::unordered_map<DWORD_PTR, bool> pageValidityCache;
|
||||
pageValidityCache.reserve(iatSize);
|
||||
struct ApiLookupResult {
|
||||
ApiInfo* api{ nullptr };
|
||||
bool suspect{ false };
|
||||
};
|
||||
std::unordered_map<DWORD_PTR, ApiLookupResult> apiLookupCache;
|
||||
apiLookupCache.reserve(iatSize);
|
||||
|
||||
|
||||
auto isInvalidAddress = [&](DWORD_PTR address) {
|
||||
if (address == 0 || address == static_cast<DWORD_PTR>(-1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const DWORD_PTR pageBase = GetPageBaseCached(address);
|
||||
auto cacheIt = pageValidityCache.find(pageBase);
|
||||
if (cacheIt != pageValidityCache.end()) {
|
||||
return cacheIt->second;
|
||||
}
|
||||
|
||||
MEMORY_BASIC_INFORMATION mbi = {};
|
||||
if (!::VirtualQueryEx(_hProcess, reinterpret_cast<LPVOID>(address), &mbi, sizeof(mbi))) {
|
||||
pageValidityCache.emplace(pageBase, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool invalid = !(mbi.State == MEM_COMMIT && IsPageAccessable(mbi.Protect));
|
||||
const DWORD_PTR regionStart = reinterpret_cast<DWORD_PTR>(mbi.BaseAddress);
|
||||
const DWORD_PTR regionEnd = regionStart + mbi.RegionSize;
|
||||
const DWORD_PTR pageSize = GetPageSizeCached();
|
||||
for (DWORD_PTR current = regionStart; current < regionEnd; current += pageSize) {
|
||||
pageValidityCache.emplace(current, invalid);
|
||||
}
|
||||
return invalid;
|
||||
};
|
||||
|
||||
auto getApiInfo = [&](DWORD_PTR apiAddress, bool& isSuspect) -> ApiInfo* {
|
||||
auto [it, inserted] = apiLookupCache.emplace(apiAddress, ApiLookupResult{});
|
||||
if (inserted) {
|
||||
it->second.api = GetApiByVirtualAddress(apiAddress, &it->second.suspect);
|
||||
}
|
||||
isSuspect = it->second.suspect;
|
||||
return it->second.api;
|
||||
};
|
||||
|
||||
for (SIZE_T i = 0; i < iatSize; i++) {
|
||||
const DWORD_PTR thunkAddress = iat + i * pointerSize;
|
||||
const DWORD_PTR apiAddress = isWow64
|
||||
? static_cast<DWORD_PTR>(reinterpret_cast<DWORD*>(pIAT)[i])
|
||||
: reinterpret_cast<DWORD_PTR*>(pIAT)[i];
|
||||
|
||||
if (isInvalidAddress(apiAddress)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isSuspect = false;
|
||||
ApiInfo* pApiFound = nullptr;
|
||||
if (apiAddress > _minApiAddress && apiAddress < _maxApiAddress) {
|
||||
pApiFound = getApiInfo(apiAddress, isSuspect);
|
||||
}
|
||||
|
||||
if (pApiFound != nullptr) {
|
||||
const bool isNewModule = pModule != pApiFound->pModule;
|
||||
pModule = pApiFound->pModule;
|
||||
AddFoundApiToModuleList(thunkAddress, pApiFound, isNewModule, isSuspect);
|
||||
}
|
||||
else {
|
||||
AddNotFoundApiToModuleList(thunkAddress, apiAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApiReader::AddApi(const char* pName, WORD hint, WORD ordinal,
|
||||
@@ -866,4 +863,4 @@ void ApiReader::AddUnknownModuleToModuleList(DWORD_PTR firstThunk) {
|
||||
wcscpy_s(thunk.m_ModuleName, L"?");
|
||||
|
||||
_moduleThunkMap->insert(std::pair<DWORD_PTR, ImportModuleThunk>(firstThunk, thunk));
|
||||
}
|
||||
}
|
||||
|
||||
+23
-48
@@ -1,6 +1,14 @@
|
||||
#include "stdafx.h"
|
||||
#include "IATSearcher.h"
|
||||
|
||||
namespace {
|
||||
DWORD GetTargetPointerSize(HANDLE hProcess) {
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(hProcess, &isWow64);
|
||||
return isWow64 ? sizeof(DWORD) : sizeof(DWORD_PTR);
|
||||
}
|
||||
}
|
||||
|
||||
bool IATSearcher::SearchImportAddressTableInProcess(DWORD_PTR startAddress, DWORD_PTR* pIAT, DWORD* pSize, bool advance) {
|
||||
DWORD_PTR addressInIAT = 0;
|
||||
*pIAT = 0;
|
||||
@@ -24,6 +32,7 @@ bool IATSearcher::FindIATAdvanced(DWORD_PTR startAddress, DWORD_PTR* pIAT, DWORD
|
||||
std::unique_ptr<BYTE[]> buffer;
|
||||
DWORD_PTR baseAddress;
|
||||
SIZE_T memorySize;
|
||||
const DWORD pointerSize = GetTargetPointerSize(_hProcess);
|
||||
|
||||
FindExecutableMemoryPagesByStartAddress(startAddress, &baseAddress, &memorySize);
|
||||
|
||||
@@ -67,16 +76,6 @@ bool IATSearcher::FindIATAdvanced(DWORD_PTR startAddress, DWORD_PTR* pIAT, DWORD
|
||||
*pIAT = start;
|
||||
iter = iatPointers.end();
|
||||
DWORD_PTR end = *(--iter);
|
||||
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
DWORD pointerSize = 0;
|
||||
if (isWow64) {
|
||||
pointerSize = 4;
|
||||
}
|
||||
else {
|
||||
pointerSize = 8;
|
||||
}
|
||||
*pSize = (DWORD)(end - start + pointerSize);
|
||||
|
||||
if (*pSize > (2000000 * pointerSize)) {
|
||||
@@ -141,6 +140,8 @@ DWORD_PTR IATSearcher::FindNextFunctionAddress() {
|
||||
}
|
||||
|
||||
DWORD_PTR IATSearcher::FindIATPointer() {
|
||||
const bool is32BitTarget = GetTargetPointerSize(_hProcess) == sizeof(DWORD);
|
||||
|
||||
for (unsigned int i = 0; i < _instCount; i++) {
|
||||
if (_insts[i].flags == FLAG_NOT_DECODABLE) {
|
||||
continue;
|
||||
@@ -149,9 +150,7 @@ DWORD_PTR IATSearcher::FindIATPointer() {
|
||||
if (META_GET_FC(_insts[i].meta) == FC_CALL
|
||||
|| META_GET_FC(_insts[i].meta) == FC_UNC_BRANCH) {
|
||||
if (_insts[i].size >= 5) {
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
if (isWow64) {
|
||||
if (is32BitTarget) {
|
||||
if (_insts[i].ops[0].type == O_DISP) {
|
||||
// jmp dword ptr || call dword ptr
|
||||
return _insts[i].disp;
|
||||
@@ -172,15 +171,7 @@ DWORD_PTR IATSearcher::FindIATPointer() {
|
||||
|
||||
bool IATSearcher::IsIATPointerValid(DWORD_PTR iatPointer, bool checkRedirects) {
|
||||
DWORD_PTR apiAddress = 0;
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
DWORD pointerSize = 0;
|
||||
if (isWow64) {
|
||||
pointerSize = 4;
|
||||
}
|
||||
else {
|
||||
pointerSize = 8;
|
||||
}
|
||||
const DWORD pointerSize = GetTargetPointerSize(_hProcess);
|
||||
if (!ReadMemoryFromProcess(iatPointer, pointerSize, &apiAddress)) {
|
||||
return false;
|
||||
}
|
||||
@@ -212,23 +203,11 @@ bool IATSearcher::FindIATStartAndSize(DWORD_PTR address, DWORD_PTR* pIAT, DWORD*
|
||||
if (!baseAddress)
|
||||
return false;
|
||||
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
DWORD pointerSize = 0;
|
||||
if (isWow64) {
|
||||
pointerSize = 4;
|
||||
}
|
||||
else {
|
||||
pointerSize = 8;
|
||||
}
|
||||
size_t size = baseSize * pointerSize * 3;
|
||||
buffer = std::make_unique<BYTE[]>(size);
|
||||
buffer = std::make_unique<BYTE[]>(baseSize);
|
||||
|
||||
if (!buffer)
|
||||
return false;
|
||||
|
||||
ZeroMemory(buffer.get(), size);
|
||||
|
||||
if (!ReadMemoryFromProcess(baseAddress, baseSize, buffer.get())) {
|
||||
return false;
|
||||
}
|
||||
@@ -240,10 +219,7 @@ bool IATSearcher::FindIATStartAndSize(DWORD_PTR address, DWORD_PTR* pIAT, DWORD*
|
||||
}
|
||||
|
||||
DWORD_PTR IATSearcher::FindIATStartAddress(DWORD_PTR baseAddress, DWORD_PTR startAddress, BYTE* pData) {
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
DWORD pointerSize = 0;
|
||||
if (isWow64) {
|
||||
if (GetTargetPointerSize(_hProcess) == sizeof(DWORD)) {
|
||||
DWORD* p32 = nullptr;
|
||||
|
||||
p32 = (DWORD*)((startAddress - baseAddress) + (DWORD_PTR)pData);
|
||||
@@ -298,13 +274,12 @@ DWORD_PTR IATSearcher::FindIATStartAddress(DWORD_PTR baseAddress, DWORD_PTR star
|
||||
DWORD IATSearcher::FindIATSize(DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE* pData, DWORD dataSize) {
|
||||
PBYTE* pIATAddress = nullptr;
|
||||
pIATAddress = (PBYTE*)((iatAddress - baseAddress) + (DWORD_PTR)pData);
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
DWORD* p32 = (DWORD*)pIATAddress;
|
||||
DWORD_PTR* p64 = (DWORD_PTR*)pIATAddress;
|
||||
const BYTE* end = pData + dataSize;
|
||||
|
||||
if (isWow64) {
|
||||
while ((DWORD_PTR)p32 < ((DWORD_PTR)pData + dataSize - 1)) {
|
||||
if (GetTargetPointerSize(_hProcess) == sizeof(DWORD)) {
|
||||
while (reinterpret_cast<const BYTE*>(p32 + 2) < end) {
|
||||
if (IsInvalidMemoryForIAT(*p32)) {
|
||||
if (IsInvalidMemoryForIAT(*(p32 + 1))) {
|
||||
DWORD_PTR apiAddress = *(p32 + 2);
|
||||
@@ -317,7 +292,7 @@ DWORD IATSearcher::FindIATSize(DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE
|
||||
}
|
||||
}
|
||||
else {
|
||||
while ((DWORD_PTR)p64 < ((DWORD_PTR)pData + dataSize - 1)) {
|
||||
while (reinterpret_cast<const BYTE*>(p64 + 2) < end) {
|
||||
if (IsInvalidMemoryForIAT(*p64)) {
|
||||
if (IsInvalidMemoryForIAT(*(p64 + 1))) {
|
||||
DWORD_PTR apiAddress = *(p64 + 2);
|
||||
@@ -334,14 +309,14 @@ DWORD IATSearcher::FindIATSize(DWORD_PTR baseAddress, DWORD_PTR iatAddress, BYTE
|
||||
}
|
||||
|
||||
void IATSearcher::FindIATPointers(std::set<DWORD_PTR>& iatPointers) {
|
||||
const bool is32BitTarget = GetTargetPointerSize(_hProcess) == sizeof(DWORD);
|
||||
|
||||
for (unsigned int i = 0; i < _instCount; i++) {
|
||||
if (_insts[i].flags != FLAG_NOT_DECODABLE) {
|
||||
uint16_t fc = META_GET_FC(_insts[i].meta);
|
||||
if (fc == FC_CALL || fc == FC_UNC_BRANCH) {
|
||||
if (_insts[i].size >= 5) {
|
||||
BOOL isWow64 = FALSE;
|
||||
::IsWow64Process(_hProcess, &isWow64);
|
||||
if (isWow64) {
|
||||
if (is32BitTarget) {
|
||||
if (_insts[i].ops[0].type == O_DISP) {
|
||||
iatPointers.insert((DWORD_PTR)_insts[i].disp);
|
||||
}
|
||||
@@ -521,4 +496,4 @@ void IATSearcher::GetMemoryBaseAndSizeForIAT(DWORD_PTR address, DWORD_PTR* pBase
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-59
@@ -3,6 +3,17 @@
|
||||
#include "ImportsHandling.h"
|
||||
#include "Architecture.h"
|
||||
|
||||
namespace {
|
||||
ImportModuleThunk* FindModuleThunkByRva(std::map<DWORD_PTR, ImportModuleThunk>& moduleMap, DWORD_PTR rva) {
|
||||
auto it = moduleMap.upper_bound(rva);
|
||||
if (it == moduleMap.begin()) {
|
||||
return nullptr;
|
||||
}
|
||||
--it;
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void ImportsHandling::SetItemData(CTreeItem item, const TreeItemData* pData)
|
||||
{
|
||||
ItemDataMap[item] = *pData;
|
||||
@@ -147,41 +158,27 @@ bool ImportsHandling::AddNotFoundApiToModuleList(const ImportThunk* pApiNotFound
|
||||
ImportModuleThunk* pModule = nullptr;
|
||||
DWORD_PTR rva = pApiNotFound->m_RVA;
|
||||
|
||||
if (m_ModuleMapNew.size() > 0) {
|
||||
auto it_module = m_ModuleMapNew.begin();
|
||||
while (it_module != m_ModuleMapNew.end()) {
|
||||
if (rva >= it_module->second.m_FirstThunk) {
|
||||
it_module++;
|
||||
if (it_module == m_ModuleMapNew.end()) {
|
||||
it_module--;
|
||||
//new unknown module
|
||||
if (it_module->second.m_ModuleName[0] == L'?')
|
||||
{
|
||||
pModule = &(it_module->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddUnknownModuleToModuleList(pApiNotFound->m_RVA);
|
||||
pModule = &(m_ModuleMapNew.find(rva)->second);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (rva < it_module->second.m_FirstThunk) {
|
||||
it_module--;
|
||||
pModule = &(it_module->second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto next = m_ModuleMapNew.upper_bound(rva);
|
||||
if (next == m_ModuleMapNew.begin()) {
|
||||
AddUnknownModuleToModuleList(pApiNotFound->m_RVA);
|
||||
pModule = &(m_ModuleMapNew.find(rva)->second);
|
||||
}
|
||||
else {
|
||||
auto prev = next;
|
||||
--prev;
|
||||
if (next == m_ModuleMapNew.end()) {
|
||||
if (prev->second.m_ModuleName[0] == L'?') {
|
||||
pModule = &(prev->second);
|
||||
}
|
||||
else {
|
||||
AddUnknownModuleToModuleList(pApiNotFound->m_RVA);
|
||||
pModule = &(m_ModuleMapNew.find(rva)->second);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pModule = &(prev->second);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pModule) {
|
||||
return false;
|
||||
@@ -207,33 +204,8 @@ bool ImportsHandling::AddNotFoundApiToModuleList(const ImportThunk* pApiNotFound
|
||||
bool ImportsHandling::AddFunctionToModuleList(const ImportThunk* pApiFound)
|
||||
{
|
||||
ImportThunk import;
|
||||
ImportModuleThunk* pModule = nullptr;
|
||||
DWORD_PTR rva = pApiFound->m_RVA;
|
||||
auto it_module = m_ModuleMapNew.begin();
|
||||
if (m_ModuleMapNew.size() > 1) {
|
||||
while (it_module != m_ModuleMapNew.end()) {
|
||||
if (rva >= it_module->second.m_FirstThunk) {
|
||||
it_module++;
|
||||
if (it_module == m_ModuleMapNew.end()) {
|
||||
it_module--;
|
||||
pModule = &(it_module->second);
|
||||
break;
|
||||
}
|
||||
else if (rva < it_module->second.m_FirstThunk) {
|
||||
it_module--;
|
||||
pModule = &(it_module->second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
it_module = m_ModuleMapNew.begin();
|
||||
pModule = &(it_module->second);
|
||||
}
|
||||
ImportModuleThunk* pModule = FindModuleThunkByRva(m_ModuleMapNew, rva);
|
||||
|
||||
if (!pModule) {
|
||||
return false;
|
||||
@@ -334,6 +306,7 @@ void ImportsHandling::DisplayAllImports()
|
||||
std::map<DWORD_PTR, ImportModuleThunk>::iterator it_module;
|
||||
std::map<DWORD_PTR, ImportThunk>::iterator it_import;
|
||||
|
||||
TreeImports.SetRedraw(FALSE);
|
||||
TreeImports.DeleteAllItems();
|
||||
ItemDataMap.clear();
|
||||
TreeImports.SetImageList(TreeIcons);
|
||||
@@ -357,6 +330,8 @@ void ImportsHandling::DisplayAllImports()
|
||||
it_module++;
|
||||
}
|
||||
|
||||
TreeImports.SetRedraw(TRUE);
|
||||
TreeImports.Invalidate();
|
||||
UpdateCounts();
|
||||
}
|
||||
|
||||
@@ -570,7 +545,7 @@ void ImportsHandling::ScanAndFixModuleList()
|
||||
it_module++;
|
||||
}
|
||||
|
||||
m_ModuleMap = m_ModuleMapNew;
|
||||
m_ModuleMap.swap(m_ModuleMapNew);
|
||||
m_ModuleMapNew.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -748,6 +748,7 @@ void CProcessInlineHookTable::Refresh() {
|
||||
m_Items = GetItems();
|
||||
m_ModuleTracker.EnumModules();
|
||||
m_Modules = m_ModuleTracker.GetModules();
|
||||
std::unordered_map<ULONG_PTR, bool> moduleArchCache;
|
||||
|
||||
m_Sys64Modules.clear();
|
||||
m_Table.data.n = 0;
|
||||
@@ -784,9 +785,24 @@ void CProcessInlineHookTable::Refresh() {
|
||||
if (m != nullptr) {
|
||||
moduleSize = m->ModuleSize;
|
||||
moduleBase = (ULONG_PTR)m->Base;
|
||||
std::wstring path = m->Path;
|
||||
PEParser parser(path.c_str());
|
||||
isX64Module = parser.IsPe64();
|
||||
auto it = moduleArchCache.find(moduleBase);
|
||||
if (it != moduleArchCache.end()) {
|
||||
isX64Module = it->second;
|
||||
}
|
||||
else {
|
||||
const SIZE_T headerSize = std::min<SIZE_T>(moduleSize, 0x4000);
|
||||
if (headerSize != 0) {
|
||||
std::vector<BYTE> moduleHeader(headerSize);
|
||||
SIZE_T bytesRead = 0;
|
||||
if (::ReadProcessMemory(m_hProcess, m->Base, moduleHeader.data(), headerSize, &bytesRead) && bytesRead == headerSize) {
|
||||
PEParser parser(moduleHeader.data(), headerSize);
|
||||
if (parser.IsValid()) {
|
||||
isX64Module = parser.IsPe64();
|
||||
}
|
||||
}
|
||||
}
|
||||
moduleArchCache.emplace(moduleBase, isX64Module);
|
||||
}
|
||||
|
||||
//uint32_t image_size = parser.GetImageSize();
|
||||
//local_image_base = ::VirtualAlloc(nullptr, image_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
+22
-37
@@ -9,6 +9,7 @@
|
||||
#include "PickDLLDlg.h"
|
||||
#include "TreeImportExport.h"
|
||||
#include <Helpers.h>
|
||||
#include <memory>
|
||||
|
||||
|
||||
CScyllaDlg::CScyllaDlg(const WinSys::ProcessManager& pm, ProcessInfoEx& px)
|
||||
@@ -207,7 +208,7 @@ void CScyllaDlg::IATAutoSearchActionHandler() {
|
||||
SetDialogIATAddressAndSize(addressIAT, sizeIAT);
|
||||
}
|
||||
else if (addressIAT == 0 && addressIATAdv != 0) {
|
||||
SetDialogIATAddressAndSize(addressIATAdv, sizeIAT);
|
||||
SetDialogIATAddressAndSize(addressIATAdv, sizeIATAdv);
|
||||
}
|
||||
else if (addressIAT != 0 && addressIATAdv != 0) {
|
||||
if (addressIAT != addressIATAdv || sizeIAT != sizeIATAdv) {
|
||||
@@ -284,51 +285,49 @@ void CScyllaDlg::OnDump(UINT uNotifyCode, int nID, CWindow wndCtl) {
|
||||
void CScyllaDlg::DumpHandler() {
|
||||
WCHAR filePath[MAX_PATH] = { 0 };
|
||||
WCHAR defaultFileName[MAX_PATH] = { 0 };
|
||||
const WCHAR* pFileFilter;
|
||||
const WCHAR* pDefExtension;
|
||||
const bool isModuleDump = ProcessAccessHelper::_pSelectedModule != nullptr;
|
||||
const WCHAR* pFileFilter = isModuleDump ? s_FilterDll : s_FilterExe;
|
||||
const WCHAR* pDefExtension = isModuleDump ? L"dll" : L"exe";
|
||||
DWORD_PTR modBase = 0;
|
||||
SIZE_T modSize = 0;
|
||||
DWORD_PTR entryPoint = 0;
|
||||
WCHAR fileName[MAX_PATH] = { 0 };
|
||||
|
||||
if (ProcessAccessHelper::_pSelectedModule) {
|
||||
pFileFilter = s_FilterDll;
|
||||
pDefExtension = L"dll";
|
||||
}
|
||||
else {
|
||||
pFileFilter = s_FilterExe;
|
||||
pDefExtension = L"exe";
|
||||
}
|
||||
|
||||
GetCurrentModulePath(_text, _countof(_text));
|
||||
GetCurrentDefaultDumpFilename(defaultFileName, _countof(defaultFileName));
|
||||
if (ShowFileDialog(filePath, true, defaultFileName, pFileFilter, pDefExtension, _text)) {
|
||||
entryPoint = _oepAddress.GetValue();
|
||||
|
||||
if (ProcessAccessHelper::_pSelectedModule) {
|
||||
if (isModuleDump) {
|
||||
modBase = ProcessAccessHelper::_pSelectedModule->_modBaseAddr;
|
||||
wcscpy_s(fileName, ProcessAccessHelper::_pSelectedModule->_fullPath);
|
||||
modSize = ProcessAccessHelper::_pSelectedModule->_modBaseSize;
|
||||
}
|
||||
else {
|
||||
modBase = ProcessAccessHelper::_targetImageBase;
|
||||
wcscpy_s(fileName, m_px.GetExecutablePath().c_str());
|
||||
modSize = ProcessAccessHelper::_targetSizeOfImage;
|
||||
}
|
||||
|
||||
void* pImageBase = new BYTE[modSize];
|
||||
if (!modBase || !modSize) {
|
||||
MessageBox(L"Invalid module range.", L"Failure", MB_ICONERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessAccessHelper::ReadMemoryFromProcess(modBase, modSize, pImageBase);
|
||||
auto imageBuffer = std::make_unique<BYTE[]>(modSize);
|
||||
if (!ProcessAccessHelper::ReadMemoryFromProcess(modBase, modSize, imageBuffer.get()) &&
|
||||
!ProcessAccessHelper::ReadMemoryPartlyFromProcess(modBase, modSize, imageBuffer.get())) {
|
||||
MessageBox(L"Cannot read image from process memory.", L"Failure", MB_ICONERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
PEParser parser(pImageBase);
|
||||
PEParser parser(imageBuffer.get(), modSize);
|
||||
if (parser.IsValid()) {
|
||||
bool success = parser.DumpProcess(modBase, entryPoint, filePath);
|
||||
if (!success) {
|
||||
MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] pImageBase;
|
||||
else {
|
||||
MessageBox(L"Invalid PE image in process memory.", L"Failure", MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,18 +421,7 @@ void CScyllaDlg::FixDumpHandler() {
|
||||
|
||||
WCHAR newFilePath[MAX_PATH] = { 0 };
|
||||
WCHAR selectedFilePath[MAX_PATH] = { 0 };
|
||||
const WCHAR* pFileFilter = nullptr;
|
||||
DWORD_PTR modBase = 0;
|
||||
DWORD_PTR entryPoint = _oepAddress.GetValue();
|
||||
|
||||
if (ProcessAccessHelper::_pSelectedModule) {
|
||||
modBase = ProcessAccessHelper::_pSelectedModule->_modBaseAddr;
|
||||
pFileFilter = s_FilterDll;
|
||||
}
|
||||
else {
|
||||
modBase = ProcessAccessHelper::_targetImageBase;
|
||||
pFileFilter = s_FilterExe;
|
||||
}
|
||||
const WCHAR* pFileFilter = ProcessAccessHelper::_pSelectedModule ? s_FilterDll : s_FilterExe;
|
||||
|
||||
GetCurrentModulePath(_text, _countof(_text));
|
||||
if (ShowFileDialog(selectedFilePath, false, nullptr, pFileFilter, nullptr, _text)) {
|
||||
@@ -464,13 +452,10 @@ void CScyllaDlg::OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl) {
|
||||
}
|
||||
|
||||
void CScyllaDlg::PERebuildHandler() {
|
||||
DWORD newSize = 0;
|
||||
WCHAR selectedFilePath[MAX_PATH] = { 0 };
|
||||
|
||||
GetCurrentModulePath(_text, _countof(_text));
|
||||
if (ShowFileDialog(selectedFilePath, false, nullptr, s_FilterExeDll, nullptr, _text)) {
|
||||
DWORD fileSize = ProcessAccessHelper::GetFileSize(selectedFilePath);
|
||||
|
||||
PEParser parser(selectedFilePath, true);
|
||||
|
||||
if (!parser.IsValid()) {
|
||||
@@ -738,7 +723,7 @@ void CScyllaDlg::LoadTreeHandler() {
|
||||
|
||||
}
|
||||
else {
|
||||
swprintf_s(_text, L"Are you sure? Replace the OEP, IAT, and IAT size with %p %p %x",
|
||||
swprintf_s(_text, L"Are you sure? Replace the OEP, IAT, and IAT size with " PRINTF_DWORD_PTR_FULL L" " PRINTF_DWORD_PTR_FULL L" %x",
|
||||
oep, iat, iatSize);
|
||||
|
||||
int result = MessageBox(_text, L"Confirmation", MB_YESNO | MB_ICONQUESTION);
|
||||
|
||||
Reference in New Issue
Block a user