一件事情不付诸实践,即使在心里|

yuanyy720

园龄:2年11个月粉丝:1关注:2

2023-12-22 14:10阅读: 573评论: 0推荐: 2

CatFly【汇编代码还原】

CatFly【难度:1】

题目界面

下载附件,发现是dll文件,放到linux中运行一下,运行界面如图所示:

从上图中可以看到两处字符串,上面的字符串不断滚动,下方字符串在次数上不断累加,猜测上方字符串与flag相关。

静态调试

  • 打开IDA,找到main函数

    方便分析,此处只粘贴关键部分代码(源代码的后半部分)

      time(&timer);
      v13 = 1;
      v24 = 0LL;
      v23 = 0;
      v22 = 0;
      v12 = off_FA88;
      while ( v13 )
      {
        if ( dword_E104 )
          printf("\x1B[H");
        else
          printf("\x1B[u");
        for ( k = dword_E1EC; k < dword_E1F0; ++k )
        {
          for ( m = dword_E1F4; m < dword_E1F8; ++m )
          {
            if ( k <= 23 || k > 42 || m >= 0 )
            {
              if ( m >= 0 && (unsigned int)k <= 0x3F && m <= 63 )
              {
    
                v19 = off_FA20[v24][k][m];
                off_FA88 = sub_6314((unsigned int)v24, k, m, (__int64)v12);
              }
              else
              {
                v19 = 44;
              }
            }
            else
            {
              v18 = (2 - m) % 16 / 8;
              if ( ((v24 >> 1) & 1) != 0 )
                v18 = 1 - v18;
              s[128] = (__int64)",,>>&&&+++###==;;;,,";
              v19 = asc_BFE3[v18 - 23 + k];
              if ( !v19 )
                v19 = 44;
            }
            if ( v25 )
            {
              printf("%s", *((const char **)&unk_FCC0 + v19));
            }
            else if ( v19 == v22 || !*((_QWORD *)&unk_FCC0 + v19) )
            {
              printf("%s", off_FA88);
            }
            else
            {
              v22 = v19;
              printf("%s%s", *((const char **)&unk_FCC0 + v19), off_FA88);
            }
          }
          sub_65E2(1LL);
        }
        if ( dword_E100 )
        {
          time(&time1);
          v11 = difftime(time1, timer);
          v10 = sub_63FF((unsigned int)(int)v11);
          for ( n = (dword_E1FC - 29 - v10) / 2; n > 0; --n )
            putchar(32);
          dword_E1E8 += printf("\x1B[1;37mYou have nyaned for %d times!\x1B[J\x1B[0m", (unsigned int)++dword_108E0);
        }
        v22 = 0;
        ++v23;
        if ( dword_104C4 && v23 == dword_104C4 )
          sub_6471();
        if ( !off_FA20[++v24] )
          v24 = 0LL;
        usleep(1000 * v27);
      }
      return 0LL;
    

    因为flag可能与屏幕上滚动的字符串有关,所以此处需要格外关注printf函数。从上述关键代码中,可以看到off_FA88最可能与flag有关,因为其他的printf函数打印的基本是一个确定的值。

  • 查看目标的交叉引用路径

    确定了off_FA88后,开始查找与其相关的函数。

    • 第一处是469行中的对off_FA88的赋值操作

      off_FA88的值是sub_6314()函数的返回值。

    • 接下来进入sub_6314()函数

      函数伪代码如下图所示:

      其功能为:当a2!=18,a3≤4||a3>54时off_FA88不变(v12的值就是off_FA88),所以此处相当于是k=18(一次)且m∈(4,53)时会执行sub_6314函数,即循环执行50次。该函数的返回值是byte_104C8的地址,byte_104C8的值与dword_E120[a3-5],dword_E120[a3-5]的值又与sub_62B5()函数的返回值有关。这里还有个sub_62E3作为逻辑判断的条件。将此处逻辑进行还原,还原代码如下:

      for (int i = 0; i < 50; i++) {
           dword_E120[i] ^= sub_62B5();
       }
      
    • 查看sub_62B5()函数

      函数伪代码如下图所示:

      可以看到该函数的返回值与dword_E1E8相关,查看dword_E1E8的交叉引用,可以看到只在main函数中有一次自增操作:

    • 总结整个流程

  • 还原关键汇编代码

    此处使用大佬wp给的代码进行分析,基本都给了解析:

    #include<stdio.h>
    #include<string.h>
    //在ida里面点开dword_E1E8会发现初始值为0x1106
    int dword_E1E8 = 0x1106;
    //同理,ida里也能看到dword_E120的初始值
    int dword_E120[50] = { 0x27fb, 0x27a4, 0x464e, 0x0e36, 0x7b70, 0x5e7a, 0x1a4a, 0x45c1, 0x2bdf, 0x23bd, 0x3a15, 0x5b83, 0x1e15, 0x5367, 0x50b8, 0x20ca, 0x41f5, 0x57d1, 0x7750, 0x2adf, 0x11f8, 0x09bb, 0x5724, 0x7374, 0x3ce6, 0x646e, 0x010c, 0x6e10, 0x64f4, 0x3263, 0x3137, 0x00b8, 0x229c, 0x7bcd, 0x73bd, 0x480c, 0x14db, 0x68b9, 0x5c8a, 0x1b61, 0x6c59, 0x5707, 0x09e6, 0x1fb9, 0x2ad3, 0x76d4, 0x3113, 0x7c7e, 0x11e0, 0x6c70 };
    //原封不动抄下来就好了
    int sub_62B5()
    {
        dword_E1E8 = 1103515245 * dword_E1E8 + 12345;
        return (dword_E1E8 >> 10) & 0x7FFF;
    }
    //这块是拿来算输出数字n需要多少个字符的。
    //因为main函数中的dword_E1E8需要接收printf函数的返回值
    //而printf函数的返回值是打印的字符长度
    int llog(int n) {
        int a = 0;
        while (n /= 10)a++;
        return a;
    }
    //这个函数我没有特别放出来,反正这里也是照抄的
    int sub_62E3(char a1)
    {
        int result; // rax
    
        if ((a1 & 0x7Fu) <= 0x7E)
            result = (a1 & 0x7Fu) > 0x20;
        else
            result = 0LL;
        return result;
    }
    
    int main() {
        //count代表那个不停自增的dword_108E0
        int count = 0;
        while (1) {
            for (int i = 0; i < 50; i++) {
                dword_E120[i] ^= sub_62B5();
            }
            count++;
            //计算printf的返回值,更改dword_E1E8,每10倍增加一个位数
            dword_E1E8 += 42 + llog(count);
            if (count % 1000000 == 0) {
                printf("Count:%d\n", count);
            }
            //flag代表off_FA88
            unsigned char flag[51] = { 0 };
            for (int i = 0; i < 50; i++) {
                //根据出题人所说,出题时循环次数为705980581,但是线性同余随机数算法出现了循环导致在100427942就出现了flag,若只考虑数组的最低字节,能在100001958得到flag
                // Loop: 100427942
                // if((dword_E120[i] & 0xff00)){
                //     break;
                // }
                // Loop: 100001958
                if (!sub_62E3(dword_E120[i])) {
                    break;
                }
                flag[i] = dword_E120[i] & 0xff;
            }
            if (memcmp("CatCTF", flag, 6) == 0) {
                puts(flag);
                printf("Count:%d\n", count);
                break;
            }
        }
    }
    
  • 运行代码,得到flag

