#fuzzing #byte-range #bit #flipper #corruption #file-manipulation

app flipperbit

Corrupted files generator. Random bits flipper.

4 releases

0.1.3 Dec 26, 2022
0.1.2 Jul 14, 2022
0.1.1 Jul 5, 2022
0.1.0 May 16, 2022

#1788 in Command line utilities

Download history 9/week @ 2024-09-22 2/week @ 2024-09-29

925 downloads per month

GPL-3.0-only

25KB
294 lines

FlipperBit

Flipperbit generates multiple corrupted variants of an input file by randomly flipping bits in selected byte ranges.

Flipperbit allows to specify multiple byte ranges and the bit flipping probabilty.

The output of flipperbit can be used as input to software (E.g., bulk file processing applications, file parsing utilities) as a form of dumb fuzzing.

Installing

Install flipperbit using cargo:

cargo install flipperbit

Building

Clone the repository and build flipperbit with:

git clone https://github.com/0xor0ne/flipperbit && cd flipperbit
cargo build --release

flipperbit built executable is located in ./target/release/flipperbit.

Usage

Here is the help message of flipperbit:

>>> ./target/release/flipperbit -h
flipperbit 0.1.0
0xor0ne
Corrupted files generator. Random bits flipper.

USAGE:
    flipperbit [OPTIONS] --infile <INFILE> --outdir <OUTDIR>

OPTIONS:
        --fprob <FPROB>      Probability of flipping a bit [default: 0.2]
    -h, --help               Print help information
        --infile <INFILE>    Original file
        --nflips <NFLIPS>    Probability of flipping a bit [default: 1]
        --outdir <OUTDIR>    Output directory where the corrupted files will be saved
        --range <RANGES>     Bytes range to corrupt. E.g., '4,30', '4,' or ',30'
    -V, --version            Print version information
  • --infile: (mandatory) path to the original file whose content will be randomly corrupted for each output file generated.
  • --outdir: (mandatory) output directory where the corrupted files generated by flipperbit will be saved.
  • --nflips: (optional) number of corrupted file variants to generate. By default only 1 output file is generated.
  • --fprob: (optional) probability of flipping a single bit. By default 0.2.
  • --range: range of bytes to corrupt (bytes are 0-based indexed). Every bit in the range has a probability of --fprob to be flipped. This option can be specified multiple times for defining different byte ranges. A range is specified as two comma separated integers (e.g., "4,63"). The first value in the range must be lower or equal to the second. flipperbit will corrupt bytes from the first value in the range up to the second value included. If the first value is not specified (e.g., ",63") flipperbit assumes 0. If the second value is not specified (e.g., "4,") flipperbit assumes input file size minus 1.

NOTE: the files generate by flipperbit and saved in --outdir will be named as <idx>_<input_file_name> where idx goes from 0 to --nflips - 1. Files with the same name already existing in --outdir will be overwritten.

Examples

ELF file corruption

The following example (assuming Linux) shows hot to generate 10000 corrupted version of /bin/ls (ELF file). The 10000 corrupted ELF files are saved in /tmp/elf_ls_corrupted. This particular example generates ELF files with a corrupted header. The specified byte range skips the first 24 bytes in order to avoid corrupting the header fields e_ident, e_type, e_machine and e_version.

flipperit --infile /bin/ls \
  --outdir /tmp/elf_ls_corrupted \
  --range "24,63" \
  --fprob 0.05 \
  --nflips 10000

The output of file command on the generated ELFs shows that they are indeed corrupted:

