Skip to content

Instantly share code, notes, and snippets.

@LYoungJoo
Last active June 27, 2020 19:31
Show Gist options
  • Save LYoungJoo/8d143b1f0c8f19d4b6d86fa10c193af4 to your computer and use it in GitHub Desktop.
Save LYoungJoo/8d143b1f0c8f19d4b6d86fa10c193af4 to your computer and use it in GitHub Desktop.
Practice angr

Top Level Interfaces

Project

>>> import angr

>>> p = angr.Project('/bin/true')

>>> p.filename
'/bin/true'

>>> p.arch
<Arch AMD64 (LE)>

>>> p.filename
'/bin/true'

>>> p.entry
4199376

>>> p.arch
<Arch AMD64 (LE)>

>>> p.arch.bytes
8

>>> p.arch.bits
64

>>> p.arch.name
'AMD64'

>>> p.arch.memory_endness
'Iend_LE'

Loader

>>> p.loader
<Loaded true, maps [0x400000:0x5008000]>

>>> p.loader.main_object
<ELF Object true, maps [0x400000:0x6063bf]>

>>> p.loader.shared_objects
OrderedDict([('true', <ELF Object true, maps [0x400000:0x6063bf]>), 
(u'libc.so.6', <ELF Object libc-2.23.so, maps [0x1000000:0x13c999f]>), 
(u'ld-linux-x86-64.so.2', <ELF Object ld-2.23.so, maps [0x2000000:0x2227167]>)])

>>> p.loader.min_addr
4194304

>>> p.loader.max_addr
83918848

>>> p.loader.main_object.execstack
False

>>> p.loader.main_object.pic
False

Factory

Block

  • angr analyzes code in units of basic blocks
>>> block = p.factory.block(p.entry)

>>> block.pp()
0x4013d0:	xor	ebp, ebp
0x4013d2:	mov	r9, rdx
0x4013d5:	pop	rsi
0x4013d6:	mov	rdx, rsp
0x4013d9:	and	rsp, 0xfffffffffffffff0
0x4013dd:	push	rax
0x4013de:	push	rsp
0x4013df:	mov	r8, 0x403fc0
0x4013e6:	mov	rcx, 0x403f50
0x4013ed:	mov	rdi, 0x401330
0x4013f4:	call	0x401180

>>> block.instructions
11

>>> block.instruction_addrs
[4199376L, 4199378L, 4199381L, 4199382L, 4199385L, 4199389L, 4199390L, 4199391L, 4199398L, 4199405L, 4199412L]

States

  • the Project object only represents an "initialization image" for the program.
  • SimState : specific object representing a simulated program state
  • BV : BitVec
>>> state = p.factory.entry_state()
<SimState @ 0x4013d0>

>>> state.regs.rip
<BV64 0x4013d0>

>>> state.regs.rax
<BV64 0x1c>

>>> state.regs.rbx
<BV64 reg_28_0_64{UNINITIALIZED}>

>>> state.regs.rdi
<BV64 reg_48_1_64{UNINITIALIZED}>

>>> state.mem[p.entry].int.resolved
<BV32 0x8949ed31>

>>> bv = state.solver.BVV(0xffffffff, 64)

>>> bv
<BV64 0xffffffff>

>>> state.solver.eval(bv)
4294967295L

>>> state.regs.rsi = state.solver.BVV(0x12341234,64)

>>> state.regs.rsi
<BV64 0x12341234>

>>> state.mem[0x1000].long = 4

>>> state.mem[0x1000].long.resolved
<BV64 0x4>

>>> state.mem[0x1000].long.concrete
4L

Simulation Managers

  • A simulation manager is the primary interface in angr for performing execution, simulation, whatever you want to call it, with states
>>> simgr = p.factory.simulation_manager(p.factory.entry_state())
<SimulationManager with 1 active>

>>> simgr = p.factory.simgr(p.factory.entry_state())
<SimulationManager with 1 active>

>>> simgr.active
[<SimState @ 0x4013d0>]

>>> simgr.step()
<SimulationManager with 1 active>

>>> simgr.active
[<SimState @ 0x1020740>]

>>> simgr.active[0].regs.rip
<BV64 0x1020740>

