CLE模块
CLE组件是angr中加载二进制文件的组件,是angr中的加载器。之前了解了下这个模块,现在来深入学习下怎么与loader交互。
>>> hex(p.loader.main_object.min_addr)
'0x400000'
>>> hex(p.loader.main_object.max_addr)//获取最低地址和最高地址
'0x601077'
>>> p.loader.main_object.segments
<Regions: [<ELFSegment offset=0x0, flags=0x5, filesize=0xae4, vaddr=0x400000, memsize=0xae4>, <ELFSegment offset=0xe08, flags=0x6, filesize=0x260, vaddr=0x600e08, memsize=0x270>]>
>>> p.loader.main_object.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 0x24>, <.dynsym | offset 0x2c0, vaddr 0x4002c0, size 0xf0>, <.dynstr | offset 0x3b0, vaddr 0x4003b0, size 0x79>, <.gnu.version | offset 0x42a, vaddr 0x40042a, size 0x14>, <.gnu.version_r | offset 0x440, vaddr 0x400440, size 0x30>, <.rela.dyn | offset 0x470, vaddr 0x400470, size 0x30>, <.rela.plt | offset 0x4a0, vaddr 0x4004a0, size 0xc0>, <.init | offset 0x560, vaddr 0x400560, size 0x1a>, <.plt | offset 0x580, vaddr 0x400580, size 0x90>, <.text | offset 0x610, vaddr 0x400610, size 0x2f2>, <.fini | offset 0x904, vaddr 0x400904, size 0x9>, <.rodata | offset 0x910, vaddr 0x400910, size 0x56>, <.eh_frame_hdr | offset 0x968, vaddr 0x400968, size 0x44>, <.eh_frame | offset 0x9b0, vaddr 0x4009b0, size 0x134>, <.init_array | offset 0xe08, vaddr 0x600e08, size 0x10>, <.fini_array | offset 0xe18, vaddr 0x600e18, size 0x8>, <.jcr | offset 0xe20, vaddr 0x600e20, size 0x8>, <.dynamic | offset 0xe28, vaddr 0x600e28, size 0x1d0>, <.got | offset 0xff8, vaddr 0x600ff8, size 0x8>, <.got.plt | offset 0x1000, vaddr 0x601000, size 0x58>, <.data | offset 0x1058, vaddr 0x601058, size 0x10>, <.bss | offset 0x1068, vaddr 0x601068, size 0x10>, <.comment | offset 0x1068, vaddr 0x0, size 0x4d>, <.shstrtab | offset 0x10b5, vaddr 0x0, size 0xf8>]>
>>> p.loader.main_object.find_section_containing(p.entry)
<.text | offset 0x610, vaddr 0x400610, size 0x2f2>
>>> p.loader.main_object.find_segment_containing(p.entry)//获取文件分段和内存分段
<ELFSegment offset=0x0, flags=0x5, filesize=0xae4, vaddr=0x400000, memsize=0xae4>
>>> d = p.loader.main_object.plt['printf']
>>> d
4195776
>>> hex(d)
'0x4005c0'
>>> p.loader.main_object.reverse_plt[d]//还能看plt表
u'printf'
>>> hex(p.loader.main_object.linked_base)
'0x400000'
>>> hex(p.loader.main_object.mapped_base)//预链接基址和加载基址
'0x400000'
>>> printf.is_export
True
>>> printf.is_import
False
>>> main_printf = p.loader.main_object.get_symbol('printf')
>>> main_printf
<Symbol "printf" in r100 (import)>
>>> main_printf.resolvedby
<Symbol "printf" in libc.so.6 at 0x1064f00>
>>> printf.owner_obj
<ELF Object libc-2.27.so, maps [0x1000000:0x13f0adf]>
>>> main_printf.owner_obj//get_symbol是返回主函数中的。find_symbol是返回库中的
<ELF Object r100, maps [0x400000:0x601077]>
>>> proj = p.loader.main_object
>>> proj.imports
{u'__gmon_start__': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe92223a410>, u'puts': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe9222356d0>, u'__stack_chk_fail': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe922220d10>, u'getenv': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe92223a2d0>, u'__libc_start_main': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe92223a290>, u'ptrace': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe92223a4d0>, u'printf': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe922235dd0>, u'fgets': <cle.backends.elf.relocation.amd64.R_X86_64_JUMP_SLOT object at 0x7fe92223a3d0>}//还能观察到符号名和他们的重定位地址的映射关系
>>> proj.symbols_by_addr
{0: <Symbol "" in r100 at 0x0>, 6295656: <Symbol "stdin" in r100 at 0x601068>}//查看重定位的信息
加载
>>> p = angr.Project('/home/fivefiveopen/Desktop/angr/r100' )
>>> q = angr.Project('/home/fivefiveopen/Desktop/angr/r100',auto_load_libs=False )
>>> p.loader.all_objects
[<ELF Object r100, maps [0x400000:0x601077]>, <ELF Object libc-2.27.so, maps [0x1000000:0x13f0adf]>, <ELF Object ld-2.27.so, maps [0x2000000:0x222916f]>, <ELFTLSObject Object cle##tls, maps [0x3000000:0x3015010]>, <ExternObject Object cle##externs, maps [0x4000000:0x4008000]>, <KernelObject Object cle##kernel, maps [0x5000000:0x5008000]>]
>>> q.loader.all_objects
[<ELF Object r100, maps [0x400000:0x601077]>, <ExternObject Object cle##externs, maps [0x1000000:0x1008000]>, <ELFTLSObject Object cle##tls, maps [0x2000000:0x2015010]>, <KernelObject Object cle##kernel, maps [0x3000000:0x3008000]>]//可以通过指令让程序不加载共享库
Hook
>>> func = angr.SIM_PROCEDURES['libc']['printf']//第一层是包名(libc,posix,win32,stubs),第二层是库函数的名字
>>> func\
...
<class 'angr.procedures.libc.printf.printf'>
>>> p.hook(0x40000,func())//对这个地址进行hook
>>> p.is_hooked(0x40000)//检查
True
>>> p.hooked_by(0x40000)
<SimProcedure printf>
>>> p.unhook(0x40000)//取消hook
>>> p.is_hooked(0x40000)
False
>>> @p.hook(0x40000,length = 0)//length表示hook的函数执行完后跳过多少个机器码继续执行
... def hook():
... printf("Hello")
...
>>> p.is_hooked(0x40000)//也能自定义函数对程序进行hook
True
>>> printf = p.loader.find_symbol('printf')//先定义一个符号名称,这样程序中所有的函数都会被hook
>>> p.hook_symbol(printf.name,func())
WARNING | 2020-10-19 18:06:18,539 | angr.project | Address is already hooked, during hook(0x1064f00, <SimProcedure printf>). Re-hooking.
17190656