[GXYCTF2019]simple CPP

感觉这个题其实还是很简单的,主要是不能看代码这么长,变量比较多就害怕!

v13是持续累加的

 v3 = 0;
  input_len = 0i64;
  v45 = 15i64;
  LOBYTE(Block[0]) = 0;
  v4 = print(std::cout, "I'm a first timer of Logic algebra , how about you?", envp);
  std::ostream::operator<<(v4, sub_7FF7D6AA1B90);
  print(std::cout, "Let's start our game,Please input your flag:", v5);
  scanf(std::cin, Block);
  std::ostream::operator<<(std::cout, sub_7FF7D6AA1B90);
  if ( input_len - 5 > 25 )
  {
    v39 = print(std::cout, "Wrong input ,no GXY{} in input words", v6);
    std::ostream::operator<<(v39, sub_7FF7D6AA1B90);
    goto LABEL_43;
  }
  v7 = (unsigned __int8 *)operator new(0x20ui64);
  xor = v7;
  if ( v7 )
  {
    *(_QWORD *)v7 = 0i64;
    *((_QWORD *)v7 + 1) = 0i64;
    *((_QWORD *)v7 + 2) = 0i64;
    *((_QWORD *)v7 + 3) = 0i64;
  }
  else
  {
    xor = 0i64;
  }
  i = 0;
  if ( input_len )
  {
    ii = 0i64;
    do
    {
      input = Block;
      if ( v45 >= 0x10 )
        input = (void **)Block[0];
      v12 = &qword_7FF7D6AA6048;
      if ( (unsigned __int64)qword_7FF7D6AA6060 >= 0x10 )
        v12 = (void **)qword_7FF7D6AA6048;
      xor[ii] = *((_BYTE *)input + ii) ^ *((_BYTE *)v12 + i % 27);// input,i,qword异或存到 xor
      ++i;
      ++ii;
    }
    while ( i < input_len );
  }
  v13 = 0i64;
  v14 = 0i64;
  v15 = 0i64;
  v16 = 0i64;
  if ( (int)input_len > 30 )                    // len应该是30
    goto LABEL_27;
  v17 = 0;
  if ( (int)input_len <= 0 )
    goto LABEL_27;
  ptr = xor;
  do
  {
    v19 = *ptr + v13;
    ++v17;
    ++ptr;
    switch ( v17 )
    {
      case 8:                                   // 累积8次后清零,存到v16
        v16 = v19;
        goto LABEL_23;
      case 16:                                  // 累积16次后清零,存到v15
        v15 = v19;
        goto LABEL_23;
      case 24:                                  // 累积24次后清零,存到v14
        v14 = v19;
LABEL_23:
        v19 = 0i64;
        break;
      case 32:                                  // 32次后报错
        print(std::cout, "ERRO,out of range", (unsigned int)input_len);
        exit(1);
    }
    v13 = v19 << 8;                             // 位移一个字节用于堆叠,
  }
  while ( v17 < (int)input_len );
  if ( v16 )
  {
    v20 = (__int64 *)operator new(0x20ui64);
    *v20 = v16;
    v20[1] = v15;
    v20[2] = v14;
    v20[3] = v13;
    goto LABEL_28;
  }
LABEL_27:
  v20 = 0i64;
