'); }

CISCN_babybc


0x1

感觉这题最大的难点是bc,实际内容很容易推理出是数独,如果知道了bc是什么,就比较容易解出。

0x2

最开始得到的是bc文件,什么是bc文件,个人觉得就是还没编译完成的中间文件,可以接着将它编译成我们能进行正常逆向分析的文件,

img

图是其他师傅画的,yeah

我们可以用clang将bc文件编译为elf文件

clang baby.bc -o baby

将得到的elf文件拖入ida,就可以进行内容的分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned __int64 v4; // [rsp+10h] [rbp-28h]
  unsigned __int64 i; // [rsp+18h] [rbp-20h]
  size_t v6; // [rsp+20h] [rbp-18h]

  __isoc99_scanf(&unk_4015B4, input, envp);
  if ( (unsigned int)strlen((const char *)(unsigned int)input) == 25 )// len==25
  {
    if ( input[0] )
    {
      if ( (unsigned __int8)(input[0] - 48) > 5u )
        return 0;
      v6 = strlen((const char *)(unsigned int)input);
      for ( i = 1LL; ; ++i )
      {
        v4 = i;
        if ( i >= v6 )
          break;
        if ( (unsigned __int8)(input[v4] - 48) > 5u )// input[i]<=5&&input[i]>0
          return 0;
      }
    }
    if ( (check1(input) & 1) != 0 && (check2() & 1) != 0 )
      printf("CISCN{MD5(%s)}", input);
  }
  return 0;
}

确定输入值的len,范围

check1函数是为了确保如果5*5的数组内如果原始值不为零的时候,你输入的值需要为零

check2的分析内容如下

__int64 check()
{
  char v1; // [rsp+34h] [rbp-B4h]
  __int64 v2; // [rsp+38h] [rbp-B0h]
  __int64 l; // [rsp+48h] [rbp-A0h]
  __int64 v4; // [rsp+58h] [rbp-90h]
  __int64 j; // [rsp+60h] [rbp-88h]
  __int64 v6; // [rsp+80h] [rbp-68h]
  char v7; // [rsp+8Fh] [rbp-59h]
  __int64 v8; // [rsp+A8h] [rbp-40h]
  __int64 k; // [rsp+B8h] [rbp-30h]
  __int64 i; // [rsp+C8h] [rbp-20h]
  char v11[6]; // [rsp+DCh] [rbp-Ch] BYREF
  char v12[6]; // [rsp+E2h] [rbp-6h] BYREF

  i = 0LL;
  do                                            // 同一排中不能有相同值
  {
    v8 = i;
    memset(v12, 0, sizeof(v12));
    if ( v12[(unsigned __int8)flag[5 * i]]
      || (v12[(unsigned __int8)flag[5 * i]] = 1, v12[(unsigned __int8)flag[5 * i + 1]])
      || (v12[(unsigned __int8)flag[5 * i + 1]] = 1, v12[(unsigned __int8)flag[5 * i + 2]])
      || (v12[(unsigned __int8)flag[5 * i + 2]] = 1, v12[(unsigned __int8)flag[5 * i + 3]])
      || (v12[(unsigned __int8)flag[5 * i + 3]] = 1, v12[(unsigned __int8)flag[5 * i + 4]]) )
    {
      v7 = 0;
      return v7 & 1;
    }
    ++i;
  }
  while ( v8 + 1 < 5 );
  k = 0LL;
  while ( 1 )                                   // 同一列中不能有相同值
  {
    v6 = k;
    memset(v11, 0, sizeof(v11));
    if ( v11[(unsigned __int8)flag[k]] )
      break;
    v11[(unsigned __int8)flag[k]] = 1;
    if ( v11[(unsigned __int8)byte_602055[k]] )
      break;
    v11[(unsigned __int8)byte_602055[k]] = 1;
    if ( v11[(unsigned __int8)byte_60205A[k]] )
      break;
    v11[(unsigned __int8)byte_60205A[k]] = 1;
    if ( v11[(unsigned __int8)byte_60205F[k]] )
      break;
    v11[(unsigned __int8)byte_60205F[k]] = 1;
    if ( v11[(unsigned __int8)byte_602064[k]] )
      break;
    ++k;
    if ( v6 + 1 >= 5 )
    {
      j = 0LL;                                  // 相邻两列进行设置限制
      while ( 1 )                               // 0==>无限制,1==>小于,2==>大于
      {
        v4 = j;
        if ( rule1[4 * j] == 1 )
        {
          if ( (unsigned __int8)flag[5 * j] < (unsigned __int8)flag[5 * j + 1] )
            goto LABEL_27;
        }
        else if ( rule1[4 * j] == 2 && (unsigned __int8)flag[5 * j] > (unsigned __int8)flag[5 * j + 1] )
        {
LABEL_27:
          v7 = 0;
          return v7 & 1;
        }
        if ( arr1[4 * j] == 1 )                 // arr1[0]=n[1]
        {
          if ( (unsigned __int8)flag[5 * j + 1] < (unsigned __int8)flag[5 * j + 2] )
            goto LABEL_27;
        }
        else if ( arr1[4 * j] == 2 && (unsigned __int8)flag[5 * j + 1] > (unsigned __int8)flag[5 * j + 2] )
        {
          goto LABEL_27;
        }
        if ( arr2[4 * j] == 1 )
        {
          if ( (unsigned __int8)flag[5 * j + 2] < (unsigned __int8)flag[5 * j + 3] )
            goto LABEL_27;
        }
        else if ( arr2[4 * j] == 2 && (unsigned __int8)flag[5 * j + 2] > (unsigned __int8)flag[5 * j + 3] )
        {
          goto LABEL_27;
        }
        if ( arr3[4 * j] == 1 )
        {
          if ( (unsigned __int8)flag[5 * j + 3] < (unsigned __int8)flag[5 * j + 4] )
            goto LABEL_27;
        }
        else if ( arr3[4 * j] == 2 && (unsigned __int8)flag[5 * j + 3] > (unsigned __int8)flag[5 * j + 4] )
        {
          goto LABEL_27;
        }
        ++j;
        if ( v4 + 1 >= 5 )
        {
          l = 0LL;                              // 相邻两行进行设置限制
          while ( 1 )
          {
            v2 = l + 1;                         // 0==>无限制,1==>大于,2==>小于
            if ( rule2[5 * l] == 1 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l] > (unsigned __int8)flag[5 * v2] )
                goto LABEL_26;
            }
            else if ( rule2[5 * l] == 2 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l] < (unsigned __int8)flag[5 * v2] )
              {
LABEL_26:
                v7 = v1;
                return v7 & 1;
              }
            }
            if ( Arr1[5 * l] == 1 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 1] > (unsigned __int8)flag[5 * v2 + 1] )
                goto LABEL_26;
            }
            else if ( Arr1[5 * l] == 2 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 1] < (unsigned __int8)flag[5 * v2 + 1] )
                goto LABEL_26;
            }
            if ( Arr2[5 * l] == 1 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 2] > (unsigned __int8)flag[5 * v2 + 2] )
                goto LABEL_26;
            }
            else if ( Arr2[5 * l] == 2 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 2] < (unsigned __int8)flag[5 * v2 + 2] )
                goto LABEL_26;
            }
            if ( Arr3[5 * l] == 1 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 3] > (unsigned __int8)flag[5 * v2 + 3] )
                goto LABEL_26;
            }
            else if ( Arr3[5 * l] == 2 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 3] < (unsigned __int8)flag[5 * v2 + 3] )
                goto LABEL_26;
            }
            if ( byte_602094[5 * l] == 1 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 4] > (unsigned __int8)flag[5 * v2 + 4] )
                goto LABEL_26;
            }
            else if ( byte_602094[5 * l] == 2 )
            {
              v1 = 0;
              if ( (unsigned __int8)flag[5 * l + 4] < (unsigned __int8)flag[5 * v2 + 4] )
                goto LABEL_26;
            }
            ++l;
            v1 = 1;
            if ( v2 >= 4 )                      // 运行四次
              goto LABEL_26;
          }
        }
      }
    }
  }
  v7 = 0;
  return v7 & 1;
}