>>> file /tmp/elf_ls_corrupted/*
...
/tmp/elf_ls_corrupted/1004_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), corrupted program header size, corrupted section header size
/tmp/elf_ls_corrupted/1005_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), corrupted program header size, missing section headers at 72057594039114192
/tmp/elf_ls_corrupted/1006_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), too many program (8207)
/tmp/elf_ls_corrupted/1007_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), can't read elf program headers at 3298535161936, missing section headers at 19140302778533328
/tmp/elf_ls_corrupted/1008_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), corrupted program header size, corrupted section header size
/tmp/elf_ls_corrupted/1009_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), can't read elf program headers at 81065892804296768, corrupted section header size
/tmp/elf_ls_corrupted/100_ls:  ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), corrupted program header size, corrupted section header size
/tmp/elf_ls_corrupted/1010_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), corrupted program header size, missing section headers at 15764797720238800
/tmp/elf_ls_corrupted/1011_ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), too many program (16429)
...

In the second example instead we corrupt only the 18-th and the 19-th byte which correspond to the field e_machine in the ELF header.

flipperit --infile /bin/ls \
  --outdir /tmp/elf_ls_corrupted \
  --range "18,19" \
  --fprob 0.3 \
  --nflips 10000

the output of file command shows that the "ELF architecture" is a random different values in each of the generated output file:

>>> file /tmp/elf_ls_corrupted/*
...
/tmp/elf_ls_corrupted/1001_ls: ELF 64-bit LSB pie executable, *unknown arch 0xffff8e36* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1002_ls: ELF 64-bit LSB pie executable, *unknown arch 0x5033* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1003_ls: ELF 64-bit LSB pie executable, *unknown arch 0x401a* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1004_ls: ELF 64-bit LSB pie executable, *unknown arch 0x4c2a* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1005_ls: ELF 64-bit LSB pie executable, *unknown arch 0x409a* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1006_ls: ELF 64-bit LSB pie executable, *unknown arch 0xffff8c5c* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1007_ls: ELF 64-bit LSB pie executable, *unknown arch 0xcd* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1008_ls: ELF 64-bit LSB pie executable, *unknown arch 0x863* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1009_ls: ELF 64-bit LSB pie executable, *unknown arch 0x226e* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/100_ls:  ELF 64-bit LSB pie executable, *unknown arch 0x293e* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1010_ls: ELF 64-bit LSB pie executable, *unknown arch 0x5ab6* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1011_ls: ELF 64-bit LSB pie executable, *unknown arch 0x1225* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
/tmp/elf_ls_corrupted/1012_ls: ELF 64-bit LSB pie executable, *unknown arch 0xffffb076* version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6193e7eab54665ca319fbbf164b4e40abdab62bc, for GNU/Linux 4.4.0, stripped
...

PCAP file corruption

This example shows how to use flipperbit to generrate corrupted pcap files. In this particular case the range "20,20" is used. This means that only the 20-th byte of the input file is randomly corrupted. The 20-th byte in the pcap file corresponds to the least significant byte of the Data Link Type field.

wget https://www.malware-traffic-analysis.net/2022/05/10/2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap.zip
unzip -Pinfected 2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap.zip
flipperit --infile 2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap \
  --outdir /tmp/pcap_corrupted \
  --range "20,20" \
  --fprob 0.5 \
  --nflips 256

the output of tcpdump shows that the data link type is indeed randomized:

>>> find /tmp/pcap_corrupted -type f -exec tcpdump -nn -c1 -r {} \;
...
reading from file /tmp/pcap_corrupted/112_2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap, link-type ARCNET_LINUX (Linux ARCNET), snapshot length 65535
reading from file /tmp/pcap_corrupted/111_2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap, link-type NULL (BSD loopback), snapshot length 65535
reading from file /tmp/pcap_corrupted/110_2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap, link-type 5, snapshot length 65535
tcpdump: unknown data link type 5
reading from file /tmp/pcap_corrupted/109_2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap, link-type ARCNET_LINUX (Linux ARCNET), snapshot length 65535
reading from file /tmp/pcap_corrupted/108_2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap, link-type EN10MB (Ethernet), snapshot length 65535
reading from file /tmp/pcap_corrupted/107_2022-05-10-Contact-Forms-IcedID-infection-with-Cobalt-Strike.pcap, link-type 5, snapshot length 65535
...

TODO

  • Improve performance by making files creation async.

References

Dependencies

~4MB
~71K SLoC