5.elf z3暴力破解

5.elf教会了我需要注意数据的类型与数据的长度,不然也容易犯错误

关键在于看懂那几个强制类型转化,和运算符的顺序

其main函数为

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[64]; // [rsp+0h] [rbp-1D0h] BYREF
  int v5[84]; // [rsp+40h] [rbp-190h] BYREF此处为int型4字节一个
  __int64 v6; // [rsp+190h] [rbp-40h]此处为int64,64bit 8字节一个
  __int64 v7[3]; // [rsp+198h] [rbp-38h] BYREF此处为int64 8字节一个
  _BYTE v8[15]; // [rsp+1B0h] [rbp-20h]此处为1字节一个
  char v9; // [rsp+1BFh] [rbp-11h]
  int v10; // [rsp+1C0h] [rbp-10h]
  int v11; // [rsp+1C4h] [rbp-Ch]
  int j; // [rsp+1C8h] [rbp-8h]
  int i; // [rsp+1CCh] [rbp-4h]

  *(_QWORD *)v8 = 0xA718337232343F22LL;
  *(_QWORD *)&v8[7] = 0x7A1EC18428F131A7LL;
  v6 = 0x1412100D0A070401LL;
  v7[0] = 0x2A2724211F1D1A17LL;
  qmemcpy((char *)v7 + 6, "'*-/147:=@CFILOR", 16);
  qmemcpy(v5, "\n", sizeof(v5));
  i = 0;
  j = 0;
  v11 = 0;
  v10 = 0;
  v9 = 0;
  memset(s, 0, sizeof(s));
  puts("PLZ input");
  __isoc99_scanf("%s", s);
  for ( i = 0; i <= 14; ++i )
  {
    for ( j = 0; j <= 1; ++j )
    {
      v10 = *((char *)&v7[-1] + v11 + j);//v7先用了括号访问符此处指针指向的是v7[0]前8个字节的数据
      switch ( v5[v10] )//此处都有强制类型转化但本质是一致的取的是数据的低八位,注意v5是int型占四字节
      {
        case 2:
          s[i] += LOBYTE(v5[v10 + 1]);
          break;
        case 3:
          s[i] -= LOBYTE(v5[v10 + 1]);
          break;
        case 4:
          s[i] ^= LOBYTE(v5[v10 + 1]);
          break;
        case 5:
          s[i] *= (unsigned __int8)v5[v10 + 1];
          break;
        case 11:
          --s[i];
          break;
        case 12:
          ++s[i];
          break;
        default:
          continue;
      }
    }
    v11 += 2;
  }
  for ( i = 0; i <= 14; ++i )
  {
    if ( s[i] != v8[i] )
    {
      printf("wrong wrong wrong");
      return 0;
    }
  }
  printf("woc,you got it,flag is your input");
  return 0;
}

根据其加密和数据类型可以通过动态调试获得几个数组的原始数据

如图v5是四个字节为一段数据(注意高位低位区别)

image

v5=[
0x0A,0x04,0x10,0x08,
0x03,0x05,0x01,0x04,
0x20,0x08,0x05,0x03,
0x01,0x03,0x02,0x08,
0x0B,0x01,0x0C,0x08,
0x04,0x04,0x01,0x05,
0x03,0x08,0x03,0x21,
0x01,0x0B,0x08,0x0B,
0x01,0x04,0x09,0x08,
0x03,0x20,0x01,0x02,
0x51,0x08,0x04,0x24,
0x01,0x0C,0x08,0x0B,
0x01,0x05,0x02,0x08,
0x02,0x25,0x01,0x02,
0x36,0x08,0x04,0x41,
0x01,0x02,0x20,0x08,
0x05,0x01,0x01,0x05,
0x03,0x08,0x02,0x25,
0x01,0x04,0x09,0x08,
0x03,0x20,0x01,0x02,
0x41,0x08,0x0C,0x01
]#此处仅有低位有数据可以直接去掉0x00的数据便于访问
v7=[
0x01,0x04,0x07,0x0a,0x0d,0x10,0x12,0x14,
0x17,0x1a,0x1d,0x1f,0x21,0x24,0x27,
0x2a,0x2d,0x2f,0x31,0x34,0x37,0x3a,0x3d,
0x40,0x43,0x46,0x49,0x4c,0x4f,0x52,0x00,
0x00,0x22,0x3f,0x34,0x32,0x72,0x33,0x18,
0xa7,0x31]#v7最开始进行的是v7[-1],因为python的[-1]跟c不同,此处可以直接将其数组前移8字节,在后续访问时可以不用使用v7[-1]
v8=[
0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xa7,
0x31,0xf1,0x28,0x84,0xc1,0x1e,0x7a,0x00]#直接从动态调试中取就行

具体解密如下

from z3 import*
v8=[
0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xa7,
0x31,0xf1,0x28,0x84,0xc1,0x1e,0x7a,0x00]
v7=[
0x01,0x04,0x07,0x0a,0x0d,0x10,0x12,0x14,
0x17,0x1a,0x1d,0x1f,0x21,0x24,0x27,
0x2a,0x2d,0x2f,0x31,0x34,0x37,0x3a,0x3d,
0x40,0x43,0x46,0x49,0x4c,0x4f,0x52,0x00,
0x00,0x22,0x3f,0x34,0x32,0x72,0x33,0x18,
0xa7,0x31]
v5=[
0x0A,0x04,0x10,0x08,
0x03,0x05,0x01,0x04,
0x20,0x08,0x05,0x03,
0x01,0x03,0x02,0x08,
0x0B,0x01,0x0C,0x08,
0x04,0x04,0x01,0x05,
0x03,0x08,0x03,0x21,
0x01,0x0B,0x08,0x0B,
0x01,0x04,0x09,0x08,
0x03,0x20,0x01,0x02,
0x51,0x08,0x04,0x24,
0x01,0x0C,0x08,0x0B,
0x01,0x05,0x02,0x08,
0x02,0x25,0x01,0x02,
0x36,0x08,0x04,0x41,
0x01,0x02,0x20,0x08,
0x05,0x01,0x01,0x05,
0x03,0x08,0x02,0x25,
0x01,0x04,0x09,0x08,
0x03,0x20,0x01,0x02,
0x41,0x08,0x0C,0x01
]
flag = [BitVec('flag[%2d]' % i, 8) for i in range(15)]
out=[0]*15
for i in range(15):
    out[i]=flag[i]
i=0
j=0
v11=0
v10=0
v9=0
for i in range(15):
    for j in range(2):
        v10=v7[v11+j]
        match v5[v10]:
            case 2:
                out[i]=out[i]+v5[v10+1]
            case 3:
                out[i]=out[i]-v5[v10+1]
            case 4:
                out[i]=out[i]^v5[v10+1]
            case 5:
                out[i]=out[i]*v5[v10+1]
            case 11:
                out[i]-=1
            case 12:
                out[i]+=1
            case _:
                continue
    v11+=2
f=Solver()
for i in range(15):
    f.add(out[i]==v8[i])
while(f.check()==sat):
    condition = []
    m = f.model()
    p=""
    for i in range(15):
        p+=chr(int("%s" % (m[flag[i]])))
        condition.append(flag[i]!=int("%s" % (m[flag[i]])))
    print(p)
    f.add(Or(condition))

解出来有两个解,依次输入其中试试

image

image

image

上一个解为正确的解:757515121f3d478

posted @ 2023-01-07 15:30  润梧  阅读(51)  评论(1编辑  收藏  举报