前言 记:又一个逆向神器——angr,详情参考官方文档 ,这里面的example是ctf的一些题例
然后这里是一些angr解题的题库 ,我还没做过,以后慢慢练习
一个简单的demo ,应该能大致了解angr
一些example 我自己也写了一个简单的demo,程序是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <stdio.h> #include <string.h> void success () { printf ("success\n" ); } void failed () { printf ("failed\n" ); } void change (char name[],int i) { if (name[i]=='l' ) name[i]='1' ; else name[i]='2' ; } int main (void ) { char name[10 ]; int i; printf ("pls enter the name:" ); scanf ("%s" ,name); change(name,2 ); change(name,3 ); change(name,8 ); if (!strcmp (name,"he11owor1d" )){ success(); }else { failed(); } return 0 ; }
利用angr来跑,目的就是要让其执行到success 处
1 2 3 4 5 6 7 8 9 10 11 import angrp= angr.Project(r'\demo.exe' ,auto_load_libs=False ) state=p.factory.entry_state() s=p.factory.simulation_manager(state) s.explore(find=0x40154a ,avoid=0x40154b ) print(len (s.found)) print(s.found[0 ].posix.dumps(1 )) print(s.found[0 ].posix.dumps(0 ))
又一个example——DEFCON 2016 quals baby-re
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import claripyimport angrp=angr.Project(r'.\baby-re' ,auto_load_libs=False ) state=p.factory.blank_state(addr=0x4028e0 ) flag_chars=[claripy.BVS('flag_%d' %i,32 ) for i in range (13 )] for i in range (13 ): state.mem[state.regs.rsp+i*4 ].dword = flag_chars[i] state.regs.rdi = state.regs.rsp s=p.factory.simulation_manager(state) s.one_active.options.add(angr.options.LAZY_SOLVES) s.explore(find=0x40293f ,aviod=0x402941 ) if len (s.found)>0 : print('get!' ) flag='' .join(chr (s.found[0 ].solver.eval (c)) for c in flag_chars) print(flag) else : print('Oh no' )
angr的一些知识点 记得可能不全,可用性也不强,日后熟悉了再慢慢更新
hook hook_symbol
:angr提供hook一些库函数得接口,从而实现其功能,在angr/procedures中可以看到这些库
例:
1 2 3 4 5 6 7 8 9 10 class my_scanf (angr.SimProcedure ): def run (self, fmt, ptr ): self.state.mem[ptr].dword = flag_chars[self.state.globals ['scanf_count' ]] self.state.globals ['scanf_count' ] += 1 proj.hook_symbol('__isoc99_scanf' , my_scanf(), replace=True ) proj.hook_symbol('printf' ,angr.SIM_PROCEDURES['stubs' ]['ReturnUnconstrained' ](),replace=True )
hook(addr=xx,hook=hook_demo,length=xx)
:程序自定义的函数没法直接hook,但是可以hook调用这个函数的地址,然后以自己的逻辑写一个hook_demo,length是hook_demo后要跳过的指令的长度
例:
1 2 3 4 5 6 def my_change (state ): print('change hooked' ) state.memory.rax=1 return proj.hook(0x4015cb ,hook=my_change,length=5 )
ps:hook的是一个state,自己实现hook_demo中的一切操作都是基于传递过来的state
find 和 avoid 关于expolor里的find和avoid,都是可以是list类型,也就是可以批量avoid(一般不会批量find吧..)
而批量avoid的地址则可以通过idapython的提取出来,这个关于idapython,就迟些学了再记
还有一个比较好用的find的方法:直接以标准输出中的关键字符串 为目标去find
就像这样s.explore(find=lambda st: b"Congrats" in st.posix.dumps(1))
pie保护 pie保护的程序,每次运行时的地址都会有变化,就像这样
但在angr中,程序的基址是固定在0x400000处的
所以在相关地址提取的时候加上0x400000即可
PS:但是ida加载的时候,每次动调之后地址都会变,所以只能参考第一次刚加载进ida时的地址
Comments