angr
边学angr,边记笔记。这也是临时想着干脆写个笔记再写个博客,有空一边把前面的补上,一边学后面的
目前是照着这位大师傅的文章学的angr:https://xz.aliyun.com/u/11261
常规操作
基本操作
1 | p = angr.Project('filename',auto_load_libs=True)#or False |
寄存器,内存地址操作
1 | >>> state.regs.rip # get the current instruction pointer |
bitvector
1 | >>> bv = state.solver.BVV(0x1234, 32) # create a 32-bit-wide bitvector with value 0x1234 |
explore的小操作
一般来说 explore
必指定find
,可选avoid
通常来说这里都是设定为地址,即sm.explore(find=FIND_ADDR,avoid=AVOID_ADDR)
这里可以有另外一种操作方式,即我不需要知道具体该选择什么地址,我可以以回显作为条件进行find和avoid的设定,例:(example/sym-write)
1 | def correct(state): |
对应的explore写为sm.explore(find=correct, avoid=wrong)
Hook
这东西有点难,先搁着,国赛出题和毕设要紧
跨平台
dll
example/mma_howtouse
1 | p = angr.Project('howtouse.dll', load_options={'main_opts': {'base_addr': 0x10000000}}) |
对于具体的值,不需要用solver.eval
求值
1 | claripy.backends.concrete.convert(howtouse(i)).value |
输入
命令行输入
1 | state = p.factory.entry_state(args={"elf",argv},add_options={angr.options.LAZY_SOLVES}) |
程序内交互输入
1 | state = p.factory.blank_state(addr=START, stdin=flag) |
参数传递
有时候可以选择绕过程序的输入函数,直接把参数传进内存和寄存器里
flareon2015_2
因为是windows下的PE文件,为了避免调用windows API,所以需要从0x401084
这个函数地址开始分析。此时需要人工设置起始状态,即传参。
1 | s.mem[s.regs.esp+8:].dword = 0x402159 |
这个可以通过动态调试查看栈情况得知
claripy.BVS
angr中可以使用claripy.BVS作为程序的输入。
以输入20位字符串flag为例。
1 | # type 1 |
比较以上两种方式,type1
将flag作为一个整体,而type2
将flag以字符位单位进行分割,其实没太大差别,但是在后续添加约束等操作上稍有不同
写入内存
在设置state
时需要申明add_options={"SYMBOLIC_WRITE_ADDRESSES"}
1 | # type 1 |
添加约束
1 | # type 1 |
小结
说到底区别就在于一个是整体,一个是分割的小块。而有的时候整体也需要
state.options
根据angr的官方文档/doc/states.md
,state既可以add_options
也可以remove_options
1 | # 添加一个lazy solves的选项 |
/doc/options
里列出了所有的options,太多了,不搬运过来了,边学边看呗~
TODO
有必要把state
的add_options=
参数研究一下