Page MenuHomedesp's stash

No OneTemporary

diff --git a/Scylla/PeDump.cpp b/Scylla/PeDump.cpp
index 41fca1f..8da6b6b 100644
--- a/Scylla/PeDump.cpp
+++ b/Scylla/PeDump.cpp
@@ -1,437 +1,383 @@
#include "PeDump.h"
#include "ProcessAccessHelp.h"
#include "Scylla.h"
#include "Architecture.h"
+#include "PeParser.h"
bool PeDump::useHeaderFromDisk = true;
bool PeDump::appendOverlayData = true;
//#define DEBUG_COMMENTS
bool PeDump::fillPeHeaderStructs(bool fromDisk)
{
DWORD dwSize = ProcessAccessHelp::PE_HEADER_BYTES_COUNT;
if (dwSize > sizeOfImage)
{
dwSize = (DWORD)sizeOfImage;
}
headerData = new BYTE[dwSize];
if (!headerData)
return false;
if (fromDisk)
{
//from disk
if (!ProcessAccessHelp::readHeaderFromFile(headerData, dwSize, fullpath))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillPeHeaderStructs -> ProcessAccessHelp::readHeaderFromFile failed - %X %s", dwSize, fullpath);
#endif
return false;
}
}
else
{
//from memory
if (!ProcessAccessHelp::readMemoryPartlyFromProcess(imageBase, dwSize, headerData))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"fillPeHeaderStructs -> ProcessAccessHelp::readMemoryFromProcess failed - " PRINTF_DWORD_PTR_FULL L" %X " PRINTF_DWORD_PTR_FULL, imageBase, dwSize, headerData);
#endif
return false;
}
}
pDOSHeader = (PIMAGE_DOS_HEADER)headerData;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)headerData + (DWORD_PTR)pDOSHeader->e_lfanew);
pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);
return true;
}
bool PeDump::validateHeaders()
{
if ((pDOSHeader != 0) && (pDOSHeader->e_magic == IMAGE_DOS_SIGNATURE) && (pNTHeader->Signature == IMAGE_NT_SIGNATURE))
{
#ifdef _WIN64
if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
#else
if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
#endif
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
bool PeDump::dumpCompleteProcessToDisk(const WCHAR * dumpFilePath)
{
if (!fillPeHeaderStructs(useHeaderFromDisk))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> fillPeHeaderStructs failed");
#endif
return false;
}
if (!validateHeaders())
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> validateHeaders failed");
#endif
return false;
}
dumpData = new BYTE[sizeOfImage];
if (dumpData)
{
if (!ProcessAccessHelp::readMemoryPartlyFromProcess(imageBase,sizeOfImage,dumpData))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> readMemoryFromProcess failed");
#endif
return false;
}
else
{
fixDump(dumpData);
if (saveDumpToDisk(dumpFilePath, dumpData, (DWORD)sizeOfImage))
{
if (appendOverlayData)
{
appendOverlayDataToDump(dumpFilePath);
}
//printf("dump success\n");
return true;
}
else
{
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"dumpCompleteProcessToDisk -> new BYTE[sizeOfImage] failed %X", sizeOfImage);
#endif
return false;
}
}
bool PeDump::appendOverlayDataToDump(const WCHAR *dumpFilePath)
{
DWORD_PTR offset = 0;
DWORD size = 0;
if (getOverlayData(fullpath,&offset,&size))
{
if (offset == 0)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"appendOverlayDataToDump :: No overlay exists");
#endif
return true;
}
else
{
if (copyFileDataFromOffset(fullpath, dumpFilePath, offset, size))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"appendOverlayDataToDump :: appending overlay success");
#endif
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"appendOverlayDataToDump :: appending overlay failed");
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"appendOverlayDataToDump :: getOverlayData failed");
#endif
return false;
}
}
bool PeDump::copyFileDataFromOffset(const WCHAR * sourceFile, const WCHAR * destFile, DWORD_PTR fileOffset, DWORD dwSize)
{
HANDLE hSourceFile, hDestFile;
BYTE * dataBuffer = 0;
bool retValue = false;
hSourceFile = CreateFile(sourceFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(hSourceFile == INVALID_HANDLE_VALUE)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"copyFileDataFromOffset :: failed to open source file");
#endif
return false;
}
hDestFile = CreateFile(destFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if(hSourceFile == INVALID_HANDLE_VALUE)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"copyFileDataFromOffset :: failed to open destination file");
#endif
CloseHandle(hSourceFile);
return false;
}
dataBuffer = new BYTE[dwSize];
if (ProcessAccessHelp::readMemoryFromFile(hSourceFile, (LONG)fileOffset, dwSize, dataBuffer))
{
if (ProcessAccessHelp::writeMemoryToFileEnd(hDestFile,dwSize,dataBuffer))
{
retValue = true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"copyFileDataFromOffset :: writeMemoryToFileEnd failed");
#endif
retValue = false;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"copyFileDataFromOffset :: readMemoryFromFile failed to read from source file");
#endif
retValue = false;
}
delete [] dataBuffer;
CloseHandle(hSourceFile);
CloseHandle(hDestFile);
return retValue;
}
void PeDump::fixDump(BYTE * dumpBuffer)
{
int counter = 0;
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)dumpBuffer;
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD_PTR)dumpBuffer + pDos->e_lfanew);
PIMAGE_SECTION_HEADER pSec = IMAGE_FIRST_SECTION(pNt);
fixNtHeaderForDump(pNt, pNTHeader);
do
{
fixSectionHeaderForDump(pSec, pSectionHeader);
pSectionHeader++;
pSec++;
counter++;
} while (counter < pNt->FileHeader.NumberOfSections);
}
void PeDump::fixBadNtHeaderValues(PIMAGE_NT_HEADERS pNtHead)
{
//maybe imagebase in process is not real imagebase
pNtHead->OptionalHeader.ImageBase = imageBase;
pNtHead->OptionalHeader.AddressOfEntryPoint = (DWORD)(entryPoint - imageBase);
pNtHead->OptionalHeader.SizeOfImage = sizeOfImage;
}
void PeDump::fixSectionHeaderForDump(PIMAGE_SECTION_HEADER oldSecHead, PIMAGE_SECTION_HEADER newSecHead)
{
memcpy_s(oldSecHead->Name, IMAGE_SIZEOF_SHORT_NAME, newSecHead->Name, IMAGE_SIZEOF_SHORT_NAME);
oldSecHead->Characteristics = newSecHead->Characteristics;
oldSecHead->Misc.VirtualSize = newSecHead->Misc.VirtualSize;
oldSecHead->VirtualAddress = newSecHead->VirtualAddress;
oldSecHead->SizeOfRawData = newSecHead->Misc.VirtualSize;
oldSecHead->PointerToRawData = newSecHead->VirtualAddress;
}
void PeDump::fixNtHeaderForDump(PIMAGE_NT_HEADERS oldNtHead, PIMAGE_NT_HEADERS newNtHead)
{
//some special
fixBadNtHeaderValues(newNtHead);
//fix FileHeader
oldNtHead->FileHeader.NumberOfSections = newNtHead->FileHeader.NumberOfSections;
//fix OptionalHeader
oldNtHead->OptionalHeader.ImageBase = newNtHead->OptionalHeader.ImageBase;
oldNtHead->OptionalHeader.SizeOfImage = newNtHead->OptionalHeader.SizeOfImage;
oldNtHead->OptionalHeader.BaseOfCode = newNtHead->OptionalHeader.BaseOfCode;
oldNtHead->OptionalHeader.AddressOfEntryPoint = newNtHead->OptionalHeader.AddressOfEntryPoint;
oldNtHead->OptionalHeader.SectionAlignment = newNtHead->OptionalHeader.SectionAlignment;
oldNtHead->OptionalHeader.FileAlignment = newNtHead->OptionalHeader.SectionAlignment;
//deleted in x64 PE
#ifndef _WIN64
oldNtHead->OptionalHeader.BaseOfData = newNtHead->OptionalHeader.BaseOfData;
#endif
}
bool PeDump::saveDumpToDisk(const WCHAR * dumpFilePath, BYTE *dumpBuffer, DWORD dumpSize)
{
DWORD lpNumberOfBytesWritten = 0;
bool retValue = false;
HANDLE hFile = CreateFile(dumpFilePath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile == INVALID_HANDLE_VALUE)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"saveDumpToDisk :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
retValue = false;
}
else
{
if (WriteFile(hFile, dumpBuffer, dumpSize, &lpNumberOfBytesWritten, 0))
{
if (lpNumberOfBytesWritten != dumpSize)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"saveDumpToDisk :: lpNumberOfBytesWritten != dumpSize %d %d", lpNumberOfBytesWritten,dumpSize);
#endif
retValue = false;
}
else
{
retValue = true;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"saveDumpToDisk :: WriteFile failed %u",GetLastError());
#endif
retValue = false;
}
CloseHandle(hFile);
}
return retValue;
}
bool PeDump::getOverlayData(const WCHAR * filepath, DWORD_PTR * overlayFileOffset, DWORD * overlaySize)
{
LONGLONG fileSize = 0;
- DWORD dwSize = 0;
- DWORD bufferSize = 1000;
- BYTE *buffer = 0;
- bool returnValue = 0;
- PIMAGE_DOS_HEADER pDOSh = 0;
- PIMAGE_NT_HEADERS pNTh = 0;
- PIMAGE_SECTION_HEADER pSech = 0;
- int counter = 0;
+ bool returnValue = false;
DWORD calcSize = 0;
- HANDLE hFile = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ PeParser peFile(filepath);
- if( hFile == INVALID_HANDLE_VALUE )
+ if (peFile.isValidPeFile())
{
-#ifdef DEBUG_COMMENTS
- Scylla::debugLog.log(L"getOverlayData :: INVALID_HANDLE_VALUE %u", GetLastError());
-#endif
- returnValue = false;
- }
- else
- {
- fileSize = ProcessAccessHelp::getFileSize(hFile);
+ fileSize = ProcessAccessHelp::getFileSize(fullpath);
if (fileSize > 0)
{
- if (fileSize > bufferSize)
- {
- dwSize = bufferSize;
- }
- else
- {
- dwSize = (DWORD)(fileSize - 1);
- }
+ calcSize = peFile.getSectionHeaderBasedFileSize();
- buffer = new BYTE[dwSize];
-
- if (ProcessAccessHelp::readMemoryFromFile(hFile, 0, dwSize, buffer))
+ if (calcSize < fileSize)
{
- pDOSh = (PIMAGE_DOS_HEADER)buffer;
- pNTh = (PIMAGE_NT_HEADERS)((DWORD_PTR)buffer + pDOSh->e_lfanew);
-
- //first section
- pSech = IMAGE_FIRST_SECTION(pNTh);
- counter = 1;
-
- //get last section
- while(counter < pNTh->FileHeader.NumberOfSections)
- {
- counter++;
- pSech++;
- }
-
- //printf("PointerToRawData %X\nSizeOfRawData %X\nfile size %X\n",pSech->PointerToRawData,pSech->SizeOfRawData,pSech->PointerToRawData+pSech->SizeOfRawData);
-
- calcSize = pSech->PointerToRawData + pSech->SizeOfRawData;
-
- if (calcSize < fileSize)
- {
- //overlay found
- *overlayFileOffset = calcSize;
- *overlaySize = (DWORD)(fileSize - calcSize);
- }
- else
- {
- *overlayFileOffset = 0;
- *overlaySize = 0;
- }
-
- returnValue = true;
+ //overlay found
+ *overlayFileOffset = calcSize;
+ *overlaySize = (DWORD)(fileSize - calcSize);
}
else
{
- returnValue = false;
+ *overlayFileOffset = 0;
+ *overlaySize = 0;
}
- delete [] buffer;
- }
- else
- {
- returnValue = false;
+ returnValue = true;
}
- CloseHandle(hFile);
}
return returnValue;
}
\ No newline at end of file
diff --git a/Scylla/PeParser.cpp b/Scylla/PeParser.cpp
index 180d542..d29dbb2 100644
--- a/Scylla/PeParser.cpp
+++ b/Scylla/PeParser.cpp
@@ -1,298 +1,410 @@
#include "PeParser.h"
+#include "ProcessAccessHelp.h"
+PeParser::PeParser()
+{
+ fileMemory = 0;
+ headerMemory = 0;
+ pDosHeader = 0;
+ pNTHeader32 = 0;
+ pNTHeader64 = 0;
+ filename = 0;
+ moduleBaseAddress = 0;
+}
PeParser::PeParser(const WCHAR * file, bool readSectionHeaders)
{
fileMemory = 0;
headerMemory = 0;
pDosHeader = 0;
pNTHeader32 = 0;
pNTHeader64 = 0;
+ moduleBaseAddress = 0;
filename = file;
- if (wcslen(filename) > 3)
+ if (filename && wcslen(filename) > 3)
{
- readPeHeader(readSectionHeaders);
+ readPeHeaderFromFile(readSectionHeaders);
if (readSectionHeaders)
{
if (isValidPeFile())
{
getSectionHeaders();
}
}
}
}
+PeParser::PeParser(const DWORD_PTR moduleBase, bool readSectionHeaders)
+{
+ fileMemory = 0;
+ headerMemory = 0;
+ pDosHeader = 0;
+ pNTHeader32 = 0;
+ pNTHeader64 = 0;
+ filename = 0;
+
+ moduleBaseAddress = moduleBase;
+
+ if (moduleBaseAddress)
+ {
+ readPeHeaderFromProcess(readSectionHeaders);
+
+ if (readSectionHeaders)
+ {
+ if (isValidPeFile())
+ {
+ getSectionHeaders();
+ }
+ }
+ }
+
+}
+
PeParser::~PeParser()
{
if (headerMemory)
{
delete [] headerMemory;
}
if (fileMemory)
{
delete [] fileMemory;
}
listSectionHeaders.clear();
}
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::readPeHeader(bool readSectionHeaders)
+bool PeParser::readPeHeaderFromProcess(bool readSectionHeaders)
{
bool retValue = false;
- DWORD readSize = sizeof(IMAGE_DOS_HEADER) + 200 + sizeof(IMAGE_NT_HEADERS64);
DWORD correctSize = 0;
- DWORD numberOfBytesRead = 0;
- if (readSectionHeaders)
+ DWORD readSize = getInitialHeaderReadSize(readSectionHeaders);
+
+ headerMemory = new BYTE[readSize];
+
+ if (ProcessAccessHelp::readMemoryPartlyFromProcess(moduleBaseAddress, readSize, headerMemory))
{
- readSize += (10 * sizeof(IMAGE_SECTION_HEADER));
+ 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];
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
if (ReadFile(hFile, headerMemory, readSize, &numberOfBytesRead, 0))
{
retValue = true;
- pDosHeader = (PIMAGE_DOS_HEADER)headerMemory;
- if (pDosHeader->e_lfanew > 0 && pDosHeader->e_lfanew < (LONG)readSize) //malformed PE
- {
- pNTHeader32 = (PIMAGE_NT_HEADERS32)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
- pNTHeader64 = (PIMAGE_NT_HEADERS64)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
- }
+ getDosAndNtHeader(headerMemory, (LONG)readSize);
if (isValidPeFile())
{
- 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 valid pe
- }
+ correctSize = calcCorrectPeHeaderSize(readSectionHeaders);
if (readSize < correctSize)
{
readSize = correctSize;
delete [] headerMemory;
headerMemory = new BYTE[readSize];
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
- if (ReadFile(hFile,headerMemory,readSize,&numberOfBytesRead,0))
+ if (ReadFile(hFile, headerMemory, readSize, &numberOfBytesRead, 0))
{
- pDosHeader = (PIMAGE_DOS_HEADER)headerMemory;
- if (pDosHeader->e_lfanew > 0 && pDosHeader->e_lfanew < (LONG)readSize) //malformed PE
- {
- pNTHeader32 = (PIMAGE_NT_HEADERS32)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
- pNTHeader64 = (PIMAGE_NT_HEADERS64)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
- }
+ getDosAndNtHeader(headerMemory, (LONG)readSize);
}
}
}
}
CloseHandle(hFile);
}
return retValue;
}
bool PeParser::readFileToMemory()
{
bool retValue = false;
DWORD numberOfBytesRead = 0;
LARGE_INTEGER largeInt = {0};
const DWORD MaxFileSize = 500 * 1024 * 1024; // GB * MB * KB * B -> 500 MB
HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
if (GetFileSizeEx(hFile, &largeInt))
{
if (largeInt.QuadPart > MaxFileSize)
{
//TODO handle big files
retValue = false;
}
else
{
fileMemory = new BYTE[largeInt.LowPart];
if (ReadFile(hFile,fileMemory,largeInt.LowPart,&numberOfBytesRead,0))
{
retValue = true;
}
else
{
delete [] fileMemory;
fileMemory = 0;
}
}
}
CloseHandle(hFile);
}
return retValue;
}
bool PeParser::getSectionHeaders()
{
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNTHeader32);
listSectionHeaders.clear();
listSectionHeaders.reserve(getNumberOfSections());
for (WORD i = 0; i < getNumberOfSections(); i++)
{
listSectionHeaders.push_back(*pSection);
pSection++;
}
return true;
}
-bool PeParser::getSectionNameUnicode(const int sectionIndex, WCHAR * output, int outputLen)
+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);
+ memcpy(sectionNameA, listSectionHeaders[sectionIndex].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()
{
return listSectionHeaders;
}
+void PeParser::getDosAndNtHeader(BYTE * memory, LONG size)
+{
+ pDosHeader = (PIMAGE_DOS_HEADER)memory;
+
+ 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);
+ }
+ else
+ {
+ pNTHeader32 = 0;
+ pNTHeader64 = 0;
+ }
+}
+
+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)
+ {
+ lastRawOffset = listSectionHeaders[i].PointerToRawData;
+ lastRawSize = listSectionHeaders[i].SizeOfRawData;
+ }
+ }
+
+ return (lastRawSize + lastRawOffset);
+}
+
diff --git a/Scylla/PeParser.h b/Scylla/PeParser.h
index 86b5c12..0512d8a 100644
--- a/Scylla/PeParser.h
+++ b/Scylla/PeParser.h
@@ -1,50 +1,58 @@
#pragma once
#include <windows.h>
#include <vector>
class PeParser
{
public:
PeParser(const WCHAR * file, bool readSectionHeaders = true);
- //PeParser(HANDLE hProcess, DWORD_PTR moduleBase, 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();
bool hasExportDirectory();
bool hasTLSDirectory();
bool hasRelocationDirectory();
DWORD getEntryPoint();
- bool getSectionNameUnicode(const int sectionIndex, WCHAR * output, int outputLen);
+ bool getSectionNameUnicode(const int sectionIndex, WCHAR * output, const int outputLen);
+
+ DWORD getSectionHeaderBasedFileSize();
private:
+ PeParser();
+
const WCHAR * filename;
+ DWORD_PTR moduleBaseAddress;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS32 pNTHeader32;
PIMAGE_NT_HEADERS64 pNTHeader64;
std::vector<IMAGE_SECTION_HEADER> listSectionHeaders;
BYTE * fileMemory;
BYTE * headerMemory;
- bool readPeHeader(bool readSectionHeaders);
+ bool readPeHeaderFromFile(bool readSectionHeaders);
+ bool readPeHeaderFromProcess(bool readSectionHeaders);
bool readFileToMemory();
bool hasDirectory(const int directoryIndex);
bool getSectionHeaders();
- bool readPeHeaderFromProcess( HANDLE hProcess, DWORD_PTR moduleBase );
+ void getDosAndNtHeader(BYTE * memory, LONG size);
+ DWORD calcCorrectPeHeaderSize( bool readSectionHeaders );
+ DWORD getInitialHeaderReadSize( bool readSectionHeaders );
};
diff --git a/Scylla/PluginLoader.cpp b/Scylla/PluginLoader.cpp
index ac0c3aa..c935a50 100644
--- a/Scylla/PluginLoader.cpp
+++ b/Scylla/PluginLoader.cpp
@@ -1,326 +1,303 @@
#include "PluginLoader.h"
#include "Logger.h"
#include "ProcessAccessHelp.h"
#include "StringConversion.h"
#include <shlwapi.h>
#include "PeParser.h"
const WCHAR PluginLoader::PLUGIN_DIR[] = L"Plugins\\";
const WCHAR PluginLoader::PLUGIN_SEARCH_STRING[] = L"*.dll";
const WCHAR PluginLoader::PLUGIN_IMPREC_DIR[] = L"ImpRec_Plugins\\";
const WCHAR PluginLoader::PLUGIN_IMPREC_WRAPPER_DLL[] = L"Imprec_Wrapper_DLL.dll";
//#define DEBUG_COMMENTS
std::vector<Plugin> & PluginLoader::getScyllaPluginList()
{
return scyllaPluginList;
}
std::vector<Plugin> & PluginLoader::getImprecPluginList()
{
return imprecPluginList;
}
bool PluginLoader::findAllPlugins()
{
if (!scyllaPluginList.empty())
{
scyllaPluginList.clear();
}
if (!imprecPluginList.empty())
{
imprecPluginList.clear();
}
if (!buildSearchString())
{
return false;
}
if (!searchForPlugin(scyllaPluginList, dirSearchString, true))
{
return false;
}
#ifndef _WIN64
if (!buildSearchStringImprecPlugins())
{
return false;
}
if (!searchForPlugin(imprecPluginList, dirSearchString, false))
{
return false;
}
#endif
return true;
}
bool PluginLoader::searchForPlugin(std::vector<Plugin> & newPluginList, const WCHAR * searchPath, bool isScyllaPlugin)
{
WIN32_FIND_DATA ffd;
HANDLE hFind = 0;
DWORD dwError = 0;
Plugin pluginData;
hFind = FindFirstFile(searchPath, &ffd);
dwError = GetLastError();
if (dwError == ERROR_FILE_NOT_FOUND)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: No files found");
#endif
return true;
}
if (hFind == INVALID_HANDLE_VALUE)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: FindFirstFile failed %d", dwError);
#endif
return false;
}
do
{
if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{
if ((ffd.nFileSizeHigh != 0) || (ffd.nFileSizeLow < 200))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: Plugin invalid file size: %s", ffd.cFileName);
#endif
}
else
{
pluginData.fileSize = ffd.nFileSizeLow;
wcscpy_s(pluginData.fullpath, baseDirPath);
wcscat_s(pluginData.fullpath, ffd.cFileName);
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"findAllPlugins :: Plugin %s", pluginData.fullpath);
#endif
if (isValidDllFile(pluginData.fullpath))
{
if (isScyllaPlugin)
{
if (getScyllaPluginName(&pluginData))
{
//add valid plugin
newPluginList.push_back(pluginData);
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"Cannot get scylla plugin name %s", pluginData.fullpath);
#endif
}
}
else
{
if (isValidImprecPlugin(pluginData.fullpath))
{
wcscpy_s(pluginData.pluginName, ffd.cFileName);
newPluginList.push_back(pluginData);
}
}
}
}
}
}
while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
FindClose(hFind);
- if (dwError == ERROR_NO_MORE_FILES)
- {
- return true;
- }
- else
- {
- return false;
- }
-
+ return (dwError == ERROR_NO_MORE_FILES);
}
bool PluginLoader::getScyllaPluginName(Plugin * pluginData)
{
bool retValue = false;
char * pluginName = 0;
def_ScyllaPluginNameW ScyllaPluginNameW = 0;
def_ScyllaPluginNameA ScyllaPluginNameA = 0;
HMODULE hModule = LoadLibraryEx(pluginData->fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain
if (hModule)
{
ScyllaPluginNameW = (def_ScyllaPluginNameW)GetProcAddress(hModule, "ScyllaPluginNameW");
if (ScyllaPluginNameW)
{
wcscpy_s(pluginData->pluginName, ScyllaPluginNameW());
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getPluginName :: Plugin name %s", pluginData->pluginName);
#endif
retValue = true;
}
else
{
ScyllaPluginNameA = (def_ScyllaPluginNameA)GetProcAddress(hModule, "ScyllaPluginNameA");
if (ScyllaPluginNameA)
{
pluginName = ScyllaPluginNameA();
StringConversion::ToUTF16(pluginName, pluginData->pluginName, _countof(pluginData->pluginName));
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getPluginName :: Plugin name mbstowcs_s %s", pluginData->pluginName);
#endif
if (wcslen(pluginData->pluginName) > 1)
{
retValue = true;
}
- else
- {
- retValue = false;
- }
- }
- else
- {
- retValue = false;
}
}
FreeLibrary(hModule);
return retValue;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getPluginName :: LoadLibraryEx failed %s", pluginData->fullpath);
#endif
return false;
}
}
bool PluginLoader::buildSearchString()
{
ZeroMemory(dirSearchString, sizeof(dirSearchString));
ZeroMemory(baseDirPath, sizeof(baseDirPath));
if (!GetModuleFileName(0, dirSearchString, _countof(dirSearchString)))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"buildSearchString :: GetModuleFileName failed %d", GetLastError());
#endif
return false;
}
//wprintf(L"dirSearchString 1 %s\n\n", dirSearchString);
PathRemoveFileSpec(dirSearchString);
//wprintf(L"dirSearchString 2 %s\n\n", dirSearchString);
PathAppend(dirSearchString, PLUGIN_DIR);
wcscpy_s(baseDirPath, dirSearchString);
wcscat_s(dirSearchString, PLUGIN_SEARCH_STRING);
//wprintf(L"dirSearchString 3 %s\n\n", dirSearchString);
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"dirSearchString final %s", dirSearchString);
#endif
return true;
}
bool PluginLoader::isValidDllFile( const WCHAR * fullpath )
{
- PeParser peFile(fullpath,false);
+ PeParser peFile(fullpath, false);
- if (peFile.isTargetFileSamePeFormat() && peFile.hasExportDirectory())
- {
- return true;
- }
- else
- {
- return false;
- }
+ return (peFile.isTargetFileSamePeFormat() && peFile.hasExportDirectory());
}
bool PluginLoader::isValidImprecPlugin(const WCHAR * fullpath)
{
def_Imprec_Trace Imprec_Trace = 0;
bool retValue = false;
HMODULE hModule = LoadLibraryEx(fullpath, 0, DONT_RESOLVE_DLL_REFERENCES); //do not call DllMain
if (hModule)
{
Imprec_Trace = (def_Imprec_Trace)GetProcAddress(hModule, "Trace");
if (Imprec_Trace)
{
retValue = true;
}
else
{
retValue = false;
}
FreeLibrary(hModule);
return retValue;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"isValidImprecPlugin :: LoadLibraryEx failed %s", pluginData->fullpath);
#endif
return false;
}
}
bool PluginLoader::buildSearchStringImprecPlugins()
{
wcscpy_s(dirSearchString, baseDirPath);
wcscat_s(dirSearchString, PLUGIN_IMPREC_DIR);
wcscpy_s(baseDirPath, dirSearchString);
//build imprec wrapper dll path
wcscpy_s(imprecWrapperDllPath, dirSearchString);
wcscat_s(imprecWrapperDllPath, PLUGIN_IMPREC_WRAPPER_DLL);
if (!fileExists(imprecWrapperDllPath))
{
return false;
}
wcscat_s(dirSearchString, PLUGIN_SEARCH_STRING);
return true;
}
bool PluginLoader::fileExists(const WCHAR * fileName)
{
return (GetFileAttributesW(fileName) != INVALID_FILE_ATTRIBUTES);
}
diff --git a/Scylla/ProcessAccessHelp.cpp b/Scylla/ProcessAccessHelp.cpp
index f7867f7..91aee0d 100644
--- a/Scylla/ProcessAccessHelp.cpp
+++ b/Scylla/ProcessAccessHelp.cpp
@@ -1,786 +1,785 @@
#include "ProcessAccessHelp.h"
#include "Scylla.h"
#include "NativeWinApi.h"
#include "PeParser.h"
HANDLE ProcessAccessHelp::hProcess = 0;
ModuleInfo * ProcessAccessHelp::selectedModule;
DWORD_PTR ProcessAccessHelp::targetImageBase = 0;
DWORD_PTR ProcessAccessHelp::targetSizeOfImage = 0;
DWORD_PTR ProcessAccessHelp::maxValidAddress = 0;
std::vector<ModuleInfo> ProcessAccessHelp::moduleList; //target process module list
std::vector<ModuleInfo> ProcessAccessHelp::ownModuleList; //own module list
_DInst ProcessAccessHelp::decomposerResult[MAX_INSTRUCTIONS];
unsigned int ProcessAccessHelp::decomposerInstructionsCount = 0;
_CodeInfo ProcessAccessHelp::decomposerCi = {0};
_DecodedInst ProcessAccessHelp::decodedInstructions[MAX_INSTRUCTIONS];
unsigned int ProcessAccessHelp::decodedInstructionsCount = 0;
BYTE ProcessAccessHelp::fileHeaderFromDisk[PE_HEADER_BYTES_COUNT];
//#define DEBUG_COMMENTS
bool ProcessAccessHelp::openProcessHandle(DWORD dwPID)
{
if (dwPID > 0)
{
if (hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: There is already a process handle, HANDLE %X", hProcess);
#endif
return false;
}
else
{
//hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, 0, dwPID);
//if (!NT_SUCCESS(NativeWinApi::NtOpenProcess(&hProcess,PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE,&ObjectAttributes, &cid)))
hProcess = NativeOpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE, dwPID);
if (hProcess)
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: Failed to open handle, PID %X", dwPID);
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"openProcessHandle :: Wrong PID, PID %X", dwPID);
#endif
return false;
}
}
HANDLE ProcessAccessHelp::NativeOpenProcess(DWORD dwDesiredAccess, DWORD dwProcessId)
{
HANDLE hProcess = 0;
CLIENT_ID cid = {0};
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS ntStatus = 0;
InitializeObjectAttributes(&ObjectAttributes, 0, 0, 0, 0);
cid.UniqueProcess = (HANDLE)dwProcessId;
ntStatus = NativeWinApi::NtOpenProcess(&hProcess,dwDesiredAccess,&ObjectAttributes, &cid);
if (NT_SUCCESS(ntStatus))
{
return hProcess;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"NativeOpenProcess :: Failed to open handle, PID %X Error 0x%X", dwProcessId, NativeWinApi::RtlNtStatusToDosError(ntStatus));
#endif
return 0;
}
}
void ProcessAccessHelp::closeProcessHandle()
{
CloseHandle(hProcess);
hProcess = 0;
moduleList.clear();
targetImageBase = 0;
selectedModule = 0;
}
bool ProcessAccessHelp::readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
DWORD_PTR addressPart = 0;
DWORD_PTR readBytes = 0;
DWORD_PTR bytesToRead = 0;
MEMORY_BASIC_INFORMATION memBasic = {0};
bool returnValue = false;
if (!hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: hProcess == NULL");
#endif
return returnValue;
}
if (!readMemoryFromProcess(address, size, dataBuffer))
{
addressPart = address;
do
{
if (!VirtualQueryEx(ProcessAccessHelp::hProcess,(LPCVOID)addressPart,&memBasic,sizeof(memBasic)))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: Error VirtualQueryEx %X %X err: %u", addressPart,size, GetLastError());
#endif
break;
}
bytesToRead = memBasic.RegionSize;
if ( (readBytes+bytesToRead) > size)
{
bytesToRead = size - readBytes;
}
if (memBasic.State == MEM_COMMIT)
{
if (!readMemoryFromProcess(addressPart, bytesToRead, (LPVOID)((DWORD_PTR)dataBuffer + readBytes)))
{
break;
}
}
else
{
ZeroMemory((LPVOID)((DWORD_PTR)dataBuffer + readBytes),bytesToRead);
}
readBytes += bytesToRead;
addressPart += memBasic.RegionSize;
} while (readBytes < size);
if (readBytes == size)
{
returnValue = true;
}
}
else
{
returnValue = true;
}
return returnValue;
}
bool ProcessAccessHelp::readMemoryFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
SIZE_T lpNumberOfBytesRead = 0;
DWORD dwProtect = 0;
bool returnValue = false;
if (!hProcess)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: hProcess == NULL");
#endif
return returnValue;
}
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError());
#endif
if (!VirtualProtectEx(hProcess, (LPVOID)address, size, PAGE_READWRITE, &dwProtect))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error VirtualProtectEx %X %X err: %u", address,size, GetLastError());
#endif
returnValue = false;
}
else
{
if (!ReadProcessMemory(hProcess, (LPVOID)address, dataBuffer, size, &lpNumberOfBytesRead))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory %X %X err: %u", address, size, GetLastError());
#endif
returnValue = false;
}
else
{
returnValue = true;
}
VirtualProtectEx(hProcess, (LPVOID)address, size, dwProtect, &dwProtect);
}
}
else
{
returnValue = true;
}
if (returnValue)
{
if (size != lpNumberOfBytesRead)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromProcess :: Error ReadProcessMemory read %d bytes requested %d bytes", lpNumberOfBytesRead, size);
#endif
returnValue = false;
}
else
{
returnValue = true;
}
}
return returnValue;
}
bool ProcessAccessHelp::decomposeMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startAddress)
{
ZeroMemory(&decomposerCi, sizeof(_CodeInfo));
decomposerCi.code = dataBuffer;
decomposerCi.codeLen = (int)bufferSize;
decomposerCi.dt = dt;
decomposerCi.codeOffset = startAddress;
decomposerInstructionsCount = 0;
if (distorm_decompose(&decomposerCi, decomposerResult, sizeof(decomposerResult)/sizeof(decomposerResult[0]), &decomposerInstructionsCount) == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"decomposeMemory :: distorm_decompose == DECRES_INPUTERR");
#endif
return false;
}
else
{
return true;
}
}
bool ProcessAccessHelp::disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset)
{
// Holds the result of the decoding.
_DecodeResult res;
// next is used for instruction's offset synchronization.
// decodedInstructionsCount holds the count of filled instructions' array by the decoder.
decodedInstructionsCount = 0;
_OffsetType offset = startOffset;
res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
/* for (unsigned int i = 0; i < decodedInstructionsCount; i++) {
#ifdef SUPPORT_64BIT_OFFSET
printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#else
printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
#endif
}*/
if (res == DECRES_INPUTERR)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"disassembleMemory :: res == DECRES_INPUTERR");
#endif
return false;
}
else if (res == DECRES_SUCCESS)
{
//printf("disassembleMemory :: res == DECRES_SUCCESS\n");
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"disassembleMemory :: res == %d", res);
#endif
return false;
}
}
DWORD_PTR ProcessAccessHelp::findPattern(DWORD_PTR startOffset, DWORD size, BYTE * pattern, const char * mask)
{
DWORD pos = 0;
size_t searchLen = strlen(mask) - 1;
for(DWORD_PTR retAddress = startOffset; retAddress < startOffset + size; retAddress++)
{
if( *(BYTE*)retAddress == pattern[pos] || mask[pos] == '?' )
{
if(mask[pos+1] == 0x00)
{
return (retAddress - searchLen);
}
pos++;
} else {
pos = 0;
}
}
return 0;
}
bool ProcessAccessHelp::readHeaderFromCurrentFile(const WCHAR * filePath)
{
return readHeaderFromFile(fileHeaderFromDisk, sizeof(fileHeaderFromDisk), filePath);
}
LONGLONG ProcessAccessHelp::getFileSize(const WCHAR * filePath)
{
LONGLONG fileSize = 0;
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
fileSize = getFileSize(hFile);
CloseHandle(hFile);
- hFile = 0;
}
return fileSize;
}
LONGLONG ProcessAccessHelp::getFileSize(HANDLE hFile)
{
LARGE_INTEGER lpFileSize = {0};
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
if (!GetFileSizeEx(hFile, &lpFileSize))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize :: GetFileSizeEx failed %u", GetLastError());
#endif
return 0;
}
else
{
return lpFileSize.QuadPart;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"ProcessAccessHelp::getFileSize hFile invalid");
#endif
return 0;
}
}
bool ProcessAccessHelp::readMemoryFromFile(HANDLE hFile, LONG offset, DWORD size, LPVOID dataBuffer)
{
DWORD lpNumberOfBytesRead = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: SetFilePointer failed error %u", dwError);
#endif
return false;
}
else
{
if (ReadFile(hFile, dataBuffer, size, &lpNumberOfBytesRead, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: ReadFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readMemoryFromFile :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToNewFile(const WCHAR * file,DWORD size, LPCVOID dataBuffer)
{
HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
return writeMemoryToFile(hFile,0,size,dataBuffer);
}
else
{
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFile(HANDLE hFile, LONG offset, DWORD size, LPCVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
DWORD dwError = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
retValue = SetFilePointer(hFile, offset, NULL, FILE_BEGIN);
dwError = GetLastError();
if ((retValue == INVALID_SET_FILE_POINTER) && (dwError != NO_ERROR))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: SetFilePointer failed error %u", dwError);
#endif
return false;
}
else
{
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: WriteFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFile :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::writeMemoryToFileEnd(HANDLE hFile, DWORD size, LPCVOID dataBuffer)
{
DWORD lpNumberOfBytesWritten = 0;
DWORD retValue = 0;
if ((hFile != INVALID_HANDLE_VALUE) && (hFile != 0))
{
SetFilePointer(hFile, 0, 0, FILE_END);
if (WriteFile(hFile, dataBuffer, size, &lpNumberOfBytesWritten, 0))
{
return true;
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFileEnd :: WriteFile failed - size %d - error %u", size, GetLastError());
#endif
return false;
}
}
else
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"writeMemoryToFileEnd :: hFile invalid");
#endif
return false;
}
}
bool ProcessAccessHelp::readHeaderFromFile(BYTE * buffer, DWORD bufferSize, const WCHAR * filePath)
{
DWORD lpNumberOfBytesRead = 0;
LONGLONG fileSize = 0;
DWORD dwSize = 0;
bool returnValue = 0;
HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"readHeaderFromFile :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
returnValue = false;
}
else
{
fileSize = getFileSize(hFile);
if (fileSize > 0)
{
if (fileSize > bufferSize)
{
dwSize = bufferSize;
}
else
{
dwSize = (DWORD)(fileSize - 1);
}
returnValue = readMemoryFromFile(hFile, 0, dwSize, buffer);
}
CloseHandle(hFile);
}
return returnValue;
}
LPVOID ProcessAccessHelp::createFileMappingViewRead(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_READ, PAGE_READONLY | SEC_IMAGE, FILE_MAP_READ);
}
LPVOID ProcessAccessHelp::createFileMappingViewFull(const WCHAR * filePath)
{
return createFileMappingView(filePath, GENERIC_ALL, PAGE_EXECUTE_READWRITE, FILE_MAP_ALL_ACCESS);
}
LPVOID ProcessAccessHelp::createFileMappingView(const WCHAR * filePath, DWORD accessFile, DWORD flProtect, DWORD accessMap)
{
HANDLE hFile = CreateFile(filePath, accessFile, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: INVALID_HANDLE_VALUE %u", GetLastError());
#endif
return NULL;
}
HANDLE hMappedFile = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL);
CloseHandle(hFile);
if( hMappedFile == NULL )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: hMappedFile == NULL");
#endif
return NULL;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS");
#endif
return NULL;
}
LPVOID addrMappedDll = MapViewOfFile(hMappedFile, accessMap, 0, 0, 0);
if( addrMappedDll == NULL )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createFileMappingView :: addrMappedDll == NULL");
#endif
CloseHandle(hMappedFile);
return NULL;
}
CloseHandle(hMappedFile);
return addrMappedDll;
}
DWORD ProcessAccessHelp::getProcessByName(const WCHAR * processName)
{
DWORD dwPID = 0;
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(PROCESSENTRY32W);
if( !Process32FirstW( hProcessSnap, &pe32 ) )
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getProcessByName :: Error getting first Process");
#endif
CloseHandle( hProcessSnap );
return 0;
}
do
{
if(!_wcsicmp(pe32.szExeFile, processName))
{
dwPID = pe32.th32ProcessID;
break;
}
} while(Process32NextW(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return dwPID;
}
bool ProcessAccessHelp::getProcessModules(DWORD dwPID, std::vector<ModuleInfo> &moduleList)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
ModuleInfo module;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
return false;
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
CloseHandle( hModuleSnap );
return false;
}
// Now walk the module list of the process,
// and display information about each module
//the first is always the .exe
if (!Module32Next(hModuleSnap, &me32))
{
CloseHandle( hModuleSnap );
return false;
}
moduleList.reserve(20);
do
{
//printf(L"\n MODULE NAME: %s", me32.szModule);
module.modBaseAddr = (DWORD_PTR)me32.modBaseAddr;
module.modBaseSize = me32.modBaseSize;
module.isAlreadyParsed = false;
module.parsing = false;
wcscpy_s(module.fullPath, me32.szExePath);
moduleList.push_back(module);
} while(Module32Next(hModuleSnap, &me32));
CloseHandle( hModuleSnap );
return true;
}
bool ProcessAccessHelp::getMemoryRegionFromAddress(DWORD_PTR address, DWORD_PTR * memoryRegionBase, SIZE_T * memoryRegionSize)
{
MEMORY_BASIC_INFORMATION memBasic;
if (VirtualQueryEx(hProcess,(LPCVOID)address,&memBasic,sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getMemoryRegionFromAddress :: VirtualQueryEx error %u", GetLastError());
#endif
return false;
}
else
{
*memoryRegionBase = (DWORD_PTR)memBasic.BaseAddress;
*memoryRegionSize = memBasic.RegionSize;
return true;
}
}
bool ProcessAccessHelp::getSizeOfImageCurrentProcess()
{
DWORD_PTR newSizeOfImage = getSizeOfImageProcess(ProcessAccessHelp::hProcess, ProcessAccessHelp::targetImageBase);
if (newSizeOfImage != 0)
{
ProcessAccessHelp::targetSizeOfImage = newSizeOfImage;
return true;
}
else
{
return false;
}
}
SIZE_T ProcessAccessHelp::getSizeOfImageProcess(HANDLE processHandle, DWORD_PTR moduleBase)
{
SIZE_T sizeOfImage = 0;
MEMORY_BASIC_INFORMATION lpBuffer = {0};
SIZE_T dwLength = sizeof(MEMORY_BASIC_INFORMATION);
do
{
moduleBase = (DWORD_PTR)((SIZE_T)moduleBase + lpBuffer.RegionSize);
sizeOfImage += lpBuffer.RegionSize;
//printf("Query 0x"PRINTF_DWORD_PTR_FULL" size 0x%08X\n",moduleBase,sizeOfImage);
if (!VirtualQueryEx(processHandle, (LPCVOID)moduleBase, &lpBuffer, dwLength))
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"getSizeOfImageProcess :: VirtualQuery failed %X", GetLastError());
#endif
lpBuffer.Type = 0;
sizeOfImage = 0;
}
/*else
{
printf("\nAllocationBase %X\n",lpBuffer.AllocationBase);
printf("AllocationProtect %X\n",lpBuffer.AllocationProtect);
printf("BaseAddress %X\n",lpBuffer.BaseAddress);
printf("Protect %X\n",lpBuffer.Protect);
printf("RegionSize %X\n",lpBuffer.RegionSize);
printf("State %X\n",lpBuffer.State);
printf("Type %X\n",lpBuffer.Type);
}*/
} while (lpBuffer.Type == MEM_IMAGE);
//printf("Real sizeOfImage %X\n",sizeOfImage);
return sizeOfImage;
}
DWORD ProcessAccessHelp::getEntryPointFromFile(const WCHAR * filePath)
{
PeParser peFile(filePath, false);
return peFile.getEntryPoint();
}
bool ProcessAccessHelp::createBackupFile(const WCHAR * filePath)
{
size_t fileNameLength = wcslen(filePath) + 5; //.bak + null
BOOL retValue = 0;
WCHAR * backupFile = new WCHAR[fileNameLength];
wcscpy_s(backupFile, fileNameLength, filePath);
wcscat_s(backupFile, fileNameLength, L".bak");
retValue = CopyFile(filePath, backupFile, FALSE);
if (!retValue)
{
#ifdef DEBUG_COMMENTS
Scylla::debugLog.log(L"createBackupFile :: CopyFile failed with error 0x%X", GetLastError());
#endif
}
delete [] backupFile;
return retValue != 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, May 9, 3:37 AM (1 d, 8 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
eb/c0/c34869c4daefe4d0b7805e9e6c1a

Event Timeline