2021国赛CISCN 初赛 部分RE writeup

2023-11-11

glass

题目名称:glass
题目描述:Reverse sign in,flag形式为"CISCN{XXXXX}"

首先查看apk

界面如下

用AndroidKiller打开,反编译成java源码

这里只是声明了一下checkflag函数 要去native-lib里找

分析\glass\Project\lib\armeabi-v7a中的libnative-lib.so

IDA打开

怀疑是RC4加密 参考 https://www.cnblogs.com/SunsetR/p/12247041.html

bool __fastcall Java_com_ciscn_glass_MainActivity_checkFlag(int a1, int a2, int a3)
{
  const char *v3; // r4
  size_t v4; // r5
  int v6; // [sp+0h] [bp-220h]
  char v7; // [sp+100h] [bp-120h]

  v3 = (const char *)sub_F0C(a1, a3);
  if ( strlen(v3) != 39 )                   //flag长度为39
    return 0;
  _aeabi_memclr8(&v7, 256);                
  _aeabi_memcpy8(&v6, "12345678", 256);		//定义v6 v7 给v6赋值12345678
  v4 = strlen((const char *)&v6);    		//v4为v6的长度 8
  sub_FFC(&v7, &v6, v4);					//RC4填充S盒,s盒乱序
  sub_1088(&v7, v3, 39);					//RC4计算密钥流,异或加密
  sub_10D4(v3, 39, &v6, v4);				//自己搞得加密
  return memcmp(v3, &unk_497C, 0x27u) == 0;
}
unk_497C
0xa3, 0x1a, 0xe3, 0x69, 0x2f, 0xbb, 0x1a, 0x84, 0x65, 0xc2, 0xad, 0xad, 0x9e, 0x96, 0x5, 0x2, 0x1f, 0x8e, 0x36, 0x4f, 0xe1, 0xeb, 0xaf, 0xf0, 0xea, 0xc4, 0xa8, 0x2d, 0x42, 0xc7, 0x6e, 0x3f, 0xb0, 0xd3, 0xcc, 0x78, 0xf9, 0x98, 0x3f
 sub_10D4(v3, 39, &v6, v4);
 int __fastcall sub_10D4(int result, int a2, int a3, int a4)
{
  int i; // r4
  int v5; // r6
  char v6; // r5
  char v7; // lr
  char v8; // r12
  int j; // lr
  int k; // r6

  for ( i = 0; i < a2; i += 3 )
  {
    v5 = result + i;
    v6 = *(_BYTE *)(result + i + 2);
    v7 = *(_BYTE *)(result + i + 1);
    v8 = *(_BYTE *)(result + i) ^ v6;
    *(_BYTE *)(result + i) = v8;
    *(_BYTE *)(v5 + 2) = v6 ^ v7;
    *(_BYTE *)(v5 + 1) = v7 ^ v8;   //交换异或
  }
  for ( j = 0; j < a2; j += a4 )
  {
    for ( k = 0; (a4 & ~(a4 >> 31)) != k && j + k < a2; ++k )
      *(_BYTE *)(result + k) ^= *(_BYTE *)(a3 + k); //分别异或12345678
    result += a4;
  }
  return result;
}

解题代码如下

#include <stdio.h>
#include <windows.h>


unsigned char *base64_encode(unsigned char *str)
{
    long len;
    long str_len;
    unsigned char *res;
    int i,j;
//定义base64编码表
    unsigned char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

//计算经过base64编码后的字符串长度
    str_len=strlen(str);
    if(str_len % 3 == 0)
        len=str_len/3*4;
    else
        len=(str_len/3+1)*4;

    res=malloc(sizeof(unsigned char)*len+1);
    res[len]='\0';

//以3个8位字符为一组进行编码
    for(i=0,j=0;i<len-2;j+=3,i+=4) {="" res[i]="base64_table[str[j]">>2]; //取出第一个字符的前6位并找出对应的结果字符
        res[i+1]=base64_table[(str[j]&0x3)<<4 | (str[j+1]>>4)]; //将第一个字符的后位与第二个字符的前4位进行组合并找到对应的结果字符
        res[i+2]=base64_table[(str[j+1]&0xf)<<2 | (str[j+2]>>6)]; //将第二个字符的后4位与第三个字符的前2位组合并找出对应的结果字符
        res[i+3]=base64_table[str[j+2]&0x3f]; //取出第三个字符的后6位并找出结果字符
    }

    switch(str_len % 3)
    {
        case 1:
            res[i-2]='=';
            res[i-1]='=';
            break;
        case 2:
            res[i-1]='=';
            break;
    }

    return res;
}

