Winafl學習筆記


最近在跟師傅們學習Winafl,也去搜集了一些資料,有了一些自己的理解,就此記錄一下。

Winafl是一個運行時插樁工具,可以提高crash的捕獲率。

同時也有自己的遺傳算法,可以根據代碼覆蓋程度進行Fuzz

下載winafl

https://github.com/ivanfratric/winafl

下載DynamoRio

https://github.com/DynamoRIO/dynamorio/wiki/Downloads

winafl包里包含源碼和編譯好的,可以直接使用編譯好的,也可以自己去編譯。

編譯winafl的步驟

For a 32-bit build:

mkdir build32

cd build32

cmake .. -DDynamoRIO_DIR=..\path\to\DynamoRIO\cmake

cmake --build . --config Release

 

For a 64-bit build:

mkdir build64

cd build64

cmake -G"Visual Studio 10 Win64" .. -DDynamoRIO_DIR=..\path\to\DynamoRIO\cmake

cmake --build . --config Release

//DDynamoRIO_DIR是你下載的DynamoRio的路徑

要運行winafl只需要winafl本體+DynamoRio,其中DynamoRio用於提供動態插樁的支持。

使用方式在github的說明中已經給出。注意的是要保證被fuzz程序的同目錄下存在winafl.dll

對於程序的輸入來說,需要在-i選項下給出輸入的文件。並且要最后附加@@

如果要fuzz 64位程序,則winafl和DynamoRIO也要指定為64位的,反之亦然。

下面是對官方readme的部分翻譯

4) Using WinAFL
---------------

Note: If you are using pre-built binaries you'll need to download DynamoRIO
release 6.1.1-3 from https://github.com/DynamoRIO/dynamorio/wiki/Downloads.
If you built WinAFL from source, you can use whatever version of DynamoRIO
you used to build WinAFL.

The command line for afl-fuzz on Windows is different than on Linux. Instead of

%s [ afl options ] -- [instrumentation options] -- 

it now looks like this

afl-fuzz [afl options] -- [instrumentation options] -- target_cmd_line

The followin afl-fuzz options are supported:

  -i dir        - input directory with test cases
  -o dir        - output directory for fuzzer findings
  -D dir        - directory containing DynamoRIO binaries (drrun, drconfig)
  -t msec       - timeout for each run
  -f file       - location read by the fuzzed program
  -M \\ -S id   - distributed mode
  -x dir        - optional fuzzer dictionary

Please refer to the original AFL documentation for more info on these flags.

The following instrumentation options are used

  -covtype         - the type of coverage being recorded. Supported options are
                     bb (basic block, default) or edge.

  -coverage_module - module for which to record coverage. Multiple module flags
                     are supported.

  -target_module   - module which contains the target function to be fuzzed.
                     Either -target_method or -target_offset need to be
                     specified together with this option.

  -target_method   - name of the method to fuzz in persistent mode. A symbol
                     for the method needs to be exported for this to work.
                     Otherwise use -target_offset instead.

  -target_offset   - offset of the method to fuzz from the start of the module.

  -fuzz_iterations - Maximum nuber of iterations for the target function to run
                     before restarting the target process.

  -nargs           - Number of arguments the fuzzed method takes. This is used
                     to save/restore the arguments between runs.

  -debug           - Debug mode. Does not try to connect to the server. Outputs
                     a log file containing loaded modules, opened files and
                     coverage infrormation.

  -logdir          - specifies in which directory the log file will be written
                     (only to be used with -debug).

In general, you should perform the following steps when fuzzing a new target:

0. Make sure your target is running correctly without instrumentations.

1. Open the target binary in WinDbg and locate the function you want to fuzz.
Note the offset of the function from the start of the module. For example, if
you want to fuzz the main function and happen to have symbols around, you can
use the following windbg command:

x test!main

2. Make sure that the target is running correctly under DynamoRIO. For this
purpose you can use the standalone debug mode of WinAFL client which does not
require connecting to afl-fuzz. Make sure you use the drrun.exe and winafl.dll
version which corresponds to your target (32 vs. 64 bit).

Example command line

