SUCTF2019-hardCPP WP

前言

  • 这两天参加了 NU1LCTFByteCTF ,签了到之后发现一题都做不出来 /(ㄒoㄒ)/~~ ,很受伤。所以打算回顾一下错过的 SUCTF2019 ,多积累经验和学习更多的技术。

分析

  • IDA打开,发现程序是 LLVM 编译的,还加了花指令,导致看起来非常绕。
    在这里插入图片描述

  • 坑爹的是还不能动态调试,只能静态分析了。过程难以描述,这里就贴一下正确的执行步骤吧:

      int __cdecl main(int argc, const char **argv, const char **envp)
      {
        signed int v3; // eax
        signed int v4; // eax
        signed int v5; // ecx
        signed int v6; // eax
        signed int v7; // eax
        signed int v8; // eax
        signed int v9; // eax
        signed int v10; // eax
        char v11; // al
        char v12; // al
        char v13; // al
        char v14; // al
        char v15; // al
        signed int v16; // ecx
        signed int v17; // eax
        signed int v18; // eax
        unsigned int v19; // eax
        unsigned int v20; // eax
        unsigned int v21; // eax
        signed int v22; // ecx
        char v24; // al
        char v25; // al
        char v26; // al
        char v27; // al
        signed int v28; // [rsp+9Ch] [rbp-94h]
        char v29; // [rsp+A0h] [rbp-90h]
        char v30; // [rsp+A8h] [rbp-88h]
        char v31; // [rsp+B0h] [rbp-80h]
        char v32; // [rsp+B8h] [rbp-78h]
        char v33; // [rsp+C0h] [rbp-70h]
        char v34; // [rsp+C8h] [rbp-68h]
        char v35; // [rsp+CFh] [rbp-61h]
        int v36; // [rsp+D0h] [rbp-60h]
        int input_len; // [rsp+D4h] [rbp-5Ch]
        int v38; // [rsp+D8h] [rbp-58h]
        int v39; // [rsp+DCh] [rbp-54h]
        char input[24]; // [rsp+E0h] [rbp-50h]
        char v41; // [rsp+F8h] [rbp-38h]
        char v42; // [rsp+100h] [rbp-30h]
        char v43; // [rsp+108h] [rbp-28h]
        char v44; // [rsp+110h] [rbp-20h]
        int v45; // [rsp+114h] [rbp-1Ch]
        const char **v46; // [rsp+118h] [rbp-18h]
        int v47; // [rsp+120h] [rbp-10h]
        int v48; // [rsp+124h] [rbp-Ch]
        int v49; // [rsp+128h] [rbp-8h]
        bool v50; // [rsp+12Eh] [rbp-2h]
        bool v51; // [rsp+12Fh] [rbp-1h]
      
        v48 = 0;
        v47 = argc;
        v46 = argv;
        v45 = time(0LL);
        puts("func(?)=\"01abfc750a0c942167651c40d088531d\"?");
        input[0] = getchar();
        fgets(&input[1], 21, stdin);
        v39 = time(0LL);
        v38 = v39 - v45;
        v49 = v39 - v45;
        v28 = 0x703FF685;
        while ( 1 )
        {
          while ( 1 )
          {
            while ( 1 )
            {
              while ( 1 )
              {
                while ( 1 )
                {
                  while ( 1 )
                  {
                    while ( 1 )
                    {
                      while ( 1 )
                      {
                        while ( 1 )
                        {
                          while ( 1 )
                          {
                            while ( 1 )
                            {
                              while ( 1 )
                              {
                                while ( 1 )
                                {
                                  while ( 1 )
                                  {
                                    while ( v28 == 0x8364E2E6 )
                                    {
                                      v35 = v38 ^ input[v36];// v35=input[v36]
                                      v34 = GetChar((__int64)&v43, v35);// v34=v35
                                      v33 = Get_Char_3((__int64)&v41, input[v38 - 1 + v36]);// v33=input[v36-1]
                                      v11 = Mod(&v33, 7);
                                      v35 = Add((__int64)&v34, v11);
                                      v32 = Get_Char_2((__int64)&v44, v35);// v32=v35
                                      v31 = Get_Char_2((__int64)&v44, input[v38 - 1 + v36]);
                                      v12 = Xor(&v31, 18);
                                      v30 = Get_Char_4((__int64)&v42, v12);
                                      v13 = Mult(&v30, 3);
                                      v29 = GetChar((__int64)&v43, v13);
                                      v14 = Add((__int64)&v29, 2);
                                      v15 = Xor(&v32, v14);
                                      v16 = 0x4D79419D;
                                      v35 = v15;
                                      v51 = enc[v36 - 1] != v15;
                                      if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                                        v16 = 0xE6B1C47D;
                                      v28 = v16;
                                    }
                                    if ( v28 != 0x8B56CD07 )
                                      break;
                                    v28 = 0x5E980F0E;
                                  }
                                  if ( v28 != 0x8FAFE559 )
                                    break;
                                  v28 = 0xC54B2616;
                                  puts("You win");
                                }
                                if ( v28 != 0x918FF00C )
                                  break;
                                v18 = 0x51FB290B;
                                if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                                  v18 = 1154698238;
                                v28 = v18;
                              }
                              if ( v28 != 0xB743BDDC )
                                break;
                              v21 = 0x8FAFE559;
                              if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                                v21 = 0xC54B2616;
                              v28 = v21;
                            }
                            if ( v28 != 0xC54B2616 )
                              break;
                            puts("You win");
                            v22 = 0x8FAFE559;
                            if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                              v22 = 0x1B327C95;
                            v28 = v22;
                          }
                          if ( v28 != 0xCB553B5C )
                            break;
      LABEL_70:
                          v19 = 0xEB1FA22E;
                          if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                            v19 = 0xFCB084AC;
                          v28 = v19;
                        }
                        if ( v28 != 0xD3E10A81 )
                          break;
                        v4 = 0x7F611913;              // (3)
                        if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                          v4 = 0x2C0D2A04;            // (4)
                        v28 = v4;                     // v28=0x2C0D2A04
                      }
                      if ( v28 == 0xE4A1C025 )
                        exit(0);
                      if ( v28 != 0xE6B1C47D )
                        break;
                      v17 = 0x6EAC82CB;
                      if ( v51 )
                        v17 = 0x918FF00C;
                      v28 = v17;
                    }
                    if ( v28 != 0xEB1FA22E )
                      break;
                    v28 = 0xFCB084AC;
                  }
                  if ( v28 != 0xEE73C818 )
                    break;
                  v6 = 0x66996259;                    // (8)
                  if ( v50 )
                    v6 = 0xE4A1C025;
                  v28 = v6;                           // v28=0x66996259
                }
                if ( v28 != 0xF28568CF )
                  break;
                v28 = 0x16FA3CE;
              }
              if ( v28 != 0xFCB084AC )
                break;
              v20 = 0xEB1FA22E;
              if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                v20 = 0xF28568CF;
              v28 = v20;
            }
            if ( v28 != 0x16FA3CE )
              break;
            ++v36;
            v28 = 0x5E980F0E;
          }
          if ( v28 == 0x1B327C95 )
            return 0;
          if ( v28 == 0x1E2AAEDE )
          {
            puts("Let the silent second hand take the place of my doubt...");
            exit(0);
          }
          if ( v28 == 0x25297AE9 )
          {
            v36 = 1;
            v28 = 0x437E1545;
          }
          else if ( v28 == 0x2C0D2A04 )
          {
            input_len = strlen(input);                // (5)
            v50 = input_len != 21;
            v5 = 0x7F611913;
            if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
              v5 = 0xEE73C818;                        // (6)
            v28 = v5;                                 // v28=0xEE73C818
          }
          else if ( v28 == 0x3C4B1D57 )
          {
            v10 = 0x4D79419D;
            if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
              v10 = 0x8364E2E6;
            v28 = v10;
          }
          else if ( v28 == 0x437E1545 )
          {
            v8 = 0x25297AE9;
            v36 = 1;
            if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
              v8 = 0x8B56CD07;
            v28 = v8;
          }
          else
          {
            if ( v28 == 0x44D34BFE )
              exit(0);
            if ( v28 == 0x4D79419D )
            {
              v35 = v38 ^ input[v36];
              v34 = GetChar((__int64)&v43, v35);
              v33 = Get_Char_3((__int64)&v41, input[v38 - 1 + v36]);
              v24 = Mod(&v33, 7);
              v35 = Add((__int64)&v34, v24);
              v32 = Get_Char_2((__int64)&v44, v35);
              v31 = Get_Char_2((__int64)&v44, input[v38 - 1 + v36]);
              v25 = Xor(&v31, 18);
              v30 = Get_Char_4((__int64)&v42, v25);
              v26 = Mult(&v30, 3);
              v29 = GetChar((__int64)&v43, v26);
              v27 = Add((__int64)&v29, 2);
              v35 = Xor(&v32, v27);
              v28 = 0x8364E2E6;
            }
            else
            {
              if ( v28 == 0x51FB290B )
                exit(0);
              switch ( v28 )
              {
                case 0x5E980F0E:                      // (10)
                  v9 = 0xB743BDDC;
                  if ( v36 < 21 )                     // 进行20轮变换
                    v9 = 0x3C4B1D57;
                  v28 = v9;
                  break;
                case 0x66996259:                      // (9)
                  v7 = 0x25297AE9;
                  if ( y < 10 || (((_BYTE)x - 1) * (_BYTE)x & 1) == 0 )
                    v7 = 0x437E1545;
                  v28 = v7;
                  break;
                case 0x6EAC82CB:
                  goto LABEL_70;
                case 0x703FF685:                      // (1)
                  v3 = 0xD3E10A81;
                  if ( v49 > 0 )
                    v3 = 0x1E2AAEDE;
                  v28 = v3;                           // (2)v28=0xD3E10A81
                  break;
                case 0x7F611913:                      // (7)
                  input_len = strlen(input);
                  v28 = 0x2C0D2A04;
                  break;
              }
            }
          }
        }
      }
    
  • 标号的地方表示第 i 次执行的位置。到了第 10 次以后,我猜测程序应该是验证输入的数据了。验证的方式在:
    在这里插入图片描述

  • 原先的函数名也是没有意义的,经过分析之后被我重定义了。

  • 所以得到递推关系:

      v15=(input[v36]+(input[v36-1]%7))^((input[v36-1]^18)*3+2)
      //验证
      v15==enc[v36 - 1]
    
  • 所以反求 input 的关系式是:

      input[i]=(enc[i-1]^((input[i-1]^18)*3+2)&0xff)-(input[i-1]%7)
    
  • 但是 input[0] 需要爆破一下

脚本

enc=[0xf3,0x2e,0x18,0x36,0xe1,0x4c,0x22,0xd1,0xf9,0x8c,0x40,0x76,0xf4,0xe,0x0,0x5,0xa3,0x90,0xe,0xa5]
for k in range(128):
    out=''
    input=[]
    input.append(k)
    out+=chr(k)
    for i in range(1,21):
        ch=(enc[i-1]^((input[i-1]^18)*3+2)&0xff)-(input[i-1]%7)
        input.append(ch&0xff)
        out+=chr(ch&0xff)
    if 'flag' in out:
        print(out)
        break

#flag{mY-CurR1ed_Fns}

总结

  • 代码量不多的情况下,可以根据初始条件和输出提示,进行目标导向性的探索。猜测程序应该怎么走才会走向成功,探测路径应围绕着输入的数据进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值