int main(){
	int j=0,i=0;

    byte result[]  = { 0xa3, 0x1a, 0xe3, 0x69, 0x2f, 0xbb, 0x1a,  0x84, 0x65,0xc2,0xad, 0xad,  0x9e, 0x96, 0x5, 0x2, 0x1f, 0x8e, 0x36, 0x4f,  0xe1,  0xeb,0xaf,  0xf0,  0xea,  0xc4,  0xa8, 0x2d, 0x42,  0xc7, 0x6e, 0x3f, 0xb0,  0xd3,0xcc, 0x78,  0xf9,  0x98, 0x3f};
    char key[] = "1234567812345678123456781234567812345678";

    for (i = 0; i < sizeof(result); i++) {
        result[i] = result[i] ^ key[i];
    }
    for (j = 0; j < sizeof(result); j += 3) {
        result[j + 1] =  result[j + 1] ^ result[j];
        result[j + 2] = result[j + 2] ^ result[j + 1];
        result[j] = result[j] ^ result[j + 2];
    }
    char* flag = base64_encode(result);
    printf(flag);


    return 0;
}

+Lpql0fK6JHFB273kgs5khSor36qUEWNbS22hm6fhl7fsx5SpmJq

秘钥12345678

CISCN{6654d84617f627c88846c172e0f4d46c}

babybc

##方法一:

手撕出来的(惭愧)

有约束条件的数独 给出了两个数

拿到bc文件

根据https://stackoverflow.com/questions/32523847/how-to-make-llvm-bc-file-executable导出32位elf文件

