Page MenuHomedesp's stash

No OneTemporary

diff --git a/Scylla/ApiReader.h b/Scylla/ApiReader.h
index d42fc35..2fe0a4d 100644
--- a/Scylla/ApiReader.h
+++ b/Scylla/ApiReader.h
@@ -1,74 +1,74 @@
#pragma once
#include <windows.h>
#include <map>
#include <hash_map>
#include "ProcessAccessHelp.h"
#include "Thunks.h"
typedef std::pair<DWORD_PTR, ApiInfo *> API_Pair;
class ApiReader : public ProcessAccessHelp
{
public:
static stdext::hash_multimap<DWORD_PTR, ApiInfo *> apiList; //api look up table
static std::map<DWORD_PTR, ImportModuleThunk> * moduleThunkList; //store found apis
static DWORD_PTR minApiAddress;
static DWORD_PTR maxApiAddress;
/*
* Read all APIs from target process
*/
void readApisFromModuleList();
bool isApiAddressValid(DWORD_PTR virtualAddress);
ApiInfo * getApiByVirtualAddress(DWORD_PTR virtualAddress, bool * isSuspect);
void readAndParseIAT(DWORD_PTR addressIAT, DWORD sizeIAT, std::map<DWORD_PTR, ImportModuleThunk> &moduleListNew );
-
+ void addFoundApiToModuleList(DWORD_PTR iatAddress, ApiInfo * apiFound, bool isNewModule, bool isSuspect);
void clearAll();
private:
void parseIAT(DWORD_PTR addressIAT, BYTE * iatBuffer, SIZE_T size);
void addApi(char *functionName, WORD hint, WORD ordinal, DWORD_PTR va, DWORD_PTR rva, bool isForwarded, ModuleInfo *moduleInfo);
void addApiWithoutName(WORD ordinal, DWORD_PTR va, DWORD_PTR rva,bool isForwarded, ModuleInfo *moduleInfo);
inline bool isApiForwarded(DWORD_PTR rva, PIMAGE_NT_HEADERS pNtHeader);
void handleForwardedApi(DWORD_PTR vaStringPointer,char *functionNameParent,DWORD_PTR rvaParent, WORD ordinalParent, ModuleInfo *moduleParent);
void parseModule(ModuleInfo *module);
void parseModuleWithProcess(ModuleInfo * module);
void parseExportTable(ModuleInfo *module, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress);
ModuleInfo * findModuleByName(WCHAR *name);
void findApiByModuleAndOrdinal(ModuleInfo * module, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
void findApiByModuleAndName(ModuleInfo * module, char * searchFunctionName, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
void findApiByModule(ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
bool isModuleLoadedInOwnProcess( ModuleInfo * module );
void parseModuleWithOwnProcess( ModuleInfo * module );
bool isPeAndExportTableValid(PIMAGE_NT_HEADERS pNtHeader);
void findApiInProcess( ModuleInfo * module, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi );
bool findApiInExportTable(ModuleInfo *module, PIMAGE_EXPORT_DIRECTORY pExportDir, DWORD_PTR deltaAddress, char * searchFunctionName, WORD ordinal, DWORD_PTR * vaApi, DWORD_PTR * rvaApi);
BYTE * getHeaderFromProcess(ModuleInfo * module);
BYTE * getExportTableFromProcess(ModuleInfo * module, PIMAGE_NT_HEADERS pNtHeader);
void setModulePriority(ModuleInfo * module);
void setMinMaxApiAddress(DWORD_PTR virtualAddress);
void parseModuleWithMapping(ModuleInfo *moduleInfo); //not used
- void addFoundApiToModuleList(DWORD_PTR iatAddress, ApiInfo * apiFound, bool isNewModule, bool isSuspect);
+
bool addModuleToModuleList(const WCHAR * moduleName, DWORD_PTR firstThunk);
bool addFunctionToModuleList(ApiInfo * apiFound, DWORD_PTR va, DWORD_PTR rva, WORD ordinal, bool valid, bool suspect);
bool addNotFoundApiToModuleList(DWORD_PTR iatAddressVA, DWORD_PTR apiAddress);
void addUnknownModuleToModuleList(DWORD_PTR firstThunk);
bool isApiBlacklisted( const char * functionName );
bool isWinSxSModule( ModuleInfo * module );
ApiInfo * getScoredApi(stdext::hash_map<DWORD_PTR, ApiInfo *>::iterator it1,size_t countDuplicates, bool hasName, bool hasUnicodeAnsiName, bool hasNoUnderlineInName, bool hasPrioDll,bool hasPrio0Dll,bool hasPrio1Dll, bool hasPrio2Dll, bool firstWin );
};
diff --git a/Scylla/IATReferenceScan.cpp b/Scylla/IATReferenceScan.cpp
index 723e58d..f37b93a 100644
--- a/Scylla/IATReferenceScan.cpp
+++ b/Scylla/IATReferenceScan.cpp
@@ -1,659 +1,714 @@
#include "IATReferenceScan.h"
#include "Scylla.h"
#include "Architecture.h"
+#include <set>
//#define DEBUG_COMMENTS
FileLog IATReferenceScan::directImportLog(L"Scylla_direct_imports.log");
int IATReferenceScan::numberOfFoundDirectImports()
{
return (int)iatDirectImportList.size();
}
+int IATReferenceScan::numberOfFoundUniqueDirectImports()
+{
+ std::set<DWORD_PTR> apiPointers;
+ for (std::vector<IATReference>::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++)
+ {
+ IATReference * ref = &(*iter);
+ apiPointers.insert(ref->targetAddressInIat);
+ }
+
+ return (int)apiPointers.size();
+}
+
+int IATReferenceScan::numberOfDirectImportApisNotInIat()
+{
+ std::set<DWORD_PTR> apiPointers;
+ for (std::vector<IATReference>::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++)
+ {
+ IATReference * ref = &(*iter);
+
+ if (ref->targetPointer == 0)
+ {
+ apiPointers.insert(ref->targetAddressInIat);
+ }
+ }
+
+ return (int)apiPointers.size();
+}
+
int IATReferenceScan::getSizeInBytesOfJumpTableInSection()
{
return ((int)iatDirectImportList.size() * 6); //for x86 and x64 the same size
}
void IATReferenceScan::startScan(DWORD_PTR imageBase, DWORD imageSize, DWORD_PTR iatAddress, DWORD iatSize)
{
MEMORY_BASIC_INFORMATION memBasic = {0};
IatAddressVA = iatAddress;
IatSize = iatSize;
ImageBase = imageBase;
ImageSize = imageSize;
if (ScanForNormalImports)
{
iatReferenceList.clear();
iatReferenceList.reserve(200);
}
if (ScanForDirectImports)
{
iatDirectImportList.clear();
iatDirectImportList.reserve(50);
}
DWORD_PTR section = imageBase;
do
{
if (!VirtualQueryEx(ProcessAccessHelp::hProcess, (LPCVOID)section, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"VirtualQueryEx failed %d", GetLastError());
#endif
break;
}
else
{
if (isPageExecutable(memBasic.Protect))
{
//do read and scan
scanMemoryPage(memBasic.BaseAddress, memBasic.RegionSize);
}
}
section = (DWORD_PTR)((SIZE_T)section + memBasic.RegionSize);
} while (section < (imageBase + imageSize));
}
//void IATReferenceScan::patchNewIatBaseMemory(DWORD_PTR newIatBaseAddress)
//{
// NewIatAddressVA = newIatBaseAddress;
//
// for (std::vector<IATReference>::iterator iter = iatReferenceList.begin(); iter != iatReferenceList.end(); iter++)
// {
// patchReferenceInMemory(&(*iter));
// }
//}
//
//void IATReferenceScan::patchNewIatBaseFile(DWORD_PTR newIatBaseAddress)
//{
// NewIatAddressVA = newIatBaseAddress;
//
// for (std::vector<IATReference>::iterator iter = iatReferenceList.begin(); iter != iatReferenceList.end(); iter++)
// {
// patchReferenceInFile(&(*iter));
// }
//}
void IATReferenceScan::patchDirectImportsMemory( bool junkByteAfterInstruction )
{
JunkByteAfterInstruction = junkByteAfterInstruction;
for (std::vector<IATReference>::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++)
{
patchDirectImportInMemory(&(*iter));
}
}
bool IATReferenceScan::isPageExecutable( DWORD Protect )
{
if (Protect & PAGE_NOCACHE) Protect ^= PAGE_NOCACHE;
if (Protect & PAGE_WRITECOMBINE) Protect ^= PAGE_WRITECOMBINE;
switch(Protect)
{
case PAGE_EXECUTE:
{
return true;
}
case PAGE_EXECUTE_READ:
{
return true;
}
case PAGE_EXECUTE_READWRITE:
{
return true;
}
case PAGE_EXECUTE_WRITECOPY:
{
return true;
}
default:
return false;
}
}
void IATReferenceScan::scanMemoryPage( PVOID BaseAddress, SIZE_T RegionSize )
{
BYTE * dataBuffer = (BYTE *)calloc(RegionSize, 1);
BYTE * currentPos = dataBuffer;
int currentSize = (int)RegionSize;
DWORD_PTR currentOffset = (DWORD_PTR)BaseAddress;
_DecodeResult res;
unsigned int instructionsCount = 0, next = 0;
if (!dataBuffer)
return;
if (ProcessAccessHelp::readMemoryFromProcess((DWORD_PTR)BaseAddress, RegionSize, (LPVOID)dataBuffer))
{
while (1)
{
ZeroMemory(&ProcessAccessHelp::decomposerCi, sizeof(_CodeInfo));
ProcessAccessHelp::decomposerCi.code = currentPos;
ProcessAccessHelp::decomposerCi.codeLen = currentSize;
ProcessAccessHelp::decomposerCi.dt = ProcessAccessHelp::dt;
ProcessAccessHelp::decomposerCi.codeOffset = currentOffset;
instructionsCount = 0;
res = distorm_decompose(&ProcessAccessHelp::decomposerCi, ProcessAccessHelp::decomposerResult, sizeof(ProcessAccessHelp::decomposerResult)/sizeof(ProcessAccessHelp::decomposerResult[0]), &instructionsCount);
if (res == DECRES_INPUTERR)
{
break;
}
for (unsigned int i = 0; i < instructionsCount; i++)
{
if (ProcessAccessHelp::decomposerResult[i].flags != FLAG_NOT_DECODABLE)
{
analyzeInstruction(&ProcessAccessHelp::decomposerResult[i]);
}
}
if (res == DECRES_SUCCESS) break; // All instructions were decoded.
else if (instructionsCount == 0) break;
next = (unsigned long)(ProcessAccessHelp::decomposerResult[instructionsCount-1].addr - ProcessAccessHelp::decomposerResult[0].addr);
if (ProcessAccessHelp::decomposerResult[instructionsCount-1].flags != FLAG_NOT_DECODABLE)
{
next += ProcessAccessHelp::decomposerResult[instructionsCount-1].size;
}
currentPos += next;
currentOffset += next;
currentSize -= next;
}
}
free(dataBuffer);
}
void IATReferenceScan::analyzeInstruction( _DInst * instruction )
{
if (ScanForNormalImports)
{
findNormalIatReference(instruction);
}
if (ScanForDirectImports)
{
findDirectIatReferenceMov(instruction);
#ifndef _WIN64
findDirectIatReferenceCallJmp(instruction);
findDirectIatReferenceLea(instruction);
findDirectIatReferencePush(instruction);
#endif
}
}
void IATReferenceScan::findNormalIatReference( _DInst * instruction )
{
#ifdef DEBUG_COMMENTS
_DecodedInst inst;
#endif
IATReference ref;
if (META_GET_FC(instruction->meta) == FC_CALL || META_GET_FC(instruction->meta) == FC_UNC_BRANCH)
{
if (instruction->size >= 5)
{
if (META_GET_FC(instruction->meta) == FC_CALL)
{
ref.type = IAT_REFERENCE_PTR_CALL;
}
else
{
ref.type = IAT_REFERENCE_PTR_JMP;
}
ref.addressVA = (DWORD_PTR)instruction->addr;
ref.instructionSize = instruction->size;
#ifdef _WIN64
if (instruction->flags & FLAG_RIP_RELATIVE)
{
#ifdef DEBUG_COMMENTS
distorm_format(&ProcessAccessHelp::decomposerCi, instruction, &inst);
Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" " PRINTF_DWORD_PTR_FULL L" %S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, (DWORD_PTR)instruction->addr, ImageBase, inst.mnemonic.p, inst.operands.p, instruction->ops[0].type, instruction->size, INSTRUCTION_GET_RIP_TARGET(instruction));
#endif
if (INSTRUCTION_GET_RIP_TARGET(instruction) >= IatAddressVA && INSTRUCTION_GET_RIP_TARGET(instruction) < (IatAddressVA + IatSize))
{
ref.targetPointer = INSTRUCTION_GET_RIP_TARGET(instruction);
getIatEntryAddress(&ref);
//Scylla::debugLog.log(L"iat entry "PRINTF_DWORD_PTR_FULL,ref.targetAddressInIat);
iatReferenceList.push_back(ref);
}
}
#else
if (instruction->ops[0].type == O_DISP)
{
//jmp dword ptr || call dword ptr
#ifdef DEBUG_COMMENTS
distorm_format(&ProcessAccessHelp::decomposerCi, instruction, &inst);
Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" " PRINTF_DWORD_PTR_FULL L" %S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL, (DWORD_PTR)instruction->addr, ImageBase, inst.mnemonic.p, inst.operands.p, instruction->ops[0].type, instruction->size, instruction->disp);
#endif
if (instruction->disp >= IatAddressVA && instruction->disp < (IatAddressVA + IatSize))
{
ref.targetPointer = (DWORD_PTR)instruction->disp;
getIatEntryAddress(&ref);
//Scylla::debugLog.log(L"iat entry "PRINTF_DWORD_PTR_FULL,ref.targetAddressInIat);
iatReferenceList.push_back(ref);
}
}
#endif
}
}
}
void IATReferenceScan::getIatEntryAddress( IATReference * ref )
{
if (!ProcessAccessHelp::readMemoryFromProcess(ref->targetPointer, sizeof(DWORD_PTR), &ref->targetAddressInIat))
{
ref->targetAddressInIat = 0;
}
}
-void IATReferenceScan::findDirectIatReferenceCallJmp( _DInst * instruction )
-{
- IATReference ref;
- ref.targetPointer = 0;
-
-
- if (META_GET_FC(instruction->meta) == FC_CALL || META_GET_FC(instruction->meta) == FC_UNC_BRANCH)
- {
- if ((instruction->size >= 5) && (instruction->ops[0].type == O_PC)) //CALL/JMP 0x00000000
- {
- if (META_GET_FC(instruction->meta) == FC_CALL)
- {
- ref.type = IAT_REFERENCE_DIRECT_CALL;
- }
- else
- {
- ref.type = IAT_REFERENCE_DIRECT_JMP;
- }
- ref.addressVA = (DWORD_PTR)instruction->addr;
- ref.targetAddressInIat = (DWORD_PTR)INSTRUCTION_GET_TARGET(instruction);
- ref.instructionSize = instruction->size;
-
- checkMemoryRangeAndAddToList(&ref, instruction);
- }
- }
-}
-
bool IATReferenceScan::isAddressValidImageMemory( DWORD_PTR address )
{
MEMORY_BASIC_INFORMATION memBasic = {0};
if (!VirtualQueryEx(ProcessAccessHelp::hProcess, (LPCVOID)address, &memBasic, sizeof(MEMORY_BASIC_INFORMATION)))
{
return false;
}
return (memBasic.Type == MEM_IMAGE && isPageExecutable(memBasic.Protect));
}
void IATReferenceScan::patchReferenceInMemory( IATReference * ref )
{
DWORD_PTR newIatAddressPointer = ref->targetPointer - IatAddressVA + NewIatAddressRVA;
DWORD patchBytes = 0;
#ifdef _WIN64
patchBytes = (DWORD)(newIatAddressPointer - ref->addressVA - 6);
#else
patchBytes = newIatAddressPointer;
#endif
ProcessAccessHelp::writeMemoryToProcess(ref->addressVA + 2, sizeof(DWORD), &patchBytes);
}
void IATReferenceScan::patchDirectImportInMemory( IATReference * ref )
{
DWORD patchBytes = 0;
BYTE patchPreBytes[2];
- ref->targetPointer = lookUpIatForPointer(ref->targetAddressInIat);
if (ref->targetPointer)
{
patchPreBytes[0] = 0xFF;
if (ref->type == IAT_REFERENCE_DIRECT_CALL) //FF15
{
patchPreBytes[1] = 0x15;
}
else if (ref->type == IAT_REFERENCE_DIRECT_JMP) //FF25
{
patchPreBytes[1] = 0x25;
}
else
{
return;
}
if (!JunkByteAfterInstruction)
{
ref->addressVA -= 1;
}
ProcessAccessHelp::writeMemoryToProcess(ref->addressVA, 2, patchPreBytes);
#ifdef _WIN64
patchBytes = (DWORD)(ref->targetPointer - ref->addressVA - 6);
#else
patchBytes = ref->targetPointer;
#endif
ProcessAccessHelp::writeMemoryToProcess(ref->addressVA + 2, sizeof(DWORD), &patchBytes);
}
}
DWORD_PTR IATReferenceScan::lookUpIatForPointer( DWORD_PTR addr )
{
if (!iatBackup)
{
iatBackup = (DWORD_PTR *)calloc(IatSize + sizeof(DWORD_PTR), 1);
if (!iatBackup)
{
return 0;
}
if (!ProcessAccessHelp::readMemoryFromProcess(IatAddressVA, IatSize, iatBackup))
{
free(iatBackup);
iatBackup = 0;
return 0;
}
}
for (int i = 0; i < ((int)IatSize / (int)sizeof(DWORD_PTR));i++)
{
if (iatBackup[i] == addr)
{
return (DWORD_PTR)&iatBackup[i] - (DWORD_PTR)iatBackup + IatAddressVA;
}
}
return 0;
}
void IATReferenceScan::patchNewIat(DWORD_PTR stdImagebase, DWORD_PTR newIatBaseAddress, PeParser * peParser)
{
NewIatAddressRVA = newIatBaseAddress;
DWORD patchBytes = 0;
for (std::vector<IATReference>::iterator iter = iatReferenceList.begin(); iter != iatReferenceList.end(); iter++)
{
IATReference * ref = &(*iter);
DWORD_PTR newIatAddressPointer = (ref->targetPointer - IatAddressVA) + NewIatAddressRVA + stdImagebase;
#ifdef _WIN64
patchBytes = (DWORD)(newIatAddressPointer - (ref->addressVA - ImageBase + stdImagebase) - 6);
#else
patchBytes = newIatAddressPointer;
#endif
DWORD_PTR patchOffset = peParser->convertRVAToOffsetRelative(ref->addressVA - ImageBase);
int index = peParser->convertRVAToOffsetVectorIndex(ref->addressVA - ImageBase);
BYTE * memory = peParser->getSectionMemoryByIndex(index);
DWORD memorySize = peParser->getSectionMemorySizeByIndex(index);
if (memorySize < (DWORD)(patchOffset + 6))
{
Scylla::debugLog.log(L"Error - Cannot fix IAT reference RVA: " PRINTF_DWORD_PTR_FULL, ref->addressVA - ImageBase);
}
else
{
memory += patchOffset + 2;
*((DWORD *)memory) = patchBytes;
}
//Scylla::debugLog.log(L"address %X old %X new %X",ref->addressVA, ref->targetPointer, newIatAddressPointer);
}
}
-void IATReferenceScan::findDirectIatReferenceMov( _DInst * instruction )
-{
- IATReference ref;
- ref.targetPointer = 0;
- ref.type = IAT_REFERENCE_DIRECT_MOV;
-
- if (instruction->opcode == I_MOV)
- {
-#ifdef _WIN64
- if (instruction->size >= 7) //MOV REGISTER, 0xFFFFFFFFFFFFFFFF
-#else
- if (instruction->size >= 5) //MOV REGISTER, 0xFFFFFFFF
-#endif
- {
- if (instruction->ops[0].type == O_REG && instruction->ops[1].type == O_IMM)
- {
- ref.targetAddressInIat = (DWORD_PTR)instruction->imm.qword;
- ref.addressVA = (DWORD_PTR)instruction->addr;
- ref.instructionSize = instruction->size;
-
- checkMemoryRangeAndAddToList(&ref, instruction);
- }
- }
- }
-}
-
void IATReferenceScan::printDirectImportLog()
{
IATReferenceScan::directImportLog.log(L"------------------------------------------------------------");
IATReferenceScan::directImportLog.log(L"ImageBase " PRINTF_DWORD_PTR_FULL L" ImageSize %08X IATAddress " PRINTF_DWORD_PTR_FULL L" IATSize 0x%X", ImageBase, ImageSize, IatAddressVA, IatSize);
int count = 0;
bool isSuspect = false;
for (std::vector<IATReference>::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++)
{
IATReference * ref = &(*iter);
ApiInfo * apiInfo = apiReader->getApiByVirtualAddress(ref->targetAddressInIat, &isSuspect);
- ref->targetPointer = lookUpIatForPointer(ref->targetAddressInIat);
-
count++;
WCHAR * type = L"U";
if (ref->type == IAT_REFERENCE_DIRECT_CALL)
{
type = L"CALL";
}
else if (ref->type == IAT_REFERENCE_DIRECT_JMP)
{
type = L"JMP";
}
else if (ref->type == IAT_REFERENCE_DIRECT_MOV)
{
type = L"MOV";
}
else if (ref->type == IAT_REFERENCE_DIRECT_PUSH)
{
type = L"PUSH";
}
else if (ref->type == IAT_REFERENCE_DIRECT_LEA)
{
type = L"LEA";
}
IATReferenceScan::directImportLog.log(L"%04d AddrVA " PRINTF_DWORD_PTR_FULL L" Type %s Value " PRINTF_DWORD_PTR_FULL L" IatRefPointer " PRINTF_DWORD_PTR_FULL L" Api %s %S", count, ref->addressVA, type, ref->targetAddressInIat, ref->targetPointer,apiInfo->module->getFilename(), apiInfo->name);
}
IATReferenceScan::directImportLog.log(L"------------------------------------------------------------");
}
+void IATReferenceScan::findDirectIatReferenceCallJmp( _DInst * instruction )
+{
+ IATReference ref;
+
+ if (META_GET_FC(instruction->meta) == FC_CALL || META_GET_FC(instruction->meta) == FC_UNC_BRANCH)
+ {
+ if ((instruction->size >= 5) && (instruction->ops[0].type == O_PC)) //CALL/JMP 0x00000000
+ {
+ if (META_GET_FC(instruction->meta) == FC_CALL)
+ {
+ ref.type = IAT_REFERENCE_DIRECT_CALL;
+ }
+ else
+ {
+ ref.type = IAT_REFERENCE_DIRECT_JMP;
+ }
+
+ ref.targetAddressInIat = (DWORD_PTR)INSTRUCTION_GET_TARGET(instruction);
+
+ checkMemoryRangeAndAddToList(&ref, instruction);
+ }
+ }
+}
+
+void IATReferenceScan::findDirectIatReferenceMov( _DInst * instruction )
+{
+ IATReference ref;
+ ref.type = IAT_REFERENCE_DIRECT_MOV;
+
+ if (instruction->opcode == I_MOV)
+ {
+#ifdef _WIN64
+ if (instruction->size >= 7) //MOV REGISTER, 0xFFFFFFFFFFFFFFFF
+#else
+ if (instruction->size >= 5) //MOV REGISTER, 0xFFFFFFFF
+#endif
+ {
+ if (instruction->ops[0].type == O_REG && instruction->ops[1].type == O_IMM)
+ {
+ ref.targetAddressInIat = (DWORD_PTR)instruction->imm.qword;
+
+ checkMemoryRangeAndAddToList(&ref, instruction);
+ }
+ }
+ }
+}
void IATReferenceScan::findDirectIatReferencePush( _DInst * instruction )
{
IATReference ref;
- ref.targetPointer = 0;
ref.type = IAT_REFERENCE_DIRECT_PUSH;
if (instruction->size >= 5 && instruction->opcode == I_PUSH)
{
ref.targetAddressInIat = (DWORD_PTR)instruction->imm.qword;
- ref.addressVA = (DWORD_PTR)instruction->addr;
- ref.instructionSize = instruction->size;
checkMemoryRangeAndAddToList(&ref, instruction);
}
}
void IATReferenceScan::findDirectIatReferenceLea( _DInst * instruction )
{
IATReference ref;
- ref.targetPointer = 0;
ref.type = IAT_REFERENCE_DIRECT_LEA;
if (instruction->size >= 5 && instruction->opcode == I_LEA)
{
if (instruction->ops[0].type == O_REG && instruction->ops[1].type == O_DISP) //LEA EDX, [0xb58bb8]
{
ref.targetAddressInIat = (DWORD_PTR)instruction->disp;
- ref.addressVA = (DWORD_PTR)instruction->addr;
- ref.instructionSize = instruction->size;
checkMemoryRangeAndAddToList(&ref, instruction);
}
}
}
void IATReferenceScan::checkMemoryRangeAndAddToList( IATReference * ref, _DInst * instruction )
{
#ifdef DEBUG_COMMENTS
_DecodedInst inst;
#endif
if (ref->targetAddressInIat > 0x000FFFFF && ref->targetAddressInIat != (DWORD_PTR)-1)
{
if ((ref->targetAddressInIat < ImageBase) || (ref->targetAddressInIat > (ImageBase+ImageSize))) //outside pe image
{
//if (isAddressValidImageMemory(ref->targetAddressInIat))
{
bool isSuspect = false;
if (apiReader->getApiByVirtualAddress(ref->targetAddressInIat, &isSuspect) != 0)
{
+ ref->addressVA = (DWORD_PTR)instruction->addr;
+ ref->instructionSize = instruction->size;
+ ref->targetPointer = lookUpIatForPointer(ref->targetAddressInIat);
+
#ifdef DEBUG_COMMENTS
distorm_format(&ProcessAccessHelp::decomposerCi, instruction, &inst);
Scylla::debugLog.log(PRINTF_DWORD_PTR_FULL L" " PRINTF_DWORD_PTR_FULL L" %S %S %d %d - target address: " PRINTF_DWORD_PTR_FULL,(DWORD_PTR)instruction->addr, ImageBase, inst.mnemonic.p, inst.operands.p, instruction->ops[0].type, instruction->size, ref->targetAddressInIat);
#endif
iatDirectImportList.push_back(*ref);
}
}
}
}
}
void IATReferenceScan::patchDirectJumpTable( DWORD_PTR stdImagebase, DWORD directImportsJumpTableRVA, PeParser * peParser, BYTE * jmpTableMemory, DWORD newIatBase )
{
DWORD patchBytes = 0;
for (std::vector<IATReference>::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++)
{
IATReference * ref = &(*iter);
DWORD_PTR refTargetPointer = ref->targetPointer;
if (newIatBase) //create new iat in section
{
refTargetPointer = (ref->targetPointer - IatAddressVA) + newIatBase + ImageBase;
}
//create jump table in section
DWORD_PTR newIatAddressPointer = refTargetPointer - ImageBase + stdImagebase;
#ifdef _WIN64
patchBytes = (DWORD)(newIatAddressPointer - (ref->addressVA - ImageBase + stdImagebase) - 6);
#else
patchBytes = newIatAddressPointer; //dont forget relocation here
directImportLog.log(L"Relocation direct imports fix: Base RVA %08X Offset %04X Type IMAGE_REL_BASED_HIGHLOW", (directImportsJumpTableRVA + 2) & 0xFFFFF000, (directImportsJumpTableRVA + 2) & 0x00000FFF);
#endif
jmpTableMemory[0] = 0xFF;
jmpTableMemory[1] = 0x25;
*((DWORD *)&jmpTableMemory[2]) = patchBytes;
//patch dump
DWORD_PTR patchOffset = peParser->convertRVAToOffsetRelative(ref->addressVA - ImageBase);
int index = peParser->convertRVAToOffsetVectorIndex(ref->addressVA - ImageBase);
BYTE * memory = peParser->getSectionMemoryByIndex(index);
DWORD memorySize = peParser->getSectionMemorySizeByIndex(index);
DWORD sectionRVA = peParser->getSectionAddressRVAByIndex(index);
if (ref->type == IAT_REFERENCE_DIRECT_CALL || ref->type == IAT_REFERENCE_DIRECT_JMP)
{
if (ref->instructionSize == 5)
{
patchBytes = directImportsJumpTableRVA - (ref->addressVA - ImageBase) - 5;
patchDirectImportInDump32(1, 5, patchBytes, memory, memorySize, false, patchOffset, sectionRVA);
}
}
else if (ref->type == IAT_REFERENCE_DIRECT_PUSH || ref->type == IAT_REFERENCE_DIRECT_MOV)
{
if (ref->instructionSize == 5)
{
patchBytes = directImportsJumpTableRVA + stdImagebase;
patchDirectImportInDump32(1, 5, patchBytes, memory, memorySize, true, patchOffset, sectionRVA);
}
}
else if (ref->type == IAT_REFERENCE_DIRECT_LEA)
{
if (ref->instructionSize == 6)
{
patchBytes = directImportsJumpTableRVA + stdImagebase;
patchDirectImportInDump32(2, 6, patchBytes, memory, memorySize, true, patchOffset, sectionRVA);
}
}
jmpTableMemory += 6;
directImportsJumpTableRVA += 6;
}
}
void IATReferenceScan::patchDirectImportInDump32( int patchPreFixBytes, int instructionSize, DWORD patchBytes, BYTE * memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA )
{
-
if (memorySize < (DWORD)(patchOffset + instructionSize))
{
Scylla::debugLog.log(L"Error - Cannot fix direct import reference RVA: %X", sectionRVA + patchOffset);
}
else
{
memory += patchOffset + patchPreFixBytes;
if (generateReloc)
{
directImportLog.log(L"Relocation direct imports fix: Base RVA %08X Offset %04X Type IMAGE_REL_BASED_HIGHLOW", (sectionRVA + patchOffset + patchPreFixBytes) & 0xFFFFF000, (sectionRVA + patchOffset+ patchPreFixBytes) & 0x00000FFF);
}
*((DWORD *)memory) = patchBytes;
}
}
+DWORD IATReferenceScan::addAdditionalApisToList()
+{
+ std::set<DWORD_PTR> apiPointers;
+
+ for (std::vector<IATReference>::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++)
+ {
+ IATReference * ref = &(*iter);
+
+ if (ref->targetPointer == 0)
+ {
+ apiPointers.insert(ref->targetAddressInIat);
+ }
+ }
+
+ DWORD_PTR iatAddy = IatAddressVA + IatSize;
+ DWORD newIatSize = IatSize;
+
+ bool isSuspect = false;
+ for (std::set<DWORD_PTR>::iterator apiIter = apiPointers.begin(); apiIter != apiPointers.end(); apiIter++)
+ {
+ for (std::vector<IATReference>::iterator iter = iatDirectImportList.begin(); iter != iatDirectImportList.end(); iter++)
+ {
+ IATReference * ref = &(*iter);
+
+ if (ref->targetPointer == 0 && ref->targetAddressInIat == *apiIter)
+ {
+ ref->targetPointer = iatAddy;
+ ApiInfo * apiInfo = apiReader->getApiByVirtualAddress(ref->targetAddressInIat, &isSuspect);
+ apiReader->addFoundApiToModuleList(iatAddy, apiInfo, true, isSuspect);
+ }
+ }
+
+ iatAddy += sizeof(DWORD_PTR);
+ newIatSize += sizeof(DWORD_PTR);
+ }
+
+ return newIatSize;
+}
+
diff --git a/Scylla/IATReferenceScan.h b/Scylla/IATReferenceScan.h
index 78c69a5..d5fb371 100644
--- a/Scylla/IATReferenceScan.h
+++ b/Scylla/IATReferenceScan.h
@@ -1,122 +1,125 @@
#pragma once
#include <vector>
#include "ProcessAccessHelp.h"
#include "PeParser.h"
#include "Logger.h"
#include "ApiReader.h"
enum IATReferenceType {
IAT_REFERENCE_PTR_JMP,
IAT_REFERENCE_PTR_CALL,
IAT_REFERENCE_DIRECT_JMP,
IAT_REFERENCE_DIRECT_CALL,
IAT_REFERENCE_DIRECT_MOV,
IAT_REFERENCE_DIRECT_PUSH,
IAT_REFERENCE_DIRECT_LEA
};
class IATReference
{
public:
DWORD_PTR addressVA; //Address of reference
DWORD_PTR targetPointer; //Place inside IAT
DWORD_PTR targetAddressInIat; //WIN API?
BYTE instructionSize;
IATReferenceType type;
};
class IATReferenceScan
{
public:
IATReferenceScan()
{
apiReader = 0;
IatAddressVA = 0;
IatSize = 0;
ImageBase = 0;
ImageSize = 0;
iatBackup = 0;
ScanForDirectImports = false;
ScanForNormalImports = true;
}
~IATReferenceScan()
{
iatReferenceList.clear();
iatDirectImportList.clear();
if (iatBackup)
{
free(iatBackup);
}
}
bool ScanForDirectImports;
bool ScanForNormalImports;
bool JunkByteAfterInstruction;
ApiReader * apiReader;
void startScan(DWORD_PTR imageBase, DWORD imageSize, DWORD_PTR iatAddress, DWORD iatSize);
//void patchNewIatBaseMemory(DWORD_PTR newIatBaseAddress);
//void patchNewIatBaseFile(DWORD_PTR newIatBaseAddress);
void patchNewIat(DWORD_PTR stdImagebase, DWORD_PTR newIatBaseAddress, PeParser * peParser);
void patchDirectJumpTable( DWORD_PTR imageBase, DWORD directImportsJumpTableRVA, PeParser * peParser, BYTE * jmpTableMemory, DWORD newIatBase);
void patchDirectImportsMemory(bool junkByteAfterInstruction);
int numberOfFoundDirectImports();
+ int numberOfFoundUniqueDirectImports();
+ int numberOfDirectImportApisNotInIat();
int getSizeInBytesOfJumpTableInSection();
static FileLog directImportLog;
void printDirectImportLog();
void changeIatBaseOfDirectImports( DWORD newIatBaseAddressRVA );
+ DWORD addAdditionalApisToList();
private:
DWORD_PTR NewIatAddressRVA;
DWORD_PTR IatAddressVA;
DWORD IatSize;
DWORD_PTR ImageBase;
DWORD ImageSize;
DWORD_PTR * iatBackup;
std::vector<IATReference> iatReferenceList;
std::vector<IATReference> iatDirectImportList;
bool isPageExecutable( DWORD Protect );
void scanMemoryPage( PVOID BaseAddress, SIZE_T RegionSize );
void analyzeInstruction( _DInst * instruction );
void findNormalIatReference( _DInst * instruction );
void getIatEntryAddress( IATReference* ref );
void findDirectIatReferenceCallJmp( _DInst * instruction );
bool isAddressValidImageMemory( DWORD_PTR address );
void patchReferenceInMemory( IATReference * ref );
void patchReferenceInFile( IATReference* ref );
void patchDirectImportInMemory( IATReference * iter );
DWORD_PTR lookUpIatForPointer( DWORD_PTR addr );
void findDirectIatReferenceMov( _DInst * instruction );
void findDirectIatReferencePush( _DInst * instruction );
void checkMemoryRangeAndAddToList( IATReference * ref, _DInst * instruction );
void findDirectIatReferenceLea( _DInst * instruction );
void patchDirectImportInDump32( int patchPreFixBytes, int instructionSize, DWORD patchBytes, BYTE * memory, DWORD memorySize, bool generateReloc, DWORD patchOffset, DWORD sectionRVA );
-
+
};
/*
PE64
----------
000000013FF82D87 FF15 137C0A00 CALL QWORD [RIP+0xA7C13]
Result: 000000014002A9A0
000000013F65C952 FF25 F8EA0B00 JMP QWORD [RIP+0xBEAF8]
Result: 000000013F71B450
PE32
----------
0120FFA5 FF15 8C6D2601 CALL DWORD [0x01266D8C]
0120FF52 FF25 D4722601 JMP DWORD [0x012672D4]
*/
diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp
index 4868117..125f99f 100644
--- a/Scylla/MainGui.cpp
+++ b/Scylla/MainGui.cpp
@@ -1,1651 +1,1661 @@
#include "MainGui.h"
#include "Architecture.h"
//#include "PluginLoader.h"
//#include "ConfigurationHolder.h"
#include "PeParser.h"
#include "DllInjectionPlugin.h"
#include "DisassemblerGui.h"
#include "PickApiGui.h"
//#include "NativeWinApi.h"
#include "ImportRebuilder.h"
#include "SystemInformation.h"
#include "Scylla.h"
#include "AboutGui.h"
#include "DonateGui.h"
#include "OptionsGui.h"
#include "TreeImportExport.h"
extern CAppModule _Module; // o_O
const WCHAR MainGui::filterExe[] = L"Executable (*.exe)\0*.exe\0All files\0*.*\0";
const WCHAR MainGui::filterDll[] = L"Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0";
const WCHAR MainGui::filterExeDll[] = L"Executable (*.exe)\0*.exe\0Dynamic Link Library (*.dll)\0*.dll\0All files\0*.*\0";
const WCHAR MainGui::filterTxt[] = L"Text file (*.txt)\0*.txt\0All files\0*.*\0";
const WCHAR MainGui::filterXml[] = L"XML file (*.xml)\0*.xml\0All files\0*.*\0";
const WCHAR MainGui::filterMem[] = L"MEM file (*.mem)\0*.mem\0All files\0*.*\0";
MainGui::MainGui() : selectedProcess(0), isProcessSuspended(false), importsHandling(TreeImports), TreeImportsSubclass(this, IDC_TREE_IMPORTS)
{
/*
Logger::getDebugLogFilePath();
ConfigurationHolder::loadConfiguration();
PluginLoader::findAllPlugins();
NativeWinApi::initialize();
SystemInformation::getSystemInformation();
if(ConfigurationHolder::getConfigObject(DEBUG_PRIVILEGE)->isTrue())
{
processLister.setDebugPrivileges();
}
ProcessAccessHelp::getProcessModules(GetCurrentProcessId(), ProcessAccessHelp::ownModuleList);
*/
hIcon.LoadIcon(IDI_ICON_SCYLLA);
hMenuImports.LoadMenu(IDR_MENU_IMPORTS);
hMenuLog.LoadMenu(IDR_MENU_LOG);
accelerators.LoadAccelerators(IDR_ACCELERATOR_MAIN);
hIconCheck.LoadIcon(IDI_ICON_CHECK, 16, 16);
hIconWarning.LoadIcon(IDI_ICON_WARNING, 16, 16);
hIconError.LoadIcon(IDI_ICON_ERROR, 16, 16);
}
BOOL MainGui::PreTranslateMessage(MSG* pMsg)
{
if(accelerators.TranslateAccelerator(m_hWnd, pMsg))
{
return TRUE; // handled keyboard shortcuts
}
else if(IsDialogMessage(pMsg))
{
return TRUE; // handled dialog messages
}
return FALSE;
}
void MainGui::InitDllStartWithPreSelect( PGUI_DLL_PARAMETER guiParam )
{
ComboProcessList.ResetContent();
std::vector<Process>& processList = Scylla::processLister.getProcessListSnapshot();
int newSel = -1;
for (size_t i = 0; i < processList.size(); i++)
{
if (processList[i].PID == guiParam->dwProcessId)
newSel = (int)i;
swprintf_s(stringBuffer, L"0x%04X - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath);
ComboProcessList.AddString(stringBuffer);
}
if (newSel != -1)
{
ComboProcessList.SetCurSel(newSel);
processSelectedActionHandler(newSel);
if (guiParam->mod) //init mod
{
//select DLL
size_t len = ProcessAccessHelp::moduleList.size();
newSel = -1;
for (size_t i = 0; i < len; i++)
{
if (ProcessAccessHelp::moduleList.at(i).modBaseAddr == (DWORD_PTR)guiParam->mod)
{
newSel = (int)i;
break;
}
}
if (newSel != -1)
{
//get selected module
ProcessAccessHelp::selectedModule = &ProcessAccessHelp::moduleList.at(newSel);
ProcessAccessHelp::targetImageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
ProcessAccessHelp::targetSizeOfImage = ProcessAccessHelp::getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase);
DWORD modEntryPoint = ProcessAccessHelp::getEntryPointFromFile(ProcessAccessHelp::selectedModule->fullPath);
EditOEPAddress.SetValue(modEntryPoint + ProcessAccessHelp::targetImageBase);
Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename());
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X EntryPoint: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize, modEntryPoint);
}
}
}
}
BOOL MainGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
if (SystemInformation::currenOS == UNKNOWN_OS)
{
if(IDCANCEL == MessageBox(L"Operating System is not supported\r\nContinue anyway?", L"Scylla", MB_ICONWARNING | MB_OKCANCEL))
{
SendMessage(WM_CLOSE);
return FALSE;
}
}
// register ourselves to receive PreTranslateMessage
CMessageLoop* pLoop = _Module.GetMessageLoop();
pLoop->AddMessageFilter(this);
setupStatusBar();
DoDataExchange(); // attach controls
DlgResize_Init(true, true); // init CDialogResize
Scylla::windowLog.setWindow(ListLog);
appendPluginListToMenu(hMenuImports.GetSubMenu(0));
appendPluginListToMenu(CMenuHandle(GetMenu()).GetSubMenu(MenuImportsOffsetTrace));
enableDialogControls(FALSE);
setIconAndDialogCaption();
if (lInitParam)
{
InitDllStartWithPreSelect((PGUI_DLL_PARAMETER)lInitParam);
}
return TRUE;
}
void MainGui::OnDestroy()
{
PostQuitMessage(0);
}
void MainGui::OnSize(UINT nType, CSize size)
{
StatusBar.SendMessage(WM_SIZE);
SetMsgHandled(FALSE);
}
void MainGui::OnContextMenu(CWindow wnd, CPoint point)
{
switch(wnd.GetDlgCtrlID())
{
case IDC_TREE_IMPORTS:
DisplayContextMenuImports(wnd, point);
return;
case IDC_LIST_LOG:
DisplayContextMenuLog(wnd, point);
return;
}
SetMsgHandled(FALSE);
}
void MainGui::OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
{
// Handle plugin trace menu selection
if(uNotifyCode == 0 && !wndCtl.IsWindow()) // make sure it's a menu
{
if ((nID >= PLUGIN_MENU_BASE_ID) && (nID <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID)))
{
pluginActionHandler(nID);
return;
}
}
SetMsgHandled(FALSE);
}
LRESULT MainGui::OnTreeImportsDoubleClick(const NMHDR* pnmh)
{
if(TreeImports.GetCount() < 1)
return 0;
// Get item under cursor
CTreeItem over = findTreeItem(CPoint(GetMessagePos()), true);
if(over && importsHandling.isImport(over))
{
pickApiActionHandler(over);
}
return 0;
}
LRESULT MainGui::OnTreeImportsKeyDown(const NMHDR* pnmh)
{
const NMTVKEYDOWN * tkd = (NMTVKEYDOWN *)pnmh;
switch(tkd->wVKey)
{
case VK_RETURN:
{
CTreeItem selected = TreeImports.GetFocusItem();
if(!selected.IsNull() && importsHandling.isImport(selected))
{
pickApiActionHandler(selected);
}
}
return 1;
case VK_DELETE:
deleteSelectedImportsActionHandler();
return 1;
}
SetMsgHandled(FALSE);
return 0;
}
UINT MainGui::OnTreeImportsSubclassGetDlgCode(const MSG * lpMsg)
{
if(lpMsg)
{
switch(lpMsg->wParam)
{
case VK_RETURN:
return DLGC_WANTMESSAGE;
}
}
SetMsgHandled(FALSE);
return 0;
}
void MainGui::OnTreeImportsSubclassChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch(nChar)
{
case VK_RETURN:
break;
default:
SetMsgHandled(FALSE);
break;
}
}
void MainGui::OnProcessListDrop(UINT uNotifyCode, int nID, CWindow wndCtl)
{
fillProcessListComboBox(ComboProcessList);
}
void MainGui::OnProcessListSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
int index = ComboProcessList.GetCurSel();
if (index != CB_ERR)
{
processSelectedActionHandler(index);
}
}
void MainGui::OnPickDLL(UINT uNotifyCode, int nID, CWindow wndCtl)
{
pickDllActionHandler();
}
void MainGui::OnOptions(UINT uNotifyCode, int nID, CWindow wndCtl)
{
optionsActionHandler();
}
void MainGui::OnDump(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpActionHandler();
}
void MainGui::OnDumpMemory(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpMemoryActionHandler();
}
void MainGui::OnDumpSection(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpSectionActionHandler();
}
void MainGui::OnFixDump(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dumpFixActionHandler();
}
void MainGui::OnPERebuild(UINT uNotifyCode, int nID, CWindow wndCtl)
{
peRebuildActionHandler();
}
void MainGui::OnDLLInject(UINT uNotifyCode, int nID, CWindow wndCtl)
{
dllInjectActionHandler();
}
void MainGui::OnDisassembler(UINT uNotifyCode, int nID, CWindow wndCtl)
{
disassemblerActionHandler();
}
void MainGui::OnIATAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl)
{
iatAutosearchActionHandler();
}
void MainGui::OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
getImportsActionHandler();
}
void MainGui::OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showInvalidImportsActionHandler();
}
void MainGui::OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showSuspectImportsActionHandler();
}
void MainGui::OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl)
{
clearImportsActionHandler();
}
void MainGui::OnInvalidateSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
invalidateSelectedImportsActionHandler();
}
void MainGui::OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl)
{
deleteSelectedImportsActionHandler();
}
void MainGui::OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl)
{
saveTreeActionHandler();
}
void MainGui::OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl)
{
loadTreeActionHandler();
}
void MainGui::OnAutotrace(UINT uNotifyCode, int nID, CWindow wndCtl)
{
// TODO
}
void MainGui::OnExit(UINT uNotifyCode, int nID, CWindow wndCtl)
{
if (isProcessSuspended)
{
int msgboxID = MessageBox(L"Process is suspended. Do you want to terminate the process?\r\n\r\nYES = Terminate Process\r\nNO = Try to resume the process\r\nCancel = Do nothing", L"Information", MB_YESNOCANCEL|MB_ICONINFORMATION);
switch (msgboxID)
{
case IDYES:
ProcessAccessHelp::terminateProcess();
break;
case IDNO:
ProcessAccessHelp::resumeProcess();
break;
default:
break;
}
}
DestroyWindow();
}
void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showAboutDialog();
}
void MainGui::OnDonate(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showDonateDialog();
}
void MainGui::setupStatusBar()
{
StatusBar.Create(m_hWnd, NULL, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_TOOLTIPS, NULL, IDC_STATUS_BAR);
CRect rcMain, rcStatus;
GetClientRect(&rcMain);
StatusBar.GetWindowRect(&rcStatus);
const int PARTS = 4;
int widths[PARTS];
widths[PART_COUNT] = rcMain.Width() / 5;
widths[PART_INVALID] = widths[PART_COUNT] + rcMain.Width() / 5;
widths[PART_IMAGEBASE] = widths[PART_INVALID] + rcMain.Width() / 3;
widths[PART_MODULE] = -1;
StatusBar.SetParts(PARTS, widths);
ResizeClient(rcMain.Width(), rcMain.Height() + rcStatus.Height(), FALSE);
}
void MainGui::updateStatusBar()
{
// Rewrite ImportsHandling so we get these easily
unsigned int totalImports = importsHandling.thunkCount();
unsigned int invalidImports = importsHandling.invalidThunkCount();
// \t = center, \t\t = right-align
swprintf_s(stringBuffer, L"\tImports: %u", totalImports);
StatusBar.SetText(PART_COUNT, stringBuffer);
if(invalidImports > 0)
{
StatusBar.SetIcon(PART_INVALID, hIconError);
}
else
{
StatusBar.SetIcon(PART_INVALID, hIconCheck);
}
swprintf_s(stringBuffer, L"\tInvalid: %u", invalidImports);
StatusBar.SetText(PART_INVALID, stringBuffer);
if(selectedProcess)
{
DWORD_PTR imageBase = 0;
const WCHAR * fileName = 0;
if(ProcessAccessHelp::selectedModule)
{
imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
fileName = ProcessAccessHelp::selectedModule->getFilename();
}
else
{
imageBase = selectedProcess->imageBase;
fileName = selectedProcess->filename;
}
swprintf_s(stringBuffer, L"\tImagebase: " PRINTF_DWORD_PTR_FULL, imageBase);
StatusBar.SetText(PART_IMAGEBASE, stringBuffer);
StatusBar.SetText(PART_MODULE, fileName);
StatusBar.SetTipText(PART_MODULE, fileName);
}
else
{
StatusBar.SetText(PART_IMAGEBASE, L"");
StatusBar.SetText(PART_MODULE, L"");
}
}
bool MainGui::showFileDialog(WCHAR * selectedFile, bool save, const WCHAR * defFileName, const WCHAR * filter, const WCHAR * defExtension, const WCHAR * directory)
{
OPENFILENAME ofn = {0};
// WTL doesn't support new explorer styles on Vista and up
// This is because it uses a custom hook, we could remove it or derive
// from CFileDialog but this solution is easier and allows more control anyway (e.g. initial dir)
if(defFileName)
{
wcscpy_s(selectedFile, MAX_PATH, defFileName);
}
else
{
selectedFile[0] = L'\0';
}
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = m_hWnd;
ofn.lpstrFilter = filter;
ofn.lpstrDefExt = defExtension; // only first 3 chars are used, no dots!
ofn.lpstrFile = selectedFile;
ofn.lpstrInitialDir = directory;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
/*
*OFN_EXPLORER is automatically used, it only has to be specified
*if using a custom hook
*OFN_LONGNAMES is automatically used by explorer-style dialogs
*/
if(save)
ofn.Flags |= OFN_OVERWRITEPROMPT;
else
ofn.Flags |= OFN_FILEMUSTEXIST;
if(save)
return 0 != GetSaveFileName(&ofn);
else
return 0 != GetOpenFileName(&ofn);
}
void MainGui::setIconAndDialogCaption()
{
SetIcon(hIcon, TRUE);
SetIcon(hIcon, FALSE);
SetWindowText(APPNAME L" " ARCHITECTURE L" " APPVERSION);
}
void MainGui::pickDllActionHandler()
{
if(!selectedProcess)
return;
PickDllGui dlgPickDll(ProcessAccessHelp::moduleList);
if(dlgPickDll.DoModal())
{
//get selected module
ProcessAccessHelp::selectedModule = dlgPickDll.getSelectedModule();
ProcessAccessHelp::targetImageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
ProcessAccessHelp::targetSizeOfImage = ProcessAccessHelp::getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase);
DWORD modEntryPoint = ProcessAccessHelp::getEntryPointFromFile(ProcessAccessHelp::selectedModule->fullPath);
EditOEPAddress.SetValue(modEntryPoint + ProcessAccessHelp::targetImageBase);
Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename());
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X EntryPoint: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize, modEntryPoint);
}
else
{
ProcessAccessHelp::selectedModule = 0;
}
updateStatusBar();
}
void MainGui::pickApiActionHandler(CTreeItem item)
{
if(!importsHandling.isImport(item))
return;
// TODO: new node when user picked an API from another DLL?
PickApiGui dlgPickApi(ProcessAccessHelp::moduleList);
if(dlgPickApi.DoModal())
{
const ApiInfo* api = dlgPickApi.getSelectedApi();
if(api && api->module)
{
importsHandling.setImport(item, api->module->getFilename(), api->name, api->ordinal, api->hint, true, api->isForwarded);
}
}
updateStatusBar();
}
void MainGui::startDisassemblerGui(CTreeItem selectedTreeNode)
{
if(!selectedProcess)
return;
DWORD_PTR address = importsHandling.getApiAddressByNode(selectedTreeNode);
if (address)
{
BYTE test;
if(!ProcessAccessHelp::readMemoryFromProcess(address, sizeof(test), &test))
{
swprintf_s(stringBuffer, L"Can't read memory at " PRINTF_DWORD_PTR_FULL, address);
MessageBox(stringBuffer, L"Failure", MB_ICONERROR);
}
else
{
DisassemblerGui dlgDisassembler(address, &apiReader);
dlgDisassembler.DoModal();
}
}
}
void MainGui::processSelectedActionHandler(int index)
{
std::vector<Process>& processList = Scylla::processLister.getProcessList();
Process &process = processList.at(index);
selectedProcess = 0;
clearImportsActionHandler();
Scylla::windowLog.log(L"Analyzing %s", process.fullPath);
if (ProcessAccessHelp::hProcess != 0)
{
ProcessAccessHelp::closeProcessHandle();
apiReader.clearAll();
}
if (!ProcessAccessHelp::openProcessHandle(process.PID))
{
enableDialogControls(FALSE);
Scylla::windowLog.log(L"Error: Cannot open process handle.");
updateStatusBar();
return;
}
ProcessAccessHelp::getProcessModules(process.PID, ProcessAccessHelp::moduleList);
apiReader.readApisFromModuleList();
Scylla::windowLog.log(L"Loading modules done.");
//TODO improve
ProcessAccessHelp::selectedModule = 0;
ProcessAccessHelp::targetImageBase = process.imageBase;
ProcessAccessHelp::targetSizeOfImage = ProcessAccessHelp::getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase);
process.imageSize = (DWORD)ProcessAccessHelp::targetSizeOfImage;
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", process.imageBase, process.imageSize);
process.entryPoint = ProcessAccessHelp::getEntryPointFromFile(process.fullPath);
EditOEPAddress.SetValue(process.entryPoint + process.imageBase);
selectedProcess = &process;
enableDialogControls(TRUE);
updateStatusBar();
}
void MainGui::fillProcessListComboBox(CComboBox& hCombo)
{
hCombo.ResetContent();
std::vector<Process>& processList = Scylla::processLister.getProcessListSnapshot();
for (size_t i = 0; i < processList.size(); i++)
{
swprintf_s(stringBuffer, L"0x%04X - %s - %s", processList[i].PID, processList[i].filename, processList[i].fullPath);
hCombo.AddString(stringBuffer);
}
}
/*
void MainGui::addTextToOutputLog(const WCHAR * text)
{
if (m_hWnd)
{
ListLog.SetCurSel(ListLog.AddString(text));
}
}
*/
void MainGui::clearOutputLog()
{
if (m_hWnd)
{
ListLog.ResetContent();
}
}
bool MainGui::saveLogToFile(const WCHAR * file)
{
const BYTE BOM[] = {0xFF, 0xFE}; // UTF-16 little-endian
const WCHAR newLine[] = L"\r\n";
bool success = true;
HANDLE hFile = CreateFile(file, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile != INVALID_HANDLE_VALUE)
{
ProcessAccessHelp::writeMemoryToFileEnd(hFile, sizeof(BOM), BOM);
WCHAR * buffer = 0;
size_t bufsize = 0;
for(int i = 0; i < ListLog.GetCount(); i++)
{
size_t size = ListLog.GetTextLen(i);
size += _countof(newLine)-1;
if(size+1 > bufsize)
{
bufsize = size+1;
delete[] buffer;
try
{
buffer = new WCHAR[bufsize];
}
catch(std::bad_alloc&)
{
buffer = 0;
success = false;
break;
}
}
ListLog.GetText(i, buffer);
wcscat_s(buffer, bufsize, newLine);
ProcessAccessHelp::writeMemoryToFileEnd(hFile, (DWORD)(size * sizeof(WCHAR)), buffer);
}
delete[] buffer;
CloseHandle(hFile);
}
return success;
}
void MainGui::showInvalidImportsActionHandler()
{
importsHandling.selectImports(true, false);
GotoDlgCtrl(TreeImports);
}
void MainGui::showSuspectImportsActionHandler()
{
importsHandling.selectImports(false, true);
GotoDlgCtrl(TreeImports);
}
void MainGui::deleteSelectedImportsActionHandler()
{
CTreeItem selected = TreeImports.GetFirstSelectedItem();
while(!selected.IsNull())
{
if(importsHandling.isModule(selected))
{
importsHandling.cutModule(selected);
}
else
{
importsHandling.cutImport(selected);
}
selected = TreeImports.GetNextSelectedItem(selected);
}
updateStatusBar();
}
void MainGui::invalidateSelectedImportsActionHandler()
{
CTreeItem selected = TreeImports.GetFirstSelectedItem();
while(!selected.IsNull())
{
if(importsHandling.isImport(selected))
{
importsHandling.invalidateImport(selected);
}
selected = TreeImports.GetNextSelectedItem(selected);
}
updateStatusBar();
}
void MainGui::loadTreeActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, false, NULL, filterXml, NULL, stringBuffer))
{
TreeImportExport treeIO(selectedFilePath);
DWORD_PTR addrOEP = 0;
DWORD_PTR addrIAT = 0;
DWORD sizeIAT = 0;
if(!treeIO.importTreeList(importsHandling.moduleList, &addrOEP, &addrIAT, &sizeIAT))
{
Scylla::windowLog.log(L"Loading tree file failed %s", selectedFilePath);
MessageBox(L"Loading tree file failed.", L"Failure", MB_ICONERROR);
}
else
{
EditOEPAddress.SetValue(addrOEP);
EditIATAddress.SetValue(addrIAT);
EditIATSize.SetValue(sizeIAT);
importsHandling.displayAllImports();
updateStatusBar();
Scylla::windowLog.log(L"Loaded tree file %s", selectedFilePath);
Scylla::windowLog.log(L"-> OEP: " PRINTF_DWORD_PTR_FULL, addrOEP);
Scylla::windowLog.log(L"-> IAT: " PRINTF_DWORD_PTR_FULL L" Size: " PRINTF_DWORD_PTR, addrIAT, sizeIAT);
}
}
}
void MainGui::saveTreeActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, filterXml, L"xml", stringBuffer))
{
TreeImportExport treeIO(selectedFilePath);
DWORD_PTR addrOEP = EditOEPAddress.GetValue();
DWORD_PTR addrIAT = EditIATAddress.GetValue();
DWORD sizeIAT = EditIATSize.GetValue();
if(!treeIO.exportTreeList(importsHandling.moduleList, selectedProcess, addrOEP, addrIAT, sizeIAT))
{
Scylla::windowLog.log(L"Saving tree file failed %s", selectedFilePath);
MessageBox(L"Saving tree file failed.", L"Failure", MB_ICONERROR);
}
else
{
Scylla::windowLog.log(L"Saved tree file %s", selectedFilePath);
}
}
}
void MainGui::iatAutosearchActionHandler()
{
DWORD_PTR searchAddress = 0;
DWORD_PTR addressIAT = 0, addressIATAdv = 0;
DWORD sizeIAT = 0, sizeIATAdv = 0;
IATSearch iatSearch;
if(!selectedProcess)
return;
if(EditOEPAddress.GetWindowTextLength() > 0)
{
searchAddress = EditOEPAddress.GetValue();
if (searchAddress)
{
if (Scylla::config[USE_ADVANCED_IAT_SEARCH].isTrue())
{
if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIATAdv, &sizeIATAdv, true))
{
Scylla::windowLog.log(L"IAT Search Advanced: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIATAdv, addressIATAdv - ProcessAccessHelp::targetImageBase, sizeIATAdv, sizeIATAdv);
}
else
{
Scylla::windowLog.log(L"IAT Search Advanced: IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress);
}
}
if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT, false))
{
Scylla::windowLog.log(L"IAT Search Normal: IAT VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIAT, addressIAT - ProcessAccessHelp::targetImageBase, sizeIAT, sizeIAT);
}
else
{
Scylla::windowLog.log(L"IAT Search Normal: IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress);
}
if (addressIAT != 0 && addressIATAdv == 0)
{
setDialogIATAddressAndSize(addressIAT, sizeIAT);
}
else if (addressIAT == 0 && addressIATAdv != 0)
{
setDialogIATAddressAndSize(addressIATAdv, sizeIATAdv);
}
else if (addressIAT != 0 && addressIATAdv != 0)
{
if (addressIATAdv != addressIAT || sizeIAT != sizeIATAdv)
{
int msgboxID = MessageBox(L"Result of advanced and normal search is different. Do you want to use the IAT Search Advanced result?", L"Information", MB_YESNO|MB_ICONINFORMATION);
if (msgboxID == IDYES)
{
setDialogIATAddressAndSize(addressIATAdv, sizeIATAdv);
}
else
{
setDialogIATAddressAndSize(addressIAT, sizeIAT);
}
}
else
{
setDialogIATAddressAndSize(addressIAT, sizeIAT);
}
}
}
}
}
void MainGui::getImportsActionHandler()
{
if(!selectedProcess)
return;
DWORD_PTR addressIAT = EditIATAddress.GetValue();
DWORD sizeIAT = EditIATSize.GetValue();
if (addressIAT && sizeIAT)
{
apiReader.readAndParseIAT(addressIAT, sizeIAT, importsHandling.moduleList);
importsHandling.displayAllImports();
updateStatusBar();
if (Scylla::config[SCAN_DIRECT_IMPORTS].isTrue())
{
iatReferenceScan.ScanForDirectImports = true;
iatReferenceScan.ScanForNormalImports = false;
iatReferenceScan.apiReader = &apiReader;
iatReferenceScan.startScan(ProcessAccessHelp::targetImageBase, (DWORD)ProcessAccessHelp::targetSizeOfImage, addressIAT, sizeIAT);
- Scylla::windowLog.log(L"DIRECT IMPORTS - Found %d possible direct imports!", iatReferenceScan.numberOfFoundDirectImports());
+ Scylla::windowLog.log(L"DIRECT IMPORTS - Found %d possible direct imports with %d unique APIs!", iatReferenceScan.numberOfFoundDirectImports(), iatReferenceScan.numberOfFoundUniqueDirectImports());
if (iatReferenceScan.numberOfFoundDirectImports() > 0)
{
+ if (iatReferenceScan.numberOfDirectImportApisNotInIat() > 0)
+ {
+ Scylla::windowLog.log(L"DIRECT IMPORTS - Found %d additional api addresses!", iatReferenceScan.numberOfDirectImportApisNotInIat());
+ DWORD sizeIatNew = iatReferenceScan.addAdditionalApisToList();
+ Scylla::windowLog.log(L"DIRECT IMPORTS - Old IAT size 0x%08X new IAT size 0x%08X!", sizeIAT, sizeIatNew);
+ EditIATSize.SetValue(sizeIatNew);
+ importsHandling.scanAndFixModuleList();
+ importsHandling.displayAllImports();
+ }
+
iatReferenceScan.printDirectImportLog();
if (Scylla::config[FIX_DIRECT_IMPORTS_NORMAL].isTrue())
{
int msgboxID = MessageBox(L"Direct Imports found. I can patch only direct imports by JMP/CALL (use universal method if you don't like this) but where is the junk byte?\r\n\r\nYES = After Instruction\r\nNO = Before the Instruction\r\nCancel = Do nothing", L"Information", MB_YESNOCANCEL|MB_ICONINFORMATION);
if (msgboxID != IDCANCEL)
{
bool isAfter;
if (msgboxID == IDYES)
{
isAfter = true;
}
else
{
isAfter = false;
}
iatReferenceScan.patchDirectImportsMemory(isAfter);
Scylla::windowLog.log(L"DIRECT IMPORTS - Patched! Please dump target.");
}
}
}
}
if (isIATOutsidePeImage(addressIAT))
{
Scylla::windowLog.log(L"WARNING! IAT is not inside the PE image, requires rebasing!");
}
}
}
void MainGui::SetupImportsMenuItems(CTreeItem item)
{
bool isItem, isImport = false;
isItem = !item.IsNull();
if(isItem)
{
isImport = importsHandling.isImport(item);
}
CMenuHandle hSub = hMenuImports.GetSubMenu(0);
UINT itemOnly = isItem ? MF_ENABLED : MF_GRAYED;
UINT importOnly = isImport ? MF_ENABLED : MF_GRAYED;
hSub.EnableMenuItem(ID__INVALIDATE, itemOnly);
hSub.EnableMenuItem(ID__DISASSEMBLE, importOnly);
hSub.EnableMenuItem(ID__CUTTHUNK, importOnly);
hSub.EnableMenuItem(ID__DELETETREENODE, itemOnly);
}
void MainGui::DisplayContextMenuImports(CWindow hwnd, CPoint pt)
{
if(TreeImports.GetCount() < 1)
return;
CTreeItem over, parent;
if(pt.x == -1 && pt.y == -1) // invoked by keyboard
{
CRect pos;
over = TreeImports.GetFocusItem();
if(over)
{
over.EnsureVisible();
over.GetRect(&pos, TRUE);
TreeImports.ClientToScreen(&pos);
}
else
{
TreeImports.GetWindowRect(&pos);
}
pt = pos.TopLeft();
}
else
{
// Get item under cursor
over = findTreeItem(pt, true);
}
SetupImportsMenuItems(over);
CMenuHandle hSub = hMenuImports.GetSubMenu(0);
BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd);
if (menuItem)
{
if ((menuItem >= PLUGIN_MENU_BASE_ID) && (menuItem <= (int)(Scylla::plugins.getScyllaPluginList().size() + Scylla::plugins.getImprecPluginList().size() + PLUGIN_MENU_BASE_ID)))
{
//wsprintf(stringBuffer, L"%d %s\n",menuItem,pluginList[menuItem - PLUGIN_MENU_BASE_ID].pluginName);
//MessageBox(stringBuffer, L"plugin selection");
pluginActionHandler(menuItem);
return;
}
switch (menuItem)
{
case ID__INVALIDATE:
if(importsHandling.isModule(over))
importsHandling.invalidateModule(over);
else
importsHandling.invalidateImport(over);
break;
case ID__DISASSEMBLE:
startDisassemblerGui(over);
break;
case ID__EXPANDALLNODES:
importsHandling.expandAllTreeNodes();
break;
case ID__COLLAPSEALLNODES:
importsHandling.collapseAllTreeNodes();
break;
case ID__CUTTHUNK:
importsHandling.cutImport(over);
break;
case ID__DELETETREENODE:
importsHandling.cutModule(importsHandling.isImport(over) ? over.GetParent() : over);
break;
}
}
updateStatusBar();
}
void MainGui::DisplayContextMenuLog(CWindow hwnd, CPoint pt)
{
if(pt.x == -1 && pt.y == -1) // invoked by keyboard
{
CRect pos;
ListLog.GetWindowRect(&pos);
pt = pos.TopLeft();
}
CMenuHandle hSub = hMenuLog.GetSubMenu(0);
BOOL menuItem = hSub.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, hwnd);
if (menuItem)
{
switch (menuItem)
{
case ID__SAVE:
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, filterTxt, L"txt", stringBuffer))
{
saveLogToFile(selectedFilePath);
}
break;
case ID__CLEAR:
clearOutputLog();
break;
}
}
}
void MainGui::appendPluginListToMenu(CMenuHandle hMenu)
{
std::vector<Plugin> &scyllaPluginList = Scylla::plugins.getScyllaPluginList();
std::vector<Plugin> &imprecPluginList = Scylla::plugins.getImprecPluginList();
if (scyllaPluginList.size() > 0)
{
CMenuHandle newMenu;
newMenu.CreatePopupMenu();
for (size_t i = 0; i < scyllaPluginList.size(); i++)
{
newMenu.AppendMenu(MF_STRING, i + PLUGIN_MENU_BASE_ID, scyllaPluginList[i].pluginName);
}
hMenu.AppendMenu(MF_MENUBARBREAK);
hMenu.AppendMenu(MF_POPUP, newMenu, L"Scylla Plugins");
}
if (imprecPluginList.size() > 0)
{
CMenuHandle newMenu;
newMenu.CreatePopupMenu();
for (size_t i = 0; i < imprecPluginList.size(); i++)
{
newMenu.AppendMenu(MF_STRING, scyllaPluginList.size() + i + PLUGIN_MENU_BASE_ID, imprecPluginList[i].pluginName);
}
hMenu.AppendMenu(MF_MENUBARBREAK);
hMenu.AppendMenu(MF_POPUP, newMenu, L"ImpREC Plugins");
}
}
void MainGui::dumpMemoryActionHandler()
{
WCHAR selectedFilePath[MAX_PATH];
DumpMemoryGui dlgDumpMemory;
if(dlgDumpMemory.DoModal())
{
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, dlgDumpMemory.dumpFilename, filterMem, L"mem", stringBuffer))
{
if (ProcessAccessHelp::writeMemoryToNewFile(selectedFilePath,dlgDumpMemory.dumpedMemorySize,dlgDumpMemory.dumpedMemory))
{
Scylla::windowLog.log(L"Memory dump saved %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"Error! Cannot write memory dump to disk");
}
}
}
}
void MainGui::dumpSectionActionHandler()
{
WCHAR selectedFilePath[MAX_PATH];
DumpSectionGui dlgDumpSection;
const WCHAR * fileFilter;
const WCHAR * defExtension;
PeParser * peFile = 0;
dlgDumpSection.entryPoint = EditOEPAddress.GetValue();
if (ProcessAccessHelp::selectedModule)
{
//dump DLL
fileFilter = filterDll;
defExtension = L"dll";
dlgDumpSection.imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
//get it from gui
wcscpy_s(dlgDumpSection.fullpath, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
fileFilter = filterExe;
defExtension = L"exe";
dlgDumpSection.imageBase = ProcessAccessHelp::targetImageBase;
//get it from gui
wcscpy_s(dlgDumpSection.fullpath, selectedProcess->fullPath);
}
if(dlgDumpSection.DoModal())
{
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, fileFilter, defExtension, stringBuffer))
{
checkSuspendProcess();
if (Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue())
{
peFile = new PeParser(dlgDumpSection.fullpath, true);
}
else
{
peFile = new PeParser(dlgDumpSection.imageBase, true);
}
std::vector<PeSection> & sectionList = dlgDumpSection.getSectionList();
if (peFile->dumpProcess(dlgDumpSection.imageBase, dlgDumpSection.entryPoint, selectedFilePath, sectionList))
{
Scylla::windowLog.log(L"Dump success %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"Error: Cannot dump image.");
MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR);
}
delete peFile;
}
}
}
void MainGui::dumpActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
const WCHAR * fileFilter;
const WCHAR * defExtension;
DWORD_PTR modBase = 0;
DWORD_PTR entrypoint = 0;
WCHAR * filename = 0;
PeParser * peFile = 0;
if (ProcessAccessHelp::selectedModule)
{
fileFilter = filterDll;
defExtension = L"dll";
}
else
{
fileFilter = filterExe;
defExtension = L"exe";
}
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, true, NULL, fileFilter, defExtension, stringBuffer))
{
entrypoint = EditOEPAddress.GetValue();
checkSuspendProcess();
if (ProcessAccessHelp::selectedModule)
{
//dump DLL
modBase = ProcessAccessHelp::selectedModule->modBaseAddr;
filename = ProcessAccessHelp::selectedModule->fullPath;
}
else
{
//dump exe
modBase = ProcessAccessHelp::targetImageBase;
filename = selectedProcess->fullPath;
}
if (Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue())
{
peFile = new PeParser(filename, true);
}
else
{
peFile = new PeParser(modBase, true);
}
if (peFile->dumpProcess(modBase, entrypoint, selectedFilePath))
{
Scylla::windowLog.log(L"Dump success %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"Error: Cannot dump image.");
MessageBox(L"Cannot dump image.", L"Failure", MB_ICONERROR);
}
delete peFile;
}
}
void MainGui::peRebuildActionHandler()
{
DWORD newSize = 0;
WCHAR selectedFilePath[MAX_PATH];
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if(showFileDialog(selectedFilePath, false, NULL, filterExeDll, NULL, stringBuffer))
{
if (Scylla::config[CREATE_BACKUP].isTrue())
{
if (!ProcessAccessHelp::createBackupFile(selectedFilePath))
{
Scylla::windowLog.log(L"Creating backup file failed %s", selectedFilePath);
}
}
DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(selectedFilePath);
PeParser peFile(selectedFilePath, true);
if (!peFile.isValidPeFile())
{
Scylla::windowLog.log(L"This is not a valid PE file %s", selectedFilePath);
MessageBox(L"Not a valid PE file.", L"Failure", MB_ICONERROR);
return;
}
if (peFile.readPeSectionsFromFile())
{
peFile.setDefaultFileAlignment();
if (Scylla::config[REMOVE_DOS_HEADER_STUB].isTrue())
{
peFile.removeDosStub();
}
peFile.alignAllSectionHeaders();
peFile.fixPeHeader();
if (peFile.savePeFileToDisk(selectedFilePath))
{
newSize = (DWORD)ProcessAccessHelp::getFileSize(selectedFilePath);
if (Scylla::config[UPDATE_HEADER_CHECKSUM].isTrue())
{
Scylla::windowLog.log(L"Generating PE header checksum");
if (!PeParser::updatePeHeaderChecksum(selectedFilePath, newSize))
{
Scylla::windowLog.log(L"Generating PE header checksum FAILED!");
}
}
Scylla::windowLog.log(L"Rebuild success %s", selectedFilePath);
Scylla::windowLog.log(L"-> Old file size 0x%08X new file size 0x%08X (%d %%)", fileSize, newSize, ((newSize * 100) / fileSize) );
}
else
{
Scylla::windowLog.log(L"Rebuild failed, cannot save file %s", selectedFilePath);
MessageBox(L"Rebuild failed. Cannot save file.", L"Failure", MB_ICONERROR);
}
}
else
{
Scylla::windowLog.log(L"Rebuild failed, cannot read file %s", selectedFilePath);
MessageBox(L"Rebuild failed. Cannot read file.", L"Failure", MB_ICONERROR);
}
}
}
void MainGui::dumpFixActionHandler()
{
if(!selectedProcess)
return;
if (TreeImports.GetCount() < 2)
{
Scylla::windowLog.log(L"Nothing to rebuild");
return;
}
WCHAR newFilePath[MAX_PATH];
WCHAR selectedFilePath[MAX_PATH];
const WCHAR * fileFilter;
DWORD_PTR modBase = 0;
DWORD_PTR entrypoint = EditOEPAddress.GetValue();
if (ProcessAccessHelp::selectedModule)
{
modBase = ProcessAccessHelp::selectedModule->modBaseAddr;
fileFilter = filterDll;
}
else
{
modBase = ProcessAccessHelp::targetImageBase;
fileFilter = filterExe;
}
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if (showFileDialog(selectedFilePath, false, NULL, fileFilter, NULL, stringBuffer))
{
wcscpy_s(newFilePath, selectedFilePath);
const WCHAR * extension = 0;
WCHAR* dot = wcsrchr(newFilePath, L'.');
if (dot)
{
*dot = L'\0';
extension = selectedFilePath + (dot - newFilePath); //wcsrchr(selectedFilePath, L'.');
}
wcscat_s(newFilePath, L"_SCY");
if(extension)
{
wcscat_s(newFilePath, extension);
}
ImportRebuilder importRebuild(selectedFilePath);
if (Scylla::config[IAT_FIX_AND_OEP_FIX].isTrue())
{
importRebuild.setEntryPointRva((DWORD)(entrypoint - modBase));
}
if (Scylla::config[OriginalFirstThunk_SUPPORT].isTrue())
{
importRebuild.enableOFTSupport();
}
if (Scylla::config[SCAN_DIRECT_IMPORTS].isTrue() && Scylla::config[FIX_DIRECT_IMPORTS_UNIVERSAL].isTrue())
{
if (iatReferenceScan.numberOfFoundDirectImports() > 0)
{
importRebuild.iatReferenceScan = &iatReferenceScan;
importRebuild.BuildDirectImportsJumpTable = true;
}
}
if (Scylla::config[CREATE_NEW_IAT_IN_SECTION].isTrue())
{
importRebuild.iatReferenceScan = &iatReferenceScan;
DWORD_PTR addressIAT = EditIATAddress.GetValue();
DWORD sizeIAT = EditIATSize.GetValue();
importRebuild.enableNewIatInSection(addressIAT, sizeIAT);
}
if (importRebuild.rebuildImportTable(newFilePath, importsHandling.moduleList))
{
Scylla::windowLog.log(L"Import Rebuild success %s", newFilePath);
}
else
{
Scylla::windowLog.log(L"Import Rebuild failed %s", selectedFilePath);
MessageBox(L"Import Rebuild failed", L"Failure", MB_ICONERROR);
}
}
}
void MainGui::enableDialogControls(BOOL value)
{
BOOL valButton = value ? TRUE : FALSE;
GetDlgItem(IDC_BTN_PICKDLL).EnableWindow(valButton);
GetDlgItem(IDC_BTN_DUMP).EnableWindow(valButton);
GetDlgItem(IDC_BTN_FIXDUMP).EnableWindow(valButton);
GetDlgItem(IDC_BTN_IATAUTOSEARCH).EnableWindow(valButton);
GetDlgItem(IDC_BTN_GETIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_SUSPECTIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_INVALIDIMPORTS).EnableWindow(valButton);
GetDlgItem(IDC_BTN_CLEARIMPORTS).EnableWindow(valButton);
CMenuHandle menu = GetMenu();
UINT valMenu = value ? MF_ENABLED : MF_GRAYED;
menu.EnableMenuItem(ID_FILE_DUMP, valMenu);
menu.EnableMenuItem(ID_FILE_DUMPMEMORY, valMenu);
menu.EnableMenuItem(ID_FILE_DUMPSECTION, valMenu);
menu.EnableMenuItem(ID_FILE_FIXDUMP, valMenu);
menu.EnableMenuItem(ID_IMPORTS_INVALIDATESELECTED, valMenu);
menu.EnableMenuItem(ID_IMPORTS_CUTSELECTED, valMenu);
menu.EnableMenuItem(ID_IMPORTS_SAVETREE, valMenu);
menu.EnableMenuItem(ID_IMPORTS_LOADTREE, valMenu);
menu.EnableMenuItem(ID_MISC_DLLINJECTION, valMenu);
menu.EnableMenuItem(ID_MISC_DISASSEMBLER, valMenu);
menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetScylla, MF_BYPOSITION | valMenu);
menu.GetSubMenu(MenuImportsOffsetTrace).EnableMenuItem(MenuImportsTraceOffsetImpRec, MF_BYPOSITION | valMenu);
//not yet implemented
GetDlgItem(IDC_BTN_AUTOTRACE).EnableWindow(FALSE);
menu.EnableMenuItem(ID_TRACE_AUTOTRACE, MF_GRAYED);
}
CTreeItem MainGui::findTreeItem(CPoint pt, bool screenCoordinates)
{
if(screenCoordinates)
{
TreeImports.ScreenToClient(&pt);
}
UINT flags;
CTreeItem over = TreeImports.HitTest(pt, &flags);
if(over)
{
if(!(flags & TVHT_ONITEM))
{
over.m_hTreeItem = NULL;
}
}
return over;
}
void MainGui::showAboutDialog()
{
AboutGui dlgAbout;
dlgAbout.DoModal();
}
void MainGui::showDonateDialog()
{
DonateGui dlgDonate;
dlgDonate.DoModal();
}
void MainGui::dllInjectActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
HMODULE hMod = 0;
DllInjection dllInjection;
getCurrentModulePath(stringBuffer, _countof(stringBuffer));
if (showFileDialog(selectedFilePath, false, NULL, filterDll, NULL, stringBuffer))
{
hMod = dllInjection.dllInjection(ProcessAccessHelp::hProcess, selectedFilePath);
if (hMod && Scylla::config[DLL_INJECTION_AUTO_UNLOAD].isTrue())
{
if (!dllInjection.unloadDllInProcess(ProcessAccessHelp::hProcess, hMod))
{
Scylla::windowLog.log(L"DLL unloading failed, target %s", selectedFilePath);
}
}
if (hMod)
{
Scylla::windowLog.log(L"DLL Injection was successful, target %s", selectedFilePath);
}
else
{
Scylla::windowLog.log(L"DLL Injection failed, target %s", selectedFilePath);
}
}
}
void MainGui::disassemblerActionHandler()
{
DWORD_PTR oep = EditOEPAddress.GetValue();
DisassemblerGui disGuiDlg(oep, &apiReader);
disGuiDlg.DoModal();
}
void MainGui::optionsActionHandler()
{
OptionsGui dlgOptions;
dlgOptions.DoModal();
}
void MainGui::clearImportsActionHandler()
{
importsHandling.clearAllImports();
updateStatusBar();
}
void MainGui::pluginActionHandler( int menuItem )
{
if(!selectedProcess)
return;
DllInjectionPlugin dllInjectionPlugin;
std::vector<Plugin> &scyllaPluginList = Scylla::plugins.getScyllaPluginList();
std::vector<Plugin> &imprecPluginList = Scylla::plugins.getImprecPluginList();
menuItem -= PLUGIN_MENU_BASE_ID;
dllInjectionPlugin.hProcess = ProcessAccessHelp::hProcess;
dllInjectionPlugin.apiReader = &apiReader;
if (menuItem < (int)scyllaPluginList.size())
{
//scylla plugin
dllInjectionPlugin.injectPlugin(scyllaPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
}
else
{
#ifndef _WIN64
menuItem -= (int)scyllaPluginList.size();
//imprec plugin
dllInjectionPlugin.injectImprecPlugin(imprecPluginList[menuItem], importsHandling.moduleList,selectedProcess->imageBase, selectedProcess->imageSize);
#endif
}
importsHandling.scanAndFixModuleList();
importsHandling.displayAllImports();
updateStatusBar();
}
bool MainGui::getCurrentModulePath(WCHAR * buffer, size_t bufferSize)
{
if(!selectedProcess)
return false;
if(ProcessAccessHelp::selectedModule)
{
wcscpy_s(buffer, bufferSize, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
wcscpy_s(buffer, bufferSize, selectedProcess->fullPath);
}
WCHAR * slash = wcsrchr(buffer, L'\\');
if(slash)
{
*(slash+1) = L'\0';
}
return true;
}
void MainGui::checkSuspendProcess()
{
if (Scylla::config[SUSPEND_PROCESS_FOR_DUMPING].isTrue())
{
if (!ProcessAccessHelp::suspendProcess())
{
Scylla::windowLog.log(L"Error: Cannot suspend process.");
}
else
{
isProcessSuspended = true;
Scylla::windowLog.log(L"Suspending process successful, please resume manually.");
}
}
}
void MainGui::setDialogIATAddressAndSize( DWORD_PTR addressIAT, DWORD sizeIAT )
{
EditIATAddress.SetValue(addressIAT);
EditIATSize.SetValue(sizeIAT);
swprintf_s(stringBuffer, L"IAT found:\r\n\r\nStart: " PRINTF_DWORD_PTR_FULL L"\r\nSize: 0x%04X (%d) ", addressIAT, sizeIAT, sizeIAT);
MessageBox(stringBuffer, L"IAT found", MB_ICONINFORMATION);
}
bool MainGui::isIATOutsidePeImage( DWORD_PTR addressIAT )
{
DWORD_PTR minAdd = 0, maxAdd = 0;
if(ProcessAccessHelp::selectedModule)
{
minAdd = ProcessAccessHelp::selectedModule->modBaseAddr;
maxAdd = minAdd + ProcessAccessHelp::selectedModule->modBaseSize;
}
else
{
minAdd = selectedProcess->imageBase;
maxAdd = minAdd + selectedProcess->imageSize;
}
if (addressIAT > minAdd && addressIAT < maxAdd)
{
return false; //inside pe image
}
else
{
return true; //outside pe image, requires rebasing iat
}
}
diff --git a/Scylla/PeParser.cpp b/Scylla/PeParser.cpp
index 453129c..da6b58e 100644
--- a/Scylla/PeParser.cpp
+++ b/Scylla/PeParser.cpp
@@ -1,1268 +1,1273 @@
#include "PeParser.h"
#include "ProcessAccessHelp.h"
#include <algorithm>
#include <imagehlp.h>
#pragma comment(lib, "Imagehlp.lib")
PeParser::PeParser()
{
initClass();
}
PeParser::PeParser(const WCHAR * file, bool readSectionHeaders)
{
initClass();
filename = file;
if (filename)
{
readPeHeaderFromFile(readSectionHeaders);
if (readSectionHeaders)
{
if (isValidPeFile())
{
getSectionHeaders();
}
}
}
}
PeParser::PeParser(const DWORD_PTR moduleBase, bool readSectionHeaders)
{
initClass();
moduleBaseAddress = moduleBase;
if (moduleBaseAddress)
{
readPeHeaderFromProcess(readSectionHeaders);
if (readSectionHeaders)
{
if (isValidPeFile())
{
getSectionHeaders();
}
}
}
}
PeParser::~PeParser()
{
if (headerMemory)
{
delete [] headerMemory;
}
if (fileMemory)
{
delete [] fileMemory;
}
for (size_t i = 0; i < listPeSection.size(); i++)
{
if (listPeSection[i].data)
{
delete [] listPeSection[i].data;
}
}
listPeSection.clear();
}
void PeParser::initClass()
{
fileMemory = 0;
headerMemory = 0;
pDosHeader = 0;
pDosStub = 0;
dosStubSize = 0;
pNTHeader32 = 0;
pNTHeader64 = 0;
overlayData = 0;
overlaySize = 0;
filename = 0;
fileSize = 0;
moduleBaseAddress = 0;
hFile = INVALID_HANDLE_VALUE;
}
bool PeParser::isPE64()
{
if (isValidPeFile())
{
return (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC);
}
else
{
return false;
}
}
bool PeParser::isPE32()
{
if (isValidPeFile())
{
return (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC);
}
else
{
return false;
}
}
bool PeParser::isTargetFileSamePeFormat()
{
#ifdef _WIN64
return isPE64();
#else
return isPE32();
#endif
}
bool PeParser::isValidPeFile()
{
bool retValue = false;
if (pDosHeader)
{
if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
if (pNTHeader32)
{
if (pNTHeader32->Signature == IMAGE_NT_SIGNATURE)
{
retValue = true;
}
}
}
}
return retValue;
}
bool PeParser::hasDirectory(const int directoryIndex)
{
if (isPE32())
{
return (pNTHeader32->OptionalHeader.DataDirectory[directoryIndex].VirtualAddress != 0);
}
else if (isPE64())
{
return (pNTHeader64->OptionalHeader.DataDirectory[directoryIndex].VirtualAddress != 0);
}
else
{
return false;
}
}
bool PeParser::hasExportDirectory()
{
return hasDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT);
}
bool PeParser::hasTLSDirectory()
{
return hasDirectory(IMAGE_DIRECTORY_ENTRY_TLS);
}
bool PeParser::hasRelocationDirectory()
{
return hasDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC);
}
DWORD PeParser::getEntryPoint()
{
if (isPE32())
{
return pNTHeader32->OptionalHeader.AddressOfEntryPoint;
}
else if (isPE64())
{
return pNTHeader64->OptionalHeader.AddressOfEntryPoint;
}
else
{
return 0;
}
}
bool PeParser::readPeHeaderFromProcess(bool readSectionHeaders)
{
bool retValue = false;
DWORD correctSize = 0;
DWORD readSize = getInitialHeaderReadSize(readSectionHeaders);
headerMemory = new BYTE[readSize];
if (ProcessAccessHelp::readMemoryPartlyFromProcess(moduleBaseAddress, readSize, headerMemory))
{
retValue = true;
getDosAndNtHeader(headerMemory, (LONG)readSize);
if (isValidPeFile())
{
correctSize = calcCorrectPeHeaderSize(readSectionHeaders);
if (readSize < correctSize)
{
readSize = correctSize;
delete [] headerMemory;
headerMemory = new BYTE[readSize];
if (ProcessAccessHelp::readMemoryPartlyFromProcess(moduleBaseAddress, readSize, headerMemory))
{
getDosAndNtHeader(headerMemory, (LONG)readSize);
}
}
}
}
return retValue;
}
bool PeParser::readPeHeaderFromFile(bool readSectionHeaders)
{
bool retValue = false;
DWORD correctSize = 0;
DWORD numberOfBytesRead = 0;
DWORD readSize = getInitialHeaderReadSize(readSectionHeaders);
headerMemory = new BYTE[readSize];
if (openFileHandle())
{
fileSize = (DWORD)ProcessAccessHelp::getFileSize(hFile);
if (ReadFile(hFile, headerMemory, readSize, &numberOfBytesRead, 0))
{
retValue = true;
getDosAndNtHeader(headerMemory, (LONG)readSize);
if (isValidPeFile())
{
correctSize = calcCorrectPeHeaderSize(readSectionHeaders);
if (readSize < correctSize)
{
readSize = correctSize;
if (fileSize > 0)
{
if (fileSize < correctSize)
{
readSize = fileSize;
}
}
delete [] headerMemory;
headerMemory = new BYTE[readSize];
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
if (ReadFile(hFile, headerMemory, readSize, &numberOfBytesRead, 0))
{
getDosAndNtHeader(headerMemory, (LONG)readSize);
}
}
}
}
closeFileHandle();
}
return retValue;
}
bool PeParser::readPeSectionsFromProcess()
{
bool retValue = true;
DWORD_PTR readOffset = 0;
listPeSection.reserve(getNumberOfSections());
for (WORD i = 0; i < getNumberOfSections(); i++)
{
readOffset = listPeSection[i].sectionHeader.VirtualAddress + moduleBaseAddress;
listPeSection[i].normalSize = listPeSection[i].sectionHeader.Misc.VirtualSize;
if (!readSectionFromProcess(readOffset, listPeSection[i]))
{
retValue = false;
}
}
return retValue;
}
bool PeParser::readPeSectionsFromFile()
{
bool retValue = true;
DWORD readOffset = 0;
listPeSection.reserve(getNumberOfSections());
if (openFileHandle())
{
for (WORD i = 0; i < getNumberOfSections(); i++)
{
readOffset = listPeSection[i].sectionHeader.PointerToRawData;
listPeSection[i].normalSize = listPeSection[i].sectionHeader.SizeOfRawData;
if (!readSectionFromFile(readOffset, listPeSection[i]))
{
retValue = false;
}
}
closeFileHandle();
}
else
{
retValue = false;
}
return retValue;
}
bool PeParser::getSectionHeaders()
{
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNTHeader32);
PeFileSection peFileSection;
listPeSection.clear();
listPeSection.reserve(getNumberOfSections());
for (WORD i = 0; i < getNumberOfSections(); i++)
{
memcpy_s(&peFileSection.sectionHeader, sizeof(IMAGE_SECTION_HEADER), pSection, sizeof(IMAGE_SECTION_HEADER));
listPeSection.push_back(peFileSection);
pSection++;
}
return true;
}
bool PeParser::getSectionNameUnicode(const int sectionIndex, WCHAR * output, const int outputLen)
{
CHAR sectionNameA[IMAGE_SIZEOF_SHORT_NAME + 1] = {0};
output[0] = 0;
memcpy(sectionNameA, listPeSection[sectionIndex].sectionHeader.Name, IMAGE_SIZEOF_SHORT_NAME); //not null terminated
return (swprintf_s(output, outputLen, L"%S", sectionNameA) != -1);
}
WORD PeParser::getNumberOfSections()
{
return pNTHeader32->FileHeader.NumberOfSections;
}
void PeParser::setNumberOfSections(WORD numberOfSections)
{
pNTHeader32->FileHeader.NumberOfSections = numberOfSections;
}
std::vector<PeFileSection> & PeParser::getSectionHeaderList()
{
return listPeSection;
}
void PeParser::getDosAndNtHeader(BYTE * memory, LONG size)
{
pDosHeader = (PIMAGE_DOS_HEADER)memory;
pNTHeader32 = 0;
pNTHeader64 = 0;
dosStubSize = 0;
pDosStub = 0;
if (pDosHeader->e_lfanew > 0 && pDosHeader->e_lfanew < size) //malformed PE
{
pNTHeader32 = (PIMAGE_NT_HEADERS32)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
pNTHeader64 = (PIMAGE_NT_HEADERS64)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
if (pDosHeader->e_lfanew > sizeof(IMAGE_DOS_HEADER))
{
dosStubSize = pDosHeader->e_lfanew - sizeof(IMAGE_DOS_HEADER);
pDosStub = (BYTE *)((DWORD_PTR)pDosHeader + sizeof(IMAGE_DOS_HEADER));
}
else if (pDosHeader->e_lfanew < sizeof(IMAGE_DOS_HEADER))
{
//Overlapped Headers, e.g. Spack (by Bagie)
pDosHeader->e_lfanew = sizeof(IMAGE_DOS_HEADER);
}
}
}
DWORD PeParser::calcCorrectPeHeaderSize(bool readSectionHeaders)
{
DWORD correctSize = pDosHeader->e_lfanew + 50; //extra buffer
if (readSectionHeaders)
{
correctSize += getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER);
}
if (isPE32())
{
correctSize += sizeof(IMAGE_NT_HEADERS32);
}
else if(isPE64())
{
correctSize += sizeof(IMAGE_NT_HEADERS64);
}
else
{
correctSize = 0; //not a valid PE
}
return correctSize;
}
DWORD PeParser::getInitialHeaderReadSize(bool readSectionHeaders)
{
DWORD readSize = sizeof(IMAGE_DOS_HEADER) + 0x300 + sizeof(IMAGE_NT_HEADERS64);
//if (readSectionHeaders)
//{
// readSize += (10 * sizeof(IMAGE_SECTION_HEADER));
//}
return readSize;
}
DWORD PeParser::getSectionHeaderBasedFileSize()
{
DWORD lastRawOffset = 0, lastRawSize = 0;
//this is needed if the sections aren't sorted by their RawOffset (e.g. Petite)
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if (listPeSection[i].sectionHeader.PointerToRawData > lastRawOffset)
{
lastRawOffset = listPeSection[i].sectionHeader.PointerToRawData;
lastRawSize = listPeSection[i].sectionHeader.SizeOfRawData;
}
}
return (lastRawSize + lastRawOffset);
}
DWORD PeParser::getSectionHeaderBasedSizeOfImage()
{
DWORD lastVirtualOffset = 0, lastVirtualSize = 0;
//this is needed if the sections aren't sorted by their RawOffset (e.g. Petite)
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if (listPeSection[i].sectionHeader.VirtualAddress > lastVirtualOffset)
{
lastVirtualOffset = listPeSection[i].sectionHeader.VirtualAddress;
lastVirtualSize = listPeSection[i].sectionHeader.Misc.VirtualSize;
}
}
return (lastVirtualSize + lastVirtualOffset);
}
bool PeParser::openFileHandle()
{
if (hFile == INVALID_HANDLE_VALUE)
{
if (filename)
{
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
}
else
{
hFile = INVALID_HANDLE_VALUE;
}
}
return (hFile != INVALID_HANDLE_VALUE);
}
bool PeParser::openWriteFileHandle( const WCHAR * newFile )
{
if (newFile)
{
hFile = CreateFile(newFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
}
else
{
hFile = INVALID_HANDLE_VALUE;
}
return (hFile != INVALID_HANDLE_VALUE);
}
void PeParser::closeFileHandle()
{
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
}
bool PeParser::readSectionFromProcess(const DWORD_PTR readOffset, PeFileSection & peFileSection)
{
return readSectionFrom(readOffset, peFileSection, true); //process
}
bool PeParser::readSectionFromFile(const DWORD readOffset, PeFileSection & peFileSection)
{
return readSectionFrom(readOffset, peFileSection, false); //file
}
bool PeParser::readSectionFrom(const DWORD_PTR readOffset, PeFileSection & peFileSection, const bool isProcess)
{
const DWORD maxReadSize = 100;
DWORD currentReadSize;
BYTE data[maxReadSize];
bool retValue = true;
DWORD valuesFound = 0;
DWORD readSize = 0;
DWORD_PTR currentOffset = 0;
peFileSection.data = 0;
peFileSection.dataSize = 0;
readSize = peFileSection.normalSize;
if (!readOffset || !readSize)
{
return true; //section without data is valid
}
if (readSize <= maxReadSize)
{
peFileSection.dataSize = readSize;
peFileSection.normalSize = readSize;
if (isProcess)
{
return readPeSectionFromProcess(readOffset, peFileSection);
}
else
{
return readPeSectionFromFile((DWORD)readOffset, peFileSection);
}
}
currentReadSize = readSize % maxReadSize; //alignment %
if (!currentReadSize)
{
currentReadSize = maxReadSize;
}
currentOffset = readOffset + readSize - currentReadSize;
while(currentOffset >= readOffset) //start from the end
{
ZeroMemory(data, currentReadSize);
if (isProcess)
{
retValue = ProcessAccessHelp::readMemoryPartlyFromProcess(currentOffset, currentReadSize, data);
}
else
{
retValue = ProcessAccessHelp::readMemoryFromFile(hFile, (LONG)currentOffset, currentReadSize, data);
}
if (!retValue)
{
break;
}
valuesFound = isMemoryNotNull(data, currentReadSize);
if (valuesFound)
{
//found some real code
currentOffset += valuesFound;
if (readOffset < currentOffset)
{
//real size
peFileSection.dataSize = (DWORD)(currentOffset - readOffset);
//some safety space because of something like this at the end of a section:
//FF25 C0604000 JMP DWORD PTR DS:[<&KERNEL32.RtlUnwind>]
- peFileSection.dataSize += sizeof(DWORD);;
+ peFileSection.dataSize += sizeof(DWORD);
+
+ if (peFileSection.normalSize < peFileSection.dataSize)
+ {
+ peFileSection.dataSize = peFileSection.normalSize;
+ }
}
break;
}
currentReadSize = maxReadSize;
currentOffset -= currentReadSize;
}
if (peFileSection.dataSize)
{
if (isProcess)
{
retValue = readPeSectionFromProcess(readOffset, peFileSection);
}
else
{
retValue = readPeSectionFromFile((DWORD)readOffset, peFileSection);
}
}
return retValue;
}
DWORD PeParser::isMemoryNotNull( BYTE * data, int dataSize )
{
for (int i = (dataSize - 1); i >= 0; i--)
{
if (data[i] != 0)
{
return i + 1;
}
}
return 0;
}
bool PeParser::savePeFileToDisk( const WCHAR * newFile )
{
bool retValue = true;
DWORD dwFileOffset = 0, dwWriteSize = 0;
if (getNumberOfSections() != listPeSection.size())
{
return false;
}
if (openWriteFileHandle(newFile))
{
//Dos header
dwWriteSize = sizeof(IMAGE_DOS_HEADER);
if (!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, pDosHeader))
{
retValue = false;
}
dwFileOffset += dwWriteSize;
if (dosStubSize && pDosStub)
{
//Dos Stub
dwWriteSize = dosStubSize;
if (!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, pDosStub))
{
retValue = false;
}
dwFileOffset += dwWriteSize;
}
//Pe Header
if (isPE32())
{
dwWriteSize = sizeof(IMAGE_NT_HEADERS32);
}
else
{
dwWriteSize = sizeof(IMAGE_NT_HEADERS64);
}
if (!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, pNTHeader32))
{
retValue = false;
}
dwFileOffset += dwWriteSize;
//section headers
dwWriteSize = sizeof(IMAGE_SECTION_HEADER);
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if (!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, &listPeSection[i].sectionHeader))
{
retValue = false;
break;
}
dwFileOffset += dwWriteSize;
}
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if (!listPeSection[i].sectionHeader.PointerToRawData)
continue;
if (listPeSection[i].sectionHeader.PointerToRawData > dwFileOffset)
{
dwWriteSize = listPeSection[i].sectionHeader.PointerToRawData - dwFileOffset; //padding
if (!writeZeroMemoryToFile(hFile, dwFileOffset, dwWriteSize))
{
retValue = false;
break;
}
dwFileOffset += dwWriteSize;
}
dwWriteSize = listPeSection[i].dataSize;
if (dwWriteSize)
{
if (!ProcessAccessHelp::writeMemoryToFile(hFile, listPeSection[i].sectionHeader.PointerToRawData, dwWriteSize, listPeSection[i].data))
{
retValue = false;
break;
}
dwFileOffset += dwWriteSize;
if (listPeSection[i].dataSize < listPeSection[i].sectionHeader.SizeOfRawData) //padding
{
dwWriteSize = listPeSection[i].sectionHeader.SizeOfRawData - listPeSection[i].dataSize;
if (!writeZeroMemoryToFile(hFile, dwFileOffset, dwWriteSize))
{
retValue = false;
break;
}
dwFileOffset += dwWriteSize;
}
}
}
//add overlay?
if (overlaySize && overlayData)
{
dwWriteSize = overlaySize;
if (!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, overlayData))
{
retValue = false;
}
dwFileOffset += dwWriteSize;
}
SetEndOfFile(hFile);
closeFileHandle();
}
return retValue;
}
bool PeParser::writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size)
{
bool retValue = false;
PVOID zeromemory = calloc(size, 1);
if (zeromemory)
{
retValue = ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, size, zeromemory);
free(zeromemory);
}
return retValue;
}
void PeParser::removeDosStub()
{
if (pDosHeader)
{
dosStubSize = 0;
pDosStub = 0; //must not delete []
pDosHeader->e_lfanew = sizeof(IMAGE_DOS_HEADER);
}
}
bool PeParser::readPeSectionFromFile(DWORD readOffset, PeFileSection & peFileSection)
{
DWORD bytesRead = 0;
peFileSection.data = new BYTE[peFileSection.dataSize];
SetFilePointer(hFile, readOffset, 0, FILE_BEGIN);
return (ReadFile(hFile, peFileSection.data, peFileSection.dataSize, &bytesRead, 0) != FALSE);
}
bool PeParser::readPeSectionFromProcess(DWORD_PTR readOffset, PeFileSection & peFileSection)
{
peFileSection.data = new BYTE[peFileSection.dataSize];
return ProcessAccessHelp::readMemoryPartlyFromProcess(readOffset, peFileSection.dataSize, peFileSection.data);
}
DWORD PeParser::alignValue(DWORD badValue, DWORD alignTo)
{
return (((badValue + alignTo - 1) / alignTo) * alignTo);
}
bool PeParser::addNewLastSection(const CHAR * sectionName, DWORD sectionSize, BYTE * sectionData)
{
size_t nameLength = strlen(sectionName);
DWORD fileAlignment = 0, sectionAlignment = 0;
PeFileSection peFileSection;
if (nameLength > IMAGE_SIZEOF_SHORT_NAME)
{
return false;
}
if (isPE32())
{
fileAlignment = pNTHeader32->OptionalHeader.FileAlignment;
sectionAlignment = pNTHeader32->OptionalHeader.SectionAlignment;
}
else
{
fileAlignment = pNTHeader64->OptionalHeader.FileAlignment;
sectionAlignment = pNTHeader64->OptionalHeader.SectionAlignment;
}
memcpy_s(peFileSection.sectionHeader.Name, IMAGE_SIZEOF_SHORT_NAME, sectionName, nameLength);
//last section doesn't need SizeOfRawData alignment
peFileSection.sectionHeader.SizeOfRawData = sectionSize; //alignValue(sectionSize, fileAlignment);
peFileSection.sectionHeader.Misc.VirtualSize = alignValue(sectionSize, sectionAlignment);
peFileSection.sectionHeader.PointerToRawData = alignValue(getSectionHeaderBasedFileSize(), fileAlignment);
peFileSection.sectionHeader.VirtualAddress = alignValue(getSectionHeaderBasedSizeOfImage(), sectionAlignment);
peFileSection.sectionHeader.Characteristics = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA;
peFileSection.normalSize = peFileSection.sectionHeader.SizeOfRawData;
peFileSection.dataSize = peFileSection.sectionHeader.SizeOfRawData;
if (sectionData == 0)
{
peFileSection.data = new BYTE[peFileSection.sectionHeader.SizeOfRawData];
ZeroMemory(peFileSection.data , peFileSection.sectionHeader.SizeOfRawData);
}
else
{
peFileSection.data = sectionData;
}
listPeSection.push_back(peFileSection);
setNumberOfSections(getNumberOfSections() + 1);
return true;
}
DWORD_PTR PeParser::getStandardImagebase()
{
if (isPE32())
{
return pNTHeader32->OptionalHeader.ImageBase;
}
else
{
return pNTHeader64->OptionalHeader.ImageBase;
}
}
int PeParser::convertRVAToOffsetVectorIndex(DWORD_PTR dwRVA)
{
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if ((listPeSection[i].sectionHeader.VirtualAddress <= dwRVA) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > dwRVA))
{
return i;
}
}
return -1;
}
DWORD_PTR PeParser::convertRVAToOffsetVector(DWORD_PTR dwRVA)
{
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if ((listPeSection[i].sectionHeader.VirtualAddress <= dwRVA) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > dwRVA))
{
return ((dwRVA - listPeSection[i].sectionHeader.VirtualAddress) + listPeSection[i].sectionHeader.PointerToRawData);
}
}
return 0;
}
DWORD_PTR PeParser::convertRVAToOffsetRelative(DWORD_PTR dwRVA)
{
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if ((listPeSection[i].sectionHeader.VirtualAddress <= dwRVA) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > dwRVA))
{
return (dwRVA - listPeSection[i].sectionHeader.VirtualAddress);
}
}
return 0;
}
DWORD_PTR PeParser::convertOffsetToRVAVector(DWORD_PTR dwOffset)
{
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if ((listPeSection[i].sectionHeader.PointerToRawData <= dwOffset) && ((listPeSection[i].sectionHeader.PointerToRawData + listPeSection[i].sectionHeader.SizeOfRawData) > dwOffset))
{
return ((dwOffset - listPeSection[i].sectionHeader.PointerToRawData) + listPeSection[i].sectionHeader.VirtualAddress);
}
}
return 0;
}
void PeParser::fixPeHeader()
{
DWORD dwSize = pDosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
if (isPE32())
{
//delete bound import directories
pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
//max 16, zeroing possible garbage values
for (DWORD i = pNTHeader32->OptionalHeader.NumberOfRvaAndSizes; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
{
pNTHeader32->OptionalHeader.DataDirectory[i].Size = 0;
pNTHeader32->OptionalHeader.DataDirectory[i].VirtualAddress = 0;
}
pNTHeader32->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
pNTHeader32->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER32);
pNTHeader32->OptionalHeader.SizeOfImage = getSectionHeaderBasedSizeOfImage();
if (moduleBaseAddress)
{
pNTHeader32->OptionalHeader.ImageBase = (DWORD)moduleBaseAddress;
}
pNTHeader32->OptionalHeader.SizeOfHeaders = alignValue(dwSize + pNTHeader32->FileHeader.SizeOfOptionalHeader + (getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER)), pNTHeader32->OptionalHeader.FileAlignment);
}
else
{
//delete bound import directories
pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
//max 16, zeroing possible garbage values
for (DWORD i = pNTHeader64->OptionalHeader.NumberOfRvaAndSizes; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
{
pNTHeader64->OptionalHeader.DataDirectory[i].Size = 0;
pNTHeader64->OptionalHeader.DataDirectory[i].VirtualAddress = 0;
}
pNTHeader64->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
pNTHeader64->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64);
pNTHeader64->OptionalHeader.SizeOfImage = getSectionHeaderBasedSizeOfImage();
if (moduleBaseAddress)
{
pNTHeader64->OptionalHeader.ImageBase = moduleBaseAddress;
}
pNTHeader64->OptionalHeader.SizeOfHeaders = alignValue(dwSize + pNTHeader64->FileHeader.SizeOfOptionalHeader + (getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER)), pNTHeader64->OptionalHeader.FileAlignment);
}
removeIatDirectory();
}
void PeParser::removeIatDirectory()
{
DWORD searchAddress = 0;
if (isPE32())
{
searchAddress = pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
}
else
{
searchAddress = pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
}
if (searchAddress)
{
for (WORD i = 0; i < getNumberOfSections(); i++)
{
if ((listPeSection[i].sectionHeader.VirtualAddress <= searchAddress) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > searchAddress))
{
//section must be read and writable
listPeSection[i].sectionHeader.Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
}
}
}
}
void PeParser::setDefaultFileAlignment()
{
if (isPE32())
{
pNTHeader32->OptionalHeader.FileAlignment = FileAlignmentConstant;
}
else
{
pNTHeader64->OptionalHeader.FileAlignment = FileAlignmentConstant;
}
}
bool PeFileSectionSortByPointerToRawData(const PeFileSection& d1, const PeFileSection& d2)
{
return d1.sectionHeader.PointerToRawData < d2.sectionHeader.PointerToRawData;
}
bool PeFileSectionSortByVirtualAddress(const PeFileSection& d1, const PeFileSection& d2)
{
return d1.sectionHeader.VirtualAddress < d2.sectionHeader.VirtualAddress;
}
void PeParser::alignAllSectionHeaders()
{
DWORD sectionAlignment = 0;
DWORD fileAlignment = 0;
DWORD newFileSize = 0;
if (isPE32())
{
sectionAlignment = pNTHeader32->OptionalHeader.SectionAlignment;
fileAlignment = pNTHeader32->OptionalHeader.FileAlignment;
}
else
{
sectionAlignment = pNTHeader64->OptionalHeader.SectionAlignment;
fileAlignment = pNTHeader64->OptionalHeader.FileAlignment;
}
std::sort(listPeSection.begin(), listPeSection.end(), PeFileSectionSortByPointerToRawData); //sort by PointerToRawData ascending
newFileSize = pDosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + pNTHeader32->FileHeader.SizeOfOptionalHeader + (getNumberOfSections() * sizeof(IMAGE_SECTION_HEADER));
for (WORD i = 0; i < getNumberOfSections(); i++)
{
listPeSection[i].sectionHeader.VirtualAddress = alignValue(listPeSection[i].sectionHeader.VirtualAddress, sectionAlignment);
listPeSection[i].sectionHeader.Misc.VirtualSize = alignValue(listPeSection[i].sectionHeader.Misc.VirtualSize, sectionAlignment);
listPeSection[i].sectionHeader.PointerToRawData = alignValue(newFileSize, fileAlignment);
listPeSection[i].sectionHeader.SizeOfRawData = alignValue(listPeSection[i].dataSize, fileAlignment);
newFileSize = listPeSection[i].sectionHeader.PointerToRawData + listPeSection[i].sectionHeader.SizeOfRawData;
}
std::sort(listPeSection.begin(), listPeSection.end(), PeFileSectionSortByVirtualAddress); //sort by VirtualAddress ascending
}
bool PeParser::dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR * dumpFilePath)
{
moduleBaseAddress = modBase;
if (readPeSectionsFromProcess())
{
setDefaultFileAlignment();
setEntryPointVa(entryPoint);
alignAllSectionHeaders();
fixPeHeader();
getFileOverlay();
return savePeFileToDisk(dumpFilePath);
}
return false;
}
bool PeParser::dumpProcess(DWORD_PTR modBase, DWORD_PTR entryPoint, const WCHAR * dumpFilePath, std::vector<PeSection> & sectionList)
{
if (listPeSection.size() == sectionList.size())
{
for (int i = (getNumberOfSections() - 1); i >= 0; i--)
{
if (!sectionList[i].isDumped)
{
listPeSection.erase(listPeSection.begin() + i);
setNumberOfSections(getNumberOfSections() - 1);
}
else
{
listPeSection[i].sectionHeader.Misc.VirtualSize = sectionList[i].virtualSize;
listPeSection[i].sectionHeader.SizeOfRawData = sectionList[i].rawSize;
listPeSection[i].sectionHeader.Characteristics = sectionList[i].characteristics;
}
}
}
return dumpProcess(modBase, entryPoint, dumpFilePath);
}
void PeParser::setEntryPointVa(DWORD_PTR entryPoint)
{
DWORD entryPointRva = (DWORD)(entryPoint - moduleBaseAddress);
setEntryPointRva(entryPointRva);
}
void PeParser::setEntryPointRva(DWORD entryPoint)
{
if (isPE32())
{
pNTHeader32->OptionalHeader.AddressOfEntryPoint = entryPoint;
}
else if (isPE64())
{
pNTHeader64->OptionalHeader.AddressOfEntryPoint = entryPoint;
}
}
bool PeParser::getFileOverlay()
{
DWORD numberOfBytesRead;
bool retValue = false;
if (!hasOverlayData())
{
return false;
}
if (openFileHandle())
{
DWORD overlayOffset = getSectionHeaderBasedFileSize();
DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(hFile);
overlaySize = fileSize - overlayOffset;
overlayData = new BYTE[overlaySize];
SetFilePointer(hFile, overlayOffset, 0, FILE_BEGIN);
if (ReadFile(hFile, overlayData, overlaySize, &numberOfBytesRead, 0))
{
retValue = true;
}
closeFileHandle();
}
return retValue;
}
bool PeParser::hasOverlayData()
{
if (!filename)
return false;
if (isValidPeFile())
{
DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(filename);
return (fileSize > getSectionHeaderBasedFileSize());
}
else
{
return false;
}
}
bool PeParser::updatePeHeaderChecksum(const WCHAR * targetFile, DWORD fileSize)
{
PIMAGE_NT_HEADERS32 pNTHeader32 = 0;
PIMAGE_NT_HEADERS64 pNTHeader64 = 0;
DWORD headerSum = 0;
DWORD checkSum = 0;
bool retValue = false;
if (!fileSize)
return retValue;
HANDLE hFileToMap = CreateFile(targetFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(hFileToMap != INVALID_HANDLE_VALUE)
{
HANDLE hMappedFile = CreateFileMapping(hFileToMap, 0, PAGE_READWRITE, 0, 0, 0);
if(hMappedFile)
{
if (GetLastError() != ERROR_ALREADY_EXISTS)
{
LPVOID addrMappedDll = MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (addrMappedDll)
{
pNTHeader32 = (PIMAGE_NT_HEADERS32)CheckSumMappedFile(addrMappedDll, fileSize, &headerSum, &checkSum);
if (pNTHeader32)
{
if (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
pNTHeader64 = (PIMAGE_NT_HEADERS64)pNTHeader32;
pNTHeader64->OptionalHeader.CheckSum = checkSum;
}
else
{
pNTHeader32->OptionalHeader.CheckSum = checkSum;
}
retValue = true;
}
UnmapViewOfFile(addrMappedDll);
}
}
CloseHandle(hMappedFile);
}
CloseHandle(hFileToMap);
}
return retValue;
}
BYTE * PeParser::getSectionMemoryByIndex(int index)
{
return listPeSection[index].data;
}
DWORD PeParser::getSectionMemorySizeByIndex(int index)
{
return listPeSection[index].dataSize;
}
DWORD PeParser::getSectionAddressRVAByIndex( int index )
{
return listPeSection[index].sectionHeader.VirtualAddress;
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jan 7, 12:33 AM (2 h, 29 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
69/c5/c583780ebd1e5b6ff0991a7ab1b1

Event Timeline