>>> state.regs.rip
<BV64 0x4013d0>

Analyses

# https://docs.angr.io/docs/toplevel.html

>>> proj.analyses.            # Press TAB here in ipython to get an autocomplete-listing of everything:
 proj.analyses.BackwardSlice        proj.analyses.CongruencyCheck      proj.analyses.reload_analyses       
 proj.analyses.BinaryOptimizer      proj.analyses.DDG                  proj.analyses.StaticHooker          
 proj.analyses.BinDiff              proj.analyses.DFG                  proj.analyses.VariableRecovery      
 proj.analyses.BoyScout             proj.analyses.Disassembly          proj.analyses.VariableRecoveryFast  
 proj.analyses.CDG                  proj.analyses.GirlScout            proj.analyses.Veritesting           
 proj.analyses.CFG                  proj.analyses.Identifier           proj.analyses.VFG                   
 proj.analyses.CFGAccurate          proj.analyses.LoopFinder           proj.analyses.VSA_DDG               
 proj.analyses.CFGFast              proj.analyses.Reassembler

Loading a Binary

Loader

>>> p = angr.Project('/bin/true')

>>> p.loader
<Loaded true, maps [0x400000:0x5008000]>

>>> p.loader.all_objects
[<ELF Object true, maps [0x400000:0x6063bf]>, <ELF Object libc-2.23.so, maps [0x1000000:0x13c999f]>, 
<ELF Object ld-2.23.so, maps [0x2000000:0x2227167]>, <ELFTLSObject Object cle##tls, maps [0x3000000:0x300d010]>, 
<ExternObject Object cle##externs, maps [0x4000000:0x4008000]>, <KernelObject Object cle##kernel, maps [0x5000000:0x5008000]>]

>>> p.loader.main_object
<ELF Object true, maps [0x400000:0x6063bf]>

>>> p.loader.shared_objects
OrderedDict([('true', <ELF Object true, maps [0x400000:0x6063bf]>), 
(u'libc.so.6', <ELF Object libc-2.23.so, maps [0x1000000:0x13c999f]>), 
(u'ld-linux-x86-64.so.2', <ELF Object ld-2.23.so, maps [0x2000000:0x2227167]>)])

>>> p.loader.all_elf_objects
[<ELF Object true, maps [0x400000:0x6063bf]>, <ELF Object libc-2.23.so, maps [0x1000000:0x13c999f]>, 
<ELF Object ld-2.23.so, maps [0x2000000:0x2227167]>]

>>> p.loader.extern_object
<ExternObject Object cle##externs, maps [0x4000000:0x4008000]>

>>> p.loader.kernel_object
<KernelObject Object cle##kernel, maps [0x5000000:0x5008000]>

>>> p.loader.find_object_containing(0x400000)
<ELF Object true, maps [0x400000:0x6063bf]>

Object

>>> obj = p.loader.main_object

>>> obj.entry
4199376

>>> obj.min_addr
4194304

>>> obj.max_addr
6316991

>>> obj.segments
<Regions: [<ELFSegment offset=0x0, flags=0x5, filesize=0x5a24, vaddr=0x400000, memsize=0x5a24>, <ELFSegment offset=0x5e10, flags=0x6, filesize=0x404, vaddr=0x605e10, memsize=0x5b0>]>

>>> obj.sections
<Regions: [<Unnamed | offset 0x0, vaddr 0x0, size 0x0>, <.interp | offset 0x238, vaddr 0x400238, size 0x1c>, <.note.ABI-tag | offset 0x254, vaddr 0x400254, size 0x20>, <.note.gnu.build-id | offset 0x274, vaddr 0x400274, size 0x24>, <.gnu.hash | offset 0x298, vaddr 0x400298, size 0x3c>, <.dynsym | offset 0x2d8, vaddr 0x4002d8, size 0x528>, <.dynstr | offset 0x800, vaddr 0x400800, size 0x24b>, <.gnu.version | offset 0xa4c, vaddr 0x400a4c, size 0x6e>, <.gnu.version_r | offset 0xac0, vaddr 0x400ac0, size 0x60>, <.rela.dyn | offset 0xb20, vaddr 0x400b20, size 0x78>, <.rela.plt | offset 0xb98, vaddr 0x400b98, size 0x468>, <.init | offset 0x1000, vaddr 0x401000, size 0x1a>, <.plt | offset 0x1020, vaddr 0x401020, size 0x300>, <.plt.got | offset 0x1320, vaddr 0x401320, size 0x8>, <.text | offset 0x1330, vaddr 0x401330, size 0x2cc9>, <.fini | offset 0x3ffc, vaddr 0x403ffc, size 0x9>, <.rodata | offset 0x4020, vaddr 0x404020, size 0xcba>, <.eh_frame_hdr | offset 0x4cdc, vaddr 0x404cdc, size 0x22c>, <.eh_frame | offset 0x4f08, vaddr 0x404f08, size 0xb1c>, <.init_array | offset 0x5e10, vaddr 0x605e10, size 0x8>, <.fini_array | offset 0x5e18, vaddr 0x605e18, size 0x8>, <.jcr | offset 0x5e20, vaddr 0x605e20, size 0x8>, <.dynamic | offset 0x5e28, vaddr 0x605e28, size 0x1d0>, <.got | offset 0x5ff8, vaddr 0x605ff8, size 0x8>, <.got.plt | offset 0x6000, vaddr 0x606000, size 0x190>, <.data | offset 0x61a0, vaddr 0x6061a0, size 0x74>, <.bss | offset 0x6214, vaddr 0x606220, size 0x1a0>, <.gnu_debuglink | offset 0x6214, vaddr 0x0, size 0x34>, <.shstrtab | offset 0x6248, vaddr 0x0, size 0x102>]>

>>> obj.find_segment_containing(obj.entry)
<ELFSegment offset=0x0, flags=0x5, filesize=0x5a24, vaddr=0x400000, memsize=0x5a24>

>>> obj.find_section_containing(obj.entry)
<.text | offset 0x1330, vaddr 0x401330, size 0x2cc9>

>>> obj.plt['abort']
4198496

>>> obj.reverse_plt[4198496]
u'abort'

>>> obj.linked_base
4194304

>>> obj.mapped_base
4194304

Using CLE

>>> malloc = p.loader.find_symbol('malloc')

>>> malloc
<Symbol "malloc" in libc.so.6 at 0x1084130>

>>> malloc.name
u'malloc'

>>> malloc.owner_obj
<ELF Object libc-2.23.so, maps [0x1000000:0x13c999f]>

>>> malloc.linked_addr
540976

>>> malloc.relative_addr
540976

>>> malloc.is_export
True

>>> malloc.is_import
False

>>> main_malloc = proj.loader.main_object.get_symbol("malloc")

>>> main_malloc
<Symbol "malloc" in true (import)>

>>> main_malloc.is_export
False

>>> main_malloc.is_import
True

>>> main_malloc.resolvedby
<Symbol "malloc" in libc.so.6 at 0x1054400>

>>> p.loader.shared_objects['libc.so.6'].imports
{u'_dl_argv': <cle.backends.elf.relocation.amd64.R_X86_64_GLOB_DAT object at 0x7fa94dc2b6d0>, 
u'__tls_get_addr': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fa94dc2bd10>, 
u'_rtld_global_ro': <cle.backends.elf.relocation.amd64.R_X86_64_GLOB_DAT object at 0x7fa94dc26110>, 
u'__libc_enable_secure': <cle.backends.elf.relocation.amd64.R_X86_64_GLOB_DAT object at 0x7fa94dc1fc90>, 
u'_rtld_global': <cle.backends.elf.relocation.amd64.R_X86_64_GLOB_DAT object at 0x7fa94dc1f950>, 
u'_dl_starting_up': <cle.backends.elf.relocation.amd64.R_X86_64_GLOB_DAT object at 0x7fa94dc26e50>, u'_dl_find_dso_for_object': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fa94dc2b850>}

Hooking

>>> stub_func = angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained']

>>> p.hook(0x10000, stub_func())

>>> p.is_hooked(0x10000)
True

>>> p.unhook(0x10000)

>>> p.hooked_by(0x10000)
WARNING | 2018-02-04 16:47:19,824 | angr.project | Address 0x10000 is not hooked
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment