Skip to content

Darkkey/erlamsa

Repository files navigation

erlamsa

Erlamsa -- "<<smart>> dumb fuzzer" aka erlang port of famous radamsa fuzzer.

TL;DR

$ sudo apt-get install git gcc make erlang erlang-dev erlang-tools erlang-ssl erlang-eunit erlang-mnesia erlang-inets
$ git clone https://github.com/Darkkey/erlamsa && cd erlamsa && make
$ echo 'Hello erlamsa!' | ./erlamsa

Features

  • mutational-based fuzzing engine based on radamsa;
  • support for fuzzing protocols over HTTP, TCP, UDP, and raw IP/network, support of fuzzing over TLS, HTTP/2 fuzzing proxy mode;
  • built-in fuzzing proxy for MitMing and fuzzing connection(s) between target's client and server;
  • FaaS (fuzzing-as-a-service) mode, plain HTTP and HTTP/json queries are supported;
  • Examples on how to call erlamsa from C#, Node.js, Go, Python2/3 are available (see clients/);
  • <<smart>> patterns and mutations, e.g. CRC and sizer fields detection, fuzzing of data inside archives, base64-encoded data decoding, e.t.c.;
  • fuzzing for SSRFs, XXEs, ZIP path traversals;
  • various monitors to detect crashes and loggers to store fuzzing data;
  • support for external modules.

Installation:

Prerequisites

Git, Erlang. If you want to use raw IP output, gcc and make are required to build procket.

Installing erlang

Erlamsa requires erlang/OTP 18.0+ to run.

Download erlang from official website http://www.erlang.org, install and put in path to erlc, erl and escript binaries into PATH variable. Or use your system's packet manager to install it.

On OS X (using homebrew):

brew install erlang

On CentOS/RHEL:

yum install erlang

On Debian/Ubuntu/Kali:

apt-get install erlang erlang-dev erlang-tools erlang-ssl erlang-eunit erlang-mnesia erlang-inets

Building erlamsa

Get the latest version of erlamsa:

git clone https://github.com/Darkkey/erlamsa
cd erlamsa

On Linux/OS X/BSD:

make 

On Windows (escript.exe and erlc.exe should be in %PATH%):

make_windows.bat

Docker

Alternatively, you could use erlamsa Docker container: https://github.com/Darkkey/erlamsa-docker-image

Standalone usage:

Under Linux/OS X use ./erlamsa, under Windows -- erlamsa.bat.

Few examples/templates for a quick start:

$ echo 'Hello erlamsa' | ./erlamsa
Hello erlmo erlamsa
$ ./erlamsa <<FILE TO FUZZ>>
$ ./erlamsa <<FILE TO FUZZ>> -o <<FILE TO FUZZ>>.fuzzed
$ ./erlamsa <<FILE TO FUZZ>> -o tcp://:<<LISTEN_ON_PORT>>
$ cat <<BINARY WITH PACKET>> | ./erlamsa -o udp://<<HOST>>:<<PORT>>
$ cat <<FILE WITH POST QUERY>> | ./erlamsa -o https://<<SERVER>>:<<PORT>>/script.jsp?param1=value,POST,<<Header1>>=<<Header1value>>
$ ./erlamsa <<BINARY WITH PACKET>> -o serial:///dev/ttyUSB0,9600
$ echo '<<DATA>>' | ./erlamsa exec://<<APP_TO_FUZZ_FROM_STDIO>>

For help try:

./erlamsa --help

or

escript erlamsa --help

Also try --list option to show all possible inputs, outputs, mutators, patterns, loggers and monitors.

Using as a service

Launch as a service:

./erlamsa -H 127.0.0.1:17771 -L -

Or, in detached mode (erlamsa will go background after launch):

./erlamsa -H 127.0.0.1:17771 -D

HTTP POST your data to http://<Host:Port>/erlamsa/erlamsa_esi:fuzz as application/octet-stream. See examples in clients/ folder (provided for C#, Go, Node.js and python2/3). E.g. for Python 2.7:

import httplib

erlamsa_url = '127.0.0.1:17771'

original_string = "Hello erlamsa!"

httpconn = httplib.HTTPConnection(erlamsa_url)
headers = {"content-type": "application/octet-stream"}
httpconn.request('POST', '/erlamsa/erlamsa_esi:fuzz', original_string, headers)
response = httpconn.getresponse()

fuzzed_string = response.read()

print(original_string + " erlamsed to " + fuzzed_string)

Result:

$ python clients/erlamsa_python_client.py
Hello erlamsa! erlamsed to rlamsa!rlallo eHello e

JSON service endpoint

Erlamsa also provides JSON service extension, which allows to send request in JSON documents. Fuzzing data should be encoded in base64 format and provided inside data field of the document, e.g.:

$ curl -H "Content-Type: application/json" -X POST -d '{"data":"aGVsbG8="}' http://localhost:17771/erlamsa/erlamsa_esi:json
{"data": "bGxvbGxvaA=="}

PyErlamsa module