int __cdecl main(int argc, const char **argv, const char **envp)
{
  size_t v3; // rax
  unsigned __int64 v4; // rcx
  unsigned __int8 v5; // dl

  __isoc99_scanf(&unk_402004, x, envp);
  if ( (unsigned int)strlen(x) == 25 ) //25位flag
  {//数组所有的元素都<=5
    if ( x[0] ) 
    {
      if ( (unsigned __int8)(x[0] - 48) > 5u )
        return 0;
      v3 = strlen(x);
      v4 = 1LL;
      while ( v4 < v3 )
      {
        v5 = x[v4++] - 48;//chr数字转int数字
        if ( v5 > 5u )
          return 0;
      }
    }
    if ( f((__int64)x) && c() )//两个check函数都得为1
      printf("CISCN{MD5(%s)}", x);
  }
  return 0;
}
char __fastcall f(__int64 a1)
{
  __int64 v1; // rax
  __int64 i; // rcx
  char v3; // dl
  char v4; // dl
  char v5; // dl
  char v6; // dl
  char v7; // dl
//填充数字 m[]为0则填充 不为0则判断输入的数是否为0,不为0报错 所以要让m[]中不为0位置的输入为0
    //这个函数的作用就是 让m[]中的4 3 位置输入为0
  v1 = 4LL;
  for ( i = 0LL; i < 5; ++i )
  {
    v3 = *(_BYTE *)(a1 + v1 - 4);
    if ( m[v1 - 4] )
    {
      if ( v3 != 48 )
        return 0;
    }
    else
    {
      if ( v3 == 48 )
        return 0;
      m[v1 - 4] = v3 - 48;
    }
    v4 = *(_BYTE *)(a1 + v1 - 3);
    if ( m[v1 - 3] )
    {
      if ( v4 != 48 )
        return 0;
    }
    else
    {
      if ( v4 == 48 )
        return 0;
      m[v1 - 3] = v4 - 48;
    }
    v5 = *(_BYTE *)(a1 + v1 - 2);
    if ( m[v1 - 2] )
    {
      if ( v5 != 48 )
        return 0;
    }
    else
    {
      if ( v5 == 48 )
        return 0;
      m[v1 - 2] = v5 - 48;
    }
    v6 = *(_BYTE *)(a1 + v1 - 1);
    if ( m[v1 - 1] )
    {
      if ( v6 != 48 )
        return 0;
    }
    else
    {
      if ( v6 == 48 )
        return 0;
      m[v1 - 1] = v6 - 48;
    }
    v7 = *(_BYTE *)(a1 + v1);
    if ( m[v1] )
    {
      if ( v7 != 48 )
        return 0;
    }
    else
    {
      if ( v7 == 48 )
        return 0;
      m[v1] = v7 - 48;
    }
    v1 += 5LL;
  }
  return 1;
}
char c()
{
  unsigned __int8 *v0; // rax
  __int64 v1; // rdx
  __int64 v2; // rsi
  __int64 v3; // rsi
  __int64 v4; // rsi
  __int64 v5; // rsi
  __int64 v6; // rax
  __int64 v7; // rdx
  __int64 v8; // rdx
  __int64 v9; // rdx
  __int64 v10; // rdx
  unsigned __int8 *v11; // rax
  __int64 v12; // rdx
  char v13; // cl
  char v14; // cl
  char v15; // cl
  char v16; // cl
  __int64 v17; // rdx
  __int64 v18; // rsi
  char result; // al
  char v20; // al
  char v21; // al
  char v22; // al
  char v23; // al
  char v24; // al
  int v25; // [rsp+0h] [rbp-10h]
  __int16 v26; // [rsp+4h] [rbp-Ch]
  int v27; // [rsp+8h] [rbp-8h]
  __int16 v28; // [rsp+Ch] [rbp-4h]

  v0 = &m[4];
  v1 = 0LL;
  while ( 1 )
  {
    v28 = 0;
    v27 = 0;
    v2 = *(v0 - 4);
    if ( *((_BYTE *)&v27 + v2) )
      break;
    *((_BYTE *)&v27 + v2) = 1;
    v3 = *(v0 - 3);
    if ( *((_BYTE *)&v27 + v3) )
      break;
    *((_BYTE *)&v27 + v3) = 1;
    v4 = *(v0 - 2);
    if ( *((_BYTE *)&v27 + v4) )
      break;
    *((_BYTE *)&v27 + v4) = 1;
    v5 = *(v0 - 1);
    if ( *((_BYTE *)&v27 + v5) )
      break;
    *((_BYTE *)&v27 + v5) = 1;
    if ( *((_BYTE *)&v27 + *v0) )
      break;
    ++v1;
    v0 += 5;
    if ( v1 >= 5 )
    {
      v6 = 0LL;
      while ( 1 )
      {
        v26 = 0;
        v25 = 0;
        v7 = m[v6];
        if ( *((_BYTE *)&v25 + v7) )
          break;
        *((_BYTE *)&v25 + v7) = 1;
        v8 = m[v6 + 5];
        if ( *((_BYTE *)&v25 + v8) )
          break;
        *((_BYTE *)&v25 + v8) = 1;
        v9 = m[v6 + 10];
        if ( *((_BYTE *)&v25 + v9) )
          break;
        *((_BYTE *)&v25 + v9) = 1;
        v10 = m[v6 + 15];
        if ( *((_BYTE *)&v25 + v10) )
          break;
        *((_BYTE *)&v25 + v10) = 1;
        if ( *((_BYTE *)&v25 + m[v6 + 20]) )
          break;
//关键代码在这 两个循环分别代表行 和 列 
//n是行 o是列 m是整个地图
          
        if ( ++v6 >= 5 )
        {
          v11 = &m[4];
          v12 = 0LL;
          //4个判断 因为5*5的棋盘 两两比较 只需要四次 
              /*n[]={0,0,0,1 
              		 1,0,0,0 
              		 2,0,0,1
              		 0,0,0,0
              		 1,0,1,0 有用的就到这
              		 0,0,0,0
              		 0,0,0,0
              		 0,0,0,0}
              */
         //1 左大 2 右大
          while ( 1 ) {	 
            v13 = n[4 * v12];
            if ( v13 == 2 )
            {
              if ( *(v11 - 4) > *(v11 - 3) )
                return 0;
            }
            else if ( v13 == 1 && *(v11 - 4) < *(v11 - 3) )
            {
              return 0;
            }
            v14 = n[4 * v12 + 1];
            if ( v14 == 1 )
            {
              if ( *(v11 - 3) < *(v11 - 2) )
                return 0;
            }
            else if ( v14 == 2 && *(v11 - 3) > *(v11 - 2) )
            {
              return 0;
            }
            v15 = n[4 * v12 + 2];
            if ( v15 == 2 )
            {
              if ( *(v11 - 2) > *(v11 - 1) )
                return 0;
            }
            else if ( v15 == 1 && *(v11 - 2) < *(v11 - 1) )
            {
              return 0;
            }
            v16 = n[4 * v12 + 3];
            if ( v16 == 2 )
            {
              if ( *(v11 - 1) > *v11 )
                return 0;
            }
            else if ( v16 == 1 && *(v11 - 1) < *v11 )
            {
              return 0;
            }
            ++v12;
            v11 += 5;
            if ( v12 >= 5 )
            {
              v17 = 4LL;
              v18 = 0LL;
                /*o[]表示列
                o[]={0,0,2,0
                	2,0,0,0
                	0,0,0,0
                	0,1,0,0
                	1,0,0,1}
                	1 上大 2 下大
                    每列的12 23 34 45分别比较
                */
              while ( 1 )
              {
                v20 = o[v17 - 4];
                if ( v20 == 2 )
                {
                  if ( m[v17 - 4] < m[v17 + 1] )
                    return 0;
                }
                else if ( v20 == 1 && m[v17 - 4] > m[v17 + 1] )
                {
                  return 0;
                }
                v21 = o[v17 - 3];
                if ( v21 == 1 )
                {
                  if ( m[v17 - 3] > m[v17 + 2] )
                    return 0;
                }
                else if ( v21 == 2 && m[v17 - 3] < m[v17 + 2] )
                {
                  return 0;
                }
                v22 = o[v17 - 2];
                if ( v22 == 2 )
                {
                  if ( m[v17 - 2] < m[v17 + 3] )
                    return 0;
                }
                else if ( v22 == 1 && m[v17 - 2] > m[v17 + 3] )
                {
                  return 0;
                }
                v23 = o[v17 - 1];
                if ( v23 == 2 )
                {
                  if ( m[v17 - 1] < m[v17 + 4] )
                    return 0;
                }
                else if ( v23 == 1 && m[v17 - 1] > m[v17 + 4] )
                {
                  return 0;
                }
                v24 = o[v17];
                if ( v24 == 2 )
                {
                  if ( m[v17] < m[v17 + 5] )
                    return 0;
                }
                else if ( v24 == 1 && m[v17] > m[v17 + 5] )
                {
                  return 0;
                }
                ++v18;
                v17 += 5LL;
                result = 1;
                if ( v18 >= 4 )
                  return result;
              }
            }
          }
        }
      }
      return 0;
    }
  }
  return 0;
}

