Ask to input 400 chars, then take it as a 20*20 arry Next the binary run a function to verify the array If the verification were success, it would give you the SHA256 hash of you input, which is flag
Let’s take a look at the function I mentioned There are 150 while loops in this function Before loops, it initialize lots of variables Those loops are all similar to each:
V1 <- fetch a local variable counter <- call addition function to determine how many time to loop
While fetch a char from UserInput according to V1 the int(char) can only be 1~9, or fail the int(char) can not repeat in this while loop, or fail add the int(char) to local variable (sum) of this loop END
sum should equal to a certain value, or fail
!!Notice that if verification was failed, the binary would not stop immediately, it only set the flag to false
It’s not so hard to find out that you can do some symbolic execution to get the right input But there are so many loops and so many variables This is a ppc problem (っ・Д・)っ
Because I don’t know how to quickly get the address that I want to put into the avoid of angr’s explorer, I decided to use z3 solver.
For convenient, let’s name some weird function. Most of them just return the argument directly, so I named them nothing Some function would return the argument adding by a number, so I named them plus_(number) OK, I dumped psudocode to sakura_de.c and seperate the syntax of initializing local variables to a text file, variable
Now, all I need to do is to write a script to generate a z3 script
solver.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import re
f = open("./sakura_de.c", "r").read()
#get the variable and constraint of every loop idx = re.findall("v[0-9]* = \(__int64 \*\)nothing_[0-9]*\(\(__int64\)\&v([0-9]*)\)", f) loop_n = re.findall("v[0-9]* = plus_([0-9]*)", f) con = re.findall("\( v[0-9]* \!= ([0-9]*) \)", f)
f = open("./variables", "r").read()
#get the local variable on stack equ = re.findall("v([0-9]*) = ([0-9]*);", f) stack = [0]*1944 for ( x , y ) in equ: stack[int(x)] = int(y)
z3_code = """ #! /usr/bin/env python # -*- coding: utf-8 -*- from z3 import * s = Solver() """
#add constraint to z3 for row inrange(20): for col inrange(20): name = chr(ord('A')+row) + str(col) z3_code += "{} = Int('{}')\n".format(name,name) z3_code += "s.add( 0 < {} , {} < 10)\n".format(name,name)
for j inrange(150): loop = int(int(loop_n[j])/8) this_loop = [] for i inrange(loop): xx = get_stack(j,i) row = xx&0xffffffff col = xx>>32 this_loop.append((row, col))
for i inrange(0,len(this_loop)-1): (row, col) = this_loop[i] a = chr(ord('A')+row) + str(col) for k inrange(i+1,len(this_loop)): (row, col) = this_loop[k] b = chr(ord('A')+row) + str(col) z3_code += "s.add( {} != {})\n".format(a, b) z3_code += "s.add(" for i inrange(len(this_loop)): (row, col) = this_loop[i] a = chr(ord('A')+row) + str(col) z3_code += " {} + ".format(a) z3_code += " 0 == {})\n".format(con[j])
z3_code += """ s.check() m = s.model() sakura = [0]*400 for i in m: row = ord(str(i)[0]) - ord('A') col = int(str(i)[1:]) sakura[ 20*row + col ] = str(m[i]) print ''.join(sakura) """