由于只是5*5的数独,自己可以手动推一下,也可以使用z3实现数独解密

import hashlib
from z3 import *
a=[0, 0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0]   #行 0==>无限制,1==>小于,2==>大于
b=[0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1]   #列 0==>无限制,1==>大于,2==>小于
s=Solver()
sudu=[[None]*5,[None]*5,[None]*5,[None]*5,[None]*5]
for i in range(5):
    for j in range(5):
        sudu[i][j]=Int("%d" %(i*5+j))

s.add(sudu[2][2]==4,sudu[3][3]==3)
for i in range(5):
    for j in range(5):
        s.add(sudu[i][j]>=1,sudu[i][j]<=5)

for i in range(5):
    for j in range(5):
        for k in range(j):
            s.add(sudu[i][j]!=sudu[i][k])
for i in range(5):
    for j in range(5):
        for k in range(j):
            s.add(sudu[j][i]!=sudu[k][i])

for i in range(5):
    for j in range(4):
        if a[4*i+j]==1:
            s.add(sudu[i][j]>sudu[i][j+1])
        elif a[4*i+j]==2:
            s.add(sudu[i][j]<sudu[i][j+1])
for i in range(4):
    for j in range(5):
        if b[5*i+j]==1:
            s.add(sudu[i][j]<sudu[(i+1)][j])
        elif b[5*i+j]==2:
            s.add(sudu[i][j]>sudu[(i+1)][j])
            
if s.check()==sat:
    print("yeah")
    strflag=""
    m=s.model()
    for i in range(5):
        for j in range(5):
            if (i==2 and j==2) or (i==3 and j==3):
                strflag+="0"
                continue
            strflag+=str(m[sudu[i][j]].as_long())
    # print(strflag)
    print(hashlib.md5(strflag.encode()).hexdigest())
else:
    print("emmm")

得到flag:

CISCN{8a04b4597ad08b83211d3adfa1f61431}

  目录