C如何存储函数以及它何时转换为机器代码?

How does C store functions and when does it convert to machine code?

所以我最近问了这个

我必须创建一个环境变量 MYENV 并在其中存储一些东西,这样我才能成功 运行 这段代码。

#include <stdio.h>
#include <stdlib.h>

int main(){
            int (*func)();
            func = getenv("MYENV");
            func();
}

早些时候我在做类似 export MYENV=ls 的事情。

用户指出的是不正确的,因为当调用 func() 时,它基本上告诉 C 运行 存储在变量 func 中的指令,这将是字符串 ls 并且不是正确的机器代码。所以我应该传递一些 shellcode。

现在我想知道这是否适用于一般功能。当我声明一个函数时,让我们说 myFunction() ,让我们说乘以 10099 和 returns 的值,然后变量 myFunction 将指向一组存储在某处的机器指令,它将 10099 和 returns 的值相乘。

如果我要找出那些机器指令并将它们存储在一个字符串中并使 myFunction 指向它,然后如果我调用 myFunction() 我们将得到 9900 回来了?

这就是我的意思:

int (*myFunc)();
char *var = <machine_instructions_in_string_format>
int returnVar = myFunc();

returnVar 会有 9900 吗?

如果是,我如何找出该字符串是什么?

我很难理解这个问题。

您必须使用目标机器的操作码填充环境变量。我做了一个小实验:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
        int (*f)();
        f = getenv("VIRUS");
        (*f)();
        printf("Haha, it returned\n");
        return 0;
}

我编译了它,然后使用execstack:

$ cc ge.c
$ execstack -s ./a.out

然后我写了一点汇编:

mov %rbp, %rsp
pop %rbp
ret

模仿函数结尾。编译它:

$ cc -c t.s

查看操作码:

$ objdump -D t.o
...
   0:   48 89 ec                mov    %rbp,%rsp
   3:   5d                      pop    %rbp
   4:   c3                      retq   

设置环境变量:

$ export VIRUS=$(printf "\x48\x89\xec\x5d\xc3")

然后运行程序:

$ ./a.out

它什么也没说,这清楚地表明 printf 行被跳过了。但是,为了检查,我尝试了:

$ export VIRUS=$(printf "\xc3")
$ ./a.out
Haha, it returned

这是 运行 在 ubuntu-18.04 上使用 amd64 指令集。如果这恰好是一项学校作业,您应该以加分为目标并弄清楚如何让它执行包含空 (0) 字节的操作码。