C ++使程序自行编写 [英] C++ Make a Program Write Over Itself

查看:114
本文介绍了C ++使程序自行编写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几天前,我发布了一个关于类似主题的问题和几年前的),但我决定继续着手。我试图将C ++代码注入C ++代码(以某种不使用os特定功能的可移植方式,并尝试独立于编译器/工具链)。我基本上是想这样做,以尝试运行运行时C ++脚本。我写了一个小型测试程序(实际上只是混在一起,很容易破解):Main.cpp:

I posted a question on a similar topic a couple days ago (and one a couple years ago), but I decided to go ahead and get started. I am trying to inject C++ code into C++ code (in a somewhat portable manner using no os specific features and trying to be compiler/toolchain independent manner). I basically want to do this in an attempt to do runtime C++ scripts. I wrote a small test program (its really just kinda thrown together and hacky): Main.cpp:

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <sstream>
#include <vector>
#include <tuple>

constexpr char hexmap[] = { '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

std::string HexStr( unsigned char *data, int len )
{
    std::string s( len * 2, ' ' );
    for( int i = 0; i < len; ++i ) {
        s[ 2 * i ] = hexmap[ ( data[ i ] & 0xF0 ) >> 4 ];
        s[ 2 * i + 1 ] = hexmap[ data[ i ] & 0x0F ];
    }
    return s;
}
/*I am aware there is a standard GC and that this is 
by no means production.*/
template< typename T, unsigned short ARRAY >
struct GarbageCollector
{
    std::vector< T* > ts;
    GarbageCollector() = default;
    ~GarbageCollector() {
        for( T* i : ts )
            delete i;
    }
};

template< typename T >
struct GarbageCollector< T, 1 >
{
    std::vector< T* > ts;
    GarbageCollector() = default;
    ~GarbageCollector() {
        for( T* i : ts )
            delete[] i;
    }
};


std::tuple< char*, std::streamoff > ReadBinaryBuffer( 
        std::string fileName, GarbageCollector< char, 1 >* gc )
{
    std::ifstream binaryData;
    binaryData.open( "Source.obj", std::ios::binary );
    if( binaryData.fail() ) {
        std::cerr << "Failed to open file!\n";
        return { "Failed to open file!\n", 1 };
    }
    binaryData.seekg( 0, std::ios::end );
    std::streamoff i = binaryData.tellg();
    char* buffer = new char[ i ];
    binaryData.seekg( 0, std::ios::beg );
    binaryData.read( buffer, i );
    binaryData.close();
    gc->ts.push_back( buffer );
    return { buffer, i };
}

std::string ReadBinary( std::string fileName )
{
    GarbageCollector< char, 1 > gc;
    auto result = ReadBinaryBuffer( fileName, &gc );
    std::string stringBuffer;
    stringBuffer.assign( std::get< 0 >( result ), std::get< 1 >( result ) );
    return stringBuffer;
}
std::string ReadBinary( std::tuple< char*, 
        std::streamoff > bufferContainer )
{
    std::string stringBuffer;
    stringBuffer.assign( std::get< 0 >( bufferContainer ), 
            std::get< 1 >( bufferContainer ) );
    return stringBuffer;
}
extern "C"
{
    int test() {
        return 3;
    }
    int( *cmpp )();
}
int main( int argc, char* args )
{
    cmpp = &test;
    auto binary = ReadBinary( "Source.obj" );
    auto function = binary.substr( 347, 56 );
    const char* code = function.c_str();
    std::cout << HexStr( ( unsigned char* ) ( code ), function.size() );
    //strcpy( ( char* )cmpp, ( ( char* ) code ) );
    char* testp = ( char* ) cmpp;
    char* testpp = ( char* ) code;
    for( size_t i = 0; i < 54; ++i ) {
        *testp++ = *testpp++;
    }
    cmpp();
    char close;
    std::cin >> close;
    return 0;
}

Source.cpp:

Source.cpp:

extern "C"
{
    int calc()
    {
        int q = 30 * 123;
        for( int i = 0; i < 10; ++i )
            q *= i;
        return q;
    }
}

基本上,我尝试使用malloc分配大量的内存和新的,但是我想也许我可以覆盖已经专用于进程内存的内存(这就是为什么我要让 cmpp 指向函数 test 并尝试覆盖它)。但是我收到写访问错误。我看了这篇文章和其中一个答案看来,可以覆盖程序自身的内存而不会发生访问冲突(这是我想要做的) ,误会不少。有人可以详细说明一下,并告诉我如何使用某种非标准功能(或至少一个可以被抽象化的功能)以的方式以某种可移植的方式进行此操作吗?

Basically I tried just allocating a hunk of memory with malloc and new, but I thought maybe I could overwrite memory already dedicated to process memory (which is why I have the function test pointed at by cmpp and try to overwrite it). However I get a write access error. I took a look at this post and from one of the answers seems that it is possible to overwrite the programs own memory without an access violation (which is what I want to do), by mistake no less. Could someone elaborate on this please and tell me how to do this in possible a somewhat portable manner without using any non - standard feature (or at least one that can be/is abstracted away)?

推荐答案

默认情况下,您的程序将被加载到只读存储器中,仅执行内存,不允许写入(至少在任何现代操作系统上)。不同的保护措施是出于安全原因,如果有人破坏了您的软件,他们就不能对您这样做,例如泄漏信息。

By default, your program will be loaded into read and execute only memory, no writing allowed (at least on any modern operating system). The different protections are for security reasons, if someone breaks your software, they shouldn't be able to do this to you and for example leak information.

此请求已存储在二进制文件中,由链接器完成。您可能可以更改链接器,以请求将程序加载到可写内存中,但这远非最佳,而且也不可移植。

This request is stored inside the binary and is done by the linker. You may be able to change your linker to request for your program to be loaded into writable memory, but this would be far from optimal and also not portable.

更好的方法将要求从您的操作系统(在Linux上是 mmap 等)上请求一个可执行的可写页面,但是据我所知,也没有可移植的方式来执行此操作

A better approach would be to request an executable and writable page from your operating system (mmap et al on linux), but there is no portable way to do this either as far as I am aware.

这篇关于C ++使程序自行编写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