根据所得条件 画出map图

每行和每列都得有 12345并且不能有重复

数独做出来后为

14253 53142 35021 21504 42315

测试一下

md5后CISCN{8a04b4597ad08b83211d3adfa1f61431}

##方法二:
下载文件后,发现是.bc文件,使用命令编译成可执行文件:
llc -filetype=obj baby.bc
gcc baby.o
使用ida打开,发现主函数:


int __cdecl main(int argc, const char **argv, const char **envp)
{
  size_t v3; // rax
  unsigned __int64 v4; // rcx
  unsigned __int8 v5; // dl

  __isoc99_scanf(&unk_402004, x, envp);
  if ( (unsigned int)strlen(x) == 25 )
  {
    if ( x[0] )
    {
      if ( (unsigned __int8)(x[0] - 48) > 5u )
        return 0;
      v3 = strlen(x);
      v4 = 1LL;
      while ( v4 < v3 )
      {
        v5 = x[v4++] - 48;
        if ( v5 > 5u )
          return 0;
      }
    }
    if ( f((__int64)x) && c() )
      printf("CISCN{MD5(%s)}", x);
  }
  return 0;
}

分析主函数可知:输入的长度为25位,并且每位都不大于5,最终flag为输入值的md5值外面加上CISCN{},经过f((int64)x) 和c()两个函数校验之后确定输入的值是不是flag.查看这两个函数:f((int64)x):


char __fastcall f(__int64 a1)
{
  signed __int64 v1; // rax
  signed __int64 v2; // rcx
  char v3; // dl
  char v4; // dl
  char v5; // dl
  char v6; // dl
  char v7; // dl

  v1 = 4LL;
  v2 = 0LL;
  do
  {
    v3 = *(_BYTE *)(a1 + v1 - 4);
    if ( m[v1 - 4] )
    {
      if ( v3 != 48 )
        return 0;
    }
    else
    {
      if ( v3 == 48 )
        return 0;
      m[v1 - 4] = v3 - 48;
    }
    v4 = *(_BYTE *)(a1 + v1 - 3);
    if ( m[v1 - 3] )
    {
      if ( v4 != 48 )
        return 0;
    }
    else
    {
      if ( v4 == 48 )
        return 0;
      m[v1 - 3] = v4 - 48;
    }
    v5 = *(_BYTE *)(a1 + v1 - 2);
    if ( m[v1 - 2] )
    {
      if ( v5 != 48 )
        return 0;
    }
    else
    {
      if ( v5 == 48 )
        return 0;
      m[v1 - 2] = v5 - 48;
    }
    v6 = *(_BYTE *)(a1 + v1 - 1);
    if ( m[v1 - 1] )
    {
      if ( v6 != 48 )
        return 0;
    }
    else
    {
      if ( v6 == 48 )
        return 0;
      m[v1 - 1] = v6 - 48;
    }
    v7 = *(_BYTE *)(a1 + v1);
    if ( m[v1] )
    {
      if ( v7 != 48 )
        return 0;
    }
    else
    {
      if ( v7 == 48 )
        return 0;
      m[v1] = v7 - 48;
    }
    ++v2;
    v1 += 5LL;
  }
  while ( v2 < 5 );
  return 1;
}

c():


