Running EXE from buffer in memory

-1

i'm trying to make exe packer 5

  1. extract exe to buffer(in my case: vector)
  2. add new section
  3. get offset of new EP and run

but after call newmain i got 0xC0000005

main.cpp: pastebin

    #define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "main.h"
typedef struct _BASE_RELOCATION_ENTRY
{
    WORD Offset : 12;
    WORD Type : 4;
} BASE_RELOCATION_ENTRY;

BOOL applyRelocBlock(BASE_RELOCATION_ENTRY* block, size_t entriesNum, DWORD page, PVOID newBase)
{
    PVOID ImageBaseAddress = NtCurrentTeb()->Peb->ImageBaseAddress;
    BASE_RELOCATION_ENTRY* entry = block;

    for (int i = 0; i < entriesNum; i++)
    {
        DWORD offset = entry->Offset;
        DWORD type = entry->Type;
        if (entry == NULL || type == 0 || offset == 0)
        {
            //printf("Applied relocations: %d\n", i);
            return TRUE; //finish
        }
        if (type != 3)
        {
            printf("Not supported relocations format at %d: %d\n", i, type);
            return FALSE;
        }
        uint32_t* relocateAddr = (uint32_t*)((ULONG_PTR)newBase + page + offset);
        (*relocateAddr) = ((*relocateAddr) - (ULONG_PTR)ImageBaseAddress) + (ULONG_PTR)newBase;
        entry = (BASE_RELOCATION_ENTRY*)((ULONG_PTR)entry + sizeof(uint16_t));
    }
    return TRUE;
}

BOOL applyRelocations(PIMAGE_NT_HEADERS NtHeaders, PVOID newBase)
{
    PVOID ImageBaseAddress = NtCurrentTeb()->Peb->ImageBaseAddress;
    //fetch relocation table from current image:
    IMAGE_DATA_DIRECTORY relocDir = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
    if (relocDir.VirtualAddress == NULL)
    {
        printf("Cannot relocate - application have no relocation table!");
        return FALSE;
    }
    DWORD maxSize = relocDir.Size;
    DWORD parsedSize = 0;

    DWORD relocAddr = relocDir.VirtualAddress;
    IMAGE_BASE_RELOCATION* reloc = NULL;

    while (parsedSize < maxSize)
    {
        reloc = (IMAGE_BASE_RELOCATION*)(relocAddr + parsedSize + (ULONG_PTR)ImageBaseAddress);
        parsedSize += reloc->SizeOfBlock;

        if (reloc->VirtualAddress == NULL || reloc->SizeOfBlock == 0)
        {
            continue;
        }

        printf("RelocBlock: %p %p\n", reloc->VirtualAddress, reloc->SizeOfBlock);

        size_t entriesNum = (reloc->SizeOfBlock - 2 * sizeof(uint32_t)) / sizeof(uint16_t);
        DWORD page = reloc->VirtualAddress;

        BASE_RELOCATION_ENTRY* block = (BASE_RELOCATION_ENTRY*)((ULONG_PTR)reloc + sizeof(uint32_t) + sizeof(uint32_t));
        if (applyRelocBlock(block, entriesNum, page, newBase) == FALSE)
        {
            return FALSE;
        }
    }
    return TRUE;
}

bool checkLibs()
{
    return load_ntdll_functions() && load_kernel32_functions();
}

