C-运行时代码可以在两次执行之间更改吗?

时间:2018-08-23 00:55:01

标签: c security runtime function-pointers

我正在学习有关软件防篡改的知识,我想开始做一些实验。这就是其中之一。

撇开未定义的行为,我有这个程序:

#include <stdio.h>

void test();

int main() {
    // Code doing all kind of things like calling functions,
    // accessing global variables, calling things from .so's, etc...

    for (int i = 0; i < ((char *)test) - ((char *)main); ++i) {
        printf("%c", ((char *)main)[i]);
    }

    printf("\n");
    return 0;
}

void test() {
}

我做了一些实验,它总是在我的mac机上打印相同的字符串:

����H)�HcM�H9��.H�=kH�����HcM����5�E�E���E�����H�=@��1ɉE��H��]�`

运行时代码可以在两次执行之间更改吗?

请注意,我问的是RAM中的运行时代码,而不是程序文件中的映像代码。

我怀疑是在执行之间,加载器可能会根据进程内存位置或类似的内容使运行时代码不同。

2 个答案:

答案 0 :(得分:0)

程序的可执行指令存储在目标文件的代码段部分中。

来自wiki

  

当加载程序将程序放入内存中以便可以执行时,会分配各种存储区域(尤其是页面),分别对应于目标文件中的两个段以及仅在运行时所需的段。 目标文件的代码段已加载到内存中的相应代码段中。

     

内存中的代码段通常为只读,并且具有固定的大小,因此在嵌入式系统上,通常可以将其放置在只读内存(ROM)中 ...

     

如果代码段为非只读,则特定的体系结构允许自修改代码

因此,除非您的程序由self-modifying code组成(某些语言(如PERL或Python允许)),否则您不必担心每次运行该程序都会执行不同的代码。

答案 1 :(得分:0)

SELECT DATEDIFF(MILLISECOND, [Time], LEAD([Time], 1, null) OVER (ORDER BY [Time])) AS interval, result FROM Data 这会调用未定义的行为,您不能从函数指针强制转换为对象指针。与(char *)test中的演员表相同。任何事情都可能发生,包括程序崩溃或任何形式的行为。

两个不指向同一数组的指针之间的指针算术也会调用未定义的行为。因此,该程序的结果是完全不可预测的。

您需要使用main而不是uintptr_t-仍然不能保证它可以保存地址,但是至少不会有错误。而且您必须对char*进行减法运算,而不要对指针类型进行减法运算。

像对待数据一样访问程序的代码段,可能会在某些系统上引发硬件异常。

除上述内容外,如果您不更改代码,则没有理由在执行之间更改二进制文件。许多操作系统上都有ASLR,因此绝对地址可能会更改。