/lwip-bug-finder

lwipのバグを半自動検出くん。First introduced in 「2018年 暗号と情報セキュリティシンポジウム」(SCIS2018).

Primary LanguagePython

lwip bug finder

Find bugs with symbolic execution!

Requirements

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 if ImportError: 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

Installation

apt install

Install following packages beforehand.

sudo apt install python python-pip pypy pypy-dev graphviz libffi-dev libncurses5-dev 

git clone

This repository has git submodule. --recursive option will work.

git clone --recursive https://github.com/ertlnagoya/lwip-bug-finder.git

build lwip applications with each versions of lwip (NOT WORKING?)

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.

Usage

Analysis Flow:

  1. Before Analysis
    • Do memory dump
    • Do preprocess
  2. Main Analysis
    • Configure analysis options
    • Run solver
  3. After Analysis
    • Check results
    • Reproduce found bug (attack lwip application)

TODO: work-flow figure

I. Before Analysis

(Optional) analyze.py

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

memory-dump.py

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:

  1. load this script in gdb attached to target process (use source command in gdb)
  2. 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!

preprocess.py

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

Don't worry, solvers mentions how to run. Follow his instructions.

II. Main Analysis

Configure analysis options

./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

Run solver

(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.

about options

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

to find bugs

(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

III. After Analysis

Check ./last-output directory

Following files are located in this directory when analysis succeeded:

  • README.md
  • result.py
  • angr.log
  • ./trace
about ./trace directory

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.

Reproduce found bug

Generated script ./result.py attacks lwip applications and invokes the bug.

Tips

emoviz

emoviz is angr's history visualizer module. See emoviz.py for detail. See lwip-bug-finder.py for usage.

lwip-solve-bug24596.py

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.