100 likes | 112 Views
Learn basic fuzzing with coding example under Linux, identifying bugs and crashing program intentionally. Fuzzing Result Recording.
E N D
CAP6135: Malware and Software Vulnerability Analysis Fuzzing Test ExampleCliff ZouSpring 2016
Objective • Explain basic fuzzing with concrete coding example • Fuzzing code that can run under Linux • Explain how the vulnerable code in programming project 2 is derived • Introduce several useful techniques in doing the fuzzing test on project 2
Example Code • $ fuzzTest-target 200 “what is this?” 2 • Example code needs three inputs • Int, string, Int int inputInteger; /* global variable */ void (*foo)(short); if (argc != 4){ fprintf(stderr, "fuzzTest needs 3 input parameters: int string int!\n"); exit(0); } sscanf(argv[1], "%d", &inputInteger); my_func(inputInteger, argv[2], argv[3]); • Subfun my_func() introduces 3 man-made bugs
Bug # 1: Integer Overflow intmy_func(short argLen, char *str, char *divStr) { int denominator; float x; char buf[bufLen]; if (argLen != inputInteger) { fprintf(stderr, "Bug #1: integer overflow triggered\n"); foo = (void *)0xbfffffff; foo(argLen); /* trigger illegal instruction fault */ exit(1); • Int variable inputInteger changes to short • Overflow happens when inputInteger>32767 • foo() is a function pointer • Give it an arbitrary address will cause illegal memory reference for executing code • A simple way to cause a program to crash
Bug # 2: buffer Overflow char buf[10]; if (strlen(str) > 10){ fprintf(stderr, "Bug #2: buffer overflow triggered. strlen=%d\n", strlen(str)); strcpy(buf, str); /* trigger segmentation fault or stack smashing error */ return 2; /*if overwriting return address, it will cause segmentation fault */ }
Bug #3: divide by zero int denominator; float x; sscanf(divStr, "%d", &denominator); if (denominator == 0){ x = argLen / denominator; fprintf(stderr, "Bug #3: division by zero triggered\n"); foo = (void *)0xbffbffff; foo(argLen); /* trigger illegal instruction fault */ }else x = argLen / denominator; return 0; • The divide by zero error will usually not cause a program to crash • Thus we use the foo function to make sure the program will crash when this bug is triggered
Fuzzer Outline • Generate inputs (random or follow rules) firstInt = rand()%50000; secondInt = rand() % 2; arraySize = rand() % 20; charArray = (char *) malloc(arraySize); for (j=0; j< arraySize; j++) charArray[j] = 'A'; charArray[arraySize-1] = NULL; • Generate execution command line sprintf(buffer, "./fuzzTest-target %d \"%s\" %d\n", firstInt, charArray, secondInt); free(charArray); /* must free memory for repeat testing! */
Fuzzer Outline • Execute target code ret = system(buffer); • Obtain target execution exit code wait(&status); retCode = WEXITSTATUS(ret); • Check abnormal exit code and record inputs that cause the abnormal if ( retCode == 128+11 || retCode ==128+4) /* segmentation fault (11) or illegal (4) */ { printf("retCode=%d ## Input: firstInt = %d, arraySize = %d, secondInt = %d\n", retCode, firstInt, arraySize, secondInt); fflush(stdout); /*make sure output is print out immediately ! */ } • Repeat from start in generating inputs
List of Unix Signal Number • You can find it at: • http://man7.org/linux/man-pages/man7/signal.7.html • The WEXITSTATUS() returns a value that is the signal number that caused the termination plus 128
How to Record Fuzzing Result? • When abnormal happens, record down inputs that cause the abnormal • Record the corresponding abnormal message printout by target code • Unix OS I/O definition: • stdin (0), stdout (1), stderr (2) • I/O redirection: • $ Command < data.txt: let stdin get from file (instead of keyboard) • $ Command > output.txt: let stdout redirect to file • $ Command 2> error.txt: let stderr redirect to file • $ Command &> output.txt: let stdout and stderr redirect to file • For our example: • $./fuzzTest100 &> output.txt