【发布时间】:2020-09-27 16:48:17
【问题描述】:
所以我最近问了这个question
我必须创建一个环境变量 MYENV 并在其中存储一些内容,以便我可以成功运行此代码。
#include <stdio.h>
#include <stdlib.h>
int main(){
int (*func)();
func = getenv("MYENV");
func();
}
之前我在做类似export MYENV=ls的事情。
用户指出的不正确,因为调用 func() 时,它基本上告诉 C 运行存储在变量 func 中的指令,该变量将是字符串 ls,并且不是正确的机器代码。所以我应该传递一些 shellcode。
现在我想知道这是否适用于一般功能。当我声明一个函数时,假设myFunction() 确实让我们说将100 和99 相乘并返回值,然后变量myFunction 将指向存储在某处的一组机器指令乘以100和99 并返回值。
如果我要找出那些机器指令并将它们存储在一个字符串中并让myFunction指向它,然后如果我调用myFunction(),我们将返回9900?
这就是我的意思:
int (*myFunc)();
char *var = <machine_instructions_in_string_format>
int returnVar = myFunc();
returnVar 会有 9900 吗?
如果是,我如何确定那个字符串是什么?
我很难理解这一点。
【问题讨论】:
-
一般来说不是。但是,它可能适用于某些平台,但根据 C 标准它是 UB。在通用平台上,您必须至少使包含代码的页面可执行(即在 unixish 系统上使用
mprotect())。 -
您可以通过编译一个执行您想要的程序的程序,然后查看生成的机器代码来“找出字符串是什么”。
-
@Barmar:更正:编译一个函数,而不是整个程序。例如How to remove "noise" from GCC/clang assembly output? / How to disassemble one single function using objdump?
-
ls不是一个函数,而是一个命令。qsort是标准 C 函数 -
作为更一般的说明,编译语言通常在代码(在 C 中:函数)和数据(在 C 中:变量,包括数组)之间有很强的区别。在现代系统上,程序不能自我修改,尽管这很酷;它不能执行数据(除非你跳过上面链接中的箍)。比如说,在 1970 年代,两者都更容易实现,有时也得到了很好的利用。但总的来说,您会为此使用解释型语言,其中一些 (Lisp) 根本没有这种区别。