直接打开程序,发现要输入三个字符串。

用IDA打开程序,get_user_input把三个输入分别放入寄存器eax、ebx、edx。我们需要跳过输入这一步,直接让Angr把用符号向量来代替输入字符串。因此,我们需要改变程序入口,直接跳转到参数入栈的位置,然后新建三个符号向量,并把三个符号向量分别放到寄存器eax、ebx、edx。

%x表示输入字符是十六进制。

import angr
import claripy
import sysdef main(argv):path_to_binary = argv[1]project = angr.Project(path_to_binary)# 重新设定入口点,此处从sanf输入开始执行。此处不用entry_state,而是blank_statestart_address = 0x08048980initial_state = project.factory.blank_state(addr=start_address)# 创建三个个符号向量,第一个参数是用来引用的,第二个参数是CPU位数,如32password0 = claripy.BVS('password0', 32)password1 = claripy.BVS('password1', 32)password2 = claripy.BVS('password2', 32)# 根据IDA,分别设置eax、ebx、edx的符号值initial_state.regs.eax = password0initial_state.regs.ebx = password1initial_state.regs.edx = password2simulation = project.factory.simgr(initial_state)def is_successful(state):stdout_output = state.posix.dumps(sys.stdout.fileno())return b'Good Job.' in stdout_outputdef should_abort(state):stdout_output = state.posix.dumps(sys.stdout.fileno())return b'Try again.' in stdout_outputsimulation.explore(find=is_successful, avoid=should_abort)if simulation.found:solution_state = simulation.found[0]# 求解solution0 = solution_state.solver.eval(password0)solution1 = solution_state.solver.eval(password1)solution2 = solution_state.solver.eval(password2)# 打印输出十六进制solution = "Solutions:{:x} {:x} {:x}".format(solution0, solution1, solution2)print(solution)else:raise Exception('Could not find the solution')if __name__ == '__main__':main(sys.argv)

附录:
C语言占位符:
%d, %i 代表整数
%f 浮点
%s 字符串
%c char
%p 指针
%fL 长log
%e 科学计数
%g 小数或科学计数。
%a,%A 读入一个浮点值(仅C99有效)。
%c 读入一个字符。
%d 读入十进制整数。
%i 读入十进制,八进制,十六进制整数。
%o 读入八进制整数。
%x,%X 读入十六进制整数。
%s 读入一个字符串,遇空格、制表符或换行符结束。
%f,%F,%e,%E,%g,%G 用来输入实数,可以用小数形式或指数形式输入。
%p 读入一个指针。
%u 读入一个无符号十进制整数。
%n 至此已读入值的等价字符数。
%[] 扫描字符集合。
%% 读 % 符号
scanf("%d,%d,%d",&a,&b,&c); // 从键盘输入三个整数,用逗号分隔
scanf("%c", &s); // 从键盘输入一个字符
scanf("%f", &f); // 从键盘输入一个浮点型数据
printf("%d\n",a); // 输出一个整数
printf("%f\n",b); // 输出一个浮点数
printf("%s\n",c); // 输出一个字符, 其中\n表示换行
















