mutator
Table of Contents
- Overview
- License
- How to get project mutator
- Dev Status
- Dev Plans
- Test Plans
- Announcements
- Buillding and Running
- Implementation Notes
- Directory Outline
- Acknowledgements
- FAQ
- Feedback
- Suggestions and Feature Requests
- TODO List
- Contributions
- Support
- Contact
- Gource
Overview
mutator is a suite of tools for C,C++ and machine code.
Here’s a detailed list of what’s currently available:
bruiser
At its core, bruiser is a Lua REPL:
- bruiser comes with its own extensions and libraries implemented in C and Cpp.
- Through bruiser’s Xobj feature, you can pull in functions from object code, run them and get the result back.
- Through the ASMRewriter functionality you can manipulate the machine code and push it back in the object. For more detail you can look at the wiki or check out bruiser’s README.md.
- Luarocks: You can use your Luarocks modules/libraries in bruiser too. Just make sure
luarocks
is in your path and bruiser will take care of the rest.
You can read more about buiser here
cgrep
cgrep is grep for c/c++ source files. simple as that.
cgrep is added here as a submodule for more exposure. You can find the main repo here.
You can read more about cgrep here
obfuscator
obfuscator is a C/C++ source code obfuscator.
You can read more about obfuscator here
delf
delf
is a custom ELF dump script developed for bruiser. bruiser uses it to interact with ELF files.
You can also use the script as a standalone to dump info on the ELF file to stdout.
delf is also hosted ona mirror repo here.
dwasm
‘dwasm’ is a custom WASM dump script. bruiser uses it to interact with WASM object files.
The script is also usable in an standalone manner.
dwasm is also hosted on a mirror repo here.
luatablegen
luatablegen
is a python script that takes a json file including the details of a C structure, and generates C source and header files, a lua file including some convinience fields for the lua table and a markdown file including a summary of the table fields and their expected arg types and return types.
luatablegen is also hosted on a mirror repo here.
m0
m0
Run static checks on the source code, which at the time of writing, includes SaferCpp, Misra-c:2004 and most of MSC2012 and MSC98 rules.
m0’s reports are generated in XML,JSON and simple text(AWK-friendly:RS="\n";FS=":"
. Look at ReportPrintPretty.sh
under extra-tools
.).
m0
also accpets a formatted file as its input, passing it all the options needed to run it. This feature is only available if m0
is called through mutator.sh
. For an example please look below.
Also to refrain from confusions, m0
’s executable is actually named mutator-lvl0
but for the sake of berevity it will be referred to as m0.
Safercpp
Runs the automatic refactoring sets on your source code, automatically changing your code to use the SaferCpp libraries.
SaferCPlusPlus is essentially a collection of safe data types that are compatible with, and can substitute for, common unsafe native C++ types. You can read more here.
mutatord
The mutator server/daemon and the client are also provided as optional features.
At the time of writing the client and server are provided to facilitate use of m0
as a plugin.
You can Join the Maillist here, mutator maillist.
You can follow Project mutator
on twitter, @xashmith.
License
SaferCpp is currently licensed under GPL-2.0.
All 3rd party libraries/code have their own respective license.
Excluding SaferCpp and other 3rd party code/libraries, everything else under project mutator is provided under GPL-3.0.
How to get project mutator
Before you run make, make sure you have all the dependencies:
- You need LLVM/Clang(for supported versions see the section under building).
- For
safercpp
you will need to have LLVM RTTI also. - For
bruiser
you will need the python 3.5 or higher’s dev package(source code and libpython), libcapstone, libkeystone and libffi. - The other libraries used are either submodules or copied inside.
load.py
needs capstone. You can get it through pip(pip install capstone
).
For More details you can look at theBuilding
section.
Assuming you already have the dependencies:
git clone https://github.com/bloodstalker/mutator
git submodule init
git submodule update
make
mutator is also being hosted using IPFS but it’s never up-to-date. To get it from IPFS just run:
git clone https://ipfs.io/ipfs/QmdBBG76K5rNSWB4iK4ZhTtiZAkSsyDpiWzcPsPfnHY2ZA/mutator
NOTE: this is mostly a novelty feature. The copy you can fetch from IPFS is usually outdated.
To build LLVM/Clang from source take a look at here and here.
To build safercpp-arr
you to need to build Clang with RTTI enabled.
If you need any help regarding getting the requirements you can look at mutator’s .travis.yaml
or check out the nightly builds for Debian/Ubuntu.
Dev Status
Currently there is only the master branch which is the dev branch. All the as-of-yet implemented features of the project are very much buildable and usable at all times, even during the dev phase on the master branch even if they are called “experimantal”. If something’s broken, please make a new issue on it.
- All tools are in the development stage.
Dev Plans
- Bruiser: have bruiser support nested function calls and calls to external SOs.
Test Plans
For a detailed list, you can view tests.md
under docs
.
- The Dev method I’m using is TDD so of course, we currently have TDD tests.
- For static analysis tools, mutator uses Coverity which is integrated with Travic CI so it runs every time on every commit.
- For dynamic analysis tools, currently mutator is using Valgrind. You can run it using
./mutator.sh -test mutator-lvl0 valgrind
. You do need to havevalgrind
installed. - The code will be reviewed after the first pre-release version. I’m hoping to find some reviewers but if not, I’ll have to do it myself.
- There will be unit tests after a first pre-release version.
Announcements
- Introducing cgrep, grep for c/c++ source files.
- I will be taking a one month break from mutator to learn/work on some other things.
- Project mutator will be re-licensed to GPL-3.0.
- bruiser has a working poc demo for asmrewriter.
- bruiser has a working poc demo for Xobjs. For more info checkout bruiser’s
README.md
. - announcing
obfuscator
, the newest mutator family member. it’s a C/C++ source obfuscation tool. - mutator has a new experimental member, bruiser. The idea is that we are already inside the code, so why not break it?
- mutator now has a daemon,a server and a client. It works, but we all know how much weight we can put on “it just works”, don’t we? I’ll be polishing it over the coming days. For more info and detail see
README.md
underdaemon
in project root. Also, please do note that you don’t have to use the server feature. You can just run mutator like before. It’s an added functionality. It does not modify previous functionality. - mutator will be implementing SaferCPlusPlus rule checks and automatic refactoring of code bases to use SaferCPlusPlus libraries. The first phase will begin with implementing the compliancy checks. You can read more about SaferCPlusPlus here.
- mutator’s first website is up: project mutator.
- project mutator has changed licenses from LGPLv3 to GPLv2.
- There are no plans in regards to keeping or dropping LLVM 3.9 support but do keep in mind the libraries mutator uses are not guaranteed to keep backwards-compatibility by their developers as they are still under development.
Building and Running
Building
Requirements
LLVM/Clang
5.0, 6.0, 8.0 and 9.0(we skip 7.0). For 10.0, the latest tested trunk version is 367652.libffi
libcapstone
libkeystone
libpython
3.5 or higher
If capstone and keystone are not included inside your distro’s reposotory and you’re lazy like me, take a look underextra-tools
. There are two scripts(one for each) to get those for the Travis image. You can use those.
The other requirements are either directly included or have to be included throughgit submodule update
.
Linux
First clone the repo and then initialize and update the submodule in it:
git clone https://github.com/bloodstalker/mutator
git submodule init
git submodule update
Here Are the build options:
- Running
make
will build the default target which isall
. This will build all the executables, without support for coverage instrumentation. - Running
make target-name
will only build the target. So for example, if you are only interested in building the Misra-C rule checker you can runmake mutator-lvl0
. - The makefile option
CXX
tells the makefile which compiler to use. The default value isclang++
. Currently the only two supported values areclang++
andg++
. - The makefile option
BUILD_MODE
determines the build mode regarding coverage and support for builds withg++
.
COV_USE
andCOV_GEN
are for use with theprofdata
format. This option can only be used to build withclang++
.COV_GNU
will generategcov
compliant coverage data. This option can only be used to build withclang++
.COV_NO_CLANG
will build the executable with no source coverage instrumentation. This option can only be used to build withclang++
.COV_NO_CLANG_1Z
will build with support for C++1z support. I use this for dev builds.WIN_BUILD
will later be used to support Windows builds. It assumes there is a llvm-config and it’s in windows path.GNU_MODE
will build the executable with no source code coverage instrumentation forg++
. Can only be used to build withg++
.
- The
LLVM_CONF
option is used to tell the compiler whichllvm-config
to use. The default value isllvm-config
. - The
PY_CONF
option tells make whichpython-config
to use. The default ispython3-config
.
So for example if you want to build the code with clang++
without any coverage, and you only want to build the Misra-C rule checker, you should run:
make mutator-lvl0 CXX=clang++ BUILD_MODE=COV_NO_CLANG
Note: if you are building the llvm and clang libraries from source, then the llvm-config name will be llvm-config
but if you are getting the libraries from a repository the llvm-config executable name may not be the same. In that case, you need to also pass make
the LLVM_CONF
variable. For example on Ubuntu trusty, if you get the repositories from llvm nightly builds, the llvm-config executable name will be llvm-config-3.9
so you need to run:
make mutator-lvl0 CXX=clang++ BUILD_MODE=COV_NO_CLANG LLVM_CONF=llvm-config-3.9
Also do note that building the llvm libraries from source in Debug mode will require big space on your harddrive and will need quite some RAM and needless say is slower. Release mode is less resource-greedy, of course.
Finally if you are having problems with the build, you could take a look at .travis.yml
or under CITPreBuildDep.sh
under extra-tools
for some hints or help apart from asking for help, of course.
After building the executables, you can run(i personally don’t):
make install
Windows
Currently only cygwin builds are supported.
To build on cygwin just get the dependencies and run make
. There are no extra steps required.
If you have trouble building, you can take a look at appveyor.yml
in the root directory.
Running
To run any of the executables, just give a filename or a whitespace-separated list of files. The executables will print out the results to stdout.
To run the executables with the mutator UI, you can use mutator.sh
. For a list of available options, you can type ./mutator.sh -h
.
-h, --help
prints out the help.-f, --file
tells mutator to run the commands from the file.-c, --command
specifies the command you want to use.
clean
runs make clean.build-all
runs make all.run
runs themutator
andmutator-lvl2
executables on the inputs.default
runs build-all and then run.format
callsclang-format
to format the mutant. Later to be used for the test command.test
runs the tests on the executables and checks the results (not implemented yet).misrac
checks for misrac rules.
-v, --version
prints out the version.-i, --input, -input
lets you choose the input file(or a white-space-separated list of files) that is going to be passed to the mutator executable(s).-o, --output, -output
lets you choose where to put the mutant.-pp, --print-pretty
, prints the output in a pretty format in a new file. The new file has the same name with a “-pretty” added to the name in the same directory.-t, --test
, runs the tests on the built executables. It should be followed by an executable name and the test to run on it. The accepted options are: tdd,valgrind. For example:-test mutator-lvl0 valgrind
.-opts --options, pass options to the executable(s). The executables support all the clang options. please enclose all the options in double quatation. This is basically a pass-through option. Everything appearing inside will be passed through to the executable.
-copts --customoptions
, just like-opts
but passes the custom options defined for each executable. It is pass-through. Example:-copts "-MainOnly=false -SysHeader"
.
m0
options:
- SysHeader, will let the executable know that you wish the checks to run through system headers as well. Off by default.
- MainOnly, will only publish check results for matches residing in the main file,i.e. The current TU(Translation Unit).
- MisraC2004,MisraC2012,C2,C3 will let the executable know which Misra guidelines you want the source to be checked against. Currently only supports MisraC2004 or C2.
Note
Some of Misra-C rules are already implemented by Clang as warnings, so for those cases, mutator uses the built-in diagnostics instead of re-inventing the wheel. For those diagnostics to appear in the mutator report you should refrain from using the Clang -w
flag as that silences the warnings.
If you are running the executables using mutator.sh
you don’t need to read this note through. If you are running the executable directly however, then you have to pass groups of arguments in a specific order otherwise the executable won’t be able to recognize the options and will throw errors. For example this is the right way to run mutator-lvl0
:
./mutator-lvl0 -SysHeader=false -MainOnly=true ./test/testFuncs3.c -- -std=c90 -Wall -I/lib/gcc/x86_64-redhat-linux/5.3.1/include
So for example if you want to run the TDD tests for the Misra-C checker, you run:
./mutator.sh -c misrac -i ./test/testFuncs2.c ./test/testFuncs1.c -opts "-Wall -std=c90"
Do note that if your file has included standard header libraries, you do need to tell it where to look for them, so for the above example on Fedora, you would need to run:
./mutator.sh -c misrac -i ./test/testFuncs2.c ./test/testFuncs1.c -opts "-Wall -I/lib/gcc/x86_64-redhat-linux/5.3.1/include/"
Here’s the command I use to run the TDD tests:
/mutator.sh -c misrac -i ./test/testFuncs1.c ./test/testFuncs2.c -pp -opts "-std=c90 -I/lib/gcc/x86_64-redhat-linux/5.3.1/include" -copts "-SysHeader=false -MainOnly=true" 2> /dev/null
The Action File
mutator
can accept a file which tells it what to do. Currently this feature is only supported for m0
. You can find a sample under ./samples
named action_file.mutator
.
action_name:my_action1
executable_name:mutator-lvl0
#these are the options specific to the executable
exec_opts:-SysHeader=false -MainOnly=true
in_files:./test/testFuncs1.c ./test/testFuncs2.c ./test/testFuncs3.c
#clang options
libtooling_options:-std=c90 -I/lib/gcc/x86_64-redhat-linux/5.3.1/include
#the output file
out_files:./test/misra-log
#the log file
log_files:
print_pretty:true
end_action:run
Here’s the explanation for the fields:
action_name
lets you specify a name for the action to run. Marks the start of an action.executable_name
is used for determining which executable to run.exec_opts
is the field used for passing the executable-specific options.in_files
is a list of the input files to pass to the executable.libtooling_options
is used for passing the clang options.out_files
is used to pass the result file to mutator. Formutator-lvl0
, this field determines the Misra-C check results.log_files
is used to pass the file to hold the log. Mostly meant to be used withmutator
andmutator-lvl2
.print_pretty
is a boolean switch. Used for runningReportPrintPretty.sh
.end_action
is used to tellmutator.sh
what action to do. Currently the only supported options are “run” and “stop”. “run” will run the action and “stop” will not run it. Also marks the end of an action.- Lines starting with a hash(
#
) are considered comments.
Field names shall not have preceding whitespace or tab. The :
character shall immediately follow the field name with options appearing after it.
end_action
field should appear as the last field of a action.
You can run the sample action file with this:
./mutator.sh --file samples/action_file.mutator
Currently, the mutation-only features(mutation for the sake of mutation, technically implementing Misra-C is also a form of mutation) are turned off in mutator and mutator-lvl2 though some automatic code refactoring features work in both executables. Just run a sample code through mutator and then mutator-lvl2 for a demo.
If your code needs a compilation database for clang to understand it and you don’t have one,you can use Bear. Please note that bear will capture what the make runs, not what is in the makefile. So run make clean
before invoking bear make target
. cmake
can also generate compilation databases if you are using it.
Implementation Notes
This part contains notes regarding the implementation of m0, m1 and m2.
mutator-lvl0
-
The implementation for the Misra-C:2004 rules 11.1,11.2,11.4 and 11.5 might seem unorthodox. Here’s the explanation. The essence of the 11.1,11.2,11.3 and 11.4 rules as a collective is (after being translated into clang AST) that any time there is an
ImplicitCastExpr
orCStyleCastExpr
that hasCastKind = CK_BitCast
the rule-checker should tag it.CK_BitCast
means that a bit-pattern of one kind is being interpreted as a bit-pattern of another kind which is dangerous. ThisCastKind
couple with the otherCastKinds
provided by the clang frontend enable us to tag cases where there is a deviation from the specified rules. Of course it is possible to check for exactly what the rules ask for but execution-time. -
The implementation for the Misra-C:2004 rule 16.7 only checks for changes made to the pointee object when the pointer is the LHS of a binary
=
operator. Changes can be made to the pointee object through UnaryOperators++
and--
but since the*
UnaryOperator is also involved, the behaviour is undefined as to which unaryOperator is evaluated at first so depending on the original build toolchain’s implementation, it could modify the pointer itself or the pointee object. such cases are already being tagged by 12.13 and the fix to that rule will either make the source code in a way that will be tagged by 16.7 or fix it so it wont get tagged. Either way, it is pointless to look for changes to pointee objects through++
and--
operators, postfix or prefix. Do note that even if at later times, mutator supports pragmas for different compiler implementation behaviours, the last argument still stands.
Directory Outline
Here’s a quick look into the project files and directories:
- mutator-lvl0.cpp contains the Misra-C rules to check. The Executable named after it, will run the Misra-C rule checks.
- mutator-lvl1.cpp contains the mutators which are not compiled for the time being since im working on Misra-C only for the time being, along with some Misra-C implementers.
- mutator-lvl2.cpp contains some other Misra-C implementers. Rewriting the code in multiple stages allows for more simplistic rewrites and is also a check to see whether the output is actually buildable.
- mutator.sh is the UI, which is supposed to work like just any other nix UI(option-wise).
- The utility folder holds the C source and headers that are necessary to run the instrumented code(currently unused).
- mutator-aux.cpp.h hold the auxiliary functions that most modules will need.
- Well there is the makefile.
- The test folder holds the TDD tests.
- The docs folder contains the documents related to the project. Currently the doc for the current status of the Misra-C:2004 implementation is there.
- The folder named tinyxml2 holds the tinyxml2 source files.
- The folder named extra-tools holds some tool that help the dev process.
- The folder named samples holds the output samples for the project. Currently, you can find the text and XML output of the Misra-C rule checker run over the TDD tests.
Dev Method
TDD tests are created for each added feature which are stored under the test folder in the repo.
Smoke tests and Daily builds are conducted to make sure the code base builds correctly more than once every day.
Every time there is a new commit, the code base is buildable and runnable. If you are having problems, raise an issue or let me know.
The code base uses Coverity for static analysis and CI Travis for checking the build matrix.
Coveralls integration with Travis for code coverage.
Also the precommitTests.sh
script under extra-tools
is run before every commit to make sure commits are not horribly broken.<br>
Notes
The project will be updated every time there is a major LLVM release and will use those libraries instead of the old ones for development
The project might, at a later point in time, start using Cmake for the build process.
Misra 2012 support will be added in the future.
Also a note regarding building the LLVM libraries. It is safer to build the libraries with clang++ if you’re going to later use those libraries with clang++(you can get the distro version of clang from your distro’s repo). The same applies to g++.
The master branch is the dev version. Release versions will be forked.
FAQ
tool complains that it can’t find stddef.h
Tool complains that it cannot find stddef.h
or some other similar header. If that happens to you , it’s because the tool can’t find the clang built-in headers. run llvm-config --libdir
, then head on to clang
. Inside that directory you should see one(or maybe more) llvm/clang versions. Pick the one you used to build cgrep against. Inside that directory there will be a directory named include
. Pass that to the tool any way you see fit.
Alternatively, $(llvm-config --libdir)/clang/$(llvm-config --version)/include
should give the path the tool needs to include. If you build your llvm/clang from upstream, this might not work. SVN bulds will have the svn string attached to the version number.
You could,for example, use --extra-arg=-I/usr/lib/llvm-9/lib/clang/9.0.0/include
to call cgrep or you could just alias cgrep
to cgrep --extra-arg=-I/usr/lib/llvm-9/lib/clang/9.0.0/include
.
Acknowledgements
Project mutator uses the following libraries:
- LLVM/Clang
- Lua
- Linenoise
- capstone
- keystone
- TinyXML2
- JSON
- SaferCPP
- LuaJIT
- keccak-tiny
- Thanks to Jonathan Brossard for WCC, specifically
wsh
which is the inspiration forbruiser
. Check it out if you haven’t already.
All mutator source code is provided under GPL-3.0.
All libraries have their respective licences. For more info you can just visit their respective links.
Feedback
Besides that, If you have any suggestions or have any feature requests for project mutator, you can send them to thabogre@gmail.com
. I’ll try to keep an open mind, so even if you feel like it might not be right up mutator’s alley, do send them. Worst case, I’ll just say no.
TODO List
For a list of things that need to be done, take a look at the list of issues.
Contributions
For a full description please read Contributions.md
in the repo root.
You can also choose to contact me directly if you want to.
Support
Well, I don’t have the Misra-C:2012 Document. If you or your organization/company are willing to donate a copy to mutator, hit me up.
Testers are always welcome. If you are interested, let me know. Testing mutator is as important, if not more, than implementing it.
Contact
You can email me at thabogre@gmail.com, there is also the twitter account for the mutator project, @xashmith and there is the mutator maillist, mutator-repost@freelists.org. You need to be a member though to be able to send mail on the maillist. The maillist is moderated.