Find bugs with symbolic execution!
Suggested commands are based on Ubuntu 16.04.
- Python2
- angr 7
sudo -H pip install angr
sudo -H pip install -I --no-use-wheel capstone
ifImportError: cannot import name arm
occurs
- cxxfilt, hexdump
sudo -H pip install cxxfilt hexdump
- scapy (packet manipulation library)
sudo -H pip install scapy
- graphviz
- To generate state history graph. Used by
emoviz.py
. sudo apt install graphviz
- To generate state history graph. Used by
Install following packages beforehand.
sudo apt install python python-pip pypy pypy-dev graphviz libffi-dev libncurses5-dev
This repository has git submodule. --recursive
option will work.
git clone --recursive https://github.com/ertlnagoya/lwip-bug-finder.git
simhost (located in unix/unixsim) and echop (located in unix/minimal) are applications provided by lwip-contrib.
build-full-version-simhost.sh
builds simhost.
Executables are located in ./bin
.
build-full-version-dns-echop.sh
builds echop which is DNS client.
Executables are located in ./bin
.
I git added my simhost-STABLE-1_3_0
and echop-STABLE-1_3_0
for my solver.
Analysis Flow:
- Before Analysis
- Do memory dump
- Do preprocess
- Main Analysis
- Configure analysis options
- Run solver
- After Analysis
- Check results
- Reproduce found bug (attack lwip application)
TODO: work-flow figure
CAUTION: Requires install radare2
This is function/data dependency analysis utility.
usage: analyze.py ELF_FILE FUNCTION_NAME_TO_START_ANALYSIS
for example:
% ./analyze.py bin/echop-STABLE-1_3_0 dns_recv
{'sym.snmp_mib_lrn_free', 'sym.pbuf_copy_partial', 'sym.memp_free', 'sym.dns_recv', 'sym.pbuf_free', 'sym.ntohl', 'sym.lwip_standard_chksum'}
{'obj.memp_tab', 'obj.dns_table', 'obj.dns_payload'}
You see functions snmp_mib_lrn_free
, pbuf_copy_partial
, ... are called after dns_recv
has called,
and objects memp_tab
, dns_table
, dns_payload
are referenced after dns_recv
has called.
Known issue:
- NOT works with ARM binary
- radare does not analyze data dependency correctly
This is memory dump utility. This dumps process memory and saves dumps with zip format. You must specify target binary name and memory regions using arguments.
dump steps:
- load this script in gdb attached to target process (use
source
command in gdb) - run
python memory_dump(BIN_NAME, [(begin,end)])
(begin, end)
is a address pair of memory area
for example:
$ sudo gdb -p `pgrep echop` ### attach to target process
[...]
gdb-peda$ source /media/sf_share/lwip/memory-dump.py
usage: python memory_dump(bin_name,[(begin,end), ...])
gdb-peda$ python memory_dump("bin/echop-STABLE-1_3_0", [(0x00619000,0x00620000)])
mem: 0x619000 0x620000
[[6393856, 6422528, "memory-619000-620000"]]
zip name: bin/echop-STABLE-1_3_0-dump.zip
[*] memory dump done! Go on your analysis!
This is helper script. Running this script is required by solvers. This script collects following informations:
- symbol information
- address and size
- function caller address
- collect instructions (such as
call func_x
) address
- collect instructions (such as
Don't worry, solvers mentions how to run. Follow his instructions.
./config
directory holds configuration files.
Configuration files describes analysis options.
Following options are available:
- arch: CPU architecture
- arch_bits: CPU bits (32 or 64)
- ELF_FILE: target binary to be analyzed
- dump: memory dump file (zip file; generated by
memory-dump.py
) - skip_funcs: functions to be blocked call
- init_objs: objectes should be initialized in the symbolic engine
- find: same with angr's find
- avoid: same with angr's avoid
(runtime: < 3 min)
Solver explores target binary to find bugs.
result.py
to reproduce found bug is generated when a bug is found.
dns-echop
(named as bin/echop-***
) is DNS client.
He sends a DNS request at initialization phase.
Exploration results are saved to last-output
directory when exploration succeeded.
Here are options in lwip-bug-finder.py
:
-c
: (required) configuration file (must be located in config
directory)
-f
: (required) function name to start analysis
--dfs
: Depth-first search mode in exploration (default is Width-first search)
--segv
: Segmentation fault detection mode
(Run time: < 3min)
DNS bug #1, #2 are described in doc/dns-bugs.md.
### to find lwip bug #24596 (TCP bug)
./lwip-bug-finder.py -c intel_simhost -f tcp_input
### to find DNS bug #1
./lwip-bug-finder.py -c intel_echop -f dns_recv --dfs # or
./lwip-bug-finder.py -c intel_echop -f dns_recv -b 1,2 --dfs
### to find DNS bug #2
./lwip-bug-finder.py -c intel_echop -f dns_recv -b 1,2 --segv
Following files are located in this directory when analysis succeeded:
- README.md
- result.py
- angr.log
- ./trace
angr's state history is visualized with emoviz in this directory (saved as {dot,png} file). Let's check!
This directory is located in root directory when analysis failed.
Generated script ./result.py
attacks lwip applications and invokes the bug.
emoviz is angr's history visualizer module.
See emoviz.py
for detail.
See lwip-bug-finder.py
for usage.
Running lwip-solve-bug24596.py
will generates attack packet for lwip bug #24596 and saves result to result.py
.
Run sudo ./simhost-STABLE-XXX -d
and run sudo python result.py 0
to attack simhost. Version of lwip must be 1.x.
script/lwip-bug24596.py
is PoC of this lwip bug #24596.