Fuzzing FFMpeg with AFL on ubuntu
https://ffmpeg.org/ is a software to record,convert and stream audio and video. this has been used by many people. in this post i will discuss how to fuzz it with afl on ubuntu.
Downloading the code:
you need to clone git repo, run this command:
git clone https://github.com/FFmpeg/FFmpeg.git
Compiling:
after you have clone the git repo, run the following configure command to make the build:
./configure --prefix="$HOME/ffmpeg_build" --pkg-config-flags="--static" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib" --extra-libs="-lpthread -lm" --bindir="$HOME/bin" --enable-gpl --enable-libass --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libx264 --enable-libx265 --enable-nonfree --cc=afl-clang --cxx=afl-clang++ --extra-cflags="-I$HOME/ffmpeg_build/include -O1 -fno-omit-frame-pointer -g" --extra-cxxflags="-O1 -fno-omit-frame-pointer -g" --extra-ldflags="-L$HOME/ffmpeg_build/include -fsanitize=address -fsanitize=undefined -lubsan" --enable-debug
at first configure will complain about missing libs.
also:
1.this will use afl-clang and afl-clang++ compilers.
2. this will use address sanitizer and undefined behavior sanitizer.
3. this will enable debug mode.
4. this will enable static libs.
as you can see it also enables following modules:
–enable-libass
–enable-libfreetype
–enable-libmp3lame
–enable-libopus
–enable-libvorbis
–enable-libx264
–enable-libx265
if you dont have all the above libs installed, then you need to install them. i will leave up to readers on figuring our how to install all the above libs. it may take some googling and searching but worth learning.
after you have installed all the dependencies, you can run the configure command again:
./configure --prefix="$HOME/ffmpeg_build" --pkg-config-flags="--static" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib" --extra-libs="-lpthread -lm" --bindir="$HOME/bin" --enable-gpl --enable-libass --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libx264 --enable-libx265 --enable-nonfree --cc=afl-clang --cxx=afl-clang++ --extra-cflags="-I$HOME/ffmpeg_build/include -O1 -fno-omit-frame-pointer -g" --extra-cxxflags="-O1 -fno-omit-frame-pointer -g" --extra-ldflags="-L$HOME/ffmpeg_build/include -fsanitize=address -fsanitize=undefined -lubsan" --enable-debug
this time ./configure should complete successfully.
Running Make:
after that lets compile using make, run following command:
AFL_HARDEN=1 make -j8
AFL_HARDEN=1 means it add some more code hardening options like -D_FORTIFY_SOURCE=2 and -fstack-protector-all this will cause very minor performance issue but can find crashes which otherwise will not be detected.
you need to wait for sometime till build gets finished. it will generate executable. we will fuzz “ffmpeg” executable.
Checking for ASAN/UBSAN build:
lets make sure its compiled with asan or not. for that we can use “checksec” utility from pwntools.
it will give output like this:
[*] '/home/FFmpeg/ffmpeg'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
FORTIFY: Enabled
ASAN: Enabled
UBSAN: Enabled
as you can see, both ASAN and UBSAN is enabled for our compiled binary. thats good.
Corpus collection:
now next step is to gather some samples. so you can google for different media filetypes and collect some corpus.
hint: there are lot of media samples already available. search them 🙂
Minimizing the corpus:
once you have collected some corpus, you need to minimize it. for that run following command:
afl-cmin -i input -o mininput -- ./ffmpeg -i @@ test
after that the minimized sample will be saved in mininput dir.
Fuzzing:
depending on number of cores you have, you can run this command to start afl-fuzz:
afl-fuzz -M master -i mininput -o fuzz -m none — ./ffmpeg -i @@ test
afl-fuzz -S slave1 -i mininput -o fuzz -m none — ./ffmpeg -i @@ test
this will run 1 master and 1 slave. you can run multiple slaves.
results:
this is a software which is heavily fuzzed. but that doesnt means you will not find any issues. i ran it for couple of days on 8 core(1 Mater and 7 Slaves) and found 1 assert failure and 1 heap-use-after free issue.
unfortunately both the issues were fixed few days back. one of the issue seems to be found by oss-fuzz.
conclusion:
if a software is already fuzzed by lot of people, you will need good corpus but you can still find crash. so keep fuzzing and do not loose hope.
[Notes] useful git commands
git reset to master
git fetch origin
git reset –hard origin/master
git check origin url
git config --get remote.origin.url
git create patch
git diff > file.patch
git apply patch
git apply file.patch
[Notes] Fuzzing on linux
some notes i have taken during my fuzzing work in last 2 years. may be useful for someone.
ram disk create
mkdir /tmp/afl-ramdisk && chmod 777 /tmp/afl-ramdisk
mount -t tmpfs -o size=2048M tmpfs /tmp/afl-ramdisk
creating build with GCC, ASAN etc, 32 bit
CFLAGS=”-m32 -g -fsanitize=address -fno-omit-frame-pointer” LDFLAGS=”-m32 -g -fsanitize=address -fno-omit-frame-pointer” ./configure
options for ASAN
-fsanitize=undefined
-fsanitize=memory
-fsanitize=address
CMAKE build
cmake .. -DCMAKE_CXX_FLAGS=”-fsanitize=address -fsanitize=leak -g” -DCMAKE_C_FLAGS=”-fsanitize=address -fsanitize=leak -g” -DCMAKE_EXE_LINKER_FLAGS=”-fsanitize=address -fsanitize=leak” -DCMAKE_MODULE_LINKER_FLAGS=”-fsanitize=address -fsanitize=leak”
deleteing CMake temp build files
rm -rf CMakeFiles/
CMake change compilers:
cmake .. -DCMAKE_C_COMPILER=path/to/afl-gcc -DCMAKE_CXX_COMPILER=path/to/afl-g++
asan with clang
CFLAGS = “-g -fsanitize=address -I/usr/lib/llvm-6.0/lib/clang/6.0.0/include”
or
../configure –cc=clang –extra-cflags=” -fsanitize=address -g ” –extra-ldflags=” -fsanitize=address -g ” –enable-debug
Configure Disable shared libraries
./configure –disable-shared
Some files related commands, used for corpus managment
find .mdb and move to new folder
find /corpus -name “*.mdb” -exec mv {} /papers \;
find file greater then 1 mb and delete them, this will ask to confirm
find . -size +1M -name “*.mdb” -exec rm -i {} \;screen –
find file greater then 1mb and delte without asking to confirm
find -type f ( -name “mdb” -o -name “accdb” ) -size +1M -delete
To Move all files, but not folders:
find ~/Downloads/ -type f -print0 | xargs -0 mv -t ~/Videos
check if elf is compiled with asan
nm -an | grep asan
alternatively use checksec utility from pwntools package.
use this command for triaging crashes with ASAN
ASAN_OPTIONS=”abort_on_error=1:symbolize=0″
WinAFL useful commands
notes to self and may be useful to someone.
Minimising a crashing test case :
afl-tmin.exe -D C:\DRIO\bin32 -i C:\winafl\crashes\crashfile -o C:\crashes\min_crashfile — -covtype edge -coverage_module coverage.dll -target_method fuzzit -nargs 2 -call_convention thiscall — C:\winafl\fuzzedapp.exe @@
Reducing corpus using winafl-cmin:
..\winafl-cmin.py -i inCorpus -o inMinCorpus -D C:\Fuzzing\DynamoRIO2\bin32 -covtype edge -call_convention thiscall -coverage_module coverage1.dll -coverage_module coverage2.dll -target_module fuzzedapp.exe -target_offset 0x1000 -nargs 2 –skip-dry-run — fuzzedapp.exe @@
Fuzzing afdko with AFL in 32bit Mode
Introduction:
Afdko is a set of tools for building opentype fonts from Postscript and true type fonts. this was previously fuzzed by j00ru of google P0. This library was also used in various adobe products and in windows too. so if you find a issue in it, there are chances that that issue is also present in adobe or windows product as well. although not all the afdko code paths are reachable in windows or adobe. by default this gets compiled in 64 bit. which has its own disadvantages like you can use -m option with AFL which limits the memory for the process. because of this we may miss some unusual crashes with ASAN.
In this post i will cover how to fuzz Afdko using AFL in 32 bit mode.
Downloading the source:
we can simply clone following git repo:
https://github.com/adobe-type-tools/afdko
Compiling:
after you have downloaded the sources, you can go to “afdko/c” directory and run following commands:
CC=afl-gcc ./builalllinux release
this will compile and create various exe files. the file of our interest is “tx” which is present in “afdko/c/tx/exe/linux” folder.
Fuzzing:
after we have instrumented file with afl we can simply run the command:
afl-fuzz -i input -o output -m none — ./tx -cff @@
this will start the fuzzing. you can also run multiple instances with 1 master and n number of slaves if you have multicore available.
but there are some issue with this:
- no ASAN/MSAN/UBSAN support
- no 32 bit build.
Compiling in 32 bit mode with ASAN/UBSAN
lets compile it with ASAN/MSAN/UBSAN
we need to change couple of files for this and add following to compile it with GCC:
+CFLAGS = $(STD_OPTS) -m32 -g -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
+LDFLAGS = $(STD_OPTS) -m32 -g -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
this will make sure that the build is 32 bit and is compiled with ASAN/UBSAN support. as ASAN and MSAN are mutually exclusive, they wont work together. so you can use either one of them depending on your need.
once you compiled the 32 bit build, you can again run afl as below with the corpus you have:
afl-fuzz -i input -o output -m 800 — ./tx -cff @@
note that -m 800 will set 800MB as memory limit, so if program tries to allocate huge memory like 1GB+ you will get crash. i in fact found couple of such cases where program tries to allocate huge memory because of corrupted headers. this may easily lead to DOS condition.
PS: i have created a patch file for compiling it with 32bit and ASAN/UBSAN. please contact me if you need it. it should be simple though to do at your own. but i did spent lot of time in figuring it out as i am not much in to linux. so happy to help if you need it.
Results:
I fuzzed this for few weeks and found lot of crashes. finally i reported around 8 issues to Afdko which where fixed. although i haven’t received any CVEs for them as Afdko issue don’t get any CVEs. but it was a good learning experience for me.
Thanks to Afdko team and Adobe PSIRT for their help in getting the reported issues fixed. they have released a new version 3.5.0 which fixes all the issues i have reported to them.
Exercise for the readers:
i have omitted various details from this post, if you are interested in learning more, you can try following:
- figure out which files needs to be modified to compile it in 32 bit with ASAN/MSAN. also check if there is already any build option for this which you can use.
- how to get good corpus so that your fuzzing yields in some good crashes?
- figure out which adobe and windows product may be using this library?
- if you get lot of crashes, how will you triage them?
using pip with proxy
if you are behind a proxy and want to use pip, use following
–proxy <proxy ip/url>:port –trusted-host pypi.python.org –trusted-host files.pythonhosted.org –trusted-host pypi.org
aws commands
To list all folders:
aws s3 ls s3://bkt –recursive | tr -s ‘ ‘ | cut -d ‘ ‘ -f4- | grep “\/$” | sed ‘s/\/$//’
To list all files:
aws s3 ls s3://bkt –recursive | tr -s ‘ ‘ | cut -d ‘ ‘ -f4- | grep -v /$
To list all .json files:
aws s3 ls s3://bkt –recursive | tr -s ‘ ‘ | cut -d ‘ ‘ -f4- | grep “.json$”
To list all .json and all .yaml files:
aws s3 ls s3://bkt –recursive | tr -s ‘ ‘ | cut -d ‘ ‘ -f4- | grep -E “(.yaml|.json)$”
To list all files except .json files:
aws s3 ls s3://bkt –recursive | tr -s ‘ ‘ | cut -d ‘ ‘ -f4- | grep -v “.json$”
enable & disable hyper-v from command line
To disable Hyper-V from starting the following command can be used:
bcdedit /set hypervisorlaunchtype off
To enable the Hyper-V role again use the following command:
bcdedit /set hypervisorlaunchtype auto
Hiring People
I am fortunate enough to interview hundreds of people in my career and also was interviewed by many companies in the past. i wanted to write a post on it to share my experience with meeting lot of people and understanding them during this process.
While i am not a professional at this(don’t have any formal training etc) what i learn is from my experience. I observed interviewing a candidates requires assessment of his/her skills, the question comes how you should assess a potential candidate?
- assess him based on the job qualification and role?
- assess him based on the what he has done and can do?
- assess him based on what you(the interviewer) have done and what you know?
Lets take a detailed look at each of them:
- assess him based on the job qualification and role? – This approach focuses on the job role, it means if the job required working on a Python project, This approach will focus on candidates python skills. Many such interviewer will focus on just checking what work a candidate has done in python? language internals, in build functions, library uses etc etc. How does a candidate will solve given problem using his knowledge of python etc. This approach will basically check how much hands on experience a candidate has. depending up on the candidate you can expect an honest no i don’t know or a brief answer on the problem solving approach or a very detailed answer.
- assess him based on the what he has done and can do? – This approach will focus on what candidate has done in the past and how much calibre he has to adopt to new things and how will he solve given challenges to him even though he currently has not worked on him.This approach focuses on how quickly a candidate can learn and adjust to new work and possibly new culture. for example if a candidate has worked in C or C++ and is interested/interviewed for a python developer role. then this approach will focus on first on C/C++ problem and then how he can solve the new problems using C/C++ and then how he can solve same problem using python? in this case you can expect a detailed answer from a candidate on how he can solve problem using C/C++ and a brief or detailed answer on how he will solve this problem using python.
- assess him based on what you(the interviewer) have done and what you know? – This approach will basically requires an interviewer focusing on the skill he has rather then the candidate has. In this approach interviewer will ask question about what he knows and worked and try to expect more or less same kind of answer from candidates. for example if a interviewer has worked on networking, his question will be based on purely networking and candidate is supposed to confirm or know what interviewer knows. you can expect an basic or detailed answer from candidate or an honest No – i dont know this answer.
Now the question comes, which of above should be used? does any one of above is strong enough or you should use a combination of all of above?
In my case i prefer combination of all the above, i also combine it with different thing like his communication skills(how well he can express his thoughts over writing or verbally), convincing power and overall behaviour shown during the process.
Interviewing a candidate is complex process, many a times we miss good candidates or we hire wrong ones. the truth is you can not judge a person in few minutes or hours. no matter if its telephonic if onsite. you definitely will need different opinions from multiple people.Also make sure the candidate you are interviewing has a pleasing experience during the entire process and he should feel happy and motivated enough to join your team as you are the person most likely he is going to work with once he joins your team!