首页
社区
课程
招聘
[原创]kctf2023 第二题 CN星际基地
发表于: 2023-9-4 23:40 9312

[原创]kctf2023 第二题 CN星际基地

2023-9-4 23:40
9312

ida打开先看初始化部分,有一个反调试,直接patch掉,IsDebuggerPresent的if判断取个反:
图片描述

直接调试main函数,主要逻辑如下(以下代码来自ida7.7):

打印提示字符:"Serial:\t\t",然后std::cin读取用户输入,存在src中。

图片描述

上述代码生成了一个string,根据调试结果得知v25(也就是string)是将输入等分为长度为39的四组,取每组的第i个元素(外层还有while)组成一个四字节的字符串。v26是将v25按照10进制转换为整数,留着后面用。

对于分割可以做如下理解:

然后if语句的三个判断条件主要是判断长度和上述分割出来的string中是否包含'2'(50的ascii)

图片描述

判断分割后的字符串中是否有2,有2的情况下判断有几个2,如果四个都是2就退出,所以输入的字符串分割后不能有'2222'

图片描述

v26就是之前将分割后是string按照10进制转换为整数,v130初始值是0,但是每次比较完之后会将v26赋给v130,由于在while循环中,如果break,就会输出fail并退出。
所以这段代码的核心逻辑的意思是每一组分割后的字符串的十进制值都要比前一组的大,所以输入的串根据前面的分割逻辑分割之后的列向量需要是单调递增的
还有一个细节就是v130的初始值是0,v26要大于v130,所以我们的输入的不能包含'0000'

图片描述

这段逻辑就是将输入的值分为四行,每行39个元素,按照矩阵的形式存入off_7FF6ED1798A8地址中。并且将2转换为-1。
从这里也可以看出我们的输入只能包含'0','1','2'三个元素

之后会进入一个超大的循环进行判断,我们调试的时候追踪一下v67的值可以发现他就是我们输入的每一行值之和(当然是2被转换为-1之后的),如果v67不为0,就退出程序,所以可以得出我们输入的每一行当中'1'和'2'的个数要一样,这样当2转换为-1之后,他们之和才会为0。

图片描述
最后对输入做了一次md5计算,并且判断md5的值。至此有了思路,根据上述对输入的控制条件,以及最终的md5值,可以爆破出输入的序列号。

上述分析中对于输入需要满足的要求都已经粗体显示了,这里总结一下:

再加上提示中的两个条件:

结合上述条件可以爆破一下,大概两分钟就能跑完。

v3 = 0i64;
v132 = 0;
v4 = time64(0i64);
srand(v4);
v5 = sub_7FF6DD8E2F10(std::cout, &unk_7FF6DD8E66E8);
v6 = std::ostream::operator<<(v5, sub_7FF6DD8E30E0);
sub_7FF6DD8E2F10(v6, "Serial:\t\t");
v154 = 0i64;
v155 = 15i64;
LOBYTE(Src) = 0;
sub_7FF6DD8E2A90(&Src, &unk_7FF6DD8E6698, 0i64);
LOBYTE(v7) = 10;
v8 = std::ios::widen((char *)&std::cin + *(int *)(std::cin + 4i64), v7);
sub_7FF6DD8E32F0(std::cin, &Src, v8);
v3 = 0i64;
v132 = 0;
v4 = time64(0i64);
srand(v4);
v5 = sub_7FF6DD8E2F10(std::cout, &unk_7FF6DD8E66E8);
v6 = std::ostream::operator<<(v5, sub_7FF6DD8E30E0);
sub_7FF6DD8E2F10(v6, "Serial:\t\t");
v154 = 0i64;
v155 = 15i64;
LOBYTE(Src) = 0;
sub_7FF6DD8E2A90(&Src, &unk_7FF6DD8E6698, 0i64);
LOBYTE(v7) = 10;
v8 = std::ios::widen((char *)&std::cin + *(int *)(std::cin + 4i64), v7);
sub_7FF6DD8E32F0(std::cin, &Src, v8);
  if ( v10 != 156 )
  {
LABEL_16:
    v15 = sub_7FF6DD8E2F10(std::cout, "fail");
    std::ostream::operator<<(v15, sub_7FF6DD8E30E0);
    goto LABEL_233;
  }
  if ( v10 != 156 )
  {
LABEL_16:
    v15 = sub_7FF6DD8E2F10(std::cout, "fail");
    std::ostream::operator<<(v15, sub_7FF6DD8E30E0);
    goto LABEL_233;
  }
