pip install z3-solver
eg:
>>> x=BitVec('x',16)
>>> x.size()
16
>>> x
x
2.BitVecs(name,bv,ctx=None),创建一个有多变量的位向量,name是名字,bv表示大小
eg:
>>> x,y,z=BitVecs('x y z',16)
>>> x
x
>>> y
y
>>> z
z
3.BitVecSort(bv,ctx=None),创建一个指定大小的位向量,
eg:
>>> a=BitVecSort(16)
>>> a
BitVec(16)
>>> b=Const('x',a)
>>> c=BitVec('x',16)
>>> eq(b,c)
True
4.BitVecVal(val,bv,ctx=None),创建一个位向量,有初始值,没名字。
eg:
>>> x=BitVecVal(10,16)
>>> x
10
>>> x.size()
16
>>> x.as_long() #as_long()函数将val参数转化成long型,输出
10
5.Int(name),创建一个Int对象
eg:
>>> x=Int('x')
>>> x
x
eg: s=solver()
s.add(条件)
eg: s.check()
if s.check()==sat:
...
eg: result=s.modul()
print(result)
来自Reversing.kr的position一题,这里用z3再解一下,
我的另一种解法
该题给出serial,要求求出对应的name。
IDA打开,可以找到主函数,从而找到加密算法
if ( *(_DWORD *)(name - 12) == 4 ) // 限定name是4位
{
v3 = 0;
while ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, v3) >= 'a'
&& (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, v3) <= 'z' )// 限定name必须是字母
{
if ( ++v3 >= 4 )
{
LABEL_7:
v4 = 0;
while ( 1 )
{
if ( v1 != v4 )
{
v5 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, v4);
if ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, v1) == v5 )// 判断name的每一位是否相同(限定name的每一位都不相同)
goto LABEL_2;
}
if ( ++v4 >= 4 )
{
if ( ++v1 < 4 )
goto LABEL_7;
CWnd::GetWindowTextW(a1 + 420, &serial);
if ( *(_DWORD *)(serial - 12) == 11
&& (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 5) == '-' )// 限定serial的第六位是‘-’
{
v6 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, 0);// v6=name[0]
v7 = (v6 & 1) + 5;
v48 = ((v6 >> 4) & 1) + 5;
v42 = ((v6 >> 1) & 1) + 5;
v44 = ((v6 >> 2) & 1) + 5;
v46 = ((v6 >> 3) & 1) + 5;
v8 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, 1);// v8=name[1]
v34 = (v8 & 1) + 1;
v40 = ((v8 >> 4) & 1) + 1;
v36 = ((v8 >> 1) & 1) + 1;
v9 = ((v8 >> 2) & 1) + 1;
v38 = ((v8 >> 3) & 1) + 1;
v10 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v7 + v9, v10, 0xAu, 10);
v11 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0);
if ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 0) == v11 )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v12 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v46 + v38, v12, 0xAu, 10);
v13 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 1);// v13=serial[1]
if ( v13 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v14 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v42 + v40, v14, 0xAu, 10);
v15 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 2);// v15=serial[2]
if ( v15 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v16 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v44 + v34, v16, 0xAu, 10);
v17 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 3);// v17=serial[3]
if ( v17 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v18 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v48 + v36, v18, 0xAu, 10);
v19 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 4);// v19=serial[4]
if ( v19 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v20 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, 2);// v20=name[2]
v21 = (v20 & 1) + 5;
v49 = ((v20 >> 4) & 1) + 5;
v43 = ((v20 >> 1) & 1) + 5;
v45 = ((v20 >> 2) & 1) + 5;
v47 = ((v20 >> 3) & 1) + 5;
v22 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&name, 3);// v22=name[3]
v35 = (v22 & 1) + 1;
v41 = ((v22 >> 4) & 1) + 1;
v37 = ((v22 >> 1) & 1) + 1;
v23 = ((v22 >> 2) & 1) + 1;
v39 = ((v22 >> 3) & 1) + 1;
v24 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v21 + v23, v24, 0xAu, 10);
v25 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 6);
if ( v25 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v26 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v47 + v39, v26, 0xAu, 10);
v27 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 7);
if ( v27 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v28 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v43 + v41, v28, 0xAu, 10);
v29 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 8);
if ( v29 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v30 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v45 + v35, v30, 0xAu, 10);
v31 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 9);
if ( v31 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
v32 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&v52);
itow_s(v49 + v37, v32, 0xAu, 10);
v33 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial, 10);
if ( v33 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v52, 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&v52, -1);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v52);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&serial);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&name);
return 1;
}
}
}
}
}
}
}
}
}
}
}
goto LABEL_2;
}
}
}
}
}
用z3写解密算法
from z3 import *
username = [BitVec('u%d'%i,8) for i in range(0,4)]
solver = Solver() #76876-77776
solver.add(((username[0]&1)+5+(((username[1]>>2) & 1 )+1))==ord('7')-0x30)
solver.add(((((username[0]>>3) & 1)+5)+(((username[1]>>3)&1)+1))==ord('6')-0x30)
solver.add((((username[0]>>1) & 1)+5+(((username[1]>>4) & 1 )+1))==ord('8')-0x30)
solver.add((((username[0]>>2) & 1)+5+(((username[1]) & 1 )+1))==ord('7')-0x30)
solver.add((((username[0]>>4) & 1)+5+(((username[1]>>1) & 1 )+1))==ord('6')-0x30)
solver.add((((username[2]) & 1)+5+(((username[3]>>2) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>3) & 1)+5+(((username[3]>>3) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>1) & 1)+5+(((username[3]>>4) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>2) & 1)+5+(((username[3]) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>4) & 1)+5+(((username[3]>>1) & 1 )+1))==ord('6')-0x30)
solver.add(username[3] == ord('p'))
for i in range(0,4):
solver.add(username[i] >= ord('a'))
solver.add(username[i] <= ord('z'))
solver.check()
result = solver.model()
flag = ''
for i in range(0,4):
flag += chr(result[username[i]].as_long().real)
print(flag)
解出flag。
(该题解法参考大佬的文章)
网上学习资料较少,以此收集资料方便自己学习,以后学到东西再写…