从本篇博客开始,我们以实例的形式来了解angr,期待共同学习,共同进步
XCTF嘉年华体验-re1 很简单的一个逆向题目
看伪代码,很明显,是通过以参数作为输入,输入应为一个四位整数,通过各位的判断是否满足条件,最终确定correct还是wrong 直接上脚本
1 2 3 4 5 6 7 for thousand in xrange(0 ,10 ): for hundred in xrange(0 ,10 ): for ten in xrange(1 ,10 ): for num in xrange(1 ,10 ): if num + thousand + ten + hundred == 23 and ten / num == 2 and hundred - ten == -1 and thousand % ten == 3 : print thousand,hundred,ten,num break
得到答案
验证下
但是这不是我们这篇文章的主要意图,这个题目特别简单,只要会编程并且了解点逆向,这个题目都很容易解出来了,下面我们进入正题,用angr求解 我们还是先上脚本,再进行分析
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 import angrp = angr.Project('./ppp' ) state = p.factory.entry_state() for _ in xrange(4 ): k = state.posix.files[0 ].read_from(1 ) state.se.add(k>47 ) k = state.posix.files[0 ].read_from(1 ) state.se.add(k==10 ) state.posix.files[0 ].seek(0 ) state.posix.files[0 ].length = 5 print '[*] simulation_manager start...............' sm = p.factory.simulation_manager(state) sm.explore(find=0x08048692 ,avoid=0x080486A5 ) if len(sm.found)>0 : inp = sm.found[0 ].posix.files[0 ].all_bytes() print sm.found[0 ].solver.eval(inp,cast_to = str) print '[*] end angr.....'
我们直接从之前未接触过的开始
1 2 3 for _ in xrange(4 ): k = state.posix.files[0 ].read_from(1 ) state.se.add(k>47 )
这个部分是用来获取标准输入并且对其长度,范围进行限制的部分,xrange(4)
函数后面的4是用来表示获取4位标准输入,并且state.posix.files[0].read_from(1)
,这个部分设置工程文件固定读取标准输入一个字节,,最后通过add()
函数对读取的字节进行限制,由于我们的输入限定于数字0~9,所有限定输入一定大于47.state.se.add(k==10)
,换行符表示输入结束
1 2 state.posix.files[0 ].seek(0 ) state.posix.files[0 ].length = 5
这个部分用于限定输入字符长度从起始位置计数一定为5位
inp = sm.found[0].posix.files[0].all_bytes()
,读取得到第一个解的所有标准输入print sm.found[0].solver.eval(inp,cast_to = str)
,以字符形式输出我的输入
sm.explore(find=0x08048692,avoid=0x080486A5)
,中地址分别为correct和wrong的分支
最终执行结果如图