首页 > 解决方案 > 汇编指令修改被调用函数内的返回地址

问题描述

我对汇编程序很陌生,但我仍然不知道大部分指令。

我正在尝试向 C 程序添加一些 asm 行(只是为了好玩,玩弄它)来修改函数的返回地址。

C代码看起来像

int my_function()
{
    int my_number = 1;

    __asm__ ("nop"); 
    __asm__ ("nop"); 

    return my_number;
}

int main(int argc, char *argv[])
{
    //declarations

    ...lots of stuff

    int my_number = my_function();

    do_something;

    ...lots of stuff

    do_other_thing;

    ... lots of stuff (46 bits in assembler)

    return 0;
}

所以,我尝试做的是修改堆栈中的返回地址,my_function所以,当返回时,它会去do_other_thing而不是去do_something

为了使它更好,动态地,我不喜欢硬编码返回地址,所以我想添加那些 46 位。我也知道退货地址在EBP + 4. 我已经在 内手动测试了它x32dgb,它可以工作。

我想我将不得不:

  1. 获取 EBP + 4 指向的内容(可能在 EAX 中)
  2. 总和 46 到 EAX
  3. 将此值写回 EBP + 4

到目前为止我已经理解了,但不知道如何将它编码成 ASM 语句......

你能帮帮我吗?

标签: assemblyx8632-bit

解决方案


我正在尝试向 C 程序添加一些 asm 行(只是为了好玩,玩弄它)来修改函数的返回地址。

不。

对于用 C 编写的代码;编译器拥有堆栈,编译器生成适合自身及其优化的函数启动代码,编译器生成退出代码以适合自己的启动代码。任何对堆栈布局做出任何假设的内联汇编都是“脆弱的”——任何地方的微小变化(甚至只是更改一个无辜的局部变量、更改编译器命令行参数或将编译器更新到下一个版本)都可能并最终导致堆栈布局的差异将破坏内联汇编。在实践中它实际上比这更糟糕 - 编译器可以并且将生成同一“C函数”的多个不同版本(并将某些版本内联到其他函数中以避免函数调用的成本等),这样您最终会得到相同的内联程序集,它正在尝试(并保证会失败)处理多个完全不同的堆栈布局;即使您确实成功地返回了其他地方,您也无法可靠地避免在函数返回后搞砸一切。

另一个问题是,几乎从来没有一个理智的理由想要首先这样做。即使您正在编写可以完全控制堆栈布局的汇编语言(而不是使用无法控制堆栈布局的内联汇编语言编写 C)。

本质上; 对于试图学习汇编以花时间学习的人来说,有很多事情更重要(这些事情不是“脆弱的”,也不是没用的)。这就像学习如何用手站立驾驶汽车(用你的脸在加速器/制动踏板上并且看不到你周围的任何东西) - 它没有用。


推荐阅读