C语言 修改代码以在f2中使用asm打印A而不是BA

ibps3vxo  于 2023-04-19  发布在  其他
关注(0)|答案(1)|浏览(95)
#include <stdio.h>
void f2(){}//no code
void f1(){
    int b=3,c=7;
    c=b+c;
    f2();//f2 call
    printf("B\n");
}
int main (void) {
    int a=3;
    a=a+1;
    f1();//f1 call
    printf("A\n");
    return 0;
}

在f2函数中编写一段代码,它将改变上述C程序的控制。根据上面的代码,控制从main函数转到f1函数,f1到f2,然后再从f2返回到f1,f1到main。但是,你只需要在f2函数中编写一些代码,这将直接将你的控制从f2移动到main,因此输出将仅为“A”而不是“BA”。F1函数在执行期间不能被多次调用。您不能修改f1和main函数。您不能在f2函数中编写任何类似printf语句(无论是在C还是在汇编中)。输出“A”应仅从main函数打印
我无法解决,也不知道该怎么做。

m1m5dgzv

m1m5dgzv1#

您可以通过不返回f1(或main)来实现这一点。只需执行main * 会执行的操作,然后退出:

void f2() {
    printf("A\n");
    exit(0);
}

不幸的是,这违反了“A必须仅由main函数输出”的要求,所以你 * 将 * 必须有一些严肃的内部知识,并执行堆栈操作。这是有风险的,而且令人难以置信的不可移植。
这个想法是分析在退出f1之前堆栈指针的值,并将代码放入f2中,将其设置为该值。这样,当退出f2时,返回点将位于main而不是f1
它可以像这样简单:

void f2() {
    asm "load sp <value>"
}

其中<value>是需要计算的值。
请注意,asm代码也需要根据您的环境进行定制。由于您没有提供CPU架构(或其他具体细节),因此我使用了上面的神话CPU,带有load指令和sp寄存器。
假设你的f2编译代码看起来像这样(注解是我添加的):

f2:     push    rbp                     ; prolog stack frame set up.
        mov     rbp, rsp

        ;; Point 1

        mov     rsp, rbp                ; epilog.
        pop     rbp
        ret

f1看起来像:

b_str:  .string "B\n"
f1:     push    rbp                     ; prolog stack frame set up.
        mov     rbp, rsp
        sub     rsp, 16                 ; allocate space for locals.

        mov     DWORD PTR [rbp-4], 3    ; store values for b and c.
        mov     DWORD PTR [rbp-8], 7

        mov     eax, DWORD PTR [rbp-4]  ; add b to c.
        add     DWORD PTR [rbp-8], eax

        mov     eax, 0                  ; make call to f2().
        call    f2

        mov     edi, OFFSET FLAT:b_str  ; printf "B\n").
        call    printf

        ;; Point 2

        mov     rsp, rbp                ; epilog.
        pop     rbp
        ret

你需要做的是在点1放置一些东西,这样它就会像在点2一样返回。在这段代码中,可以通过向rbp添加一个值来实现,正好足够回退:

  • call f2推送的返回值;和
  • push rbpf2的开始。

我还没有做过深入的分析来确认这是要添加的正确值,但它给了你基本的想法。无论如何,它可能需要根据你的情况进行定制,因为它取决于编译器,调用约定,CPU选择,优化级别等因素。

相关问题