本文作者:yuanyy

本文链接:https://www.cnblogs.com/yuanyy/p/17921456.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yuanyy720  阅读(573)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 Raindrops (Intl. Version) Katja Krasavice,Leony
  2. 2 Cheap Thrills Sia
Raindrops (Intl. Version) - Katja Krasavice,Leony
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : Katja Krasavice/Leonie Burger

作曲 : Mark Becker/Vitali Zestovskih

Raindrops on my window pane

But nothing takes the pain away

Blood is pumping through my veins

But I will never feel the same

Worst thing about a breaking heart

The one you love ripped it apart

Raindrops on my window pane

But nothing takes the pain away

Every time I hear my phone ring

I'm afraid it might be you

And I don't know why you're still calling

I see your name out of the blue

It's like every time you broke my heart

I heard the pieces fall apart

Raindrops on my window pane

You make moving on too hard, yeah

Raindrops on my window pane

But nothing takes the pain away

Blood is pumping through my veins

But I will never feel the same

Worst thing about a breaking heart

The one you love ripped it apart

Raindrops on my window pane

But nothing takes the pain away

All those years went by

And you never cared about me

Doesn't matter now, you

See my face all over Berlin

And now I can hear your breaking heart

I should've known right from the start

Raindrops on my window pane

Moving on for you is hard, yeah

Raindrops on my window pane

But nothing takes the pain away

Blood is pumping through my veins

But I will never feel the same

Worst thing about a breaking heart

The one you love ripped it apart

Raindrops on my window pane

But nothing takes the pain away

I don't know why, I don't know why

You said goodbye, you said goodbye

You make me cry, why you make me cry?

I don't know why, I don't know why