Page MenuHomedesp's stash

No OneTemporary

diff --git a/Scylla/ConfigurationHolder.cpp b/Scylla/ConfigurationHolder.cpp
index c04838f..ea530f9 100644
--- a/Scylla/ConfigurationHolder.cpp
+++ b/Scylla/ConfigurationHolder.cpp
@@ -1,202 +1,203 @@
#include "ConfigurationHolder.h"
#include <shlwapi.h>
#include "Architecture.h"
const WCHAR ConfigurationHolder::CONFIG_FILE_SECTION_NAME[] = L"SCYLLA_CONFIG";
//#define DEBUG_COMMENTS
ConfigurationHolder::ConfigurationHolder(const WCHAR* fileName)
{
config[USE_PE_HEADER_FROM_DISK] = Configuration(L"USE_PE_HEADER_FROM_DISK", Configuration::Boolean);
config[DEBUG_PRIVILEGE] = Configuration(L"DEBUG_PRIVILEGE", Configuration::Boolean);
config[CREATE_BACKUP] = Configuration(L"CREATE_BACKUP", Configuration::Boolean);
config[DLL_INJECTION_AUTO_UNLOAD] = Configuration(L"DLL_INJECTION_AUTO_UNLOAD", Configuration::Boolean);
config[UPDATE_HEADER_CHECKSUM] = Configuration(L"UPDATE_HEADER_CHECKSUM", Configuration::Boolean);
config[IAT_SECTION_NAME] = Configuration(L"IAT_SECTION_NAME", Configuration::String);
+ config[REMOVE_DOS_HEADER_STUB] = Configuration(L"REMOVE_DOS_HEADER_STUB", Configuration::Boolean);
buildConfigFilePath(fileName);
}
bool ConfigurationHolder::loadConfiguration()
{
std::map<ConfigOption, Configuration>::iterator mapIter;
if (configPath[0] == '\0')
{
return false;
}
for (mapIter = config.begin() ; mapIter != config.end(); mapIter++)
{
Configuration& configObject = mapIter->second;
if (!loadConfig(configObject))
{
return false;
}
}
return true;
}
bool ConfigurationHolder::saveConfiguration() const
{
std::map<ConfigOption, Configuration>::const_iterator mapIter;
if (configPath[0] == '\0')
{
return false;
}
for (mapIter = config.begin() ; mapIter != config.end(); mapIter++)
{
const Configuration& configObject = mapIter->second;
if (!saveConfig(configObject))
{
return false;
}
}
return true;
}
Configuration& ConfigurationHolder::operator[](ConfigOption option)
{
return config[option];
}
const Configuration& ConfigurationHolder::operator[](ConfigOption option) const
{
static const Configuration dummy;
std::map<ConfigOption, Configuration>::const_iterator found = config.find(option);
if(found != config.end())
{
return found->second;
}
else
{
return dummy;
}
}
bool ConfigurationHolder::saveNumericToConfigFile(const Configuration & configObject, int nBase) const
{
WCHAR buf[21]; // UINT64_MAX in dec has 20 digits
if (nBase == 16)
{
swprintf_s(buf, PRINTF_DWORD_PTR_FULL, configObject.getNumeric());
}
else
{
swprintf_s(buf, PRINTF_INTEGER, configObject.getNumeric());
}
BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), buf, configPath);
return ret == TRUE;
}
bool ConfigurationHolder::readNumericFromConfigFile(Configuration & configObject, int nBase)
{
WCHAR buf[21]; // UINT64_MAX in dec has 20 digits
DWORD read = GetPrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), L"", buf, _countof(buf), configPath);
if (read > 0 && wcslen(buf) > 0)
{
#ifdef _WIN64
configObject.setNumeric(_wcstoui64(buf, NULL, nBase));
#else
configObject.setNumeric(wcstoul(buf, NULL, nBase));
#endif
return true;
}
return false;
}
bool ConfigurationHolder::saveStringToConfigFile(const Configuration & configObject) const
{
BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), configObject.getString(), configPath);
return ret == TRUE;
}
bool ConfigurationHolder::readStringFromConfigFile(Configuration & configObject)
{
WCHAR buf[Configuration::CONFIG_STRING_LENGTH];
DWORD read = GetPrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), L"", buf, _countof(buf), configPath);
if(read > 0 && wcslen(buf) > 0)
{
configObject.setString(buf);
return true;
}
return false;
}
bool ConfigurationHolder::readBooleanFromConfigFile(Configuration & configObject)
{
UINT val = GetPrivateProfileInt(CONFIG_FILE_SECTION_NAME, configObject.getName(), 0, configPath);
configObject.setBool(val != 0);
return true;
}
bool ConfigurationHolder::saveBooleanToConfigFile(const Configuration & configObject) const
{
const WCHAR *boolValue = configObject.isTrue() ? L"1" : L"0";
BOOL ret = WritePrivateProfileString(CONFIG_FILE_SECTION_NAME, configObject.getName(), boolValue, configPath);
return ret == TRUE;
}
bool ConfigurationHolder::loadConfig(Configuration & configObject)
{
switch (configObject.getType())
{
case Configuration::String:
return readStringFromConfigFile(configObject);
case Configuration::Boolean:
return readBooleanFromConfigFile(configObject);
case Configuration::Decimal:
return readNumericFromConfigFile(configObject, 10);
case Configuration::Hexadecimal:
return readNumericFromConfigFile(configObject, 16);
default:
return false;
}
}
bool ConfigurationHolder::saveConfig(const Configuration & configObject) const
{
switch (configObject.getType())
{
case Configuration::String:
return saveStringToConfigFile(configObject);
case Configuration::Boolean:
return saveBooleanToConfigFile(configObject);
case Configuration::Decimal:
return saveNumericToConfigFile(configObject, 10);
case Configuration::Hexadecimal:
return saveNumericToConfigFile(configObject, 16);
default:
return false;
}
}
bool ConfigurationHolder::buildConfigFilePath(const WCHAR* fileName)
{
ZeroMemory(configPath, sizeof(configPath));
if (!GetModuleFileName(0, configPath, _countof(configPath)))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"buildConfigFilePath :: GetModuleFileName failed %d", GetLastError());
#endif
return false;
}
PathRemoveFileSpec(configPath);
PathAppend(configPath, fileName);
return true;
}
diff --git a/Scylla/ConfigurationHolder.h b/Scylla/ConfigurationHolder.h
index 174196e..ab526d6 100644
--- a/Scylla/ConfigurationHolder.h
+++ b/Scylla/ConfigurationHolder.h
@@ -1,48 +1,49 @@
#pragma once
#include <windows.h>
#include <map>
#include "Configuration.h"
enum ConfigOption
{
USE_PE_HEADER_FROM_DISK,
DEBUG_PRIVILEGE,
CREATE_BACKUP,
DLL_INJECTION_AUTO_UNLOAD,
IAT_SECTION_NAME,
UPDATE_HEADER_CHECKSUM,
+ REMOVE_DOS_HEADER_STUB
};
class ConfigurationHolder
{
public:
ConfigurationHolder(const WCHAR* fileName);
bool loadConfiguration();
bool saveConfiguration() const;
Configuration& operator[](ConfigOption option);
const Configuration& operator[](ConfigOption option) const;
private:
static const WCHAR CONFIG_FILE_SECTION_NAME[];
WCHAR configPath[MAX_PATH];
std::map<ConfigOption, Configuration> config;
bool buildConfigFilePath(const WCHAR* fileName);
bool readStringFromConfigFile(Configuration & configObject);
bool readBooleanFromConfigFile(Configuration & configObject);
bool readNumericFromConfigFile(Configuration & configObject, int nBase);
bool saveStringToConfigFile(const Configuration & configObject) const;
bool saveBooleanToConfigFile(const Configuration & configObject) const;
bool saveNumericToConfigFile(const Configuration & configObject, int nBase) const;
bool loadConfig(Configuration & configObject);
bool saveConfig(const Configuration & configObject) const;
};
diff --git a/Scylla/DumpMemoryGui.cpp b/Scylla/DumpMemoryGui.cpp
index 11c9cf3..33f7aae 100644
--- a/Scylla/DumpMemoryGui.cpp
+++ b/Scylla/DumpMemoryGui.cpp
@@ -1,571 +1,571 @@
#include "DumpMemoryGui.h"
#include "Architecture.h"
#include "ProcessAccessHelp.h"
#include <Psapi.h>
#include "PeParser.h"
WCHAR DumpMemoryGui::protectionString[100];
const WCHAR DumpMemoryGui::MemoryUndefined[] = L"UNDEF";
const WCHAR DumpMemoryGui::MemoryUnknown[] = L"UNKNOWN";
const WCHAR * DumpMemoryGui::MemoryStateValues[] = {L"COMMIT",L"FREE",L"RESERVE"};
const WCHAR * DumpMemoryGui::MemoryTypeValues[] = {L"IMAGE",L"MAPPED",L"PRIVATE"};
const WCHAR * DumpMemoryGui::MemoryProtectionValues[] = {L"EXECUTE",L"EXECUTE_READ",L"EXECUTE_READWRITE",L"EXECUTE_WRITECOPY",L"NOACCESS",L"READONLY",L"READWRITE",L"WRITECOPY",L"GUARD",L"NOCACHE",L"WRITECOMBINE"};
DumpMemoryGui::DumpMemoryGui()
{
dumpedMemory = 0;
dumpedMemorySize = 0;
deviceNameResolver = new DeviceNameResolver();
}
DumpMemoryGui::~DumpMemoryGui()
{
if (dumpedMemory)
{
delete [] dumpedMemory;
}
if (deviceNameResolver)
{
delete deviceNameResolver;
}
}
BOOL DumpMemoryGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
DoDataExchange(); // attach controls
DlgResize_Init(true, true);
addColumnsToMemoryList(ListMemorySelect);
displayMemoryList(ListMemorySelect);
forceDump = false;
DoDataExchange(DDX_LOAD);
EditMemoryAddress.SetValue(ProcessAccessHelp::targetImageBase);
EditMemorySize.SetValue((DWORD)ProcessAccessHelp::targetSizeOfImage);
CenterWindow();
return TRUE;
}
void DumpMemoryGui::addColumnsToMemoryList(CListViewCtrl& list)
{
list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
list.InsertColumn(COL_ADDRESS, L"Address", LVCFMT_CENTER);
list.InsertColumn(COL_SIZE, L"Size", LVCFMT_CENTER);
list.InsertColumn(COL_FILENAME, L"File", LVCFMT_LEFT);
list.InsertColumn(COL_PESECTION, L"PE Section", LVCFMT_LEFT);
list.InsertColumn(COL_TYPE, L"Type", LVCFMT_CENTER);
list.InsertColumn(COL_PROTECTION, L"Protection", LVCFMT_CENTER);
list.InsertColumn(COL_STATE, L"State", LVCFMT_CENTER);
list.InsertColumn(COL_MAPPED_FILE, L"Mapped File", LVCFMT_LEFT);
}
void DumpMemoryGui::displayMemoryList(CListViewCtrl& list)
{
int count = 0;
WCHAR temp[20];
list.DeleteAllItems();
getMemoryList();
std::vector<Memory>::const_iterator iter;
for( iter = memoryList.begin(); iter != memoryList.end(); iter++ , count++)
{
swprintf_s(temp, PRINTF_DWORD_PTR_FULL, iter->address);
list.InsertItem(count,temp);
swprintf_s(temp, L"%08X", iter->size);
list.SetItemText(count, COL_SIZE, temp);
list.SetItemText(count, COL_FILENAME, iter->filename);
list.SetItemText(count, COL_PESECTION, iter->peSection);
if (iter->state == MEM_FREE)
{
list.SetItemText(count, COL_TYPE, MemoryUndefined);
}
else
{
list.SetItemText(count, COL_TYPE, getMemoryTypeString(iter->type));
}
if ( (iter->state == MEM_RESERVE) || (iter->state == MEM_FREE) )
{
list.SetItemText(count, COL_PROTECTION, MemoryUndefined);
}
else
{
list.SetItemText(count, COL_PROTECTION, getMemoryProtectionString(iter->protect));
}
list.SetItemText(count, COL_STATE, getMemoryStateString(iter->state));
list.SetItemText(count, COL_MAPPED_FILE, iter->mappedFilename);
list.SetItemData(count, (DWORD_PTR)&(*iter));
}
list.SetColumnWidth(COL_ADDRESS, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_SIZE, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_FILENAME, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_PESECTION, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_TYPE, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_PROTECTION, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_STATE, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_MAPPED_FILE, LVSCW_AUTOSIZE_USEHEADER);
}
const WCHAR * DumpMemoryGui::getMemoryTypeString(DWORD value)
{
switch(value)
{
case MEM_IMAGE:
return MemoryTypeValues[TYPE_IMAGE];
case MEM_MAPPED:
return MemoryTypeValues[TYPE_MAPPED];
case MEM_PRIVATE:
return MemoryTypeValues[TYPE_PRIVATE];
default:
return MemoryUnknown;
}
}
const WCHAR * DumpMemoryGui::getMemoryStateString(DWORD value)
{
switch(value)
{
case MEM_COMMIT:
return MemoryStateValues[STATE_COMMIT];
case MEM_FREE:
return MemoryStateValues[STATE_FREE];
case MEM_RESERVE:
return MemoryStateValues[STATE_RESERVE];
default:
return MemoryUnknown;
}
}
WCHAR * DumpMemoryGui::getMemoryProtectionString(DWORD value)
{
protectionString[0] = 0;
if (value & PAGE_GUARD)
{
wcscpy_s(protectionString, MemoryProtectionValues[PROT_GUARD]);
wcscat_s(protectionString, L" | ");
value ^= PAGE_GUARD;
}
if (value & PAGE_NOCACHE)
{
wcscpy_s(protectionString, MemoryProtectionValues[PROT_NOCACHE]);
wcscat_s(protectionString, L" | ");
value ^= PAGE_NOCACHE;
}
if (value & PAGE_WRITECOMBINE)
{
wcscpy_s(protectionString, MemoryProtectionValues[PROT_WRITECOMBINE]);
wcscat_s(protectionString, L" | ");
value ^= PAGE_WRITECOMBINE;
}
switch(value)
{
case PAGE_EXECUTE:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE]);
break;
}
case PAGE_EXECUTE_READ:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE_READ]);
break;
}
case PAGE_EXECUTE_READWRITE:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE_READWRITE]);
break;
}
case PAGE_EXECUTE_WRITECOPY:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_EXECUTE_WRITECOPY]);
break;
}
case PAGE_NOACCESS:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_NOACCESS]);
break;
}
case PAGE_READONLY:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_READONLY]);
break;
}
case PAGE_READWRITE:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_READWRITE]);
break;
}
case PAGE_WRITECOPY:
{
wcscat_s(protectionString, MemoryProtectionValues[PROT_WRITECOPY]);
break;
}
default:
{
wcscat_s(protectionString, MemoryUnknown);
}
}
return protectionString;
}
LRESULT DumpMemoryGui::OnListMemoryColumnClicked(NMHDR* pnmh)
{
NMLISTVIEW* list = (NMLISTVIEW*)pnmh;
int column = list->iSubItem;
if(column == prevColumn)
{
ascending = !ascending;
}
else
{
prevColumn = column;
ascending = true;
}
// lo-byte: column, hi-byte: sort-order
ListMemorySelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending));
return 0;
}
LRESULT DumpMemoryGui::OnListMemoryClick(NMHDR* pnmh)
{
int index = ListMemorySelect.GetSelectionMark();
if (index != -1)
{
selectedMemory = (Memory *)ListMemorySelect.GetItemData(index);
if (selectedMemory)
{
updateAddressAndSize(selectedMemory);
}
}
return 0;
}
void DumpMemoryGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl)
{
DoDataExchange(DDX_SAVE);
if (EditMemoryAddress.GetValue() == 0 || EditMemorySize.GetValue() == 0)
{
wndCtl.MessageBoxW(L"Textbox is empty!",L"Error",MB_ICONERROR);
}
else
{
if (dumpMemory())
{
EndDialog(1);
}
else
{
wndCtl.MessageBoxW(L"Reading memory from process failed",L"Error",MB_ICONERROR);
}
}
}
void DumpMemoryGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(0);
}
void DumpMemoryGui::updateAddressAndSize( Memory * selectedMemory )
{
EditMemoryAddress.SetValue(selectedMemory->address);
EditMemorySize.SetValue(selectedMemory->size);
}
int DumpMemoryGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
const Memory * module1 = (Memory *)lParam1;
const Memory * module2 = (Memory *)lParam2;
int column = LOBYTE(lParamSort);
bool ascending = (HIBYTE(lParamSort) == TRUE);
int diff = 0;
switch(column)
{
case COL_ADDRESS:
diff = module1->address < module2->address ? -1 : 1;
break;
case COL_SIZE:
diff = module1->size < module2->size ? -1 : 1;
break;
case COL_FILENAME:
diff = _wcsicmp(module1->filename, module2->filename);
break;
case COL_PESECTION:
diff = _wcsicmp(module1->peSection, module2->peSection);
break;
case COL_TYPE:
diff = module1->type < module2->type ? -1 : 1;
break;
case COL_PROTECTION:
diff = module1->protect < module2->protect ? -1 : 1;
break;
case COL_STATE:
diff = _wcsicmp(getMemoryStateString(module1->state), getMemoryStateString(module2->state));
//diff = module1->state < module2->state ? -1 : 1;
break;
case COL_MAPPED_FILE:
diff = _wcsicmp(module1->mappedFilename, module2->mappedFilename);
break;
}
return ascending ? diff : -diff;
}
void DumpMemoryGui::getMemoryList()
{
DWORD count = 0;
DWORD_PTR address = 0;
MEMORY_BASIC_INFORMATION memBasic = {0};
Memory memory;
HMODULE * hMods = 0;
DWORD cbNeeded = 0;
bool notEnough = true;
WCHAR target[MAX_PATH];
count = 100;
hMods = new HMODULE[count];
if (memoryList.empty())
{
memoryList.reserve(20);
}
else
{
memoryList.clear();
}
memory.filename[0] = 0;
memory.peSection[0] = 0;
memory.mappedFilename[0] = 0;
while(VirtualQueryEx(ProcessAccessHelp::hProcess,(LPCVOID)address,&memBasic,sizeof(memBasic)))
{
memory.address = (DWORD_PTR)memBasic.BaseAddress;
memory.type = memBasic.Type;
memory.state = memBasic.State;
memory.size = (DWORD)memBasic.RegionSize;
memory.protect = memBasic.Protect;
if (memory.type == MEM_MAPPED)
{
if (!getMappedFilename(&memory))
{
memory.mappedFilename[0] = 0;
}
}
memoryList.push_back(memory);
memory.mappedFilename[0] = 0;
address += memBasic.RegionSize;
}
do
{
if (!EnumProcessModules(ProcessAccessHelp::hProcess, hMods, count * sizeof(HMODULE), &cbNeeded))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getMemoryList :: EnumProcessModules failed count %d", count);
#endif
delete [] hMods;
return;
}
if ( (count * sizeof(HMODULE)) < cbNeeded )
{
delete [] hMods;
count += 100;
hMods = new HMODULE[count];
}
else
{
notEnough = false;
}
} while (notEnough);
for (DWORD i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
if (GetModuleFileNameExW(ProcessAccessHelp::hProcess, hMods[i], target, _countof(target)))
{
setModuleName((DWORD_PTR)hMods[i],target);
setAllSectionNames((DWORD_PTR)hMods[i],target);
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getMemoryList :: GetModuleFileNameExW failed 0x%X", GetLastError());
#endif
}
}
delete [] hMods;
}
void DumpMemoryGui::setSectionName(DWORD_PTR sectionAddress, DWORD sectionSize, const WCHAR * sectionName)
{
bool found = false;
std::vector<Memory>::const_iterator iter;
for( iter = memoryList.begin(); iter != memoryList.end(); iter++)
{
if (!found)
{
if ( (iter->address <= sectionAddress) && (sectionAddress < (iter->address + iter->size)) )
{
if (wcslen(iter->peSection) == 0)
{
wcscpy_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName);
}
else
{
wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, L"|");
wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName);
}
found = true;
}
}
else
{
if ((sectionSize+sectionAddress) < iter->address)
{
break;
}
if (wcslen(iter->peSection) == 0)
{
wcscpy_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName);
}
else
{
wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, L"|");
wcscat_s((WCHAR *)iter->peSection, IMAGE_SIZEOF_SHORT_NAME * 4, sectionName);
}
}
}
}
void DumpMemoryGui::setModuleName(DWORD_PTR moduleBase, const WCHAR * moduleName)
{
bool found = false;
std::vector<Memory>::const_iterator iter;
//get filename
const WCHAR* slash = wcsrchr(moduleName, L'\\');
if(slash)
{
moduleName = slash+1;
}
for( iter = memoryList.begin(); iter != memoryList.end(); iter++)
{
if (iter->address == moduleBase)
{
found = true;
}
if (found)
{
if (iter->type == MEM_IMAGE)
{
wcscpy_s((WCHAR *)iter->filename, MAX_PATH, moduleName);
}
else
{
break;
}
}
}
}
void DumpMemoryGui::setAllSectionNames( DWORD_PTR moduleBase, WCHAR * moduleName )
{
WCHAR sectionNameW[IMAGE_SIZEOF_SHORT_NAME + 1] = {0};
PeParser peFile(moduleName);
if (peFile.isValidPeFile())
{
- std::vector<IMAGE_SECTION_HEADER> & listSectionHeader = peFile.getSectionHeaderList();
+ std::vector<PeFileSection> & listSectionHeader = peFile.getSectionHeaderList();
for (WORD i = 0; i < peFile.getNumberOfSections(); i++)
{
peFile.getSectionNameUnicode(i, sectionNameW, _countof(sectionNameW));
- setSectionName(moduleBase + listSectionHeader[i].VirtualAddress, listSectionHeader[i].Misc.VirtualSize, sectionNameW);
+ setSectionName(moduleBase + listSectionHeader[i].sectionHeader.VirtualAddress, listSectionHeader[i].sectionHeader.Misc.VirtualSize, sectionNameW);
}
}
else
{
MessageBox(moduleName,L"Not a valid PE -> This should never happen",MB_ICONERROR);
}
}
bool DumpMemoryGui::dumpMemory()
{
DWORD_PTR address = EditMemoryAddress.GetValue();
dumpedMemorySize = EditMemorySize.GetValue();
swprintf_s(dumpFilename,TEXT("MEM_")TEXT(PRINTF_DWORD_PTR_FULL_S)TEXT("_")TEXT("%08X"),address,dumpedMemorySize);
dumpedMemory = new BYTE[dumpedMemorySize];
if (dumpedMemory)
{
if (forceDump)
{
return ProcessAccessHelp::readMemoryPartlyFromProcess(address,dumpedMemorySize,dumpedMemory);
}
else
{
return ProcessAccessHelp::readMemoryFromProcess(address,dumpedMemorySize,dumpedMemory);
}
}
else
{
return false;
}
}
bool DumpMemoryGui::getMappedFilename( Memory* memory )
{
WCHAR filename[MAX_PATH] = {0};
//TODO replace with Nt direct syscall
if (GetMappedFileNameW(ProcessAccessHelp::hProcess, (LPVOID)memory->address, filename, _countof(filename)) > 0)
{
return deviceNameResolver->resolveDeviceLongNameToShort(filename, memory->mappedFilename);
}
return false;
}
diff --git a/Scylla/DumpSectionGui.cpp b/Scylla/DumpSectionGui.cpp
index 6a044b2..5b2480b 100644
--- a/Scylla/DumpSectionGui.cpp
+++ b/Scylla/DumpSectionGui.cpp
@@ -1,355 +1,355 @@
#include "DumpSectionGui.h"
#include "Architecture.h"
#include "ProcessAccessHelp.h"
#include "PeParser.h"
bool PeSection::highlightVirtualSize()
{
//highlight big virtual sizes -> anti-dump protection
return (virtualSize > 0x2000000);
}
std::vector<PeSection> & DumpSectionGui::getSectionList()
{
return sectionList;
}
BOOL DumpSectionGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
DoDataExchange(); // attach controls
DlgResize_Init(true, true);
addColumnsToSectionList(ListSectionSelect);
displaySectionList(ListSectionSelect);
selectOrDeselectAll();
isEditing = false;
selectedSection = 0;
CenterWindow();
return TRUE;
}
LRESULT DumpSectionGui::OnListSectionColumnClicked(NMHDR* pnmh)
{
NMLISTVIEW* list = (NMLISTVIEW*)pnmh;
int column = list->iSubItem;
if(column == prevColumn)
{
ascending = !ascending;
}
else
{
prevColumn = column;
ascending = true;
}
// lo-byte: column, hi-byte: sort-order
ListSectionSelect.SortItems(&listviewCompareFunc, MAKEWORD(column, ascending));
return 0;
}
LRESULT DumpSectionGui::OnListSectionClick(NMHDR* pnmh)
{
//int index = ListSectionSelect.GetSelectionMark();
//if (index != -1)
//{
//}
return 0;
}
LRESULT DumpSectionGui::OnListDoubleClick(NMHDR* pnmh)
{
RECT rect;
RECT rect1,rect2;
NMITEMACTIVATE* ia = (NMITEMACTIVATE*)pnmh;
if (ia->iSubItem != COL_VSize)
{
return 0;
}
LVHITTESTINFO hti;
hti.pt = ia->ptAction;
int clicked = ListSectionSelect.HitTest(&hti);
if(clicked != -1)
{
selectedSection = (PeSection *)ListSectionSelect.GetItemData(clicked);
}
ListSectionSelect.GetSubItemRect(ia->iItem,ia->iSubItem,LVIR_BOUNDS,&rect);
//Get the Rectange of the listControl
ListSectionSelect.GetWindowRect(&rect1);
//Get the Rectange of the Dialog
GetWindowRect(&rect2);
int x = rect1.left - rect2.left;
int y = rect1.top - rect2.top;
isEditing = true;
EditListControl.SetWindowPos(HWND_TOP,rect.left + 7, rect.top + 7, rect.right - rect.left, rect.bottom - rect.top, NULL);
EditListControl.ShowWindow(SW_SHOW);
EditListControl.SetFocus();
//Draw a Rectangle around the SubItem
//Rectangle(ListSectionSelect.GetDC(),rect.left,rect.top-1,rect.right,rect.bottom);
//Set the listItem text in the EditBox
EditListControl.SetValue(selectedSection->virtualSize);
return 0;
}
void DumpSectionGui::OnSectionSelectAll(UINT uNotifyCode, int nID, CWindow wndCtl)
{
selectOrDeselectAll();
}
void DumpSectionGui::OnEditList(UINT uNotifyCode, int nID, CWindow wndCtl)
{
switch (uNotifyCode)
{
case EN_KILLFOCUS:
{
isEditing = false;
updateEditedItem();
EditListControl.ShowWindow(SW_HIDE);
}
break;
}
}
void DumpSectionGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl)
{
if (isEditing) //EN_KILLFOCUS not sent?
{
updateEditedItem();
}
updateCheckState();
EndDialog(1);
}
void DumpSectionGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(0);
}
int DumpSectionGui::listviewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
const PeSection * module1 = (PeSection *)lParam1;
const PeSection * module2 = (PeSection *)lParam2;
int column = LOBYTE(lParamSort);
bool ascending = (HIBYTE(lParamSort) == TRUE);
int diff = 0;
switch(column)
{
case COL_NAME:
diff = _wcsicmp(module1->name, module2->name);
break;
case COL_VA:
diff = module1->virtualAddress < module2->virtualAddress ? -1 : 1;
break;
case COL_VSize:
diff = module1->virtualSize < module2->virtualSize ? -1 : 1;
break;
case COL_RVA:
diff = module1->rawAddress < module2->rawAddress ? -1 : 1;
break;
case COL_RSize:
diff = module1->rawSize < module2->rawSize ? -1 : 1;
break;
case COL_Characteristics:
diff = module1->characteristics < module2->characteristics ? -1 : 1;
break;
}
return ascending ? diff : -diff;
}
void DumpSectionGui::addColumnsToSectionList(CListViewCtrl& list)
{
list.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES|LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES|LVS_EX_GRIDLINES);
list.InsertColumn(COL_NAME, L"Name", LVCFMT_CENTER);
list.InsertColumn(COL_VA, L"Virtual Address", LVCFMT_CENTER);
list.InsertColumn(COL_VSize, L"Virtual Size", LVCFMT_CENTER);
list.InsertColumn(COL_RVA, L"Raw Address", LVCFMT_CENTER);
list.InsertColumn(COL_RSize, L"Raw Size", LVCFMT_CENTER);
list.InsertColumn(COL_Characteristics, L"Characteristics", LVCFMT_CENTER);
}
void DumpSectionGui::displaySectionList(CListViewCtrl& list)
{
int count = 0;
WCHAR temp[20];
list.DeleteAllItems();
if (sectionList.empty())
{
getAllSectionsFromFile();
}
std::vector<PeSection>::const_iterator iter;
for( iter = sectionList.begin(); iter != sectionList.end(); iter++ , count++)
{
list.InsertItem(count, iter->name);
swprintf_s(temp, PRINTF_DWORD_PTR_FULL, iter->virtualAddress);
list.SetItemText(count, COL_VA, temp);
swprintf_s(temp, L"%08X", iter->virtualSize);
list.SetItemText(count, COL_VSize, temp);
swprintf_s(temp, L"%08X", iter->rawAddress);
list.SetItemText(count, COL_RVA, temp);
swprintf_s(temp, L"%08X", iter->rawSize);
list.SetItemText(count, COL_RSize, temp);
swprintf_s(temp, L"%08X", iter->characteristics);
list.SetItemText(count, COL_Characteristics, temp);
list.SetItemData(count, (DWORD_PTR)&(*iter));
}
list.SetColumnWidth(COL_NAME, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_VA, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_VSize, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_RVA, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_RSize, LVSCW_AUTOSIZE_USEHEADER);
list.SetColumnWidth(COL_Characteristics, LVSCW_AUTOSIZE_USEHEADER);
}
LRESULT DumpSectionGui::OnNMCustomdraw(NMHDR* pnmh)
{
LRESULT pResult = 0;
unsigned int vectorIndex = 0;
LPNMLVCUSTOMDRAW lpLVCustomDraw = (LPNMLVCUSTOMDRAW)(pnmh);
switch(lpLVCustomDraw->nmcd.dwDrawStage)
{
case CDDS_ITEMPREPAINT:
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
{
vectorIndex = (unsigned int)lpLVCustomDraw->nmcd.dwItemSpec;
if (lpLVCustomDraw->iSubItem == COL_VSize)
{
if (sectionList[vectorIndex].highlightVirtualSize())
{
lpLVCustomDraw->clrText = RGB(255,255,255); // white text
lpLVCustomDraw->clrTextBk = RGB(255,0,0); // red background
}
}
else
{
lpLVCustomDraw->clrText = CLR_DEFAULT;
lpLVCustomDraw->clrTextBk = CLR_DEFAULT;
}
}
break;
default:
break;
}
pResult |= CDRF_NOTIFYPOSTPAINT;
pResult |= CDRF_NOTIFYITEMDRAW;
pResult |= CDRF_NOTIFYSUBITEMDRAW;
return pResult;
}
void DumpSectionGui::getAllSectionsFromFile()
{
PeSection peSection;
if (sectionList.empty())
{
sectionList.reserve(3);
}
else
{
sectionList.clear();
}
PeParser peFile(fullpath);
if (peFile.isValidPeFile())
{
- std::vector<IMAGE_SECTION_HEADER> & listSectionHeader = peFile.getSectionHeaderList();
+ std::vector<PeFileSection> & listSectionHeader = peFile.getSectionHeaderList();
for (WORD i = 0; i < peFile.getNumberOfSections(); i++)
{
peFile.getSectionNameUnicode(i, peSection.name, _countof(peSection.name));
- peSection.virtualAddress = imageBase + listSectionHeader[i].VirtualAddress;
- peSection.virtualSize = listSectionHeader[i].Misc.VirtualSize;
- peSection.rawAddress = listSectionHeader[i].PointerToRawData;
- peSection.rawSize = listSectionHeader[i].SizeOfRawData;
- peSection.characteristics = listSectionHeader[i].Characteristics;
+ peSection.virtualAddress = imageBase + listSectionHeader[i].sectionHeader.VirtualAddress;
+ peSection.virtualSize = listSectionHeader[i].sectionHeader.Misc.VirtualSize;
+ peSection.rawAddress = listSectionHeader[i].sectionHeader.PointerToRawData;
+ peSection.rawSize = listSectionHeader[i].sectionHeader.SizeOfRawData;
+ peSection.characteristics = listSectionHeader[i].sectionHeader.Characteristics;
peSection.isDumped = true;
sectionList.push_back(peSection);
}
}
else
{
MessageBox(fullpath, L"Not a valid PE -> This should never happen", MB_ICONERROR);
}
}
void DumpSectionGui::updateEditedItem()
{
if (selectedSection)
{
DWORD newValue = EditListControl.GetValue();
if (selectedSection->virtualSize != newValue)
{
selectedSection->virtualSize = newValue;
displaySectionList(ListSectionSelect);
selectOrDeselectAll();
}
}
}
void DumpSectionGui::updateCheckState()
{
PeSection * pesection;
for (size_t i = 0; i < sectionList.size(); i++)
{
pesection = (PeSection *)ListSectionSelect.GetItemData((int)i);
pesection->isDumped = ListSectionSelect.GetCheckState((int)i) == TRUE;
}
}
void DumpSectionGui::selectOrDeselectAll()
{
BOOL checkState = ListSectionSelect.GetCheckState((int)0) ? FALSE : TRUE;
for (size_t i = 0; i < sectionList.size(); i++)
{
ListSectionSelect.SetCheckState((int)i, checkState);
}
}
diff --git a/Scylla/MainGui.cpp b/Scylla/MainGui.cpp
index dbdce44..188a08a 100644
--- a/Scylla/MainGui.cpp
+++ b/Scylla/MainGui.cpp
@@ -1,1318 +1,1334 @@
#include "MainGui.h"
#include "Architecture.h"
//#include "PluginLoader.h"
//#include "ConfigurationHolder.h"
#include "PeDump.h"
-#include "PeRebuild.h"
+//#include "PeRebuild.h"
+#include "PeParser.h"
#include "DllInjectionPlugin.h"
#include "DisassemblerGui.h"
#include "PickApiGui.h"
//#include "NativeWinApi.h"
#include "ImportRebuild.h"
#include "SystemInformation.h"
#include "Scylla.h"
#include "AboutGui.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), 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);
*/
Scylla::init();
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;
}
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();
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)
{
processSelectedActionHandler(ComboProcessList.GetCurSel());
}
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::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)
{
DestroyWindow();
}
void MainGui::OnAbout(UINT uNotifyCode, int nID, CWindow wndCtl)
{
showAboutDialog();
}
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;
Scylla::windowLog.log(L"->>> Module %s selected.", ProcessAccessHelp::selectedModule->getFilename());
Scylla::windowLog.log(L"Imagebase: " PRINTF_DWORD_PTR_FULL L" Size: %08X", ProcessAccessHelp::selectedModule->modBaseAddr, ProcessAccessHelp::selectedModule->modBaseSize);
}
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);
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::targetSizeOfImage = process.imageSize;
ProcessAccessHelp::targetImageBase = process.imageBase;
ProcessAccessHelp::getSizeOfImageCurrentProcess();
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;
DWORD sizeIAT = 0;
IATSearch iatSearch;
if(!selectedProcess)
return;
if(EditOEPAddress.GetWindowTextLength() > 0)
{
searchAddress = EditOEPAddress.GetValue();
if (searchAddress)
{
if (iatSearch.searchImportAddressTableInProcess(searchAddress, &addressIAT, &sizeIAT))
{
Scylla::windowLog.log(L"IAT found at VA " PRINTF_DWORD_PTR_FULL L" RVA " PRINTF_DWORD_PTR_FULL L" Size 0x%04X (%d)", addressIAT, addressIAT - ProcessAccessHelp::targetImageBase, sizeIAT, 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);
}
else
{
Scylla::windowLog.log(L"IAT not found at OEP " PRINTF_DWORD_PTR_FULL L"!", searchAddress);
}
}
}
}
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();
}
}
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;
if (ProcessAccessHelp::selectedModule)
{
//dump DLL
dlgDumpSection.imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
dlgDumpSection.sizeOfImage = ProcessAccessHelp::selectedModule->modBaseSize;
//get it from gui
wcscpy_s(dlgDumpSection.fullpath, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
dlgDumpSection.imageBase = ProcessAccessHelp::targetImageBase;
dlgDumpSection.sizeOfImage = (DWORD)ProcessAccessHelp::targetSizeOfImage;
//get it from gui
wcscpy_s(dlgDumpSection.fullpath, selectedProcess->fullPath);
}
if(dlgDumpSection.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::dumpActionHandler()
{
if(!selectedProcess)
return;
WCHAR selectedFilePath[MAX_PATH];
const WCHAR * fileFilter;
const WCHAR * defExtension;
PeDump peDump;
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))
{
if (ProcessAccessHelp::selectedModule)
{
//dump DLL
peDump.imageBase = ProcessAccessHelp::selectedModule->modBaseAddr;
peDump.sizeOfImage = ProcessAccessHelp::selectedModule->modBaseSize;
//get it from gui
peDump.entryPoint = EditOEPAddress.GetValue();
wcscpy_s(peDump.fullpath, ProcessAccessHelp::selectedModule->fullPath);
}
else
{
peDump.imageBase = ProcessAccessHelp::targetImageBase;
peDump.sizeOfImage = (DWORD)ProcessAccessHelp::targetSizeOfImage;
//get it from gui
peDump.entryPoint = EditOEPAddress.GetValue();
wcscpy_s(peDump.fullpath, selectedProcess->fullPath);
}
peDump.useHeaderFromDisk = Scylla::config[USE_PE_HEADER_FROM_DISK].isTrue();
if (peDump.dumpCompleteProcessToDisk(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);
}
}
}
void MainGui::peRebuildActionHandler()
{
DWORD newSize = 0;
WCHAR selectedFilePath[MAX_PATH];
- PeRebuild peRebuild;
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);
}
}
- LONGLONG fileSize = ProcessAccessHelp::getFileSize(selectedFilePath);
- LPVOID mapped = peRebuild.createFileMappingViewFull(selectedFilePath);
+ DWORD fileSize = (DWORD)ProcessAccessHelp::getFileSize(selectedFilePath);
- newSize = peRebuild.realignPE(mapped, (DWORD)fileSize);
- peRebuild.closeAllMappingHandles();
-
- if (newSize < 10)
+ PeParser peFile(selectedFilePath, true);
+ if (peFile.readPeSectionsFromFile())
{
- Scylla::windowLog.log(L"Rebuild failed %s", selectedFilePath);
- MessageBox(L"Rebuild failed.", L"Failure", MB_ICONERROR);
+ 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);
+
+ 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
{
- peRebuild.truncateFile(selectedFilePath, newSize);
-
- Scylla::windowLog.log(L"Rebuild success %s", selectedFilePath);
- Scylla::windowLog.log(L"-> Old file size 0x%08X new file size 0x%08X (%d %%)", (DWORD)fileSize, newSize, (DWORD)((newSize * 100) / (DWORD)fileSize) );
+ 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;
if (ProcessAccessHelp::selectedModule)
{
fileFilter = filterDll;
}
else
{
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);
}
ImportRebuild importRebuild;
if (importRebuild.rebuildImportTable(selectedFilePath,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.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::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::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;
}
diff --git a/Scylla/MainGui.rc b/Scylla/MainGui.rc
index b90752d..544a714 100644
Binary files a/Scylla/MainGui.rc and b/Scylla/MainGui.rc differ
diff --git a/Scylla/OptionsGui.cpp b/Scylla/OptionsGui.cpp
index 1fc51e4..39083ac 100644
--- a/Scylla/OptionsGui.cpp
+++ b/Scylla/OptionsGui.cpp
@@ -1,49 +1,52 @@
#include "OptionsGui.h"
#include "Scylla.h"
BOOL OptionsGui::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
loadOptions();
DoDataExchange(DDX_LOAD); // show settings
EditSectionName.LimitText(IMAGE_SIZEOF_SHORT_NAME);
CenterWindow();
return TRUE;
}
void OptionsGui::OnOK(UINT uNotifyCode, int nID, CWindow wndCtl)
{
DoDataExchange(DDX_SAVE);
saveOptions();
Scylla::config.saveConfiguration();
EndDialog(0);
}
void OptionsGui::OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl)
{
EndDialog(0);
}
void OptionsGui::saveOptions() const
{
Scylla::config[USE_PE_HEADER_FROM_DISK].setBool(usePEHeaderFromDisk);
Scylla::config[DEBUG_PRIVILEGE].setBool(debugPrivilege);
Scylla::config[CREATE_BACKUP].setBool(createBackup);
Scylla::config[DLL_INJECTION_AUTO_UNLOAD].setBool(dllInjectionAutoUnload);
Scylla::config[UPDATE_HEADER_CHECKSUM].setBool(updateHeaderChecksum);
Scylla::config[IAT_SECTION_NAME].setString(iatSectionName);
+ Scylla::config[REMOVE_DOS_HEADER_STUB].setBool(removeDosHeaderStub);
}
void OptionsGui::loadOptions()
{
usePEHeaderFromDisk = Scylla::config[USE_PE_HEADER_FROM_DISK].getBool();
debugPrivilege = Scylla::config[DEBUG_PRIVILEGE].getBool();
createBackup = Scylla::config[CREATE_BACKUP].getBool();
dllInjectionAutoUnload = Scylla::config[DLL_INJECTION_AUTO_UNLOAD].getBool();
updateHeaderChecksum = Scylla::config[UPDATE_HEADER_CHECKSUM].getBool();
wcsncpy_s(iatSectionName, Scylla::config[IAT_SECTION_NAME].getString(), _countof(iatSectionName)-1);
iatSectionName[_countof(iatSectionName) - 1] = L'\0';
+
+ removeDosHeaderStub = Scylla::config[REMOVE_DOS_HEADER_STUB].getBool();
}
diff --git a/Scylla/OptionsGui.h b/Scylla/OptionsGui.h
index 8d3fd95..6e94ca3 100644
--- a/Scylla/OptionsGui.h
+++ b/Scylla/OptionsGui.h
@@ -1,63 +1,65 @@
#pragma once
#include <windows.h>
#include "resource.h"
// WTL
#include <atlbase.h> // base ATL classes
#include <atlapp.h> // base WTL classes
#include <atlwin.h> // ATL GUI classes
#include <atlcrack.h> // WTL enhanced msg map macros
#include <atlctrls.h> // WTL controls
#include <atlddx.h> // WTL dialog data exchange
class OptionsGui : public CDialogImpl<OptionsGui>, public CWinDataExchange<OptionsGui>
{
public:
enum { IDD = IDD_DLG_OPTIONS };
BEGIN_DDX_MAP(OptionsGui)
DDX_CONTROL_HANDLE(IDC_OPTIONS_SECTIONNAME, EditSectionName)
DDX_TEXT(IDC_OPTIONS_SECTIONNAME, iatSectionName)
DDX_CHECK(IDC_CHECK_HEADER_CHECKSUM, updateHeaderChecksum)
DDX_CHECK(IDC_CHECK_CREATE_BACKUP, createBackup)
DDX_CHECK(IDC_CHECK_UNLOAD_DLL, dllInjectionAutoUnload)
DDX_CHECK(IDC_CHECK_PE_HEADER_FROM_DISK, usePEHeaderFromDisk)
DDX_CHECK(IDC_CHECK_DEBUG_PRIVILEGES, debugPrivilege)
+ DDX_CHECK(IDC_CHECK_REMOVE_DOS_STUB, removeDosHeaderStub)
END_DDX_MAP()
BEGIN_MSG_MAP(OptionsGui)
MSG_WM_INITDIALOG(OnInitDialog)
COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_OK, OnOK)
COMMAND_ID_HANDLER_EX(IDC_BTN_OPTIONS_CANCEL, OnCancel)
COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
END_MSG_MAP()
protected:
// Settings (filled by DDX)
WCHAR iatSectionName[IMAGE_SIZEOF_SHORT_NAME+1];
bool updateHeaderChecksum;
bool createBackup;
bool dllInjectionAutoUnload;
bool usePEHeaderFromDisk;
bool debugPrivilege;
+ bool removeDosHeaderStub;
// Controls
CEdit EditSectionName;
// Message handlers
BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl);
// Gui helpers
void saveOptions() const;
void loadOptions();
};
diff --git a/Scylla/PeParser.cpp b/Scylla/PeParser.cpp
index 135b323..b3584e5 100644
--- a/Scylla/PeParser.cpp
+++ b/Scylla/PeParser.cpp
@@ -1,703 +1,1046 @@
#include "PeParser.h"
#include "ProcessAccessHelp.h"
+#include <algorithm>
PeParser::PeParser()
{
initClass();
}
PeParser::PeParser(const WCHAR * file, bool readSectionHeaders)
{
initClass();
filename = file;
if (filename && wcslen(filename) > 3)
{
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;
}
- listSectionHeaders.clear();
+ 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 numberOfBytesRead = 0;
- DWORD readSize = 0;
DWORD readOffset = 0;
- PeFileSection peFileSection;
+ listPeSection.reserve(getNumberOfSections());
+
if (openFileHandle())
{
- listPeSection.reserve(getNumberOfSections());
-
for (WORD i = 0; i < getNumberOfSections(); i++)
{
- readOffset = listSectionHeaders[i].PointerToRawData;
- readSize = listSectionHeaders[i].SizeOfRawData;
+ readOffset = listPeSection[i].sectionHeader.PointerToRawData;
- peFileSection.normalSize = readSize;
+ listPeSection[i].normalSize = listPeSection[i].sectionHeader.SizeOfRawData;
- if (readSectionFromFile(readOffset, readSize, peFileSection))
- {
- listPeSection.push_back(peFileSection);
- }
- else
+ if (!readSectionFromFile(readOffset, listPeSection[i]))
{
retValue = false;
}
}
closeFileHandle();
}
else
{
retValue = false;
}
return retValue;
}
bool PeParser::getSectionHeaders()
{
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNTHeader32);
- listSectionHeaders.clear();
- listSectionHeaders.reserve(getNumberOfSections());
+ PeFileSection peFileSection;
+
+ listPeSection.clear();
+ listPeSection.reserve(getNumberOfSections());
for (WORD i = 0; i < getNumberOfSections(); i++)
{
- listSectionHeaders.push_back(*pSection);
+ 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, listSectionHeaders[sectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME); //not null terminated
+ 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;
}
-std::vector<IMAGE_SECTION_HEADER> & PeParser::getSectionHeaderList()
+void PeParser::setNumberOfSections(WORD numberOfSections)
+{
+ pNTHeader32->FileHeader.NumberOfSections = numberOfSections;
+}
+
+std::vector<PeFileSection> & PeParser::getSectionHeaderList()
{
- return listSectionHeaders;
+ 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));
}
}
}
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) + 200 + 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 (listSectionHeaders[i].PointerToRawData > lastRawOffset)
+ if (listPeSection[i].sectionHeader.PointerToRawData > lastRawOffset)
{
- lastRawOffset = listSectionHeaders[i].PointerToRawData;
- lastRawSize = listSectionHeaders[i].SizeOfRawData;
+ 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::readSectionFromFile(DWORD readOffset, DWORD readSize, PeFileSection & peFileSection)
+bool PeParser::readSectionFromFile(DWORD readOffset, PeFileSection & peFileSection)
{
const DWORD maxReadSize = 100;
BYTE data[maxReadSize];
DWORD bytesRead = 0;
bool retValue = true;
DWORD valuesFound = 0;
DWORD currentOffset = 0;
+ DWORD readSize = 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;
return readPeSectionFromFile(readOffset, peFileSection);
}
currentOffset = readOffset + readSize - maxReadSize;
while(currentOffset >= readOffset) //start from the end
{
SetFilePointer(hFile, currentOffset, 0, FILE_BEGIN);
+ ZeroMemory(data, sizeof(data));
if (!ReadFile(hFile, data, sizeof(data), &bytesRead, 0))
{
retValue = false;
break;
}
valuesFound = isMemoryNotNull(data, sizeof(data));
if (valuesFound)
{
//found some real code
currentOffset += valuesFound;
if (readOffset < currentOffset)
{
//real size
peFileSection.dataSize = currentOffset - readOffset;
}
break;
}
currentOffset -= maxReadSize;
}
if (peFileSection.dataSize)
{
- readPeSectionFromFile(readOffset, peFileSection);
+ retValue = readPeSectionFromFile(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() != listSectionHeaders.size() || getNumberOfSections() != listPeSection.size())
+ 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, &listSectionHeaders[i]))
+ if (!ProcessAccessHelp::writeMemoryToFile(hFile, dwFileOffset, dwWriteSize, &listPeSection[i].sectionHeader))
{
retValue = false;
break;
}
dwFileOffset += dwWriteSize;
}
for (WORD i = 0; i < getNumberOfSections(); i++)
{
- if (!listSectionHeaders[i].PointerToRawData)
+ if (!listPeSection[i].sectionHeader.PointerToRawData)
continue;
- dwWriteSize = listSectionHeaders[i].PointerToRawData - dwFileOffset; //padding
- if (dwWriteSize)
+ 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, dwFileOffset, dwWriteSize, listPeSection[i].data))
+ if (!ProcessAccessHelp::writeMemoryToFile(hFile, listPeSection[i].sectionHeader.PointerToRawData, dwWriteSize, listPeSection[i].data))
{
retValue = false;
break;
}
dwFileOffset += dwWriteSize;
- if (listPeSection[i].dataSize < listSectionHeaders[i].SizeOfRawData) //padding
+ if (listPeSection[i].dataSize < listPeSection[i].sectionHeader.SizeOfRawData) //padding
{
- dwWriteSize = listSectionHeaders[i].SizeOfRawData - listPeSection[i].dataSize;
+ 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);
- if (!ReadFile(hFile, peFileSection.data, peFileSection.dataSize, &bytesRead, 0))
+
+ return (ReadFile(hFile, peFileSection.data, peFileSection.dataSize, &bytesRead, 0) != FALSE);
+}
+
+bool PeParser::readSectionFromProcess( DWORD_PTR readOffset, PeFileSection & peFileSection )
+{
+ const DWORD maxReadSize = 100;
+ 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;
+
+ return readPeSectionFromProcess(readOffset, peFileSection);
+ }
+
+ currentOffset = readOffset + readSize - maxReadSize;
+
+ while(currentOffset >= readOffset) //start from the end
+ {
+ if (!ProcessAccessHelp::readMemoryPartlyFromProcess(currentOffset, sizeof(data), data))
+ {
+ retValue = false;
+ break;
+ }
+
+ valuesFound = isMemoryNotNull(data, sizeof(data));
+ if (valuesFound)
+ {
+ //found some real code
+
+ currentOffset += valuesFound;
+
+ if (readOffset < currentOffset)
+ {
+ //real size
+ peFileSection.dataSize = (DWORD)(currentOffset - readOffset);
+ }
+
+ break;
+ }
+
+ currentOffset -= maxReadSize;
+ }
+
+ if (peFileSection.dataSize)
+ {
+ retValue = readPeSectionFromProcess(readOffset, peFileSection);
+ }
+
+ return retValue;
+}
+
+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::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::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
+ if (pNTHeader64->OptionalHeader.NumberOfRvaAndSizes > 0x10)
+ {
+ pNTHeader64->OptionalHeader.NumberOfRvaAndSizes = 0x10;
+ }
+
+ pNTHeader32->OptionalHeader.SizeOfImage = getSectionHeaderBasedSizeOfImage();
+
+ 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
+ if (pNTHeader64->OptionalHeader.NumberOfRvaAndSizes > 0x10)
+ {
+ pNTHeader64->OptionalHeader.NumberOfRvaAndSizes = 0x10;
+ }
+
+ pNTHeader64->OptionalHeader.SizeOfImage = getSectionHeaderBasedSizeOfImage();
+
+ 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
{
- return true;
+ 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
+}
diff --git a/Scylla/PeParser.h b/Scylla/PeParser.h
index 600bd79..e4ddfba 100644
--- a/Scylla/PeParser.h
+++ b/Scylla/PeParser.h
@@ -1,94 +1,122 @@
#pragma once
#include <windows.h>
#include <vector>
-class PeFileSection
-{
+class PeFileSection {
public:
+ IMAGE_SECTION_HEADER sectionHeader;
BYTE * data;
DWORD dataSize;
DWORD normalSize;
+
+ PeFileSection()
+ {
+ ZeroMemory(&sectionHeader, sizeof(IMAGE_SECTION_HEADER));
+ data = 0;
+ dataSize = 0;
+ normalSize = 0;
+ }
};
class PeParser
{
public:
PeParser(const WCHAR * file, bool readSectionHeaders = true);
PeParser(const DWORD_PTR moduleBase, bool readSectionHeaders = true);
~PeParser();
bool isValidPeFile();
bool isPE64();
bool isPE32();
bool isTargetFileSamePeFormat();
WORD getNumberOfSections();
- std::vector<IMAGE_SECTION_HEADER> & getSectionHeaderList();
+ std::vector<PeFileSection> & getSectionHeaderList();
bool hasExportDirectory();
bool hasTLSDirectory();
bool hasRelocationDirectory();
DWORD getEntryPoint();
bool getSectionNameUnicode(const int sectionIndex, WCHAR * output, const int outputLen);
DWORD getSectionHeaderBasedFileSize();
+ DWORD getSectionHeaderBasedSizeOfImage();
+ bool readPeSectionsFromProcess();
bool readPeSectionsFromFile();
bool savePeFileToDisk(const WCHAR * newFile);
void removeDosStub();
+ void alignAllSectionHeaders();
+ void fixPeHeader();
+ void setDefaultFileAlignment();
protected:
PeParser();
+
+ static const DWORD FileAlignmentConstant = 0x200;
+
const WCHAR * filename;
DWORD_PTR moduleBaseAddress;
/************************************************************************/
/* PE FILE */
/* */
/* IMAGE_DOS_HEADER 64 0x40 */
/* IMAGE_NT_HEADERS32 248 0xF8 */
/* IMAGE_NT_HEADERS64 264 0x108 */
/* IMAGE_SECTION_HEADER 40 0x28 */
/************************************************************************/
PIMAGE_DOS_HEADER pDosHeader;
BYTE * pDosStub; //between dos header and section header
DWORD dosStubSize;
PIMAGE_NT_HEADERS32 pNTHeader32;
PIMAGE_NT_HEADERS64 pNTHeader64;
- std::vector<IMAGE_SECTION_HEADER> listSectionHeaders;
std::vector<PeFileSection> listPeSection;
BYTE * overlayData;
DWORD overlaySize;
/************************************************************************/
BYTE * fileMemory;
BYTE * headerMemory;
HANDLE hFile;
DWORD fileSize;
bool readPeHeaderFromFile(bool readSectionHeaders);
bool readPeHeaderFromProcess(bool readSectionHeaders);
bool hasDirectory(const int directoryIndex);
bool getSectionHeaders();
void getDosAndNtHeader(BYTE * memory, LONG size);
DWORD calcCorrectPeHeaderSize( bool readSectionHeaders );
DWORD getInitialHeaderReadSize( bool readSectionHeaders );
bool openFileHandle();
void closeFileHandle();
void initClass();
- bool readSectionFromFile( DWORD readOffset, DWORD readSize, PeFileSection & peFileSection );
+
DWORD isMemoryNotNull( BYTE * data, int dataSize );
bool openWriteFileHandle( const WCHAR * newFile );
bool writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size);
+
bool readPeSectionFromFile( DWORD readOffset, PeFileSection & peFileSection );
+ bool readPeSectionFromProcess( DWORD_PTR readOffset, PeFileSection & peFileSection );
+
+ bool readSectionFromFile( DWORD readOffset, PeFileSection & peFileSection );
+ bool readSectionFromProcess( DWORD_PTR readOffset, PeFileSection & peFileSection );
+
+ bool addNewLastSection(const CHAR * sectionName, DWORD sectionSize, BYTE * sectionData);
+ DWORD alignValue(DWORD badValue, DWORD alignTo);
+ DWORD_PTR convertOffsetToRVAVector(DWORD_PTR dwOffset);
+ DWORD_PTR convertRVAToOffsetVector(DWORD_PTR dwRVA);
+ void setNumberOfSections(WORD numberOfSections);
+
+ void removeIatDirectory();
};
diff --git a/Scylla/resource.h b/Scylla/resource.h
index 8281203..2072e6a 100644
Binary files a/Scylla/resource.h and b/Scylla/resource.h differ

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 21, 12:05 PM (1 d, 12 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
7f/71/f471b87bcf5cb33e987c579094e4

Event Timeline