c 生成函数并调用它

标签 c x86 runtime code-generation

#include <stdio.h>

#define uint unsigned int
#define AddressOfLabel(sectionname,out) __asm{mov [out],offset sectionname};

void* CreateFunction(void* start,void *end) {
    uint __start=(uint)start,__end=(uint)end-1
        ,size,__func_runtime;
    void* func_runtime=malloc(size=(((__end)-(__start)))+1);
    __func_runtime=(uint)func_runtime;
    memcpy((void*)(__func_runtime),start,size);
    ((char*)func_runtime)[size]=0xC3; //ret
    return func_runtime;
}
void CallRuntimeFunction(void* address) {
    __asm {
        call address
    }
}

main() {
    void* _start,*_end;
    AddressOfLabel(__start,_start);
    AddressOfLabel(__end,_end);
    void* func = CreateFunction(_start,_end);
    CallRuntimeFunction(func); //I expected this method to print "Test"
    //but this method raised exception
    return 0;
__start:
    printf("Test");
__end:
}

CreateFunction - 在内存(函数作用域)中获取两个点,分配,将其复制到分配的内存并返回(void* 用作调用函数与组装)

CallRuntimeFunction - 运行从 CreateFunction

返回的函数

#define AddressOfLabel(sectionname,out) - 将标签 (sectionname) 的地址输出到变量 (out)

当我调试此代码并介入 CallRuntimeFunction 的调用并进行反汇编时, 我看到了很多 ??? 而不是 __start__end 标签之间的汇编代码。

我试图在两个标签之间复制机器代码,然后运行它。但是我不知道为什么我不能调用用 malloc 分配的函数。

编辑:

我更改了一些代码并完成了部分工作。 运行时函数的内存分配:

void* func_runtime=VirtualAlloc(0, size=(((__end)-(__start)))+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

从函数范围复制:

CopyMemory((void*)(__func_runtime),start,size-1);

但是当我运行这个程序时,我可以:

mov         esi,esp  
push        0E4FD14h  
call        dword ptr ds:[0E55598h] ; <--- printf ,after that I don't know what is it
add         esp,4  
cmp         esi,esp  
call        000B9DBB  ; <--- here
mov         dword ptr [ebp-198h],0  
lea         ecx,[ebp-34h]  
call        000B9C17  
mov         eax,dword ptr [ebp-198h]
jmp         000D01CB  
ret  

这里,它进入了另一个函数和奇怪的东西。

最佳答案

void CallRuntimeFunction(void* address) {
    __asm {
        call address
    }
}

这里的address是一个指向这个函数参数的“指针”,它也是一个指针。

指向指针的指针

使用:

void CallRuntimeFunction(void* address) {
_asm {
    mov ecx,[address] //we get address of "func"
    mov ecx,[ecx]   //we get "func"
    call [ecx]      //we jump func(ecx is an address. yes)
    }
}

你想调用 func,它是一个指针。当传入您的 CallRunt... 函数时,这会生成一个指向该指针的新指针。二阶指针。

void* func = CreateFunction(_start,_end);

是的,func 是一个指针

重要:检查你的编译器“调用约定”选项。试试 decl one

关于c 生成函数并调用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11739281/

相关文章:

c - 请帮助制作 strstr()

python - 使用 ctypes 在 Python 中访问 c​​_char_p_Array_256

loops - x86 LOOP指令到底如何工作?

dynamic - FORTRAN 动态分配派生类型

c - 需要解释一下这段代码是如何工作的

c++ - SetConsoleMode() 和 ENABLE_VIRTUAL_TERMINAL_PROCESSING?

x86 - .align 指令有什么作用?

c - 优化简单的模具操作,将变量保存在寄存器中

iPhone:如何在 tabelview 加载后在 tableview 中添加行?

c - 指定行运行次数的边界函数 (Big-O) 是多少? (C)