bool mapAndRun()
{
    HANDLE hSection = NULL;

    PVOID ImageBaseAddress = NtCurrentTeb()->Peb->ImageBaseAddress;
    PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader(ImageBaseAddress);

    if (NtHeaders == NULL)
    {
        printf("[ERROR] RtlImageNtHeader failed, error : %d\n", GetLastError());
        return false;
    }

    LARGE_INTEGER MaximumSize;
    ULONG ImageSize = NtHeaders->OptionalHeader.SizeOfImage;

    MaximumSize.LowPart = ImageSize;
    MaximumSize.HighPart = 0;

    NTSTATUS Status = NULL;

    if ((Status = ZwCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL)) != STATUS_SUCCESS)
    {
        printf("[ERROR] ZwCreateSection failed, status : %x\n", Status);
        system("pause");
        return false;
    }

    printf("Section handle: %x\n", hSection);

    HANDLE hProcess = NULL;
    PVOID pSectionBaseAddress = NULL;
    SIZE_T ViewSize = 0;
    DWORD dwInheritDisposition = 1; //VIEW_SHARE

    // map the section in context of current process:
    if ((Status = NtMapViewOfSection(hSection, GetCurrentProcess(), &pSectionBaseAddress, NULL, NULL, NULL, &ViewSize, dwInheritDisposition, NULL, PAGE_EXECUTE_READWRITE)) != STATUS_SUCCESS)
    {
        printf("[ERROR] NtMapViewOfSection failed, status : %x\n", Status);
        system("pause");
        return false;
    }

    printf("Created new section, BaseAddress: %p ViewSize: %p\n", pSectionBaseAddress, ViewSize);
    printf("Mapping into: %p <- current image: %p %p\n", pSectionBaseAddress, ImageBaseAddress, ImageSize);
    RtlCopyMemory(pSectionBaseAddress, ImageBaseAddress, ImageSize);

    ZwClose(hSection);
    hSection = NULL;
    if (applyRelocations(NtHeaders, pSectionBaseAddress) == FALSE) {
        printf("Applying relocations failed, cannot continue!");
        ZwTerminateProcess(GetCurrentProcess(), STATUS_FAILURE);
    }
    printf("Applied relocations!\n");

    //

    std::vector<unsigned char> extractedData = unpackExe(); //packe exe

    IMAGE_NT_HEADERS INH;
    IMAGE_DOS_HEADER IDH;
    memcpy(&IDH, &extractedData[0], sizeof(IDH));
    memcpy(&INH, (void*)((DWORD)&extractedData[0] + IDH.e_lfanew), sizeof(INH));

    LARGE_INTEGER MaximumSizeEX;
    ULONG ImageSizeEX = INH.OptionalHeader.SizeOfImage;

    MaximumSizeEX.LowPart = ImageSizeEX;
    MaximumSizeEX.HighPart = 0;
    ULONG_PTR exEP = INH.OptionalHeader.AddressOfEntryPoint;

    ULONG_PTR offsetFromBase = exEP - (ULONG_PTR)ImageBaseAddress;
    printf("extracted EP offset: %p\n", offsetFromBase);

    ULONG_PTR newMain = ((ULONG_PTR)pSectionBaseAddress + offsetFromBase);
    printf("extracted EP address in new section: %p\n", newMain);

    __asm {
        call newMain
    };

    return true;
}

bool mapAndExecute()
{
    if (checkLibs())
    {
        if (mapAndRun())
        {
        }
    }
    return true;
}


int main()
{
    mapAndExecute();
    std::cin.get();
}

main.h:pastebin: pastebin.com/Spc5WTsQ

    #pragma once

#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#if !defined NTSTATUS
typedef LONG NTSTATUS;
#endif

#define STATUS_SUCCESS 0
#define STATUS_FAILURE (-1)
#define NtCurrentProcess() ((HANDLE)-1)

