【问题标题】:Call a function with its parameters from a stack frame based on EBP in c在 c 中基于 EBP 从堆栈帧调用带有参数的函数
【发布时间】:2016-10-27 20:59:30
【问题描述】:

我已经阅读了Extended Asm - Assembler Instructions with C Expression OperandsA side-by-side look at GNU Assembler (GAS) and Netwide Assembler (NASM),但是有些问题还不能解决。

好吧,我动态设计了一段代码。

; int xx_method_stub(void *fix_arg1, void* fix_arg2, void* arg3)
push  ebp                   ; 55
mov   ebp, esp              ; 89 E5
sub   esp, imm8_local_size  ; 83 EC imm8_local_size
mov   [ebp-4], imm_ptr_mid  ; C7 45 FC imm_ptr_mid
jmp   rel16_offset          ; E9 rel16_offset

查看详情here,可能有点过头了。

现在它跳转到一个精心设计的地址,栈帧上下文如下:

16(%ebp)  - third function parameter
12(%ebp)  - second function parameter
 8(%ebp)  - first function parameter
 4(%ebp)  - old %EIP (the function's "return address")
 0(%ebp)  - old %EBP (previous function's base pointer)
-4(%ebp)  - first local variable

到目前为止,我需要c 中的 jmp 标签代码。

void stubthunk_init(stubthunk *stub, mid_t mid) {
    memcpy(stub, &stubthunk_templet, sizeof(stubthunk));
    stub->ph_mid = mid;
    stub->ph_eip_to_dispatch = (int) ((uintptr_t) dispatch - ((uintptr_t) stub + sizeof(stubthunk)));

// TODO retrieve stack variables as c-syntax local variables to make a function call in c for for portability.
//stack frame context
void *param_1; // 8(%%ebp)
void* param_2; //12(%%ebp)
void* local_1; //-4(%%ebp)

    disp:

#ifdef _MSC_VER
    __asm {
        mov param_1 [ebp+8]
        mov param_2 [ebp+12]
        mov local_1 [ebp-4]
    }
#else
    __asm__ __volatile(
        "mov 8(%%ebp), %0\n\t"
        "mov 12(%%ebp), %1\n\t"
        "mov -4(%%ebp), %2\n\t"
        :"=m" (param_1), "=m" (param_2), "=m" (local_1)
        :
        : /* clobbered register.  */
    );
#endif
    //USE #param_1 to restore or blance the stack
}

所以

有没有办法得到它 get jmp code block in c 并检索堆栈变量作为 c 语法局部变量以在 c 中进行函数调用,这样我就不会必须在asm 中编写更多代码,在这种情况下,无论函数调用约定如何,编译器都会帮助我解决诸如 arm、x86、x64、...

我希望我可以自己设置函数prologue 的堆栈框架和c 中的结语。通过这种方式,我可以将一个函数改造成一个 jmp 代码块,并以我自己的方式手动平衡堆栈。

或者,就像在 masm 中一样,有一个伪指令 invoke,例如invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK,但它只存在于masm中。

=========已更新===========

我的目标:

static native int foo(int otherArgsMaybeExist);
int stdcall Java_xx_foo(void *fixedArgEnv, void *fixedArgCls, jint otherArgsMaybeExist){
    return 0;
}

// TODO release stubthunk *stub
stubthunk *stub = (stubthunk*) alloc_code(sizeof(stubthunk));
stubthunk_init(stub, (intptr_t) argsize);

现在,我在内存中动态创建一个stdcall函数启动代码,它 除了一些必要的数据外,应该尽可能少(这里传递一个jmethodID,以便让关注的interpret_stdcall_x86知道谁被调用)。

stub 注册一个带有 native 修饰符的 java 方法并进入本地世界后,它将进入我的代码。实际上,它就像 Windows 上的 Detours 一样的蹦床。

跳转后,所有被拦截的方法都会进入interpret_stdcall_x86, 负责堆栈平衡。

原来是这样的:

foo -> Java_xx_foo -> return

现在,会是这样的:

foo -> stubthunk + interpret_stdcall_x86 + blance the stack -> return

这里,thubthunk 是硬编码,但使用指令动态创建。然而,我希望我可以使用 c 为interpret_stdcall_x86 进行编码。

============================

【问题讨论】:

  • jmp rel16_offset???在 32 位或 64 位代码中,您唯一的选择是 rel8 and rel32。当然,汇编程序会为您处理这些。使用操作数大小的前缀来获取 rel16 编码也会用 0x0000FFFF 屏蔽 EIP。
  • 所以你正试图从 asm 跳转到 C 函数的中间?完全不清楚使用 asm 获得了什么。为什么你不能在 C 中编写一个包装函数来操作 args 并调用另一个函数?或者从 asm,通过它的正常入口点尾调用一个 C 函数(根据调用约定,args 在它们通常的位置)。
  • 我不是 100% 清楚您在寻找什么,但 GCC's builtins for constructing function calls 似乎它们可能是相关的。
  • 有帮助~我下次试试。

标签: c gcc assembly x86


【解决方案1】:

如果你想在函数体内放置一个跳转目标,你可以使用asm volatile (".globl my_label\n" "my_label:" );并从asm跳转到那里。

不过,您不应该期望这会起作用。

编译器选择如何构建堆栈帧将取决于优化级别和内联,因此没有安全的方法来编写与您想要跳转到的任何函数的结尾相匹配的 asm。


不清楚这一切的目的是什么,以及为什么不能只用 C 来做。


您显示的 inline-asm 已损坏:

__asm__ __volatile(
    "mov 8(%%ebp), %0\n\t"   // mov mem,mem  isn't valid.
    "mov 12(%%ebp), %1\n\t"
    "mov -4(%%ebp), %2\n\t"
    :"=m" (param_1), "=m" (param_2), "=m" (local_1)
     // instead, use "=r" constraints to have the outputs in registers
     // from there, the compiler will put them where it wants them
    :
    : /* clobbered register.  */
);

我不明白自己从内联 asm 的堆栈中加载 args 有什么意义。为什么不直接使用函数 args 以便编译器知道发生了什么?

【讨论】:

  • 确实,你是对的。我只是忍不住期待一个 c 局部变量可以附加一个寄存器或堆栈,然后分离。
  • 因为有多个文件,所以我创建了一个github测试repository,而ideone做不到。
猜你喜欢
  • 2014-01-08
  • 2011-06-23
  • 2011-03-26
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
  • 2013-10-12
  • 2011-11-12
  • 1970-01-01
相关资源
最近更新 更多