In the following code, I want to change the arguments of main function without modifying main function.
Recently, I read the code of AFL fuzzing tool, for the forkserver, I do not understand how to pass the parameters to the target program, so I write this simple program.
I have tried to use pipe to redirect stdin and write parameters to stdin, but it does not work.
#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;
}
If "hello" in argv, argc should be 2 and the output should have "1 hello".
int argc
argument counter before the C int main(int argc, char **argv)
method is called. . . - - - = = = (; A NASTY HACK ;) = = = - - - . . .I am using:
brew
.To reproduce the results below argc.cpp
code listing, either:
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;
}
Compilation:
$ /usr/local/bin/c++-9 argc.cpp -o argc
Running with 0
arguments, original 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
Running with 3
arguments, original 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
Running , to demonstrate argc
reduction capability,
argc = 2
) : *pc = 2; // uncomment this to see that you can also reduce argc
with the same 3
arguments, as above, original 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
If the C Runtime Environment is not initialized on your system similar to the listing:
you may need to either:
argv
and see what you find there...If you find hacking your current C Runtime Environment too hard, try to:
C Runtime Environment
function applicable for your setup (there are multiple possibilities) saves the int argc, char **argv, char **envp
arguments in some memory locations - these are luckily adjacent in case of my setup.64 bit
system, due to memory alignment rules the int argc
address would be just 1 extra sizeof(int)
ahead of the memory pointed to by char **argv
, that is why the - 2
in the: int * pc = (int *) argv - 2;
line is not - 1
.╦ ╦ ╔═╗ ╔═╗ ╔═╗ ╦ ╦ ╦ ╦ ╔═╗ ╔═╗ ╦╔═ ╦ ╔╗╔ ╔═╗ ╦ ╦ ╦
╠═╣ ╠═╣ ╠═╝ ╠═╝ ╚╦╝ ─── ╠═╣ ╠═╣ ║ ╠╩╗ ║ ║║║ ║ ╦ ║ ║ ║
╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╚═╝ ╩ ╩ ╩ ╝╚╝ ╚═╝ o o o