天天看点

z3约束器学习笔记0X1 下载0X2 基本语法0X3 例子

0X1 下载

pip install z3-solver
           

0X2 基本语法

变量初始化

  1. Bitvex(name,bv,ctx=None),创建一个位向量,name是他的名字,bv表示大小
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
           

计算函数

  1. solver(),创建一个解的对象。
eg: s=solver()
           
  1. add(),为解增加一个限制条件
s.add(条件)
           
  1. check(),检查解是否存在,如果存在,会返回"sat"
eg: s.check()
if s.check()==sat:
    ...
           
  1. modul(),输出解得结果
eg: result=s.modul()
print(result)
           

0X3 例子

来自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。

(该题解法参考大佬的文章)

网上学习资料较少,以此收集资料方便自己学习,以后学到东西再写…