# 输入的序列号
1234567812345678
# 分割后的序列号
# 我这里一行只有四个,题目中一行有39个值,因为输入总长度为156,分割为4组
1234
5678
1234
5678
# 此时每轮v25的值就是'1515'、'2626'...以此类推
# 输入的序列号
1234567812345678
# 分割后的序列号
# 我这里一行只有四个,题目中一行有39个值,因为输入总长度为156,分割为4组
1234
5678
1234
5678
# 此时每轮v25的值就是'1515'、'2626'...以此类推
while ( 1 )
      {
        v65 = 0;
        v66 = 0;
        v67 = 0;
        v68 = *(_QWORD *)((char *)off_7FF6ED1798A8 + v64);
        v69 = 2;
        for ( j = 12i64; j < 168; j += 52i64 )
        {
          v71 = *(_DWORD *)(j + v68 - 12);
          if ( v71 == -1 )
          {
            v65 += v69 - 1 == v63;
          }
          else if ( v71 == 1 )
          {
            v66 += v69 - 1 == v63;
          }
          v72 = v71 + v67;
          v73 = *(_DWORD *)(j + v68 - 8);
          if ( v73 == -1 )
          {
            v65 += v69 == v63;
          }
          else if ( v73 == 1 )
          {
            v66 += v69 == v63;
          }
          v74 = v73 + v72;
          v75 = *(_DWORD *)(j + v68 - 4);
          if ( v75 == -1 )
          {
            v65 += v69 + 1 == v63;
          }
          else if ( v75 == 1 )
          {
            v66 += v69 + 1 == v63;
          }
          v76 = v75 + v74;
          v77 = *(_DWORD *)(j + v68);
          if ( v77 == -1 )
          {
            v65 += v69 + 2 == v63;
          }
          else if ( v77 == 1 )
          {
            v66 += v69 + 2 == v63;
          }
          v78 = v77 + v76;
          v79 = *(_DWORD *)(j + v68 + 4);
          if ( v79 == -1 )
          {
            v65 += v69 + 3 == v63;
          }
          else if ( v79 == 1 )
          {
            v66 += v69 + 3 == v63;
          }
          v80 = v79 + v78;
          v81 = *(_DWORD *)(j + v68 + 8);
          if ( v81 == -1 )
          {
            v65 += v69 + 4 == v63;
          }
          else if ( v81 == 1 )
          {
            v66 += v69 + 4 == v63;
          }
          v82 = v81 + v80;
          v83 = *(_DWORD *)(j + v68 + 12);
          if ( v83 == -1 )
          {
            v65 += v69 + 5 == v63;
          }
          else if ( v83 == 1 )
          {
            v66 += v69 + 5 == v63;
          }
          v84 = v83 + v82;
          v85 = *(_DWORD *)(j + v68 + 16);
          if ( v85 == -1 )
          {
            v65 += v69 + 6 == v63;
          }
          else if ( v85 == 1 )
          {
            v66 += v69 + 6 == v63;
          }
          v86 = v85 + v84;
          v87 = *(_DWORD *)(j + v68 + 20);
          if ( v87 == -1 )
          {
            v65 += v69 + 7 == v63;
          }
          else if ( v87 == 1 )
          {
            v66 += v69 + 7 == v63;
          }
          v88 = v87 + v86;
          v89 = *(_DWORD *)(j + v68 + 24);
          if ( v89 == -1 )
          {
            v65 += v69 + 8 == v63;
          }
          else if ( v89 == 1 )
          {
            v66 += v69 + 8 == v63;
          }
          v90 = v89 + v88;
          v91 = *(_DWORD *)(j + v68 + 28);
          if ( v91 == -1 )
          {
            v65 += v69 + 9 == v63;
          }
          else if ( v91 == 1 )
          {
            v66 += v69 + 9 == v63;
          }
          v92 = v91 + v90;
          v93 = *(_DWORD *)(j + v68 + 32);
          if ( v93 == -1 )
          {
            v65 += v69 + 10 == v63;
          }
          else if ( v93 == 1 )
          {
            v66 += v69 + 10 == v63;
          }
          v94 = v93 + v92;
          v95 = *(_DWORD *)(j + v68 + 36);
          if ( v95 == -1 )
          {
            v65 += v69 + 11 == v63;
          }
          else if ( v95 == 1 )
          {
            v66 += v69 + 11 == v63;
          }
          v67 = v95 + v94;
          v69 += 13;
        }
        if ( v65 == v66 )
        {
          **(_DWORD **)((char *)off_7FF6ED1798B8 + v64) = 0;
        }
        else
        {
          v96 = -1;
          if ( v65 < v66 )
            v96 = 1;
          **(_DWORD **)((char *)off_7FF6ED1798B8 + v64) = v96;
        }
        if ( v67 )
          goto LABEL_16;
while ( 1 )
      {
        v65 = 0;
        v66 = 0;
        v67 = 0;
        v68 = *(_QWORD *)((char *)off_7FF6ED1798A8 + v64);
        v69 = 2;
        for ( j = 12i64; j < 168; j += 52i64 )
        {
          v71 = *(_DWORD *)(j + v68 - 12);
          if ( v71 == -1 )
          {
            v65 += v69 - 1 == v63;
          }
          else if ( v71 == 1 )
          {
            v66 += v69 - 1 == v63;
          }
          v72 = v71 + v67;
          v73 = *(_DWORD *)(j + v68 - 8);
          if ( v73 == -1 )
          {
            v65 += v69 == v63;
          }
          else if ( v73 == 1 )
          {
            v66 += v69 == v63;
          }
          v74 = v73 + v72;
          v75 = *(_DWORD *)(j + v68 - 4);
          if ( v75 == -1 )
          {
            v65 += v69 + 1 == v63;
          }
          else if ( v75 == 1 )
          {
            v66 += v69 + 1 == v63;
          }
          v76 = v75 + v74;
          v77 = *(_DWORD *)(j + v68);
          if ( v77 == -1 )
          {
            v65 += v69 + 2 == v63;
          }
          else if ( v77 == 1 )
          {
            v66 += v69 + 2 == v63;
          }
          v78 = v77 + v76;
          v79 = *(_DWORD *)(j + v68 + 4);
          if ( v79 == -1 )
          {
            v65 += v69 + 3 == v63;
          }
          else if ( v79 == 1 )
          {
            v66 += v69 + 3 == v63;
          }
          v80 = v79 + v78;
          v81 = *(_DWORD *)(j + v68 + 8);
          if ( v81 == -1 )
          {
            v65 += v69 + 4 == v63;
          }
          else if ( v81 == 1 )
          {
            v66 += v69 + 4 == v63;
          }
          v82 = v81 + v80;
          v83 = *(_DWORD *)(j + v68 + 12);
          if ( v83 == -1 )
          {
            v65 += v69 + 5 == v63;
          }
          else if ( v83 == 1 )
          {
            v66 += v69 + 5 == v63;
          }
          v84 = v83 + v82;
          v85 = *(_DWORD *)(j + v68 + 16);
          if ( v85 == -1 )
          {
            v65 += v69 + 6 == v63;
          }
          else if ( v85 == 1 )
          {
            v66 += v69 + 6 == v63;
          }
          v86 = v85 + v84;
          v87 = *(_DWORD *)(j + v68 + 20);
          if ( v87 == -1 )
          {
            v65 += v69 + 7 == v63;
          }
          else if ( v87 == 1 )
          {
            v66 += v69 + 7 == v63;
          }
          v88 = v87 + v86;
          v89 = *(_DWORD *)(j + v68 + 24);
          if ( v89 == -1 )
          {
            v65 += v69 + 8 == v63;
          }
          else if ( v89 == 1 )
          {
            v66 += v69 + 8 == v63;
          }
          v90 = v89 + v88;
          v91 = *(_DWORD *)(j + v68 + 28);
          if ( v91 == -1 )
          {
            v65 += v69 + 9 == v63;
          }
          else if ( v91 == 1 )

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 2
支持
分享
最新回复 (3)
雪    币: 238
活跃值: (247)
能力值: ( LV3,RANK:21 )
在线值:
发帖
回帖
粉丝
2
          v138 = 0x67452301;
          v139 = 0xEFCDAB89;
          v140 = 0x98BADCFE;
          v141 = 0x10325476;
          v107 = v149;
          if ( v151 >= 0x10 )
            v107 = (void **)v149[0];
          sub_1400036A0(v137, v107, v150, v97);
          v108 = sub_1400034C0(v137);

你好,请问是如何判断这个是求MD5的函数; 是v138至v141这4个特征数字吗?

2023-9-5 14:08
0
雪    币: 2259
活跃值: (1400)
能力值: ( LV8,RANK:138 )
在线值:
发帖
回帖
粉丝
3
hesl &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...
对的,md5特征值是这个,还可以复制这段算法给ai,他会从逐行给你分析,结合md5的算法过程也能确认,再加上组后那段字符串长得也像md5的串所以就可以判断
2023-9-5 18:14
0
雪    币: 3614
活跃值: (31036)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2023-9-6 09:31
1
游客
登录 | 注册 方可回帖
返回
//