typedef struct _CLIENT_ID
{
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;

typedef LONG NTSTATUS, *PNTSTATUS;
typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _PEB_LDR_DATA
{
    ULONG               Length;
    BOOLEAN             Initialized;
    PVOID               SsHandle;
    LIST_ENTRY          InLoadOrderModuleList;
    LIST_ENTRY          InMemoryOrderModuleList;
    LIST_ENTRY          InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _PEB
{
    BYTE                         Reserved1[2];       /*  00 */
    BYTE                         BeingDebugged;      /*  02 */
    BYTE                         Reserved2[5];       /*  03 */
    HMODULE                      ImageBaseAddress;   /*  08 */
    PPEB_LDR_DATA                LdrData;            /*  0c */
    DWORD                        ProcessParameters;  /*  10 */
    PVOID                        __pad_14;           /*  14 */
    HANDLE                       ProcessHeap;        /*  18 */
    BYTE                         __pad_1c[36];       /*  1c */
    DWORD                        TlsBitmap;          /*  40 */
    ULONG                        TlsBitmapBits[2];   /*  44 */
    BYTE                         __pad_4c[24];       /*  4c */
    ULONG                        NumberOfProcessors; /*  64 */
    BYTE                         __pad_68[128];      /*  68 */
    PVOID                        Reserved3[59];      /*  e8 */
    ULONG                        SessionId;          /* 1d4 */
} PEB, *PPEB;

typedef struct _TEB
{
    NT_TIB          Tib;                        /* 000 */
    PVOID           EnvironmentPointer;         /* 01c */
    CLIENT_ID       ClientId;                   /* 020 */
    PVOID           ActiveRpcHandle;            /* 028 */
    PVOID           ThreadLocalStoragePointer;  /* 02c */
    PPEB            Peb;                        /* 030 */
    ULONG           LastErrorValue;             /* 034 */
    BYTE            __pad038[140];              /* 038 */
    ULONG           CurrentLocale;              /* 0c4 */
    BYTE            __pad0c8[1752];             /* 0c8 */
    PVOID           Reserved2[278];             /* 7a0 */
    UNICODE_STRING  StaticUnicodeString;        /* bf8 used by advapi32 */
    WCHAR           StaticUnicodeBuffer[261];   /* c00 used by advapi32 */
    PVOID           DeallocationStack;          /* e0c */
    PVOID           TlsSlots[64];               /* e10 */
    LIST_ENTRY      TlsLinks;                   /* f10 */
    PVOID           Reserved4[26];              /* f18 */
    PVOID           ReservedForOle;             /* f80 Windows 2000 only */
    PVOID           Reserved5[4];               /* f84 */
    PVOID           TlsExpansionSlots;          /* f94 */
} TEB, *PTEB;

typedef
void
(*PKNORMAL_ROUTINE) (
    void* NormalContext,
    void* SystemArgument1,
    void* SystemArgument2
    );

typedef struct {
    int info;
    PKNORMAL_ROUTINE fun;
} *PIO_STATUS_BLOCK;

// Make sure we print the __stdcall properly
typedef
void
(__stdcall *PIO_APC_ROUTINE) (
    void* ApcContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    long Reserved
    );


#if !defined PROCESSINFOCLASS
typedef LONG PROCESSINFOCLASS;
#endif

#if !defined THREADINFOCLASS
typedef LONG THREADINFOCLASS;
#endif

#if !defined PPEB
typedef struct _PEB *PPEB;
#endif

#if !defined PROCESS_BASIC_INFORMATION
typedef struct _PROCESS_BASIC_INFORMATION {
    PVOID Reserved1;
    PPEB PebBaseAddress;
    PVOID Reserved2[2];
    ULONG_PTR UniqueProcessId;
    PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
#endif;

/*
typedef LONG NTSTATUS, *PNTSTATUS;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
*/

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;
    PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

typedef NTSTATUS(WINAPI * PFN_ZWQUERYINFORMATIONPROCESS)(HANDLE, PROCESSINFOCLASS,
    PVOID, ULONG, PULONG);

//ntdll api:
NTSTATUS(NTAPI *ZwQueryInformationProcess)(
    HANDLE  ProcessHandle,
    PROCESSINFOCLASS  ProcessInformationClass,
    PVOID  ProcessInformation,
    ULONG  ProcessInformationLength,
    PULONG  ReturnLength  OPTIONAL
    );

NTSTATUS(NTAPI *ZwCreateSection)(
    __out    PHANDLE            SectionHandle,
    __in     ACCESS_MASK        DesiredAccess,
    __in POBJECT_ATTRIBUTES ObjectAttributes,
    __in PLARGE_INTEGER     MaximumSize,
    __in     ULONG              SectionPageProtection,
    __in     ULONG              AllocationAttributes,
    __in HANDLE             FileHandle
    );


NTSTATUS(NTAPI *NtMapViewOfSection)(
    __in        HANDLE          SectionHandle,
    __in        HANDLE          ProcessHandle,
    __inout     PVOID           *BaseAddress,
    __in        ULONG_PTR       ZeroBits,
    __in        SIZE_T          CommitSize,
    __inout  PLARGE_INTEGER  SectionOffset,
    __inout     PSIZE_T         ViewSize,
    __in        DWORD InheritDisposition,
    __in        ULONG           AllocationType,
    __in        ULONG           Win32Protect
    );

NTSTATUS(NTAPI *ZwCreateThreadEx) (
    __out PHANDLE ThreadHandle,
    __in ACCESS_MASK DesiredAccess,
    __in POBJECT_ATTRIBUTES ObjectAttributes,
    __in HANDLE ProcessHandle,
    __in PVOID StartRoutine,
    __in PVOID Argument,
    __in ULONG CreateFlags,
    __in ULONG_PTR ZeroBits,
    __in SIZE_T StackSize,
    __in SIZE_T MaximumStackSize,
    __in PVOID AttributeList
    );

NTSTATUS(NTAPI *ZwUnmapViewOfSection) (
    __in     HANDLE ProcessHandle,
    __in PVOID  BaseAddress
    );

NTSTATUS(NTAPI *ZwClose) (
    __in HANDLE Handle
    );

NTSTATUS(NTAPI *ZwTerminateProcess) (
    __in HANDLE   ProcessHandle,
    __in     NTSTATUS ExitStatus
    );

NTSTATUS(NTAPI *NtQueueApcThread)(
    __in HANDLE ThreadHandle,
    __in PVOID ApcRoutine,
    __in PVOID ApcRoutineContext OPTIONAL,
    __in PVOID ApcStatusBlock OPTIONAL,
    __in ULONG ApcReserved OPTIONAL
    );

NTSTATUS(NTAPI *ZwSetInformationThread) (
    __in HANDLE ThreadHandle,
    __in THREADINFOCLASS ThreadInformationClass,
    __in PVOID ThreadInformation,
    __in ULONG ThreadInformationLength
    );

PIMAGE_NT_HEADERS(NTAPI *RtlImageNtHeader) (
    __in PVOID ModuleAddress
    );


//kernel32 api
BOOL
(WINAPI *CreateProcessInternalW)(HANDLE hToken,
    LPCWSTR lpApplicationName,
    LPWSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCWSTR lpCurrentDirectory,
    LPSTARTUPINFOW lpStartupInfo,
    LPPROCESS_INFORMATION lpProcessInformation,
    PHANDLE hNewToken
    );

trying to adoptate source from here

https://github.com/hasherezade/snippets/tree/master/inject4

c++
exe
asked on Stack Overflow Aug 18, 2016 by own2pwn • edited Oct 10, 2018 by miken32

3 Answers

0

The data you have loaded is in the loading application's data space and execution of data is blocked in modern memory protected operating systems - because that was previously a common and rather easy exploit for viruses.

In order to run, an executable must have been loaded and located by the operating system.

answered on Stack Overflow Oct 15, 2017 by Clifford
-1

It would be impossible to run an executable from memory without having the executable data reside in a physical file. Windows won't allow it. No windows API provides mechanism to execute file directly from memory. All windows API like CreateProcess() or ShellExcute() require a physical file to be present. If there is a way, it would be considered a vulnerability and will be soon patched.

answered on Stack Overflow Oct 15, 2017 by Michael Haephrati • edited Jan 8, 2018 by Michael Haephrati
-1

Not sure how to post a large code snippet in response to a request that was a remark. Michael Haephrati asked for an x64 example of executing data as x64 code. Here's the code (x64 only for this code, the calling conventions differ in 32 bit code):

#include <windows.h>
#include <iostream>

typedef int(*PMULFUNC)(int l, int r);

PMULFUNC buildFunction()
{
    LPVOID pMem = VirtualAlloc(NULL, 6, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    unsigned char *pNext = (unsigned char *)pMem;

    *pNext = 0x8b; ++pNext;     // mov eax, ecx
    *pNext = 0xc1; ++pNext;

    *pNext = 0x0f; ++pNext;     // imul eax, edx
    *pNext = 0xaf; ++pNext;
    *pNext = 0xc2; ++pNext;

    *pNext = 0xc3; ++pNext;     // ret

    return (PMULFUNC)pMem;
}

int main()
{
    using namespace std;

    PMULFUNC pMul = buildFunction();

    int l = 5;
    for (int r=1; r<=12; ++r)
    {
        cout << l << "x" << r << "=" << (*pMul)(l, r) << endl;
    }

    return 0;
}

typedef int(__stdcall *PMULFUNC)(int l, int r);

PMULFUNC buildFunction()
{
    LPVOID pMem = VirtualAlloc(NULL, 6, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    unsigned char *pNext = (unsigned char *)pMem;

    *pNext = 0x8b; ++pNext;     // mov eax, ecx
    *pNext = 0xc1; ++pNext;

    *pNext = 0x0f; ++pNext;     // imul eax, edx
    *pNext = 0xaf; ++pNext;
    *pNext = 0xc2; ++pNext;

    *pNext = 0xc3; ++pNext;     // ret

    return (PMULFUNC)pMem;
}

int main()
{
    using namespace std;

    PMULFUNC pMul = buildFunction();

    int l = 5;
    for (int r=1; r<=12; ++r)
    {
        cout << l << "x" << r << "=" << (*pMul)(l, r) << endl;
    }

    return 0;
}

In response to the specific question, it's possible but advanced. EXEs aren't simply copied into memory: references to other DLL's are resolved, sections that are adjacent in the image may be separated in memory, and many other things. In short you would have to re-implement the loader. But one thing is certain, if a page has the correct permissions it can be executed,

answered on Stack Overflow Dec 29, 2017 by Steve • edited Dec 29, 2017 by Steve

User contributions licensed under CC BY-SA 3.0