LABEL_28:
  v42 = v20[2];
  v21 = v20[1];
  v22 = *v20;
  v23 = (__int64 *)operator new(0x20ui64);
  if ( IsDebuggerPresent() )
  {
    print(std::cout, "Hi , DO not debug me !", v24);
    Sleep(0x7D0u);
    exit(0);
  }
  v25 = v21 & v22;
  *v23 = v21 & v22;
  v26 = v42 & ~v22;
  v23[1] = v26;
  v27 = ~v21;
  v28 = v42 & v27;
  v23[2] = v42 & v27;
  v29 = v22 & v27;
  v23[3] = v29;
  if ( v26 != 0x11204161012i64 )
  {
    v23[1] = 0i64;
    v26 = 0i64;
  }
  v30 = v26 | v25 | v28 | v29;
  v31 = v20[1];
  v32 = v20[2];
  v33 = v28 & *v20 | v32 & (v25 | v31 & ~*v20 | ~(v31 | *v20));
  v34 = 0;
  if ( v33 == 0x8020717153E3013i64 )
    v34 = v30 == 0x3E3A4717373E7F1Fi64;
  if ( (v30 ^ v20[3]) == 0x3E3A4717050F791Fi64 )
    v3 = v34;
  if ( (v26 | v25 | v31 & v32) == (~*v20 & v32 | 0xC00020130082C0Ci64) && v3 )
  {
    v35 = (__int64 *)print(std::cout, "Congratulations!flag is GXY{", v33);
    v36 = Block;
    if ( v45 >= 16 )
      v36 = (void **)Block[0];
    v37 = sub_7FF7D6AA1FD0(v35, (__int64)v36, input_len);
    print(v37, "}", v38);
    j_j_free(xor);
  }
  else
  {
    print(std::cout, "Wrong answer!try again", v33);
    j_j_free(xor);
  }
LABEL_43:
  if ( v45 >= 0x10 )
  {
    v40 = Block[0];
    if ( v45 + 1 >= 4096 )
    {
      v40 = (void *)*((_QWORD *)Block[0] - 1);
      if ( (unsigned __int64)(Block[0] - v40 - 8) > 0x1F )
        invalid_parameter_noinfo_noreturn();
    }
    j_j_free(v40);
  }
  return 0;
}

动静结合,分段大致猜测

整个 Main 函数就是:输入32位字符,经过异或变换,判断长度,然后将字符串堆叠成四个整型,经过下面许多变量可以反推出这四个变量,然后就可以逆回去了。

哦,对了中间有一个反调试注意跳过,那个qword可以动调得到也可以通过交叉引用。

from z3 import *
x,y,z,w=BitVecs('x y z w',64)
s=Solver()
s.add((~x)&z==1176889593874)
s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==4483974543195470111)
s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==577031497978884115)
s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==4483974544037412639)
s.add(((z&(~x)) | (x&y) | y & z) == (((~x)& z)|864693332579200012))

s.check()
m = s.model()
for i in m:
    print("%s = 0x%x"%(i,m[i].as_long()))

然后反堆叠(也就是固定16字节),得到字节

li=[]
# 拼接
li.append(hex(m[x].as_long())[2:].rjust(16,"0"))
li.append(hex(m[y].as_long())[2:].rjust(16,"0"))
li.append(hex(m[z].as_long())[2:].rjust(16,"0"))
li.append(hex(m[w].as_long())[2:-2])
print(li)
['3e3a460533286f0d', '0c00020130082c0c', '08020717153e3013', '323106']

主要是得到字节,这个反堆叠没什么

for i in range(0,len(li[0]),2):
    print(li[0][i:i+2]+',',end='')
for i in range(0,len(li[1]),2):
    print(li[1][i:i+2]+',',end='')
for i in range(0,len(li[2]),2):
    print(li[2][i:i+2]+',',end='')
for i in range(0,len(li[3]),2):
    print(li[3][i:i+2]+',',end='')
3e,3a,46,05,33,28,6f,0d,0c,00,02,01,30,08,2c,0c,08,02,07,17,15,3e,30,13,32,31,06,

最后异或回去就行了:

Dst = 'i_will_check_is_debug_or_noi_wil'
flag=[0x3E,0x3A,0x46,0x05,0x33,0x28,0x6F,0x0D,0x8C,0x00,0x8A,0x09,0x78,0x49,0x2C,0xAC,0x08,0x02,0x07,0x17,0x15,0x3E,0x30,0x13,0x32,0x31,0x06]
s=''
for i in range(len(flag)):
    s+=chr(ord(Dst[i]) ^ flag[i])
print(s)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值