Page MenuHomedesp's stash

No OneTemporary

diff --git a/README.md b/README.md
index deda214..a98eb38 100644
--- a/README.md
+++ b/README.md
@@ -1,115 +1,103 @@
Scylla - x64/x86 Imports Reconstruction
=======================================
ImpREC, CHimpREC, Imports Fixer... this are all great tools to rebuild an import table,
but they all have some major disadvantages, so I decided to create my own tool for this job.
Scylla's key benefits are:
- x64 and x86 support
- - full unicode support (probably some russian or chinese will like this :-) )
+ - full unicode support
- written in C/C++
- plugin support
- works great with Windows 7
This tool was designed to be used with Windows 7 x64, so it is recommend to use this operating system.
But it may work with XP and Vista, too.
Source code is licensed under GNU GENERAL PUBLIC LICENSE v3.0
Known Bugs
----------
### Only Windows XP x64:
Windows XP x64 has some API bugs. 100% correct imports reconstruction is impossible.
If you still want to use XP x64, here are some hints:
* EncodePointer/DecodePointer exported by kernel32.dll have both the same VA.
Scylla, CHimpREC and other tools cannot know which API is correct. You need to fix this manually.
Your fixed dump will probably run fine on XP but crash on Vista/7.
### ImpREC plugin support:
Some ImpREC Plugins don't work with Windows Vista/7 because they don't "return 1" in the DllMain function.
Keyboard Shortcuts
------------------
- CTRL + D: [D]ump
- CTRL + F: [F]ix Dump
- CTRL + R: PE [R]ebuild
- CTRL + O: L[o]ad Tree
- CTRL + S: [S]ave Tree
- CTRL + T: Auto[t]race
- CTRL + G: [G]et Imports
- CTRL + I: [I]AT Autosearch
Changelog
---------
Version 0.6b
- internal code changes
- added option: fix iat and oep
Version 0.6a
- fixed buffer to small bug in dump memory
Version 0.6
- added dump memory regions
- added dump pe sections -> you can edit some values in the dialog
- improved dump engine with intelligent dumping
- improved pe rebuild engine -> removed yoda's code
- fixed various bugs
Version 0.5a:
- fixed memory leak
- improved IAT search
Version 0.5:
- added save/load import tree feature
- multi-select in tree view
- fixed black icons problem in tree view
- added keyboard shortcuts
- dll dump + dll dump fix now working
- added support for scattered IATs
- pre select target path in open file dialogs
- improved import resolving engine with api scoring
- api selection dialog
- minor bug fixes and improvements
Version 0.4:
- GUI code improvements
- bug fixes
- imports by ordinal
Version 0.3a:
- Improved import resolving
- fixed buffer overflow errors
Version 0.3:
- ImpREC plugin support
- minor bug fix
-
-Version 0.2a:
-
- - improved disassembler dialog
- - improved iat search
-
-Version 0.2:
-
- - improved process detection
- - added some options
- - new options dialog
- - improved source code
diff --git a/Scylla/ImportRebuilder.cpp b/Scylla/ImportRebuilder.cpp
index 016d3dd..ab0afdf 100644
--- a/Scylla/ImportRebuilder.cpp
+++ b/Scylla/ImportRebuilder.cpp
@@ -1,288 +1,288 @@
#include "ImportRebuilder.h"
#include "Scylla.h"
#include "StringConversion.h"
-#define DEBUG_COMMENTS
+//#define DEBUG_COMMENTS
bool ImportRebuilder::rebuildImportTable(const WCHAR * newFilePath, std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
{
bool retValue = false;
if (isValidPeFile())
{
if (readPeSectionsFromFile())
{
setDefaultFileAlignment();
retValue = buildNewImportTable(moduleList);
if (retValue)
{
alignAllSectionHeaders();
fixPeHeader();
retValue = savePeFileToDisk(newFilePath);
}
}
}
return retValue;
}
bool ImportRebuilder::buildNewImportTable(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
{
createNewImportSection(moduleList);
importSectionIndex = listPeSection.size() - 1;
DWORD dwSize = fillImportSection(moduleList);
if (!dwSize)
{
return false;
}
setFlagToIATSection((*moduleList.begin()).second.firstThunk);
if (isPE32())
{
pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = listPeSection[importSectionIndex].sectionHeader.VirtualAddress;
pNTHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
}
else
{
pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = listPeSection[importSectionIndex].sectionHeader.VirtualAddress;
pNTHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
}
return true;
}
bool ImportRebuilder::createNewImportSection(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
{
char sectionName[IMAGE_SIZEOF_SHORT_NAME + 1] = {0};
const WCHAR * sectionNameW = Scylla::config[IAT_SECTION_NAME].getString();
calculateImportSizes(moduleList);
if (wcslen(sectionNameW) > IMAGE_SIZEOF_SHORT_NAME)
{
strcpy_s(sectionName, ".SCY");
}
else
{
StringConversion::ToASCII(sectionNameW, sectionName, _countof(sectionName));
}
return addNewLastSection(sectionName, (DWORD)sizeOfImportSection, 0);
}
void ImportRebuilder::setFlagToIATSection(DWORD_PTR iatAddress)
{
for (size_t i = 0; i < listPeSection.size(); i++)
{
if ((listPeSection[i].sectionHeader.VirtualAddress <= iatAddress) && ((listPeSection[i].sectionHeader.VirtualAddress + listPeSection[i].sectionHeader.Misc.VirtualSize) > iatAddress))
{
//section must be read and writeable
listPeSection[i].sectionHeader.Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
}
}
}
DWORD ImportRebuilder::fillImportSection(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
{
std::map<DWORD_PTR, ImportModuleThunk>::iterator mapIt;
std::map<DWORD_PTR, ImportThunk>::iterator mapIt2;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0;
PIMAGE_IMPORT_BY_NAME pImportByName = 0;
PIMAGE_THUNK_DATA pThunk = 0;
ImportModuleThunk * importModuleThunk = 0;
ImportThunk * importThunk = 0;
size_t stringLength = 0;
DWORD_PTR lastRVA = 0;
BYTE * sectionData = listPeSection[importSectionIndex].data;
DWORD offset = 0;
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(sectionData);
//skip the IMAGE_IMPORT_DESCRIPTOR
offset += (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
{
importModuleThunk = &((*mapIt).second);
stringLength = addImportDescriptor(importModuleThunk, offset);
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillImportSection :: importDesc.Name %X", pImportDescriptor->Name);
#endif
offset += (DWORD)stringLength; //stringLength has null termination char
pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)sectionData + offset);
//pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importModuleThunk->firstThunk));
lastRVA = importModuleThunk->firstThunk - sizeof(DWORD_PTR);
for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
{
importThunk = &((*mapIt2).second);
pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importThunk->rva));
//check wrong iat pointer
if (!pThunk)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillImportSection :: Failed to get pThunk RVA: %X", importThunk->rva);
#endif
return 0;
}
if ((lastRVA + sizeof(DWORD_PTR)) != importThunk->rva)
{
//add additional import desc
addSpecialImportDescriptor(importThunk->rva);
}
lastRVA = importThunk->rva;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillImportSection :: importThunk %X pThunk %X pImportByName %X offset %X", importThunk,pThunk,pImportByName,offset);
#endif
stringLength = addImportToImportTable(importThunk, pThunk, pImportByName, offset);
offset += (DWORD)stringLength; //is 0 bei import by ordinal
pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pImportByName + stringLength);
}
pImportDescriptor++;
}
return offset;
}
size_t ImportRebuilder::addImportDescriptor(ImportModuleThunk * pImportModule, DWORD sectionOffset)
{
char dllName[MAX_PATH];
StringConversion::ToASCII(pImportModule->moduleName, dllName, _countof(dllName));
size_t stringLength = strlen(dllName) + 1;
/*
Warning: stringLength MUST include null termination char
*/
memcpy((listPeSection[importSectionIndex].data + sectionOffset), dllName, stringLength); //copy module name to section
pImportDescriptor->FirstThunk = (DWORD)pImportModule->firstThunk;
pImportDescriptor->Name = (DWORD)convertOffsetToRVAVector(listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffset);
return stringLength;
}
void ImportRebuilder::addSpecialImportDescriptor(DWORD_PTR rvaFirstThunk)
{
PIMAGE_IMPORT_DESCRIPTOR oldID = pImportDescriptor;
pImportDescriptor++;
pImportDescriptor->FirstThunk = (DWORD)rvaFirstThunk;
pImportDescriptor->Name = oldID->Name;
}
void ImportRebuilder::calculateImportSizes(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
{
std::map<DWORD_PTR, ImportModuleThunk>::iterator mapIt;
std::map<DWORD_PTR, ImportThunk>::iterator mapIt2;
DWORD_PTR lastRVA = 0;
numberOfImportDescriptors = 0;
sizeOfImportSection = 0;
sizeOfApiAndModuleNames = 0;
numberOfImportDescriptors = moduleList.size() + 1; //last is zero'd
for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
{
lastRVA = (*mapIt).second.firstThunk - sizeof(DWORD_PTR);
sizeOfApiAndModuleNames += (DWORD)(wcslen((*mapIt).second.moduleName) + 1);
for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
{
if ((lastRVA + sizeof(DWORD_PTR)) != (*mapIt2).second.rva)
{
numberOfImportDescriptors++; //add additional import desc
}
if((*mapIt2).second.name[0] != '\0')
{
sizeOfApiAndModuleNames += sizeof(WORD); //Hint from IMAGE_IMPORT_BY_NAME
sizeOfApiAndModuleNames += (DWORD)(strlen((*mapIt2).second.name) + 1);
}
lastRVA = (*mapIt2).second.rva;
}
}
sizeOfImportSection = sizeOfApiAndModuleNames + (numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
}
size_t ImportRebuilder::addImportToImportTable( ImportThunk * pImport, PIMAGE_THUNK_DATA pThunk, PIMAGE_IMPORT_BY_NAME pImportByName, DWORD sectionOffset)
{
size_t stringLength = 0;
if(pImport->name[0] == '\0')
{
pThunk->u1.AddressOfData = (IMAGE_ORDINAL(pImport->ordinal) | IMAGE_ORDINAL_FLAG);
}
else
{
pImportByName->Hint = pImport->hint;
stringLength = strlen(pImport->name) + 1;
memcpy(pImportByName->Name, pImport->name, stringLength);
pThunk->u1.AddressOfData = convertOffsetToRVAVector(listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffset);
if (!pThunk->u1.AddressOfData)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"addImportToImportTable :: failed to get AddressOfData %X %X", listPeSection[importSectionIndex].sectionHeader.PointerToRawData, sectionOffset);
#endif
}
//next import should be nulled
pThunk++;
pThunk->u1.AddressOfData = 0;
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"addImportToImportTable :: pThunk->u1.AddressOfData %X %X %X", pThunk->u1.AddressOfData, pThunk, listPeSection[importSectionIndex].sectionHeader.PointerToRawData + sectionOffset);
#endif
stringLength += sizeof(WORD);
}
return stringLength;
}
BYTE * ImportRebuilder::getMemoryPointerFromRVA(DWORD_PTR dwRVA)
{
DWORD_PTR offset = convertRVAToOffsetVector(dwRVA);
for (size_t i = 0; i < listPeSection.size(); i++)
{
if ((listPeSection[i].sectionHeader.PointerToRawData <= offset) && ((listPeSection[i].sectionHeader.PointerToRawData + listPeSection[i].sectionHeader.SizeOfRawData) > offset))
{
return (BYTE *)((DWORD_PTR)listPeSection[i].data + (offset - listPeSection[i].sectionHeader.PointerToRawData));
}
}
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Apr 14, 2:29 PM (9 h, 26 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
49/c9/c771e16c853039b238a615aac55a

Event Timeline