如何在运行前更改主函数的参数

时间:2019-06-20 03:12:15

标签: c compiler-construction main

在下面的代码中,我想更改main函数的参数而不修改main函数。

最近,我阅读了AFL模糊工具的代码,对于forkserver,我不了解如何将参数传递给目标程序,因此我编写了这个简单程序。

我尝试使用管道重定向标准输入并将参数写入标准输入,但这不起作用。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

__attribute__((constructor))
void __start() {
    static unsigned char tmp[4];
    int count = 0;
    pid_t pid;
    int status;
    while(count < 3){
        pid = fork();
        if(pid < 0) _exit(1);
        if(!pid){
            //how to pass "hello" to main without modfiying main function.
            return;
        }

        count++;
        if(count == 3) _exit(1);
    }
    //_exit(0);

}

int main(int argc, char** argv){
  for(int i = 0; i < argc; i++){
    printf("%d %s\n", i, argv[i]);
  }
  return 0;
}

如果argv中为“ hello”,则argc应该为2,输出应为“ 1 hello”。

1 个答案:

答案 0 :(得分:1)

在调用C int argc方法之前,在 之前修改C运行时环境的int main(int argc, char **argv)参数计数器。 。 。 ---= = =(; NASTY HACK;)= = =--- 。


我正在使用:

  • 当前可用于OS X High Sierra的最新C ++编译器,
  • 使用brew安装了当前标准方式。

要在argc.cpp代码清单下重现结果,请执行以下操作之一:


argc.cpp:

    #include <stdio.h>

    __attribute__((constructor)) void start(int argc, char **argv)
    {
        int * pc = (int *) argv - 2; // NASTY HACK TO GET C RUNTIME argc * ;)
        printf("argc = %d \n", *pc); // the original argc, on most systems ;)
        int NUMBER_OF_PARAMETERS_NEEDED_FOR_FUZZING = 1; // Replace this line 
        // with the simple/complex logic needed for fuzz testing (fuzzing)
        if(!(argc > NUMBER_OF_PARAMETERS_NEEDED_FOR_FUZZING)){ 
            argc = NUMBER_OF_PARAMETERS_NEEDED_FOR_FUZZING + 1;
            *pc = argc; // NASTY HACK TO OVERWRITE C RUNTIME argc ;)
        } 
        // *pc = 2; // uncomment this to see that you can also reduce argc
        argv[1] = "hello"; // Example setting of a fuzzy argument
        // Add more lines, a loop, etc... here to set more fuzzy arguments 
        for (int i = 0; i < argc; i++) {
            printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
        }
        printf("argc = %d \n", argc); // the possibly modified argc
    }

    int main(int argc, char **argv)
    {
        for (int i = 0; i < argc; i++) {
            printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
        }
        printf("argc = %d \n", argc); // the possibly modified argc
        return 0;
    }

Mac OS终端:


编译:

    $ /usr/local/bin/c++-9 argc.cpp -o argc

运行,带有0个参数,原始参数int argc = 1

    $ ./argc
    argc = 1 
    start: argv[0] = './argc'
    start: argv[1] = 'hello'
    argc = 2 
    main: argv[0] = './argc'
    main: argv[1] = 'hello'
    argc = 2 

运行,带有3个参数,原始参数int argc = 4

    $ ./argc 1 2 3
    argc = 4 
    start: argv[0] = './argc'
    start: argv[1] = 'hello'
    start: argv[2] = '2'
    start: argv[3] = '3'
    argc = 4 
    main: argv[0] = './argc'
    main: argv[1] = 'hello'
    main: argv[2] = '2'
    main: argv[3] = '3'
    argc = 4 

运行,以演示减少argc的功能

  • 取消注释第13行并重新编译(对argc = 2进行硬编码):
        *pc = 2; // uncomment this to see that you can also reduce argc

具有与上面相同的3参数,原始int argc = 4

    $ ./argc 1 2 3
    argc = 4 
    start: argv[0] = './argc'
    start: argv[1] = 'hello'
    start: argv[2] = '2'
    start: argv[3] = '3'
    argc = 4 
    main: argv[0] = './argc'
    main: argv[1] = 'hello'
    argc = 2 

如果 C Runtime Environment 在您的系统上未未初始化,则类似于清单

您可能需要:

  • 通过将您的本地 C运行时环境与上面的GNU示例进行比较,来研究差异,和/或
  • 通过实验修改我的代码,直到它对您有用为止。例如:在 之前以及 !after! 的位置分别指针argv和看看你在那里找到了什么...

如果发现对当前的 C运行时环境进行黑客攻击太难了,请尝试:


以下是这种黑客行为的方式/原因:

  1. 适用于您的设置的C Runtime Environment函数(有多种可能)将int argc, char **argv, char **envp参数保存在某些存储位置-幸运的是,在我的设置中这些参数是相邻的。
  2. 在我的64 bit系统上,由于内存对齐规则,int argc地址比sizeof(int)指向的内存仅多了char **argv个,这就是为什么- 2行中的int * pc = (int *) argv - 2;不是- 1

╦ ╦  ╔═╗  ╔═╗  ╔═╗  ╦ ╦       ╦ ╦  ╔═╗  ╔═╗  ╦╔═  ╦  ╔╗╔  ╔═╗ ╦ ╦ ╦
╠═╣  ╠═╣  ╠═╝  ╠═╝  ╚╦╝  ───  ╠═╣  ╠═╣  ║    ╠╩╗  ║  ║║║  ║ ╦ ║ ║ ║
╩ ╩  ╩ ╩  ╩    ╩     ╩        ╩ ╩  ╩ ╩  ╚═╝  ╩ ╩  ╩  ╝╚╝  ╚═╝ o o o