char c()
{
  unsigned __int8 *v0; // rax
  signed __int64 v1; // rdx
  __int64 v2; // rsi
  __int64 v3; // rsi
  __int64 v4; // rsi
  __int64 v5; // rsi
  __int64 v6; // rax
  __int64 v7; // rdx
  __int64 v8; // rdx
  __int64 v9; // rdx
  __int64 v10; // rdx
  unsigned __int8 *v11; // rax
  signed __int64 v12; // rdx
  char v13; // cl
  char v14; // cl
  char v15; // cl
  char v16; // cl
  signed __int64 v17; // rdx
  signed __int64 v18; // rsi
  char result; // al
  char v20; // al
  char v21; // al
  char v22; // al
  char v23; // al
  char v24; // al
  int v25; // [rsp+0h] [rbp-10h]
  __int16 v26; // [rsp+4h] [rbp-Ch]
  int v27; // [rsp+8h] [rbp-8h]
  __int16 v28; // [rsp+Ch] [rbp-4h]

  v0 = &m[4];
  v1 = 0LL;
  while ( 1 )
  {
    v28 = 0;
    v27 = 0;
    v2 = *(v0 - 4);
    if ( *((_BYTE *)&v27 + v2) )
      break;
    *((_BYTE *)&v27 + v2) = 1;
    v3 = *(v0 - 3);
    if ( *((_BYTE *)&v27 + v3) )
      break;
    *((_BYTE *)&v27 + v3) = 1;
    v4 = *(v0 - 2);
    if ( *((_BYTE *)&v27 + v4) )
      break;
    *((_BYTE *)&v27 + v4) = 1;
    v5 = *(v0 - 1);
    if ( *((_BYTE *)&v27 + v5) )
      break;
    *((_BYTE *)&v27 + v5) = 1;
    if ( *((_BYTE *)&v27 + *v0) )
      break;
    ++v1;
    v0 += 5;
    if ( v1 >= 5 )
    {
      v6 = 0LL;
      while ( 1 )
      {
        v26 = 0;
        v25 = 0;
        v7 = m[v6];
        if ( *((_BYTE *)&v25 + v7) )
          break;
        *((_BYTE *)&v25 + v7) = 1;
        v8 = m[v6 + 5];
        if ( *((_BYTE *)&v25 + v8) )
          break;
        *((_BYTE *)&v25 + v8) = 1;
        v9 = m[v6 + 10];
        if ( *((_BYTE *)&v25 + v9) )
          break;
        *((_BYTE *)&v25 + v9) = 1;
        v10 = m[v6 + 15];
        if ( *((_BYTE *)&v25 + v10) )
          break;
        *((_BYTE *)&v25 + v10) = 1;
        if ( *((_BYTE *)&v25 + m[v6 + 20]) )
          break;
        if ( ++v6 >= 5 )
        {
          v11 = &m[4];
          v12 = 0LL;
          while ( 1 )
          {
            v13 = n[4 * v12];
            if ( v13 == 2 )
            {
              if ( *(v11 - 4) > *(v11 - 3) )
                return 0;
            }
            else if ( v13 == 1 && *(v11 - 4) < *(v11 - 3) )
            {
              return 0;
            }
            v14 = n[4 * v12 + 1];
            if ( v14 == 1 )
            {
              if ( *(v11 - 3) < *(v11 - 2) )
                return 0;
            }
            else if ( v14 == 2 && *(v11 - 3) > *(v11 - 2) )
            {
              return 0;
            }
            v15 = n[4 * v12 + 2];
            if ( v15 == 2 )
            {
              if ( *(v11 - 2) > *(v11 - 1) )
                return 0;
            }
            else if ( v15 == 1 && *(v11 - 2) < *(v11 - 1) )
            {
              return 0;
            }
            v16 = n[4 * v12 + 3];
            if ( v16 == 2 )
            {
              if ( *(v11 - 1) > *v11 )
                return 0;
            }
            else if ( v16 == 1 && *(v11 - 1) < *v11 )
            {
              return 0;
            }
            ++v12;
            v11 += 5;
            if ( v12 >= 5 )
            {
              v17 = 4LL;
              v18 = 0LL;
              while ( 1 )
              {
                v20 = o[v17 - 4];
                if ( v20 == 2 )
                {
                  if ( m[v17 - 4] < m[v17 + 1] )
                    return 0;
                }
                else if ( v20 == 1 && m[v17 - 4] > m[v17 + 1] )
                {
                  return 0;
                }
                v21 = o[v17 - 3];
                if ( v21 == 1 )
                {
                  if ( m[v17 - 3] > m[v17 + 2] )
                    return 0;
                }
                else if ( v21 == 2 && m[v17 - 3] < m[v17 + 2] )
                {
                  return 0;
                }
                v22 = o[v17 - 2];
                if ( v22 == 2 )
                {
                  if ( m[v17 - 2] < m[v17 + 3] )
                    return 0;
                }
                else if ( v22 == 1 && m[v17 - 2] > m[v17 + 3] )
                {
                  return 0;
                }
                v23 = o[v17 - 1];
                if ( v23 == 2 )
                {
                  if ( m[v17 - 1] < m[v17 + 4] )
                    return 0;
                }
                else if ( v23 == 1 && m[v17 - 1] > m[v17 + 4] )
                {
                  return 0;
                }
                v24 = o[v17];
                if ( v24 == 2 )
                {
                  if ( m[v17] < m[v17 + 5] )
                    return 0;
                }
                else if ( v24 == 1 && m[v17] > m[v17 + 5] )
                {
                  return 0;
                }
                ++v18;
                v17 += 5LL;
                result = 1;
                if ( v18 >= 4 )
                  return result;
              }
            }
          }
        }
      }
      return 0;
    }
  }
  return 0;
}

