Gravitational plate of three masses and a slashed discABC0Static engraved plate. Three-dimensional view is unavailable or reduced motion is requested.

← back to fieldarticle

articleAug 14, 2020

Using angr for Binary Analysis, Part 3

Walkthrough of the fauxware sample with angr: find the accept path, avoid the reject branch, and recover inputs from forked simulation states.

Solving fauxware with angr

Challenge binary: dnsdudrla97/angr-doc

Data section

./0.png
./0.png

authenticate function

./1.png
./1.png

  • authenticate compares the username against the string behind the global sneaky with strcmp. On a match it returns 1. Otherwise it opens a file named after the username and compares that file's contents to the password, returning 1 on match and 0 otherwise.
  • The address we need to avoid is 0x4006E6.

./2.png
./2.png

Target path

./3.png
./3.png

  • When authenticate returns 1, the binary calls accepted.

./4.png
./4.png

angr solve 1

def solve2():
    p = angr.Project('./fauxware', auto_load_libs=False)
    state=p.factory.entry_state()
    sm=p.factory.simgr(state)
    sm.explore(find=0x4006F6, avoid=(0x4007CE, 0x4006E6))
 
    print(sm.found[0].posix.dumps(0))

./5.png
./5.png

angr solve 2

def solve1():
    p = angr.Project('./fauxware', auto_load_libs=False)
    state = p.factory.entry_state()
    sm = p.factory.simgr(state)
    sm.run(until = lambda sm_: len(sm_.active) > 1)
    input_0 = sm.active[0].posix.dumps(0)
    input_1 = sm.active[1].posix.dumps(0)
    r = None
    print(input_0)
    print(input_1)

./6.png
./6.png

import angr
import sys
 
def bse():
    # Load the binary into an Angr project first.
    p = angr.Project('./fauxware', auto_load_libs=False)
    # entry_state builds a generic SimState at the program entry point.
    state = p.factory.entry_state()
 
    # SimulationManager is a collection of tagged states with helpers for
    # stepping and exploring them.
    sm = p.factory.simgr(state)
 
    # Run until a satisfying branch produces more than one active state.
    sm.run(until = lambda sm_: len(sm_.active) > 1)
 
    # Recover stdin for each branch.
    input_0 = sm.active[0].posix.dumps(0)
    input_1 = sm.active[1].posix.dumps(0)
 
    r = None
    
    print(input_0)
    print(input_1)
 
if __name__ == "__main__":
    bse()

related

  1. Aug 14, 2020/archiveUsing angr for Binary Analysis, Part 1
  2. Aug 14, 2020/archiveangr binary analysis notes 2: the loader
  3. Aug 16, 2020/articleHITCON 2017 Sakura writeup

graphfeed