For Python 3 you could use more handy pyerlamsa (check https://github.com/Darkkey/pyerlamsa/ for more info) module:

Connecting to local erlamsa instance:

$ pip3 install pyerlamsa
$ python3
...
>>> import pyerlamsa
>>> e = pyerlamsa.Erlamsa('http://127.0.0.1:17771')
>>> e.call('Hello erlamsa!');
(True, 'Hell4amsa15i685\x81\x91')

Connecting to erlamsa cloud:

...
>>> e = pyerlamsa.Erlamsa('https://erlamsa.online', token="yourtoken")
>>> e.call('Hello erlamsa!');
(True, '%n erlamsa!')
>>> e.call('Hello erlamsa!');
(True, 'lamsa!lo\x1ferHel')
>>> e.call('Hello erlamsa!');
(True, 'Hello erlamsa!Hello erlamsa!')

Fuzzing options

For standalone Web or JSON fuzzing, along with fuzzing data, you could also provide fuzzing options, including mutations, patterns, seed, blockscale, e.t.c. The format of these options should be the same as in according command line keys. Pass them as HTTP headers (for standalone Web service) or as JSON members (for JSON endpoint). E.g.:

$ curl -H "Content-Type: application/json" -X POST -d '{"data":"aGVsbG8=","seed": "1,2,3"}' http://localhost:17771/erlamsa/erlamsa_esi:json
{"data": "aGVsW2xv"}

Using as fuzzing proxy

Erlamsa could be used a fuzzing "MiTM" proxy for HTTP(s), TCP (also TLS) and UDP protocols. This allow to fuzz the communication between server and client, modifying packets coming from server to client, from client to server, or in both cases.

To use it as fuzzing proxy, run as:

./erlamsa -i proto://lport:[udpclientport:]rhost:rport -P probsc,probcs

where probsc and probcs are floats in range of 0.0 to 1.0, that represents probabilities of fuzzing packets from server to client and client to server.

E.g. erlamsa, that is started as

./erlamsa -i tcp://7777:192.168.0.1:7777 -P 0.1,0.7 -L -

will accept packets on port 7777 (on all network interfaces, basically on 0.0.0.0 interface) and send them to host's 192.168.0.1 port 7777. All packets coming from server to client will be fuzzed with probability of 0.1(10%), from client to server -- with probability of 0.7(70%). In this case, to start fuzzing just point your client application to erlamsa's host and port 7777. -L - options means that all logging will be output to stdout.

Addtionally, erlamsa supports so-called "standalone http-proxy mode", when erlamsa proxifies connections as standard HTTP-proxy and fuzzing requests/replies based on provide probabilities. To use erlamsa in this mode, please use e.g.:

./erlamsa -i http://proxy:7777 -P 0.1,0.7 -L -

Then, specify in the target HTTP proxy settings erlamsa host as a hostname and 7777 as proxy port. If you're planning to fuzz TLS-connections, don't forget to supply correct certificate to erlamsa via --certfile and --keyfile options. If target is using binary connection, please user tcp instead of http in -i option.

Example usage from erlang code

There are two possible ways to call erlamsa from your code: static (same host, library call) and dynamic (query the application on another node)

  1. Static direct usage: see erlamsa_app:fuzz/1 and erlamsa_app:fuzz/2, e.g.:
$ erl -pa ebin -pa deps/*/ebin
...
Eshell V10.0.3  (abort with ^G)

1> erlamsa_app:fuzz(<<"123">>).
<<243,160,128,169,49,50,51>>
2>
  1. Remotely, on another node:

    a) Start and test fuzzing node:

    $ erl -pa ebin -pa deps/*/ebin -sname erlamsa
    ...
    
    (erlamsa@server)1> erlamsa_app:start(direct, maps:new()).
    ok
    (erlamsa@server)2> erlamsa_app:call(erlamsa, <<"123">>).
    <<"12311223123">>
    (erlamsa@server)3>
    

    b) Run on client node:

    $ erl -pa ebin -pa deps/*/ebin -sname client
    ...
    
    (client@user)1> erlamsa_app:start(remote, {erlamsa, 'erlamsa@server'}).
    {test,<0.66.0>}
    (client@user)2> erlamsa_app:call(erlamsa, <<"321">>).
    <<"3321">>
    

External (extension) scripts

Erlamsa could use external scripts for generation-based fuzzing, custom fuzzing, custom post-fuzzing procedures or custom mutation types. Module should be compiled with erlc before using and passed using -e option to erlamsa. Due to internal mechanism of external modules inclusion, you should pass external module ALWAYS as a FIRST argument to erlamsa.

In the following example, erlamsa is run with custom mutation module (see external_muta.erl for details):

$ echo -n 123 | ./erlamsa -e external_muta -m pan=1 -p od
<pancaked>123</pancaked>

Custom fuzzing extension

Could be used in fuzzing proxy mode, to replace standard fuzzing procedure with a custom one. See external_test.erl for example template.

Custom mutation extension

Adds custom mutation to the list of erlamsa mutators. See external_muta.erl for example.

Custom post-processing extension

Adds post-processing procedure that will be applied to fuzzing result just before output. Useful for fixing checksum or form of data to avoid unnessesary noise. See external_nhrp.erl for example.

Monitors

Erlamsa is using monitors, special modules that are intended to detect various events, like application crashes, freezes, SSRFs, backconnects, e.t.c. Monitor is waiting for some event, and, upon receiving it, reports to the logs and execute specified after actions. Each monitor is a separate process, that could be initiated via passing -O name:params in the command line. By default, cm (connect monitor) is run. To disable monitors that are run by default, one could pass -O !monitor_name:off in the command line. E.g., to disable connection monitor, pass -O !cm:off as an command line option to erlamsa.

Monitor parameters

Parameters are passed to monitors in a form of comma-delimeted list, e.g.: -O monitor_name:param1=value1,.... Parameters are split to the generic ones and monitor-specific ones. Generic ones include:

  • after= -- specifies the type of after-action that will be performed after monitor event is triggered. After-action options are specified in the after_params= monitor parameter. Below, there is a list of currently supported after actions:
    • exec -- executes specific process or shell script right after the monitor event is triggered. E.g., the following command line forces to restart run script hello.sh after connection event was triggered: -O cm:after=exec,after_params=hello.sh.

Monitors list

Below, it could be found all currently supported by erlamsa monitors and corresponding parameters:

  • cm -- connection event monitor. Run by default when eramsa is started. Listen on the endpoint specificed by host= option and port= option (default is 51234). Upon recieving the connection, reports incoming data to the logs, and wait for connection is being closed by client or a certaing timeout (specified by timeout= option, default is 5000 (5 seconds)). This event monitor is intended to catch SSRFs, XXEs, backconnects or other events that could be generated during the fuzzing.

    • built-in event monitor -- connection monitor has built-in event monitor. This could be used for writing your own agents that will monitor the state of target and send events to erlamsa. It comes very handy when you want to have time syncronization with the fuzzing data that is generated by fuzzer. E.g., you could use clients/simple_process_monitor.sh on a remote host to monitor a state of a process and send event to erlamsa in case of absence of the process. Later, by reviewing logs you will be able to see at what actual time the process was crashed and determine what data caused it. To send an event to erlamsa, just send message with the prefix {event} to the connection event monitor port. See simple_process_monitor.sh as an example of doing it.
  • cdb -- monitor for CDB Windows debugger. This monitor is attaching to / running fuzzed process and catches potential crashes. Upon catching a crash, it reports it to the logs and writes minidump file. Only for Windows platform. Supported options includes:

    • app= -- runs executable file to be monitored; application will be automatically restarted after crash;
    • pid= or attach= -- attaches to the process by pid or its name.
  • lc -- monitor for adb/logcat crash detection for Android applications. This monitor is runs and monitors fuzzed process and catches potential crashes. Upon catching a crash, it reports data that appeared in the Android log. Supported options includes:

    • app= -- application name to be run and monitored;
    • activity= -- application activity to be invoked upon application run;
    • adbpath= -- path to adb executable.
  • probe -- network probe monitor. This monitor send network "probes" (e.g. UDP packets or TCP connections) to the target endpoint and alarms if there is a timeout and/or connection refused happened. Supported options includes:

    • url= -- target endpoint URL in form of {tcp|udp}://host:port
    • hello= -- packet to send (in hex)
    • delay= -- delay between probes (1000 by default)
    • timeout= -- timeout on absence of answer (5000 by default)
    • report= -- what to report: all, timeout or econnrefused (all by default)
  • r2 -- monitor for Radare2 debugger. This monitor is running fuzzed process and catches potential crashes. Upon catching a crash, it reports backtrace and registers to the logs. Only for Linux/OS X platforms. Supported options includes:

    • app= -- runs executable file to be monitored; application will be automatically restarted after crash;
    • r2path= -- path to r2 executable.

Platform limitations

  • on unix platforms (Linux, OS X, ...) erlamsa could not be launched in background mode using standard & shell symbol due to erlang VM limitations; -D option is intended for it. E.g., instead of ./erlamsa -H 127.0.0.1:17771 & use ./erlamsa -H 127.0.0.1:17771 -D
  • exec://, serial://, ip:// and raw:// outputs are not supported on Windows, raw:// output is not supported on OS X
  • minimum recommended RAM to run on Windows OS is 4Gb
  • erlamsa spawns separate process upon startup, to avoid this behaviour (and save some performance) you could use eerlamsa/eerlamsa.bat scripts.

Warning

Erlamsa is a tool that tries to generate data that could be used for testing programs against unexpected data. Thus, using erlamsa against software that may contain bugs (especially in a case when it is running with high privileges), can result in crashes, freezes, reboots, kernel panics, bluescreens, loss of data and other stuff. DO NOT use it against production system or under high-privilege user account. Using emulators or disposable systems is highly recommended.

Remember, that THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Code Status

Build Status