可以看出f(x)函数是先对m数组的值判断,如果当前值不是0,判断输入的值是不是0,如果不是,则退出,即代表输入错误,如果当前m值是0,判断输入值是0,则退出,代表输入错误,如果不是,则把输入值赋值给m数组当前值.可以得出输入的第13和第19位为0c()函数是对赋值后的m数组校验,先是判断相邻数字横向大小,再判断竖向,可以据此写出z3脚本求解:


from z3 import *
x1 = Int('x1')
x2 = Int('x2')
x3 = Int('x3')
x4 = Int('x4')
x5 = Int('x5')
x6 = Int('x6')
x7 = Int('x7')
x8 = Int('x8')
x9 = Int('x9')
x10 = Int('x10')
x11 = Int('x11')
x12 = Int('x12')
x13 = Int('x13')
x14 = Int('x14')
x15 = Int('x15')
x16 = Int('x16')
x17 = Int('x17')
x18 = Int('x18')
x19 = Int('x19')
x20 = Int('x20')
x21 = Int('x21')
x22 = Int('x22')
x23 = Int('x23')
x24 = Int('x24')
x25 = Int('x25')
s = Solver()
s.add(x13 == 4,x19 == 3)
s.add(x1 < 6, x1 > 0)
s.add(x2 < 6, x2 > 0)
s.add(x3 < 6, x3 > 0)
s.add(x4 < 6, x4 > 0)
s.add(x5 < 6, x5 > 0)
s.add(x6 < 6, x6 > 0)
s.add(x7 < 6, x7 > 0)
s.add(x8 < 6, x8 > 0)
s.add(x9 < 6, x9 > 0)
s.add(x10 < 6, x10 > 0)
s.add(x11 < 6, x11 > 0)
s.add(x12 < 6, x12 > 0)
s.add(x13 < 6, x13 > 0)
s.add(x14 < 6, x14 > 0)
s.add(x15 < 6, x15 > 0)
s.add(x16 < 6, x16 > 0)
s.add(x17 < 6, x17 > 0)
s.add(x18 < 6, x18 > 0)
s.add(x19 < 6, x19 > 0)
s.add(x20 < 6, x20 > 0)
s.add(x21 < 6, x21 > 0)
s.add(x22 < 6, x22 > 0)
s.add(x23 < 6, x23 > 0)
s.add(x24 < 6, x24 > 0)
s.add(x25 < 6, x25 > 0)
s.add(x6 > x7)
s.add(x3 > x8)
s.add(x4 > x5)
s.add(x5 > x10)
s.add(x14 > x15)
s.add(x19 > x14)
s.add(x23 > x24)
s.add(x25 > x20)
s.add(x21 > x22)
s.add(x22 > x17)
s.add(x12 > x11)
s.add(x1 != x2, x1 != x3, x1 != x4, x1 != x5, x2 != x3, x2 != x4, x2 != x5, x3 != x4, x3 != x5, x4 != x5)
s.add(x6 != x7, x6 != x8, x6 != x9, x6 != x10, x7 != x8, x7 != x9, x7 != x10, x8 != x9, x8 != x10, x9 != x10)
s.add(x11 != x12, x11 != x13, x11 != x14, x11 != x15, x12 != x13, x21 != x14, x12 != x15, x13 != x14, x13 != x15,
      x14 != x15)
s.add(x16 != x17, x16 != x18, x16 != x19, x16 != x20, x17 != x18, x17 != x19, x17 != x20, x18 != x19, x18 != x20,
      x19 != x20)
s.add(x21 != x22, x21 != x23, x21 != x24, x21 != x25, x22 != x23, x22 != x24, x22 != x25, x23 != x24, x23 != x25,
      x24 != x25)
s.add(x1 != x6, x1 != x11, x1 != x16, x1 != x21, x6 != x11, x6 != x16, x6 != x21, x11 != x16, x11 != x21, x16 != x21)
s.add(x2 != x7, x2 != x12, x2 != x17, x2 != x22, x7 != x12, x7 != x17, x7 != x22, x12 != x17, x12 != x22, x17 != x22)
s.add(x3 != x8, x3 != x13, x3 != x18, x3 != x23, x8 != x13, x8 != x18, x8 != x23, x13 != x18, x13 != x23, x18 != x23)
s.add(x4 != x9, x4 != x14, x4 != x19, x4 != x24, x9 != x14, x9 != x19, x9 != x24, x14 != x19, x14 != x24, x19 != x24)
s.add(x5 != x10, x5 != x15, x5 != x20, x5 != x25, x10 != x15, x10 != x20, x10 != x25, x15 != x20, x15 != x25,
      x20 != x25)
