You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
basically a list of individual 1s and 0s (bits lol)
Algebraic data types (lists, arrays, tuples...)
Data types (all called sorts)
IntSort
RealSort
BoolSort
ArraySort
BitVecSort
ListSort
...
Setup
Install z3
import in file
declare variables
create solver object
add constraints to solver
solve
Boolean Logic
# pip install z3-solverfromz3import*p=Bool('p')
q=Bool('q')
r=Bool('r')
s=Solver()
s.add(Implies(p,q)) # add contsraint that p->qs.add(r==Not(q),Or(Not(p),r)) # add multiple constraints at onces.check() # check if there is a possible solutionm=s.model() # get valuesp_res=m[p] # get evaluation of variableprint(f"p={str(m.eval(p, model_completion=True)}")
# p = <val>
Integer Logic
# pip install z3-solverfromz3import*x=Int('x')
y=Int('y')
z=Int('z')
s=Solver()
n=bigs.add(x*x+y*y==z*z, 0<x, x<n, 0<y, y<n, 0<z, z<n)
s.check()
m=s.model()
x_res=m[x]
y_res=m[y]
z_res=m[z]
# Need to convert back from z3 symbolic data type to intx_res=x_res.as_long()
y_res=y_res.as_long()
z_res=z_res.as_long()
print(m)
BitVectors
# pip install z3-solverfromz3import*a=BitVec('a',8) # 8 bit bit-vectorb=BitVec('b',64) # name, positive bit-lengths=Solver()
s.add(a*a==289) # doesn't work, bc 8 bits can have max 256 value# Instead: this returns a*a % 256 = 33s.add(b*b==289) # does work# You can't promote types with bitvectors# a + b gets an error bc of diff sizess.check()
m=s.model()
Ex.
Problem
Find an input string that prints "Correct"
publicclassHasher {
privatestaticbooleanhash(finalStrings) {
intn = 7;
finalintn2 = 593779930;
for (inti = 0; i < s.length(); ++i) {
n = n * 31 + s.charAt(i);
}
returnn == n2;
}
publicstaticvoidmain(finalString[] array) {
if (array.length != 1) {
System.out.println("Usage: java Hasher <password>");
System.exit(1);
}
if (hash(array[0])) {
System.out.println("Correct");
}
else {
System.out.println("Incorrect");
}
}
}
Solution
fromz3import*flag_length=6names= [f'x{i}'foriinrange(flag_length)] # creating all the variable nameschars= [Int(n) forninnames] # list of symbolic integers# do the problemn=7n2=593779930forcinchars:
n=n*31+c# prevents integer overflow for the variableret= (n% (2**32)) ==n2s=Solver()
s.add(ret)
forcinchars:
s.add(ord('a') <=c, c<=ord('z')) # add constraints for lowercase alphaifs.check().r!=1:
print("can't solve!")
else:
m=s.model()
flag="".join([chr(m[c].as_long()) forcinchars])
print(flag)
The flag is dragon
2. angr
importangrimportclaripyproj=angr.Project("./binaryName")
proj.arch# returns program architecturestate=proj.factory.entry_state()
state.regs.rax# gives us value of rax register at this pointsimgr=proj.factory.simulation_manager(state)
simgr.explore() # run until the program stopssimgr.deadended[0].posix.dumps(1) # 1 is the fd for stdout# get 0th element # If we wanted to, we could loop through all the elements until# we see the input we want# Now lets make angr explore but only until we get where we wantsimgr=proj.factory.simulation_manager(state)
simgr.explore(find=lambdanewState: b"String in correct output"innewState.posix.dumps(1))
simgr.found[0] # will give us the statesimgr.found[0].posix.dumps(1) # stdout that we wantsimgr.found[0].posix.dumps(0) # stdin that gives us the correct stdout
boilerplate
importangrbinaryName=""winAddress= [] # can be array of ints or single intloseAddress= []
p=angr.Project(binaryName)
simgr=p.factory.simulation_manager(p.factory.full_init_state())
simgr.explore(find=winAddress, avoid=loseAddress)
print(simgr.found[0].posix.dumps(0))
super duper boilerplate code
importangrimportclaripyproj=angr.Project("./binaryName")
state=proj.factory.entry_state()
simgr=proj.factory.simulation_manager(state)
simgr.explore(find=lambdanewState: b"String in correct output"innewState.posix.dumps(1))
simgr.found[0] # will give us the stateprint(simgr.found[0].posix.dumps(0)) # stdin that gives us the correct stdout
importangrimportclaripymax_flag_length=40base_address=0x00100000# first location of the programsuccess_address=0x0010134d# where the success function is calledfailure_address=0x0010135b# all the failsproj=angr.Project('./proprietary', main_opts={"base_addr":base_address})
# BVS means a (symbolic, bit vector)flag_chars= [claripy.BVS(f'flag{i}', 8) foriinrange(max_flag_length)]
# BVV means a (value, bit vector)# b'' turns the character into a byte # add \n in order to allow input to be acceptedflag=claripy.Concat(*flag_chars+ [claripy.BVV(b'\n')])
state=proj.factory.full_init_state(
args=['./proprietary'],
add_options=angr.options.unicorn,
stdin=flag
)
forcinflag_chars:
state.solver.add(c>=ord('!'))
state.solver.add(c<=ord('~'))
simmgr=proj.factory.simulation_manager(state)
simmgr.explore(find=success_address)
iflen(simmgr.found)>0:
forfoundinsimmgr.found:
print(found.posix.dumps(0))
else:
print("found nothing")