This article for the Pepper Map technology Authorized hissing release, if reproduced, please indicate from Roar: http://www.4hou.com/technology/2800.html
Introduction: WINAFL is a file format and protocol vulnerability of the semi-automatic discovery tool, can help us to find a variety of applications using specific format files, such as file editing software, picture viewing software, video playback software.
WINAFL is the Windows version of the smart Blur test artifact Afl-fuzz under Linux. Afl-fuzz from 2013 to the present, found a lot of real loopholes, by the vast number of network security practitioners used, now, the Windows version is also available, we can also use it to test software under windows and try to discover vulnerabilities.
WINAFL is a semi-automatic discovery tool for file format and protocol vulnerabilities that can help us discover application vulnerabilities in specific format files, such as file editing software (Doc, xls, PDF, etc.), picture viewing software (BMP, JPG, PNG, etc.), video player (AVI, MP4, MPG, etc.).
First, compile ( directly download, which contains the compiled files )
WINAFL compilation generally does not appear to be the problem, the process is as follows:
You can download all of your code's packaged files directly from HTTPS://GITHUB.COM/IVANFRATRIC/WINAFL, or you can use Git for Windows to clone all your code from the site. The downloaded code itself contains the compiled version, including 32-bit and 64-bit, which you can compile yourself to facilitate understanding, modification, and use of WINAFL.
1. Download CMake (http://www.cmake.org), WINAFL compilation requires Cmake,cmake is a cross-platform compilation software.
2. Download Dynamorio (http://dynamorio.org/), a cross-platform open source Analysis Code dynamic Instrumentation tool software.
3. Then you need a compiler, you can use visual Studio C + +, version of the problem is related to CMake, download the latest cmake, support vs 2005-2015 version, but because the VS 2010 before the version is not fully compatible with C99, Therefore, the compile time will appear stdint.h not found errors, can be copied from other and C99 compatible compilers, such as MinGW, or directly from the web search to download one.
Install CMake to automatically create environment variables.
4. Create a directory such as C:\test, unzip WINAFL, Dynamorio to C:\test directory.
5. Start the Visual Studio command-line compilation environment, if you want to compile a 32-bit version into a 32-bit environment, otherwise go into a 64-bit environment, compile what version depends on the software version we need to fuzzing.
6. Enter the WINAFL directory, you can find the Bin32 and Bin64 directories, these 2 directories are compiled WINAFL, we can recompile
32-bit Type the following command to complete the compilation:
MD B32CD B32cmake. -ddynamorio_dir=c:\test\dynamorio\cmake (Dynamorio the path on your machine) CMake--build. --config Release (can also be debug)
64-bit Type the following command to complete the compilation:
MD b64cd B64cmake-g "Visual Studio ten Win64". -ddynamorio_dir=c:\test\dynamorio\cmake (Dynamorio the path on your machine) CMake--build. --config Release (can also be debug)
WINAFL compilation can be done using a compiled file in the current directory of the release (or debug) directory.
Second, use
The main files generated after the code compilation are:
Afl-fuzz.exe Main program Winafl.dll injection into the Fuzzing program module
The Afl-fuzz.exe command line format is as follows:
Afl-fuzz [AFL options]--[instrumentation options]--target_cmd_line
The parameters commonly used in [the AFL options] include (these parameters are handled by Afl-fuzz.exe):
-I dir– test Case store Directory-o dir–fuzzing process and Results Store directory-D dir– binary dynamic instrumentation tool execute file path-t msec– timeout setting-x dir– dictionary file
... Please refer to the main function of afc-fuzz.c for more parameters.
[Instrumentation options] commonly used parameters include (these parameters are processed by Winafl.dll):
The-coverage_module–fuzzing object program calls to the module-target_module–fuzzing object module, which is the-target_offset module-target_offset– The offset address of the fuzzing, that is, the offset of the instrumentation-fuzz_iterations– again fuzzing the object program to restart the maximum number of iterations -debug–debug mode of running the target function
... For more parameters, please refer to the Options_init function of WINAFL.C.
The Target_cmd_line parameter is the initiator of the object you want to fuzzing.
Well, if fuzzing WINAFL the default band example, the entire command line is as follows:
Afl-fuzz.exe-i in-o out-d C:\test\DynamoRIO\bin32-t 20000---Coverage_module gdiplus.dll-coverage_module Windowscode Cs.dll-fuzz_iterations 5000-target_module test_gdiplus.exe-target_offset 0x1260-nargs 2--Test_gdiplus.exe @@
The-I in test case is stored in the current directory in the in Directory-O-out test result and the process output to the current directory of Out directory-D c:\DynamoRIO-Windows-6.1.1-3\bin32 instrumentation tool execution file path, you can Time-out for running Fuzzing object files with relative path -t 20000-split
-coverage_module Gdiplus.dll-coverage_module WindowsCodecs.dll for the Fuzzing object program will call the module , which means you fuzzing the offset address of the Functions are called into the functions of these modules , which can be viewed through some PE tools to see the Fuzzing object call those modules, or through the Winafl.dll-debug mode, and then according to the disassembly code to determine the invocation of those modules , We write the same as-target_module in cases where we cannot judge by ourselves.
-target_module Test_gdiplus.exe-target_offset module, which is also the Fuzzing object module
-target_offset 0x1260 fuzzing Module Instrumentation offset address, such as Test_ Gdiplus.exe is a very simple program, so the main function is fuzzing, and through IDA or similar tool found that the main function is offset from the Test_gdiplus.exe base address is 0x1260
(Note: Here the offset address is computed, Ida opens after the code start address is the 0x401000,main function address is 0x401260, but the EXE base is: imagebase:400000, so the offset is 0x1260, not minus the code start address.)
In the case of a PDB, write directly-target_method main.)
Test_gdiplus.exe @@ fuzzing Object Program start command line
Run the command above to see the following interface, Afl-fuzz.exe began to work.
Third, the use of analysis
The general flow of AFL-FUZZ.C:
Build the entire out directory structure and related files
Process test cases and write to out directory
Run the Fuzzing object program through Drrun.exe and insert the Winafl.dll, test with the deformed test case, and return the results. Then the specific out directory structure is as follows:
Out//crashes makes the application crash the use case, that is WINAFL the directory where the final result is stored/hangs the use case that suspends the application, and the file of this directory may also make the application crash/queue some process files fuzzing Input current fuzzing use case/fuzz_bitmap is mapped by fuzzing function
3.1. Deformation processing of test case files
Afl-fuzz.exe reads the user-supplied test file through the directory pointed to by the-I parameter and stores it through various variants to the Out/.cur_input file for the fuzzing application call to open and view Afl_ FUZZ.C can find out which variants of the test case have been made.
The main function of AFL-FUZZ.C is Fuzz_one (char** argv), the deformation of the test file is also done through this function, in the Fuzz_one function will be called trim_case (char** argv, struct queue_entry * Q, u8* in_buf) function, the test case is clipped first, the test case is too general to affect the test speed, this is certain, so in theory, the smaller the test case, then all fuzzing the shorter the time to complete, then how to crop will not affect the results of fuzzing? , AFL-FUZZ.C is done by the following means.
First, WINAFL will create a 64KB shared memory to store the execution path of the application being fuzzing, such as:E (Tuples:ab, BC, CD, DE), C, D, B , When the path changes, such as C-E (Tuples:ab, BD, DC, CE), such as a-B, D, WINAFL will update the shared memory and discover that the new execution path is more helpful in discovering the vulnerability of the code, because most security vulnerabilities are often not The expected state shifts, not because the piece of code is not covered .
The Trim_case function divides the total length of the test case by 16 and deletes the length of the data to the Fuzzing application to open and record the execution path to the shared memory, and the Trim_case function hashes the shared memory after the execution is done. If this shared memory does not change, then the description does not discover a new execution path, and also indicates that the clipped data has little effect on the whole test result, so the test case will be removed to a reasonable size without affecting the fuzzing result.
In the Fuzz_one function, a number of deformation operations are done on the test case file, including the following types of transformations: bit flips, byte flips, arithmetics, known ints, dictionary, Havoc.
In bit flips mode, the contents of the test case files are sequentially deformed by the length of each 1, 2, 4 bits, and the following algorithms are used for the length distortion of 1, 2, 4 bits:
#define FLIP_BIT (_ar, _b) do {u8* _arf = (u8*) (_ar); U32 _bf = (_b); _arf[(_BF) >> 3] ^= (>> (_BF) & 7)); } while (0)
In the byte flips mode, the contents of the test case file are ordered according to the length of each 8, 16, 32 bits, and the statement is used when morphing: Out_buf[stage_cur] ^= 0xFF;, * (u16*) (out_buf + i) ^= 0xFFFF; u32*) (out_buf + i) ^= 0xFFFFFFFF; to deform and pass the deformed test case to the Common_fuzz_stuff function for subsequent processing.
In arithmetics mode, the 8-bit operation uses the Morph statement: out_buf[i] = orig + j;, 16-bit operation uses the MORPH statement: * (u16*) (out_buf + i) = Orig–j, and 32-bit operation using the MORPH statement: * (u32*) ( Out_buf + i) = orig + j;. After the deformation, the test cases are given to the Common_fuzz_stuff function for subsequent processing.
In known ints mode, the 8-bit operation uses the deformation statement: out_buf[i] = interesting_8[j];, 16-bit operation uses the VARIANT statement: * (u16*) (out_buf + i) = Interesting_16[j]; The 32-bit operation uses the VARIANT statement: * (u32*) (out_buf + i) = Interesting_32[j];. After the deformation, the test cases are given to the Common_fuzz_stuff function for subsequent processing. Where interesting related definitions are as follows:
static S8 interesting_8[] = {interesting_8};static s16 interesting_16[] = {interesting_8, interesting_16};static s32 i Nteresting_32[] = {interesting_8, interesting_16, interesting_32};
In dictionary mode, the user is allowed to use a dictionary, which can be used to replace the relevant parts of the test case with a dictionary file and to fuzz some formatted text and protocols, such as HTML, JS, PHP, etc. If a dictionary is used, the parameter is-X, which can be either a directory or a dictionary file, such as:-X dict\xml.dict,-x dict, the function that loads the dictionary is Load_extras, and if the argument is a file, it is opened and formatted with Load_extras_file , used to fuzz some text file handlers, such as PHP, SQL, and so on, if it is a directory, then the Load_extras function reads all the contents of the file into the extras array, the binary file processing program fuzz, such as Doc, XLS, etc. At this time the size of the dictionary file is limited to less than 128B, but this version of the Load_extras function write a problem, no way to use, but you can easily modify, such as the Load_extras_file (dir, &min_len, &max_ Len, dict_level); goto Check_and_sort; These 2 statements move up, do not make redundant judgments, execute the Load_extras_file function directly, or at least use a dictionary to run some formatted text files. Some dictionaries for text format files can refer to testcases examples.
In havoc mode, a value is computed with the following expression, ur ((extras_cnt + a_extras_cnt), 2:0), and different matching variants are performed by Switch...case.
3.2, through the Dynamorio instrumentation
Afl-fuzz after the deformation of the test case, call the Dynamorio program to instrumentation the target program to be fuzz and set the target program parameters to the deformed test case, monitor the target program's operation, if the target program crash, Then copy the deformed test case into the Out\crashes directory, and if the target program is unresponsive, copy the deformed test case into the Out\hangs directory. The function that is responsible for running Dynamorio here is the Run_target function.
Run_target first checks to see if the target process exists, if there is a termination process, and the Drconfig.exe-nudge_pid%d 0 1 command sends a nudge event with a parameter of 1 to the client callback, both the target Fuzz program's parameter is 1. The target program is then started through the drrun.exe-pidfile%s-no_follow_children-c winafl.dll%s-%s command. and inject Winafl.dll to the target program process, after the operation can be analyzed by viewing the winafl.c file, winafl.c the entry function for the Dr_client_main function, the first to continue some necessary initialization work, first through the Options_ The init function handles WINAFL related command-line arguments, including Coverage_module, Target_module, Target_offset, and so on, and then mounts various callback functions: Event_exit, Exit event callback; onexception , exception callback;
Instrument_bb_coverage,instrument_edge_coverage, the callback of the two modes instrumentation; event_module_load,event_module_ Unload module mount, unload callback. In the Event_module_load function, you can see WINAFL through Drwrap_wrap (To_wrap, Pre_fuzz_handler, Post_fuzz_handler); Complete the Pre_fuzz_handler function when the point function enters the given offset (offset), run the Post_fuzz_handler function when exiting, and monitor the run of the offset pointing function.
3.3. Parameter selection
Coverage_module can have multiple, target_module only one, and Target_offset specifies an offset of target_module relative to the base address, Coverage_module and target_ The module must be the one that the target is called by the Fuzz program or itself, and the determined method can be accomplished by-debug parameters, such as running the following command line:
C:\test\DynamoRIO\bin32\drrun.exe-c Winafl.dll-debug-target_module Test_gdiplus.exe-target_offset 0x1650-fuzz_ Iterations 10-nargs 2-test_gdiplus.exe input.bmp
WINAFL will generate a log file in the current directory with a file name similar to Afl.test_gdiplus.exe.13280.0000.proc.log, as shown in the following:
You can see that many lines begin with the module loaded, which means that the parameters Coverage_module and Target_module specified must appear here.
Target_offset set simple command-line program can be directly set to the main function of the program, such as the above example of Test_gdiplus.exe, complex interface with the program to find the offset can be as follows:
1. Start the ollydbg and load the target program, the parameter is set to the test case document, press F9, the target program stops at the program entrance;
2. Establish a breakpoint in the command input box: BP Createfilea, BP Createfilew, in general the application if the open file will definitely call these 2 APIs;
3. Press F9 to see if the parameter is an input test case document, not to continue F9 (the function call is too frequent to use conditional breakpoint BP kernel32. Createfilew, [UNICODE [esp+4]]== "C:\\test\\1.mov"), if it is entered by F7, press ctrl+f9 execution to return, record the EIP address;
4. Continue ctrl+f9 execution to return, record under the EIP address, so repeated several times, get multiple offset address;
5. Using IDA to disassemble the target program, find the offset of the function where the compiled address of all the records is located, so that we get an execution path, with each offset address tested with the command line with the-debug parameter mentioned above, if the generated log file contains the statement: everything appears To be running normally, then it is possible to specify this offset address. Next, we can fuzz the target program with a command line similar to the following.
Afl-fuzz.exe-i in-o out-d C:\test\DynamoRIO\bin32-t 20000---Coverage_module gdiplus.dll-coverage_module Windowscode Cs.dll-fuzz_iterations 5000-target_module test_gdiplus.exe-target_offset 0x1650-nargs 2--Test_gdiplus.exe @@
Of course, you can view the call stack directly alt+k, but sometimes you want to see deeper calls to do so. This simple way to find the offset address is most likely not the best offset address or useless, and this is related to the method and habits written by the target program, but regardless of the determined Target_offset offset address must be the target application open test case will definitely call to the offset, Otherwise the Fuzz program cannot continue running.
四、一个 Example
The real situation is through the WINAFL to find a short time popular software bugs or is relatively difficult, and even found not. I use WINAFL run a very popular word processing software ran a day, a crash did not appear, may not be long enough, hehe, or first find an not popular software test under the small crowd. I downloaded some of the non-popular software to run, so WINAFL finally have the application, each software ran not too long time, there are a lot of crash.
Ran a lot of software, there are a lot of crash, but to determine whether these crash can be used to spend a lot of time, and the value of these software is not very large, only a cursory look at the bottom, basically are read anomalies, the likelihood of being exploited is very small, of course, careful analysis of the words may still be exploited, However, due to the above reasons are not carefully analyzed. One of the software crash very much like can be used, so simple analysis of the next, the final thought also can not be used, the following to paste this example.
Program Error Location:
Exception statement: Rep MOVSD dword ptr Es:[edi], dword ptr [ESI], is obviously a memcpy operation, check whether ESI can be controlled, and look up a layer:
ESI is the EAX from the yellow display after the calculation, by default this value should be 50, when the test file related to the offset of the content, this value is limited control, but after reading ESI continue to see EDI, found completely uncontrollable, EDI is the function of the internal malloc out, The length of the copy is fixed, meaning the crash is unlikely to be used.
Anyway, WINAFL is an open source of excellent semi-automated fuzz testing tools, compared to other public fuzz testing tools still have a great advantage, so let's find the loopholes. ^_^
Turn: Use and analysis of Intelligent fuzzy Test tool WINAFL