if s.check() == sat:
    m = s.model()
    print(m.eval(x1),m.eval(x2),m.eval(x3),m.eval(x4),
          m.eval(x5),m.eval(x6),m.eval(x7),m.eval(x8),
          m.eval(x9),m.eval(x10),m.eval(x11),m.eval(x12),
          m.eval(x13),m.eval(x14),m.eval(x15),m.eval(x16),
          m.eval(x17),m.eval(x18),m.eval(x19),m.eval(x20),
          m.eval(x21),m.eval(x22),m.eval(x23),m.eval(x24),m.eval(x25))

得到m数组值:1 4 2 5 3 5 3 1 4 2 3 5 4 2 1 2 1 5 3 4 4 2 3 1 5

则输入值为: 1425353142350212150442315

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2021国赛CISCN 初赛 部分RE writeup 的相关文章

  • docker安装fastdfs集群

    在dockerhub上搜索fastdfs 我选择了使用最多的星星最多的镜像 season fastdfs 拉取镜像 docker pull season fastdfs 创建数据卷 docker volume create tracker
  • 恒指李阳12.9日预测及操作建议

    恒指早盘资讯 上周五美股集体收涨 道指收涨逾330点 标普500指数收涨0 91 科技股普涨 苹果涨近2 再创历史新高 港股ADR指数小幅下跌 按比例计算 收报26489点 跌9 13点或0 03 汇丰控股收报57 74元 较港收市升0 2
  • 避免同一个文件被include多次

    在C C 中 为了避免同一个文件被include多次 有两种方式 一种是 ifndef方式 一种是 pragma once方式 在头文件的最开始加入 ifndef ifndef的是方式是受C C 语言标准支持 ifndef方式依赖于宏名不能
  • TS 的类

    一 基础语法 class Person constructor 二 类的属性 1 属性的初始化 在 TS 中 我们如果在要 constructor 中定义一个属性 必须先在 constructor 之前对数据进行初始化 class Pers
  • css禁止滑动页面_弹出层完美禁止页面滚动

    Html Css Js 弹出层去除背景滚动 原生版 使用js构建的弹出层类 使用new的方式实例化 传入的参数为 el 触发元素 click触发弹出层 content 弹出层内容 time 0 显示持续时间 使用 passive 事件和ov
  • mysql一对多关联查询语句_mysql 一对多的时分 关联查询 筛选多方

    mysql 一对多的时候 关联查询 筛选多方 users 表和 auth token log表是一对多 现在是把user的信息找出来 关联上一些 auth token log表的数据 因为a表是多的一方 要多他的数据进行一些条件匹配 这个s
  • 数字化时代-7:从三大产业看赚钱的立足点

    摘要 通过观察不同产业的发展特点 发现社会发展的趋势 农业社会 工业社会 信息社会 虚拟社会演进 物质产品生产 精神产品的生产 把握大势 让猪遇到风飞起来 违背大势 飞机也会坠毁 何为产业 主要是指在经济社会中 能够生产某种类型产品的部门的

