Page MenuHomedesp's stash

No OneTemporary

diff --git a/Scylla/PeRebuild.cpp b/Scylla/PeRebuild.cpp
index 09e4922..14be173 100644
--- a/Scylla/PeRebuild.cpp
+++ b/Scylla/PeRebuild.cpp
@@ -1,732 +1,736 @@
#include "PeRebuild.h"
#include <imagehlp.h>
#pragma comment(lib,"imagehlp.lib")
#include "ProcessAccessHelp.h"
#include "Logger.h"
#include "ConfigurationHolder.h"
//#define DEBUG_COMMENTS
bool PeRebuild::truncateFile(WCHAR * szFilePath, DWORD dwNewFsize)
{
bool retValue = true;
HANDLE hFile = CreateFile(szFilePath,GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return false;
}
if (SetFilePointer(hFile, dwNewFsize, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
if (GetLastError() == NO_ERROR)
{
retValue = true;
}
else
{
retValue = false;
}
}
else
{
retValue = true;
}
if (!SetEndOfFile(hFile))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("SetEndOfFile failed error %d\r\n", GetLastError());
#endif
retValue = false;
}
CloseHandle(hFile);
return retValue;
}
DWORD PeRebuild::validAlignment(DWORD BadSize)
{
div_t DivRes;
DivRes = div(BadSize, FileAlignmentConstant);
if (DivRes.rem == 0)
return BadSize;
return ((DivRes.quot+1) * FileAlignmentConstant);
}
DWORD PeRebuild::validAlignmentNew(DWORD badAddress)
{
DWORD moduloResult = badAddress % FileAlignmentConstant;
if (moduloResult)
{
return (FileAlignmentConstant - moduloResult);
}
else
{
return 0;
}
}
bool PeRebuild::isRoundedTo(DWORD_PTR dwTarNum, DWORD_PTR dwRoundNum)
{
+ return (dwTarNum % dwRoundNum) == 0;
+// WTF:
+/*
#ifdef _WIN64
lldiv_t d;
d = div((__int64)dwTarNum, (__int64)dwRoundNum);
#else
ldiv_t d;
d = div((long)dwTarNum, (long)dwRoundNum);
#endif
return (d.rem == 0);
+*/
}
void PeRebuild::cleanSectionPointer()
{
if (pSections)
{
for (int j = 0; j < MAX_SEC_NUM; j++)
{
if (pSections[j])
{
free(pSections[j]);
pSections[j] = 0;
}
}
}
}
DWORD PeRebuild::realignPE(LPVOID AddressOfMapFile, DWORD dwFsize)
{
PIMAGE_DOS_HEADER pDosh = 0;
PIMAGE_NT_HEADERS pPeh = 0;
PIMAGE_SECTION_HEADER pSectionh = 0;
int i = 0;
DWORD extraAlign = 0;
ZeroMemory(&pSections, sizeof(pSections));
// get the other parameters
pMap = AddressOfMapFile;
dwMapBase = (DWORD_PTR)pMap;
if (dwFsize == 0 || pMap == NULL)
return 1;
// access the PE Header and check whether it's a valid one
pDosh = (PIMAGE_DOS_HEADER)(pMap);
pPeh = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosh+pDosh->e_lfanew);
if (!validatePeHeaders(pDosh))
{
return 0;
}
if (pPeh->FileHeader.NumberOfSections > MAX_SEC_NUM)
{
return 3;
}
__try
{
/* START */
pPeh->OptionalHeader.FileAlignment = FileAlignmentConstant;
/* Realign the PE Header */
// get the size of all headers
dwTmpNum = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pPeh->FileHeader.SizeOfOptionalHeader + (pPeh->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
// kill room between the "win32 pls" message and the PE signature
// find the end of the message
pW = (WORD*)(dwMapBase + ScanStartDS);
while (*pW != 0 || (!isRoundedTo((DWORD_PTR)pW, 0x10)))
{
pW = (WORD*)((DWORD_PTR)pW + 1);
}
wTmpNum = (WORD)((DWORD_PTR)pW - dwMapBase);
if (wTmpNum < pDosh->e_lfanew)
{
CopyMemory((LPVOID)pW,(VOID*)pPeh,dwTmpNum); // copy the Header to the right place
pDosh->e_lfanew = wTmpNum;
}
dwSectionBase = validAlignment(dwTmpNum + pDosh->e_lfanew);
pPeh = (PIMAGE_NT_HEADERS)(dwMapBase + pDosh->e_lfanew); // because the NT header moved
// correct the SizeOfHeaders
pPeh->OptionalHeader.SizeOfHeaders = dwSectionBase;
/* Realign all sections */
// make a copy of all sections
// this is needed if the sections aren't sorted by their RawOffset (e.g. Petite)
pSectionh = IMAGE_FIRST_SECTION(pPeh);
for (i=0; i<pPeh->FileHeader.NumberOfSections; i++)
{
if (pSectionh->SizeOfRawData == 0 || pSectionh->PointerToRawData == 0)
{
++pSectionh;
continue;
}
// get a valid size
dwTmpNum = pSectionh->SizeOfRawData;
if ((pSectionh->SizeOfRawData + pSectionh->PointerToRawData) > dwFsize)
{
dwTmpNum = dwFsize - pSectionh->PointerToRawData;
}
//dwTmpNum -= 1;
// copy the section into some memory
// limit max section size to 300 MB = 300000 KB = 300000000 B
if (dwTmpNum > 300000000)
{
dwTmpNum = 300000000;
}
//because of validAlignment we need some extra space, max 0x200 extra
extraAlign = validAlignmentNew(dwTmpNum);
pSections[i] = malloc(dwTmpNum + extraAlign);
ZeroMemory(pSections[i], dwTmpNum + extraAlign);
if (pSections[i] == NULL) // fatal error !!!
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("realignPE :: malloc failed with dwTmpNum %08X %08X\r\n", dwTmpNum, extraAlign);
#endif
cleanSectionPointer();
return 4;
}
CopyMemory(pSections[i],(LPVOID)(pSectionh->PointerToRawData+dwMapBase),dwTmpNum);
++pSectionh;
}
// start realigning the sections
pSectionh = IMAGE_FIRST_SECTION(pPeh);
for (i=0;i<pPeh->FileHeader.NumberOfSections;i++)
{
// some anti crash code :P
if (pSectionh->SizeOfRawData == 0 || pSectionh->PointerToRawData == 0)
{
++pSectionh;
if (pSectionh->PointerToRawData == 0)
{
continue;
}
pSectionh->PointerToRawData = dwSectionBase;
continue;
}
// let pCH point to the end of the current section
if ((pSectionh->PointerToRawData+pSectionh->SizeOfRawData) <= dwFsize)
{
pCH = (char*)(dwMapBase+pSectionh->PointerToRawData+pSectionh->SizeOfRawData-1);
}
else
{
pCH = (char*)(dwMapBase+dwFsize-1);
}
// look for the end of this section
while (*pCH == 0)
{
--pCH;
}
// calculate the new RawSize
dwTmpNum = (DWORD)(((DWORD_PTR)pCH - dwMapBase) + MinSectionTerm - pSectionh->PointerToRawData);
if (dwTmpNum < pSectionh->SizeOfRawData)
{
pSectionh->SizeOfRawData = dwTmpNum;
}
else // the new size is too BIG
{
dwTmpNum = pSectionh->SizeOfRawData;
}
// copy the section to the new place
if (i != pPeh->FileHeader.NumberOfSections-1)
{
dwTmpNum = validAlignment(dwTmpNum);
}
CopyMemory((LPVOID)(dwMapBase+dwSectionBase), pSections[i], dwTmpNum);
// set the RawOffset
pSectionh->PointerToRawData = dwSectionBase;
// get the RawOffset for the next section
dwSectionBase = dwTmpNum+dwSectionBase; // the last section doesn't need to be aligned
// go to the next section
++pSectionh;
}
// delete bound import directories because it is destroyed if present
pPeh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
pPeh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
// clean up
cleanSectionPointer();
}
__except(1)
{
// clean up
cleanSectionPointer();
#ifdef DEBUG_COMMENTS
Logger::debugLog("realignPE :: Exception occured\r\n");
#endif
return 0;
}
if (ConfigurationHolder::getConfigObject(UPDATE_HEADER_CHECKSUM)->isTrue())
{
updatePeHeaderChecksum(AddressOfMapFile, dwSectionBase);
}
return dwSectionBase; // return the new filesize
}
// returns:
// -1 - access violation
// -2 - no relocation found
// -3 - no own section
// -4 - dll characteristics found
// -5 - invalid PE file
// else the new raw size
DWORD PeRebuild::wipeReloc(void* pMap, DWORD dwFsize)
{
PIMAGE_DOS_HEADER pDosH;
PIMAGE_NT_HEADERS pNTH;
PIMAGE_SECTION_HEADER pSecH;
PIMAGE_SECTION_HEADER pSH, pSH2;
DWORD dwRelocRVA, i;
BOOL bOwnSec = FALSE;
DWORD dwNewFsize;
__try // =)
{
// get pe header pointers
pDosH = (PIMAGE_DOS_HEADER)pMap;
if (pDosH->e_magic != IMAGE_DOS_SIGNATURE)
return -5;
pNTH = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosH + pDosH->e_lfanew);
if (pNTH->Signature != IMAGE_NT_SIGNATURE)
return -5;
pSecH = IMAGE_FIRST_SECTION(pNTH);
// has PE dll characteristics ?
if (pNTH->FileHeader.Characteristics & IMAGE_FILE_DLL)
return -4;
// is there a reloc section ?
dwRelocRVA = pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
if (!dwRelocRVA)
return -2;
// check whether the relocation has an own section
pSH = pSecH;
for (i=0; i < pNTH->FileHeader.NumberOfSections; i++)
{
if (pSH->VirtualAddress == dwRelocRVA)
{
bOwnSec = TRUE;
break; // pSH -> reloc section header and i == section index
}
++pSH;
}
if (!bOwnSec)
return -3;
if (i+1 == pNTH->FileHeader.NumberOfSections)
{
//--- relocation is the last section ---
// truncate at the start of the reloc section
dwNewFsize = pSH->PointerToRawData;
}
else
{
//--- relocation isn't the last section ---
dwNewFsize = dwFsize - pSH->SizeOfRawData;
//-> copy the section(s) after the relocation to the start of the relocation
pSH2 = pSH;
++pSH2; // pSH2 -> pointer to first section after relocation
memcpy(
(void*)(pSH->PointerToRawData + (DWORD)pMap),
(const void*)(pSH2->PointerToRawData + (DWORD)pMap),
dwFsize - pSH2->PointerToRawData);
//-> fix the section headers
// (pSH -> reloc section header)
// (pSH2 -> first section after reloc section)
for (++i; i < pNTH->FileHeader.NumberOfSections; i++)
{
// apply important values
pSH->SizeOfRawData = pSH2->SizeOfRawData;
pSH->VirtualAddress = pSH2->VirtualAddress;
pSH->Misc.VirtualSize = pSH2->Misc.VirtualSize;
// apply section name
memcpy(
(void*)(pSH->Name),
(const void*)(pSH2->Name),
sizeof(pSH2->Name));
++pSH;
++pSH2;
}
}
// dec section number
--pNTH->FileHeader.NumberOfSections;
// kill reloc directory entry
pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
// fix virtual parts of the PE Header (a must for win2k)
pSH2 = pSH = pSecH;
++pSH2;
for (i=0; i < (DWORD)pNTH->FileHeader.NumberOfSections-1; i++)
{
pSH->Misc.VirtualSize = pSH2->VirtualAddress - pSH->VirtualAddress;
++pSH;
++pSH2;
}
// (pSH -> pointer to last section)
if (pSH->Misc.PhysicalAddress)
pNTH->OptionalHeader.SizeOfImage = pSH->VirtualAddress + pSH->Misc.VirtualSize;
else // WATCOM is always a bit special >:-)
pNTH->OptionalHeader.SizeOfImage = pSH->VirtualAddress + pSH->SizeOfRawData;
}
__except(1)
{
// an access violation occurred :(
return -1;
}
return dwNewFsize;
}
bool PeRebuild::validatePE(void* pPEImage, DWORD dwFileSize)
{
PIMAGE_NT_HEADERS pNTh;
PIMAGE_SECTION_HEADER pSech,pSH, pSH2, pLastSH;
UINT i;
DWORD dwHeaderSize;
// get PE base information
pNTh = ImageNtHeader(pPEImage);
if (!pNTh)
return FALSE;
pSech = IMAGE_FIRST_SECTION(pNTh);
// FIX:
// ... the SizeOfHeaders
pSH = pSech;
dwHeaderSize = 0xFFFFFFFF;
for(i=0; i < pNTh->FileHeader.NumberOfSections; i++)
{
if (pSH->PointerToRawData && pSH->PointerToRawData < dwHeaderSize)
{
dwHeaderSize = pSH->PointerToRawData;
}
++pSH;
}
pNTh->OptionalHeader.SizeOfHeaders = dwHeaderSize;
// ...Virtual Sizes
pSH2 = pSH = pSech;
++pSH2;
for (i=0; i < (DWORD)pNTh->FileHeader.NumberOfSections-1; i++)
{
pSH->Misc.VirtualSize = pSH2->VirtualAddress - pSH->VirtualAddress;
++pSH;
++pSH2;
}
// (pSH -> pointer to last section)
pLastSH = pSH;
// ...RawSize of the last section
pLastSH->SizeOfRawData = dwFileSize - pLastSH->PointerToRawData;
// ...SizeOfImage
if (pLastSH->Misc.PhysicalAddress)
{
pNTh->OptionalHeader.SizeOfImage = pLastSH->VirtualAddress + pLastSH->Misc.VirtualSize;
}
else // WATCOM is always a bit special >:-)
{
pNTh->OptionalHeader.SizeOfImage = pLastSH->VirtualAddress + pLastSH->SizeOfRawData;
}
return true;
}
ReBaseErr PeRebuild::reBasePEImage(void* pPE, DWORD_PTR dwNewBase)
{
PIMAGE_NT_HEADERS pNT;
PIMAGE_RELOCATION pR;
ReBaseErr ret;
DWORD_PTR dwDelta;
DWORD *pdwAddr, dwRva, dwType;
UINT iItems, i;
WORD *pW;
// dwNewBase valid ?
if (dwNewBase & 0xFFFF)
{
ret = RB_INVALIDNEWBASE;
goto Exit; // ERR
}
//
// get relocation dir ptr
//
pNT = ImageNtHeader(pPE);
if (!pNT)
{
ret = RB_INVALIDPE;
goto Exit; // ERR
}
// new base = old base ?
if (pNT->OptionalHeader.ImageBase == dwNewBase)
{
ret = RB_OK;
goto Exit; // OK
}
if (!pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
{
ret = RB_NORELOCATIONINFO;
goto Exit; // ERR
}
pR = (PIMAGE_RELOCATION)ImageRvaToVa(
pNT,
pPE,
pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
NULL);
if (!pR)
{
ret = RB_INVALIDRVA;
goto Exit; // ERR
}
//
// add delta to relocation items
//
dwDelta = dwNewBase - pNT->OptionalHeader.ImageBase;
__try
{
do
{
// get number of items
if (pR->SymbolTableIndex)
iItems = (pR->SymbolTableIndex - 8) / 2;
else
break; // no items in this block
// trace/list block items...
pW = (WORD*)((DWORD_PTR)pR + 8);
for (i = 0; i < iItems; i++)
{
dwRva = (*pW & 0xFFF) + pR->VirtualAddress;
dwType = *pW >> 12;
if (dwType != 0) // fully compatible ???
{
// add delta
pdwAddr = (PDWORD)ImageRvaToVa(
pNT,
pPE,
dwRva,
NULL);
if (!pdwAddr)
{
ret = RB_INVALIDRVA;
goto Exit; // ERR
}
*pdwAddr += dwDelta;
}
// next item
++pW;
}
pR = (PIMAGE_RELOCATION)pW; // pR -> next block header
} while ( *(DWORD*)pW );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
ret = RB_ACCESSVIOLATION;
goto Exit; // ERR
}
// apply new base to header
pNT->OptionalHeader.ImageBase = dwNewBase;
ret = RB_OK; // OK
Exit:
return ret;
}
bool PeRebuild::updatePeHeaderChecksum(LPVOID AddressOfMapFile, DWORD dwFsize)
{
PIMAGE_NT_HEADERS32 pNTHeader32 = 0;
PIMAGE_NT_HEADERS64 pNTHeader64 = 0;
DWORD headerSum = 0;
DWORD checkSum = 0;
pNTHeader32 = (PIMAGE_NT_HEADERS32)CheckSumMappedFile(AddressOfMapFile, dwFsize, &headerSum, &checkSum);
if (!pNTHeader32)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("updatePeHeaderChecksum :: CheckSumMappedFile failed error %X\r\n", GetLastError());
#endif
return false;
}
#ifdef DEBUG_COMMENTS
Logger::debugLog("Old checksum %08X new checksum %08X\r\n",headerSum,checkSum);
#endif
if (pNTHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
pNTHeader64 = (PIMAGE_NT_HEADERS64)pNTHeader32;
pNTHeader64->OptionalHeader.CheckSum = checkSum;
}
else
{
pNTHeader32->OptionalHeader.CheckSum = checkSum;
}
return true;
}
LPVOID PeRebuild::createFileMappingViewFull(const WCHAR * filePath)
{
hFileToMap = CreateFile(filePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if( hFileToMap == INVALID_HANDLE_VALUE )
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("createFileMappingView :: INVALID_HANDLE_VALUE %u\r\n",GetLastError());
#endif
hMappedFile = 0;
hFileToMap = 0;
addrMappedDll = 0;
return NULL;
}
hMappedFile = CreateFileMapping(hFileToMap, 0, PAGE_READWRITE, 0, 0, NULL);
if( hMappedFile == NULL )
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("createFileMappingViewFull :: hMappedFile == NULL\r\n");
#endif
CloseHandle(hFileToMap);
hMappedFile = 0;
hFileToMap = 0;
addrMappedDll = 0;
return NULL;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("createFileMappingView :: GetLastError() == ERROR_ALREADY_EXISTS\r\n");
#endif
CloseHandle(hFileToMap);
hMappedFile = 0;
hFileToMap = 0;
addrMappedDll = 0;
return NULL;
}
addrMappedDll = MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if(!addrMappedDll)
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("createFileMappingView :: addrMappedDll == NULL\r\n");
#endif
CloseHandle(hFileToMap);
CloseHandle(hMappedFile);
hMappedFile = 0;
hFileToMap = 0;
return NULL;
}
return addrMappedDll;
}
void PeRebuild::closeAllMappingHandles()
{
if (addrMappedDll)
{
if (!FlushViewOfFile(addrMappedDll, 0))
{
#ifdef DEBUG_COMMENTS
Logger::debugLog("closeAllMappingHandles :: Could not flush memory to disk (%d)\r\n", GetLastError());
#endif
}
UnmapViewOfFile(addrMappedDll);
addrMappedDll = 0;
}
if (hMappedFile)
{
CloseHandle(hMappedFile);
hMappedFile = 0;
}
if (hFileToMap)
{
CloseHandle(hFileToMap);
hFileToMap = 0;
}
}
bool PeRebuild::validatePeHeaders( PIMAGE_DOS_HEADER pDosh )
{
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosh + pDosh->e_lfanew);
if ((pDosh != 0) && (pDosh->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;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 21, 9:48 PM (1 d, 15 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
02/1f/318e858ed76822503bd117358f40

Event Timeline