Is there a way to store binary code in memory (as a value) then execute it?

For instance if I have an array of bytes I have filled with the binary code of say, a .exe, is it possible to execute it?

Dani AI

Generated

The short answer is yes for raw machine code (shellcode), but not by just dropping a full PE (.exe) image into a byte array and jumping to it. A PE needs the Windows loader: relocations, import resolution, TLS, etc. If your bytes are a position‑independent routine with the right calling convention, you can execute them by placing them in memory that is marked executable, as showed for Linux.

On Windows, use VirtualAlloc to get writable memory, copy the bytes, then flip the protection to executable with VirtualProtect before calling them. Keep to W^X: write as RW, then change to RX (avoid RWX). Minimal example:

#include <windows.h>
#include <stdint.h>
#include <string.h>

int main(void) {
    uint8_t payload[] = { 0xC3 }; // ret; replace with your code
    SIZE_T size = sizeof(payload);

    void *mem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!mem) return 1;

    memcpy(mem, payload, size);

    DWORD oldProt;
    if (!VirtualProtect(mem, size, PAGE_EXECUTE_READ, &oldProt)) return 1;

    ((void(*)(void))mem)();  // or CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)mem,NULL,0,NULL);

    VirtualFree(mem, 0, MEM_RELEASE);
    return 0;
}

About the masking in ’s Linux sample: pages are typically 4096 bytes, so addr & ~0xFFF aligns a pointer down to the start of its page because ~0xFFF clears the low 12 bits. Linux mprotect requires a page‑aligned address. VirtualProtect will round the address down internally, but you still need the correct region size (round up to a page multiple; use GetSystemInfo to query dwPageSize).

Practical cautions:

  • DEP/NX means executable permission is required; RX after writing is safer.
  • AV/EDR often flags this pattern.
  • A whole .exe in a byte array will not run this way; you would need a proper in‑memory PE loader.

Recommended Answers

All 4 Replies

You'll have to change the memory attributes of the array to read and execute and then point the instruction pointer at it.

Here's an example that displays 'Hello, World!'. Note this will only work on a Linux 64 bit PC.

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

unsigned char mya[] = 	{
			  0x50,0x57,0x56,0x52,0xe8,
			  0x00,0x00,0x00,0x00,0x5e,
			  0x48,0x81,0xc6,0x24,0x00,
			  0x00,0x00,0x48,0xc7,0xc0,
			  0x01,0x00,0x00,0x00,0x48,
			  0xc7,0xc7,0x01,0x00,0x00,
			  0x00,0x48,0xc7,0xc2,0x0e,
			  0x00,0x00,0x00,0x0f,0x05,
			  0x5a,0x5e,0x5f,0x5a,0xc3,
			  0x48,0x65,0x6c,0x6c,0x6f,
			  0x2c,0x20,0x57,0x6f,0x72,
			  0x6c,0x64,0x21,0x0a,0x00
			};
			
int main(int argc, char**argv)
{
  void *addr = (void*)((unsigned long)mya & ((0UL - 1UL) ^ 0xfff));/*get memory page*/
  int ans = mprotect(addr, 1, PROT_READ|PROT_WRITE|PROT_EXEC);/*set page attributes*/
  if (ans)
  {
    perror("mprotect");
    exit(EXIT_FAILURE);
  }
  
  ((void(*)(void))mya)();/*execute array*/
  
  return 0;
}
commented: Absolutely good, hard to find this information too. +1
commented: Hello dear , Please tell me how did you get the raw code of the function? +0

Forgot to mention I'm using Windows.

Also, what is the reason for bitwise AND'ing the address of the array with -1UL then XOR'ing it with 0xfff ?

Memory pages on my system are 4096 bytes which is 0xfff so that line of code is getting the address of the memory page that contains the array mya. Why you ask? The mprotect() function requires that the address past to it be aligned on a page boundary.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.