angr就是一个工具提供了对一个程序某一段代码的测试功能,在ctf中一般其实就是用来爆破。
之前一个示例演示了基本的运行,接下来呢看一下如果程序不从头开始,设置运行环境。
上面是个base64解密,下面是另一个加密,前面的没必要测试,看后面的。
看汇编代码
原始数据的赋值是R0决定的(也就是用R0来传参的)
#coding=utf-8
import angr
import claripy
import base64
def main():
load_option={}
b=angr.Project("./validate",load_options=load_option)
state=b.factory.blank_state(addr=0x401760)#设置加载位置
#print b.stack_object
concrete_addr=0xffe10000
code=claripy.BVS('code',10*8)
state.memory.store(concrete_addr,code,endness='Iend_BE') #把数据存放到concrete_addr指定的地址处,第三个参数不知道是什么
state.regs.r0=concrete_addr #修改寄存器值
sm=b.factory.simulation_manager(state) #运行做准备
sm.explore(find=0x401840,avoid=0x401854)#找到incorrect,避免incorrect,没有避免会有一些无所谓的输出
found=sm.found[0]
solution=found.solver.eval(code,cast_to=bytes)
print(solution)
print (base64.b32encode(solution))
return code,found
if __name__=='__main__':
main()
这里的完成了设置运行参数,爆破一段代码的过程。
跟前一个不同的是这个程序有一个加密过程如果直接符号执行的话很难执行完,符号执行对这种加密好像很难解决。
但是对简单的执行过程觉得效果很好。(决定性因素应该是base加密里面有很多if语句,那么我们的操作就很明确了,尽量跳过程序中含有很多if的函数或者代码段)
githuab上的大神脚本
#!/usr/bin/python
#coding=utf-8
'''
Quick-and-dirty solution for the (un-obfuscated) Android License Check crackme from the Obfuscation Metrics Project.
The full how-to can be found in the 'Android' section of the OWASP Mobile Security Testing Guide:
https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06a-Reverse-Engineering-and-Tampering-Android.md
'''
import angr
import claripy
import base64
def main():
load_options = {}
# Android NDK library path:
# load_options['ld_path'] = ['/Users/berndt/Tools/android-ndk-r10e/platforms/android-21/arch-arm/usr/lib']
b = angr.Project("./validate", load_options = load_options)
# The key validation function starts at 0x401760, so that's where we create the initial state.
# This speeds things up a lot because we're bypassing the Base32-encoder.
state = b.factory.blank_state(addr=0x401760)#加载位置
concrete_addr = 0xffe00000
code = claripy.BVS('code', 10*8)
state.memory.store(concrete_addr, code, endness='Iend_BE')
state.regs.r0 = concrete_addr
sm = b.factory.simulation_manager(state)
# 0x401840 = Product activation passed
# 0x401854 = Incorrect serial
sm.explore(find=0x401840, avoid=0x401854)
found = sm.found[0]
# Get the solution string from *(R11 - 0x20).
solution = found.solver.eval(code, cast_to=bytes)
print(base64.b32encode(solution))
return code, found
def test():
user_input, found = main()
found.solver.add(user_input.get_byte(0) == ord('L'))
found.solver.add(user_input.get_byte(2) == ord('O'))
found.solver.add(user_input.get_byte(4) == ord('L'))
found.solver.add(user_input.get_byte(6) == ord('Z'))
found.solver.add(user_input.get_byte(8) == ord('!'))
solution = found.solver.eval(user_input, cast_to=bytes)
assert found.solver.satisfiable() == True
# why does b32encode produce bytes and not str? great quesiton!
assert base64.b32encode(solution) == b'JQAE6ACMABNAAIIA'
if __name__ == '__main__':
main()
angr有自己的加载器,并不需要系统来加载它,也就是说可以测试任何平台上的程序。