Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在不创建新流程的情况下运行汇编代码?_C++_C_Assembly_Native Code - Fatal编程技术网

C++ 如何在不创建新流程的情况下运行汇编代码?

C++ 如何在不创建新流程的情况下运行汇编代码?,c++,c,assembly,native-code,C++,C,Assembly,Native Code,该文件包含本机程序集代码,我希望在当前进程中运行它。 但我不想创建真正的文件(.com或.exe),因此我尝试: ... using namespace std; typedef void bitcode(); void testcode(){ cout<<"test"; }; int main() { bitcode *c=&testcode; // bitcode *c stands for the file containing the assembly

该文件包含本机程序集代码,我希望在当前进程中运行它。 但我不想创建真正的文件(.com或.exe),因此我尝试:

...
using namespace std;
typedef void bitcode();
void testcode(){
    cout<<"test";
};
int main()
{
    bitcode *c=&testcode; // bitcode *c stands for the file containing the assembly code.
    bitcode *d=reinterpret_cast<bitcode*> (malloc(20));
    memcpy(d, c, 20);
    d(); // it doesn't work
    return 0;
};
。。。
使用名称空间std;
typedef void位码();
void testcode(){

cout您需要映射一个可写页面,将代码写入该页面,将该页面切换为可执行页面,然后执行它。

我不确定,但您是否在寻找asm关键字

更多信息,请访问:

伊格纳西奥已经描述了如何做这件事的大致轮廓

由于您使用的是Windows,因此此操作所需的函数不是
malloc
,特别是带有获取写入内存和执行内存权限的标志

然后,根据文档,您仍然需要在写入内存之后和执行之前使用显式设置执行标志

最后,在使用内存后,您需要使用来释放它,而不是
free

std::size_t size = 20;
void* mem = VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
// Write assembly opcodes to mem

DWORD old_protect;
VirtualProtect(mem, size, PAGE_EXECUTE_READWRITE, &old_protect);
typedef (void)(*fptr)();
fptr f = *reinterpret_cast<fptr*>(&mem);

f();

// Later …
VirtualFree(mem, 0, MEM_RELEASE);
std::size\u t size=20;
void*mem=VirtualAlloc(空ptr、大小、mem_COMMIT、mem_RESERVE、PAGE_EXECUTE_READWRITE);
//将程序集操作码写入mem
德沃德·奥尔德·保护者;
虚拟保护(内存、大小、页面执行、读写和旧保护);
类型定义(无效)(*fptr)();
fptr f=*重新解释铸件(&mem);
f();
//后来…
VirtualFree(mem,0,mem_发布);
<>注意在代码< ReCurtTyCase< /Cord>中添加间接的内容。这是避免不确定行为的必要条件:C++不允许在对象指针和函数指针之间进行转换。但是,上面的代码是实现定义的,因此,就C++而言,是可以的。 此外,请注意,为了保持简单,我省略了上面的错误检查代码。您不能在实际代码中执行此操作。有关正确错误处理的信息,请参阅文档


在Linux上,工作流是类似的,只是对函数使用了不同的名称。

。因为您也询问了Linux
在这里,您可以使用
mmap

例如:

foo.cpp

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <assert.h>

void bar(int n) { printf("bar invoked: %d\n", n); }
typedef void(*fp_bar)(int);

typedef union
{
   unsigned char*   pb;
   void*            pv;
   void(*pf)();
} 
foocodes;

//some _unencrypted random foo code segment
const unsigned char ar_foos[]=
{
    0xbb,0x00,0x00,0x00,0x00,   //mov ebx addy of a function to invoke
    0xb8,0x0d,0x00,0x00,0x00,   //mov eax 13 ~int input arg 
    0x50,                       //push eax
    0xff,0xd3,                  //call absolute addy ebx
    0x5b,                       //pop
    0x90,                       //throw in a nop to make up 16 foos
    0xC3                        //return
};


int main()
{
    size_t foos_size=sizeof ar_foos;
    foocodes ufoos;
    fp_bar pbar=&bar;
    assert(4==sizeof pbar); //example requires a 32bit fn address

    ufoos.pv=mmap(
        NULL, 
        foos_size, 
        PROT_WRITE|PROT_EXEC, 
        MAP_PRIVATE|MAP_ANONYMOUS,
        -1, 
        0);

    memcpy(ufoos.pv, ar_foos, foos_size);    
    memcpy(ufoos.pb+1, &pbar, sizeof pbar); //poke in the bar fn address

    ufoos.pf(); //invoke foo codes

    return munmap(ufoos.pv, foos_size);    
}

(;ook,为了清晰起见,我还省略了错误处理;)

在windows上,这是我以前编写的代码。至少在我的机器上,它可以在Win7+VS2010上工作

基本思想是调用VirtualAlloc来分配带有PAGE_EXECUTE_READWRITE标志的内存。 并以正确的方式调用它,即保持堆栈平衡

#include "stdafx.h"
#include "windows.h"


int emitcode[] = 
{0x83ec8b55,0x565340ec,0x0c758b57,0x8b087d8b,
 0x348d104d,0xcf3c8dce,0x6f0fd9f7,0x6f0fce04,
 0x0f08ce4c,0x10ce546f,0xce5c6f0f,0x646f0f18,
 0x6f0f20ce,0x0f28ce6c,0x30ce746f,0xce7c6f0f,
 0x04e70f38,0x4ce70fcf,0xe70f08cf,0x0f10cf54,
 0x18cf5ce7,0xcf64e70f,0x6ce70f20,0xe70f28cf,
 0x0f30cf74,0x38cf7ce7,0x7508c183,0xf8ae0fad,
 0x5e5f770f,0x5de58b5b,0xccccccc3};

int _tmain(int argc, _TCHAR* argv[])
{
    int *src = new int[64];
    int *dst = new int[64];
    int *dst2 = new int[64];

    for (int i = 0; i < 64; ++i){
        src[i] = i;
    }

    //fastercopy(dst,src, 64/2);

    void* address = NULL;
    address= VirtualAlloc(NULL,
            sizeof(emitcode),
            MEM_COMMIT|MEM_RESERVE,
            PAGE_EXECUTE_READWRITE);

    memcpy(address,emitcode,sizeof(emitcode));

    //call emit code from assemble
    __asm {
      push        20h  
      mov         eax,dword ptr [src]  
      push        eax  
      mov         ecx,dword ptr [dst]  
      push        ecx
      mov         ecx, dword ptr [address]
      call        ecx
      add         esp,0Ch 
    }

    for (int i = 0; i < 64; ++i){
        printf("%d ",dst[i]);
    }

    //call emit code from function pointer
    typedef void (*FASTCALL)(void* dst, void* src, int len);
    FASTCALL fastcall;
    fastcall = (FASTCALL)address;
    fastcall(dst2,src,64/2);

    printf("\n");
    for (int i = 0; i < 64; ++i){
        printf("%d ",dst2[i]);
    }

    return 0;
}
#包括“stdafx.h”
#包括“windows.h”
int emitcode[]=
{0x83ec8b55,0x565340ec,0x0c758b57,0x8b087d8b,
0x348d104d、0xcf3c8dce、0x6f0fd9f7、0x6f0fce04、,
0x0f08ce4c、0x10ce546f、0xce5c6f0f、0x646f0f18、,
0x6f0f20ce、0x0f28ce6c、0x30ce746f、0xce7c6f0f、,
0x04e70f38、0x4ce70fcf、0xe70f08cf、0x0f10cf54、,
0x18cf5ce7、0xcf64e70f、0x6ce70f20、0xe70f28cf、,
0x0f30cf74,0x38cf7ce7,0x7508c183,0xf8ae0fad,
0x5e5f770f,0x5de58b5b,0xCCC3};
int _tmain(int argc,_TCHAR*argv[]
{
int*src=newint[64];
int*dst=新的int[64];
int*dst2=新int[64];
对于(int i=0;i<64;++i){
src[i]=i;
}
//快速复印(dst、src,64/2);
void*地址=NULL;
地址=VirtualAlloc(空,
sizeof(代码),
记住承诺,记住保留,
页面(执行、读写);
memcpy(地址、emitcode、sizeof(emitcode));
//从汇编中调用emit代码
__asm{
推20小时
mov eax,dword ptr[src]
推送eax
mov ecx,dword ptr[dst]
推ecx
mov ecx,dword ptr[地址]
打电话给ecx
添加esp,0Ch
}
对于(int i=0;i<64;++i){
printf(“%d”,dst[i]);
}
//从函数指针调用emit代码
typedef void(*FASTCALL)(void*dst,void*src,int len);
快速呼叫;
fastcall=(fastcall)地址;
快速呼叫(dst2,src,64/2);
printf(“\n”);
对于(int i=0;i<64;++i){
printf(“%d”,dst2[i]);
}
返回0;
}

你的意思是我应该尽量避免使用DEP吗?你能详细告诉我怎么做吗?非常感谢!请注意,尽管这样做有很多好处…看看这些::似乎内联程序集应该放在C/CPP源文件中,并编译到.com或.exe中,但当进程正在运行。当您说“本机程序集代码”,您是指像
xchg eax、eax
这样的汇编指令,还是像
0x90
这样的汇编机器代码?后者是像
0x90
@linzuzeng这样的汇编机器代码,请查看更新。显然需要
VirtualProtect
,即使权限相同。此外,请确保分配的大小和tect实际上对于您要执行的整个程序集代码来说已经足够大了,否则执行只会尝试在受保护区域之外继续。还要注意我的代码的其他更改–我应该更仔细地阅读文档。@harold是的,这就是问题所在:显然,它有时甚至在参数错误的情况下也能工作s、 例如,
VirtualProtect
的最后一个参数不能为null。然而,我知道使用null作为其最后一个值的代码(不是我的),并且多年来一直如此,没有任何问题。除了汇编指令代码之外,如何做同样的事情?例如,emitcode是一个文本:move ax,add bx,…等等
#include "stdafx.h"
#include "windows.h"


int emitcode[] = 
{0x83ec8b55,0x565340ec,0x0c758b57,0x8b087d8b,
 0x348d104d,0xcf3c8dce,0x6f0fd9f7,0x6f0fce04,
 0x0f08ce4c,0x10ce546f,0xce5c6f0f,0x646f0f18,
 0x6f0f20ce,0x0f28ce6c,0x30ce746f,0xce7c6f0f,
 0x04e70f38,0x4ce70fcf,0xe70f08cf,0x0f10cf54,
 0x18cf5ce7,0xcf64e70f,0x6ce70f20,0xe70f28cf,
 0x0f30cf74,0x38cf7ce7,0x7508c183,0xf8ae0fad,
 0x5e5f770f,0x5de58b5b,0xccccccc3};

int _tmain(int argc, _TCHAR* argv[])
{
    int *src = new int[64];
    int *dst = new int[64];
    int *dst2 = new int[64];

    for (int i = 0; i < 64; ++i){
        src[i] = i;
    }

    //fastercopy(dst,src, 64/2);

    void* address = NULL;
    address= VirtualAlloc(NULL,
            sizeof(emitcode),
            MEM_COMMIT|MEM_RESERVE,
            PAGE_EXECUTE_READWRITE);

    memcpy(address,emitcode,sizeof(emitcode));

    //call emit code from assemble
    __asm {
      push        20h  
      mov         eax,dword ptr [src]  
      push        eax  
      mov         ecx,dword ptr [dst]  
      push        ecx
      mov         ecx, dword ptr [address]
      call        ecx
      add         esp,0Ch 
    }

    for (int i = 0; i < 64; ++i){
        printf("%d ",dst[i]);
    }

    //call emit code from function pointer
    typedef void (*FASTCALL)(void* dst, void* src, int len);
    FASTCALL fastcall;
    fastcall = (FASTCALL)address;
    fastcall(dst2,src,64/2);

    printf("\n");
    for (int i = 0; i < 64; ++i){
        printf("%d ",dst2[i]);
    }

    return 0;
}