[buuctf.reverse] 111_[b01lers2020]chugga_chugga

这篇博客探讨了一段看似混乱但实际上简单的程序代码,通过Z3进行逻辑验证。作者利用Z3的赋值语句对代码中的条件进行了建模和求解,最终得到了满足条件的解并输出了结果。文章展示了如何借助形式化验证工具理解和分析程序逻辑。
摘要由CSDN通过智能技术生成

虽然不知道是什么写的程序,但看起来确实很乱,不过程序很简单,一上来就scanf输入然后开始一步步运算

  v21 = runtime_newobject((__int64)&RTYPE_string);
  for ( i = 0LL; ; i = v3 )
  {
    v20 = i;
    v19 = runtime_convT64(i);
    v25[0] = (__int64)&RTYPE_string;
    v25[1] = (__int64)&main_statictmp_2;
    v26 = &RTYPE_int;
    v27 = v19;
    fmt_Fprintln((__int64)&go_itab__ptr_os_File_comma_io_Writer, os_Stdout, (__int64)v25, 2LL, 2LL);
    v24[0] = (__int64)&RTYPE_string;
    v24[1] = (__int64)&main_statictmp_3;
    fmt_Fprintln((__int64)&go_itab__ptr_os_File_comma_io_Writer, os_Stdout, (__int64)v24, 1LL, 1LL);
    v23[0] = (__int64)&RTYPE__ptr_string;
    v23[1] = v21;
    fmt_Fscan((__int64)&go_itab__ptr_os_File_comma_io_Reader, os_Stdin, (__int64)v23, 1LL, 1LL);
    v1 = *(_QWORD *)(v21 + 8);
    v2 = *(_BYTE **)v21;
    if ( v1 <= 2 )
      break;
    if ( v2[2] != 116 )
      goto LABEL_5;
    if ( v1 <= 9 )
      break;
    if ( v2[9] != 99 )
      goto LABEL_5;
    if ( v1 <= 0x10 )
      break;
    if ( v2[16] != 110 )
      goto LABEL_5;
    if ( v1 <= 0x15 )
      break;
    if ( v2[21] != 122 )
      goto LABEL_5;
    if ( v1 <= 0x16 )
      break;
    if ( v2[22] != 125 )
      goto LABEL_5;
    v4 = v2[5];
    if ( v4 != 115 )
      goto LABEL_5;
    if ( (v2[3] ^ 0x74) != 18 )
      goto LABEL_5;
    v5 = v2[1];
    if ( v5 != 99 )
      goto LABEL_5;
    v6 = v2[7];
    if ( v6 != 100 )
      goto LABEL_5;
    v7 = v2[13];
    if ( v2[12] != v7 )
      goto LABEL_5;
    if ( v2[19] != 0x7A )
      goto LABEL_5;
    v8 = v2[14];
    v9 = v2[6];
    if ( v9 + v8 != 104 )
      goto LABEL_5;
    v10 = v2[4];
    if ( v10 != 123 )
      goto LABEL_5;
    v11 = v2[8];
    if ( v2[15] != v11 )
      goto LABEL_5;
    if ( v11 + 4 == v5
      && (v12 = v2[17], v13 = v2[11], 125 - v12 + 40 == v13)
      && (v14 = v2[18], v15 = v12 + v13 - v4 - v14, v16 = v14 - v12, v15 == v16)
      && (v17 = v9 - v12, *v2 == v16 * (v17 >> 1) + 110)
      && (v18 = v2[10], v7 + 1 == v18)
      && v17 + 2 * v17 + 4 * (v10 - v6) == v18
      && v2[20] - v5 == 2 * v16
      && (v4 ^ 0x6E) == 29
      && v17 == 4 * v16
      && v2[6] == v8 )
    {
      main_win();
      v3 = v20;
    }
    else
    {
LABEL_5:
      v22[0] = (__int64)&RTYPE_string;
      v22[1] = (__int64)&main_statictmp_4;
      fmt_Fprintln((__int64)&go_itab__ptr_os_File_comma_io_Writer, os_Stdout, (__int64)v22, 1LL, 1LL);
      v3 = v20 + 1;
    }
  }
  runtime_panicindex();

这运算非常多,手工看来是算不了了,没办法只能用z3,在z3里可以直接用赋值语句,这可太强了。后边比较乱的公式几乎是直接搬过来。

from z3 import *

v = [BitVec(f'v{i}', 7) for i in range(23)]
s = Solver()
s.add(v[2]==116, v[9]==99, v[16]==110, v[21]==122, v[22]==125, v[5]==115, v[3]==18^0x74, v[1]==99, v[7]==100, v[19]==0x7a, v[4]== 123 )

v4 = v[5];
v5 = v[1];
v6 = v[7];
v7 = v[13];
v8 = v[14];
v9 = v[6];
v10 = v[4];
v11 = v[8];
s.add(v[12] == v[13])
s.add(v8 + v9 == 104)
s.add(v[15] == v11)
s.add(v11 + 4 == v5)
v12 = v[17]
v13 = v[11]
s.add(125 - v12 + 40 == v13)
v14 = v[18]
v15 = v12 + v13 - v4 - v14
v16 = v14 - v12
s.add(v15 == v16)
v17 = v9 - v12
s.add(v[0] == v16 * (v17 >> 1) + 110)
v18 = v[10]
s.add(v7 + 1 == v18)
s.add(v17 + 2 * v17 + 4 * (v10 - v6) == v18 )
s.add(v[20] - v5 == 2 * v16)
s.add(v17 == 4 * v16)
s.add(v[6] == v8 )

s.check()
d = s.model()
print(bytes([d[i].as_long() for i in v]))

#pctf{s4d_chugg4_n01zez}
#flag{s4d_chugg4_n01zez}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值