随机推荐

  • 出门问问把AIGC看得很透彻

    图片来源 Pixabay 李志飞将AIGC看得很透 他可能是行业里 最不着急 的人 数科星球原创 作者丨苑晶 编辑丨大兔 几乎每一个行业 从业者都是国外的2倍 利润又是同行的1 5 让中国的创业难度提升了10倍 李志飞的这句话适用于广大行业
  • Echarts 各种点击事件监听

    目录 一 鼠标事件 1 1 左击 1 2 双击 1 3 右击 1 4 右键双击 1 5 中轴滚动 二 时间轴 2 1 时间轴监听 三 拖动 3 1 拖动事件 一 鼠标事件 1 1 左击 chart on click function par
  • 乘积尾零(蓝桥杯省赛2018C/C++A组第三题)

    题目 如下的 10 行数据 每行有 10 个整数 请你求出它们的乘积的末尾有多少个零 5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3
  • 图像分类篇:实现pytorch官网demo(LeNet)

    跟着b站up主学习整理 2 1 pytorch官方demo Lenet 哔哩哔哩 bilibili 目录 一 CNN的雏形 LeNet网络结构 二 官网demo文件 三 代码实现 1 model py 2 train py 3 predic
  • 最酷炫的Python进度条使用教程

    原文链接 https mp weixin qq com s gRpNq15bX4OgpiY5NNO OQ 效果展示 基础使用 导入 alive progress 库 from alive progress import alive bar
  • overleaf入门教程

    overleaf入门教程 中文学习文档 供自己学习记录 1 编译中文 输入内容为中文时 有两种方式 需要将 documentclass article 改为 documentclass ctexart 或者引用宏包 usepaceage c
  • 获取每个年龄段的人数

  • Android 实现无需权限的悬浮球效果,可适配至Android 10

    前言 最近闲来无事 突然想起搞一下悬浮球 之前的项目的悬浮球一直都需要授权 android6 0以后需要手动授权 悬浮球使用时就非常不便 这里为大家带来一种无需权限的悬浮球实现方式 无需权限 无需权限 功能 自动贴边 显示红点 隐藏红点 自
  • 微信小程序—tabBar导航栏

    1 什么是tabBar tabBar是移动端应用常见的页面效果 用于实现多页面的快速切换 小程序中常分为 底部 tabBar 顶部 tabBar 2 tabBar 节点的配置项 position tabBar的位置 仅支持bottom to
  • python操作mysql数据库详解

    使用Python操作MySQL数据库 MySQL是一种关系型数据库管理系统 它可以用来存储和管理大量的数据 之前介绍了大部分主流数据库 今天将介绍如何使用Python来操作MySQL数据库 安装MySQL 首先 我们需要安装MySQL服务器
  • 测试数据埋点

    简单理解下 埋点其实就是在程序中的某个位置加一个标记 当用户触发到某个行为的时候 就采集一下数据 然后将数据上报到某个位置进行存储 埋点的最终目的是收集到相关的数据 用于给运营人员提供数据支撑等 什么是埋点测试 埋点也分前端埋点和后端埋 前
  • LR(1)算法

    构造出LR 1 项的规范族 先从起始状态设为CC0 然后对于每一个语法符号构造出下一个CCX 意味着吸收了这个语法符号后可能到达的状态 运用不动点算法不断迭代 构造出CCI 意思是如果输入某个符号 可能到达的状态 吸收算法更精妙 即将状态与
  • 织梦DedeCms文章标题字数限制的解决方法

    织梦系统默认的文章标题字数限制是60 也就是30个汉字 不够用怎么办 很简单 只需两步搞定织梦DedeCms文章标题字数的限制 1 在后台选择系统 gt 其它选项 gt 文档标题最大长度改此参数后需要手工修改数据表修改为需要设置的标题最大长
  • 启动服务失败,Java HotSpot(TM) 64-Bit Server VM warning: error='Cannot allocate memory' (errno=12)

    反复启动 down了又起 没起成功down了又起 反复操作了三遍 应用服务 有多个netty服务端 的时候报这个错误 RealServer Start OK 2018 10 30 15 46 52 INFO 2018 10 30 15 46
  • HDU 1106 排序

    题目 输入一行数字 如果我们把这行数字中的 5 都看成空格 那么就得到一行用空格分割的若干非负整数 可能有些整数以 0 开头 这些头部的 0 应该被忽略掉 除非这个整数就是由若干个 0 组成的 这时这个整数就是0 你的任务是 对这些分割得到
  • 【秒懂+解决方案】git error: The following untracked working tree files would be overwritten by checkout: ...

    问题分析 问题出在 Error 所列出的文件在本地的当前分支下未授权给 git 追踪 但同样命名的文件 也即出现在另一个 远程 分支下的同一文件却正在远程仓库或其它分支被 git 进行追踪 接下来的操作 git merge checkout
  • html5将文字生成图片

    由于canvas能够将画布上的纹理生成数据给img显示出来 所以 我们在html5里面可以实现将文字生成图片显示 首先我书写了一个将文字绘制到canvas上面的函数 然后函数会返回canvas绘制的纹理数据 绘制文字到canvas 判断换行
  • MATLAB三维绘图(四)绘制特殊的三维图

    MATLAB三维绘图 四 绘制特殊的三维图 1 使用pie3绘制三维饼状图 示例 绘制三维饼图 clear all x 0 2 0 1 0 25 0 15 0 16 y 3 5 5 7 10 5 8 5 figure subplot 121
  • 求高手:jquery中的$('.XXX')中的.是什么意思啊

    求高手 jquery中的 XXX 中的 是什么意思啊 问题点数 30分 结帖人montelaa 不显示删除回复 显示所有回复 显示星级回复 显示得分回复 只显示楼主 收藏 montelaa montelaa
  • 2021国赛CISCN 初赛 部分RE writeup

    glass 题目名称 glass 题目描述 Reverse sign in flag形式为 CISCN XXXXX 首先查看apk 界面如下 用AndroidKiller打开 反编译成java源码 这里只是声明了一下checkflag函数