path\to\DynamoRIO\bin64\drrun.exe -c winafl.dll -debug
-target_module test_gdiplus.exe -target_offset 0x1270 -fuzz_iterations 10
-nargs 2 -- test_gdiplus.exe input.bmp

You should see the output corresponding to your target function being run 10
times after which the target executable will exit. A .log file should be
created in the current directory. The log file contains useful information
such as the files and modules loaded by the target as well as the dump of AFL
coverage map. In the log you should see pre_fuzz_handler and post_fuzz_handler
being run exactly 10 times as well as your input file being open in each
iteration. Note the list of loaded modules for setting the -coverage_module
flag. Note that you must use the same values for module names as seen in the
log file (case sensitive).

3. Now you should be ready to fuzz the target. First, make sure that both
afl-fuzz.exe and winafl.dll are in the current directory. As stated earlier,
the command line for afl-fuzz on Windows is

afl-fuzz [afl options] -- [instrumentation options] -- target_cmd_line

Please refer above for the list of supported AFL and instrumentation options.

In AFL options, you must specify the DynamoRIO binaries directory via the new
-D option. You need to match the DynamoRIO and winafl.dll build (32 vs. 64 bit)
to the target binary. -t (timeout) option is mandatory for winafl as execution
time can vary significantly under instrumentation so it’s not a good idea to
rely on the auto-determined values.

You can use the same winafl options as in step 2 but remember to exclude the
-debug flag and you'll probably want to increase the iteration count.

Note that, unlike linux AFL, in WinAFL the default coverage mode is basic
block. This is because in multithreaded (i.e. most real-world) applications
every context switch would be interpreted as new coverage even when no new
coverage actually occured. If you are confident that all your coverage modules
execute only a single thread at a time you can change this by adding
-covtype edge
to your instrumentation flags.

As in afl-fuzz on Linux you can replace the input file param of the target
binary with @@

An example command line would look like

afl-fuzz.exe -i in -o out -D C:\work\winafl\DynamoRIO\bin64 -t 20000 --
-coverage_module gdiplus.dll -coverage_module WindowsCodecs.dll
-fuzz_iterations 5000 -target_module test_gdiplus.exe -target_offset 0x1270
-nargs 2 -- test_gdiplus.exe @@

That’s it. Happy fuzzing! Let me know if you find any bugs.
  • -i   測試樣本的輸入目錄
  • -o  fuzz結果的輸出目錄
  • -D  DynamoRIO所處的目錄
  • -t   每次的運行時間
  • -f   被fuzz的進程要讀取的文件
  • -x  可選fuzzer目錄

使用說明

  1. 首先找出要fuzz的函數基於模塊的地址偏移
  2. 要保證程序可以正常的跑在DynamoRIO下面,可以通過WinAFL的獨立調試模式來測試這一點。獨立調試模式不會使用fuzz部分(使用-debug選項)
  3. 要想正常運行,必須要保證afl-fuzz.exe和winafl.dll在同一目錄下
  4. afl-fuzz [afl options] -- [instrumentation options] -- target_cmd_line
  5. -D選項是必須啟用的,用於指定DynamoRIO所處的目錄
  6. -t選項也是必須啟用的,由於不同的選項導致的執行效率不同。所以-t的時間應該靈活設置。
  7. 默認是支持多線程的程序記錄的。如果是單線程程序可以使用-covtype edge選項

instrumentation options

  • -covtype                  設置記錄方式,為多線程和單線程程序所使用。bb/edge
  • -coverage_module    設置要記錄的模塊,支持多個模塊的記錄
  • -target_module         fuzz目標函數所處的模塊,必須要設置-target_method或-target_offset
    • -target_method        只有有符號表的情況下才能用的方法,根據符號名去搞
    • -target_offset           要fuzz函數的相對模塊頭的偏移
  • -fuzz_iterations         目標函數的最大迭代次數
  • -nargs                      被fuzz的函數有幾個參數?
  • -debug                     不會連接fuzzer部分,只會輸出一個日志文件。包含加載的模塊、打開的文件和輸出報告。
    • -logdir                      只在-debug下可用,輸出的log文件的位置


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM