angr符号执行用例解析——codegate_2017-angrybird

用例源码以及二进制文件链接:https://github.com/angr/angr-doc/tree/master/examples/codegate_2017-angrybird

这个二进制文件执行起来没反应,给参数也不可以。看了用例源码,才知道这个二进制文件很怪,加了“anti-run instructions”(嗯,反运行指令)。除非更改二进制文件,删除掉反运行指令或直接跳转到正确代码块才可以。

有了angr,我们就不用这么纠结了,直接查看字符串,确定有效输入和成功点,符号执行,然后求解就可以了。

还是先是IDA静态分析,识别一下数据位置和成功输出点。

结果发现main函数,简直有毒:

angr符号执行用例解析——codegate_2017-angrybird_第1张图片

从main函数起始处分析:

1.首先构造一个GOT表,对应四个函数。

mov     [rbp+var_70], offset off_606018
mov     [rbp+var_68], offset off_606020
mov     [rbp+var_60], offset off_606028

mov     [rbp+var_58], offset off_606038

在后面的计算中有用到这四个函数。

2.输出 you should return 21 not 1 :( ;

3.栈检查;

4.和字符串hello比较;

5.从标准输入接收数据,并将数据读取到栈中;

由于flag就是程序输入的数据,因此flag=found.posix.dumps(0)

用例跳过了反执行指令程序初始化等,从地址START_ADDR = 0x4007c2开始符号执行(即,标准输入接收数据开始执行)。

用例确定最后的输出'you typed : %s'字符串所在的地方就是成功输出点了。所以find_addr=0x404fab(也就是字符串被调用的地址)。

因此只需要利用angr找到从地址START_ADDR = 0x4007c2到地址find_addr=0x404fab的一条有效路径,输出此时的flag即可。

用例代码:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# Author: David Manouchehri
# Runtime: ~3 minutes

import angr

START_ADDR = 0x4007c2
FIND_ADDR = 0x404fab  # This is right before the printf

def main():
	proj = angr.Project('angrybird')
	# There's a couple anti-run instructions in this binary.
	# Yes, anti-run. That's not a typo.

	# Because I'm not interested in fixing a weird binary, I'm going to skip all the beginning of the program.
	# this also skips a bunch of initialization, so let's fix that:
	state = proj.factory.entry_state(addr=START_ADDR)
	state.regs.rbp = state.regs.rsp
	# using the same values as the binary doesn't work for these variables, I think because they point to the GOT and the binary is using that to try to fingerprint that it's loaded in angr. Setting them to pointers to symbolic memory works fine.
	'''state.mem[state.regs.rbp - 0x70].long = 0x1000
	state.mem[state.regs.rbp - 0x68].long = 0x1008
	state.mem[state.regs.rbp - 0x60].long = 0x1010
	state.mem[state.regs.rbp - 0x58].long = 0x1018'''

	sm = proj.factory.simulation_manager(state)  # Create the SimulationManager.
	sm.explore(find=FIND_ADDR)  # This will take a couple minutes. Ignore the warning message(s), it's fine.
	found = sm.found[-1]
	flag = found.posix.dumps(0)

	# This trims off anything that's not printable.
	return flag[:30]

def test():
	assert main() == 'Im_so_cute&pretty_:)'

if __name__ == '__main__':
	print(main())

我将原作者关于state.mem[state.regs.rbp - 0x70].long = 0x1000的四条语句都注释掉,还是可以得到正确的结果。

同时我们发现与以往套路中的符号执行多了一个语句:

state.regs.rbp = state.regs.rsp

这是由于main函数的起始语句包括:

push    rbp

mov     rbp, rsp

说明这个main函数是由rbp传参数的。






你可能感兴趣的:(漏洞挖掘,物联网)