zoukankan      html  css  js  c++  java
  • buu 红帽杯 XX

    一.拖入ida,静态分析

    __int64 __fastcall sub_7FF65D4511A0(__int64 a1, __int64 a2)
    {
      signed __int64 v2; // rbx
      signed __int64 v3; // rax
      __int64 v4; // rax
      __int64 v5; // r11
      __int128 *v6; // r14
      int v7; // edi
      _BYTE *v8; // rsi
      char v9; // r10
      int v10; // edx
      __int64 v11; // r8
      unsigned __int64 v12; // rcx
      signed __int64 v13; // rcx
      unsigned __int64 v14; // rax
      unsigned __int64 i; // rax
      __int64 v16; // rax
      size_t v17; // rsi
      _BYTE *v18; // rbx
      _BYTE *v19; // r9
      signed int v20; // er11
      char *v21; // r8
      signed __int64 v22; // rcx
      char v23; // al
      signed __int64 v24; // r9
      signed __int64 v25; // rdx
      __int64 v26; // rax
      size_t Size; // [rsp+20h] [rbp-48h]
      __int128 v29; // [rsp+28h] [rbp-40h]
      int v30; // [rsp+38h] [rbp-30h]
      int v31; // [rsp+3Ch] [rbp-2Ch]
      int Code[4]; // [rsp+40h] [rbp-28h]
      int v33; // [rsp+50h] [rbp-18h]
    
      *(_OWORD *)Code = 0i64;
      v33 = 0;
      sub_7FF65D4518C0(std::cin, a2, Code); //根据cin,知道是在输入字符串,存入Code里面
      v2 = -1i64;
      v3 = -1i64;
      do
        ++v3;
      while ( *((_BYTE *)Code + v3) );
      if ( v3 != 19 )   //字符串长度为19
      {
        sub_7FF65D451620(std::cout, "error
    ");
        _exit((unsigned __int64)Code);
      }
      v4 = sub_7FF65D451E5C(5ui64);  //根据后面的判断是申请内存空间
      v5 = *(_QWORD *)&::Code;  //这里有点迷惑性,看似是输入的字符串,实际点进去就知道是个常量
      v6 = (__int128 *)v4;
      v7 = 0;
      v8 = (_BYTE *)v4;
      do                     
      {
        v9 = v8[(_QWORD)Code - v4];
        v10 = 0;
        *v8 = v9;
        v11 = 0i64;
        v12 = -1i64;
        do
          ++v12;
        while ( *(_BYTE *)(v5 + v12) );
        if ( v12 )
        {
          do
          {
            if ( v9 == *(_BYTE *)(v5 + v11) )
              break;
            ++v10;
            ++v11;
          }
          while ( v10 < v12 );
        }
        v13 = -1i64;
        do
          ++v13;
        while ( *(_BYTE *)(v5 + v13) );
        if ( v10 == v13 )
          _exit(v5);
        ++v8;
      }
      while ( (signed __int64)&v8[-v4] < 4 );
      *(_BYTE *)(v4 + 4) = 0;                  //判断字符串的前四位在字符串常量中,基本判断出是flag
      do
        ++v2;
      while ( *((_BYTE *)Code + v2) );    //字符串常量长度为36
      v14 = 0i64;
      v29 = *v6;
      while ( *((_BYTE *)&v29 + v14) )
      {
        if ( !*((_BYTE *)&v29 + v14 + 1) )
        {
          ++v14;
          break;
        }
        if ( !*((_BYTE *)&v29 + v14 + 2) )
        {
          v14 += 2i64;
          break;
        }
        if ( !*((_BYTE *)&v29 + v14 + 3) )
        {
          v14 += 3i64;
          break;
        }
        v14 += 4i64;
        if ( v14 >= 0x10 )
          break;
      }                              //测试那段内存空间字符串的长度
      for ( i = v14 + 1; i < 0x10; ++i )  //补齐16位,也就是128bits
        *((_BYTE *)&v29 + i) = 0;
      v16 = sub_7FF65D451AB0(Code, v2, &v29, &Size); //结合题目,和上面的基本判定是xxtea加密
      v17 = Size;
      v18 = (_BYTE *)v16;
      v19 = (_BYTE *)sub_7FF65D451E5C(Size);
      v20 = 1;
      *v19 = v18[2];
      v21 = v19 + 1;
      v19[1] = *v18;
      v19[2] = v18[3];
      v19[3] = v18[1];
      v19[4] = v18[6];
      v19[5] = v18[4];
      v19[6] = v18[7];
      v19[7] = v18[5];
      v19[8] = v18[10];
      v19[9] = v18[8];
      v19[10] = v18[11];
      v19[11] = v18[9];
      v19[12] = v18[14];
      v19[13] = v18[12];
      v19[14] = v18[15];
      v19[15] = v18[13];
      v19[16] = v18[18];
      v19[17] = v18[16];
      v19[18] = v18[19];
      v19[19] = v18[17];
      v19[20] = v18[22];
      v19[21] = v18[20];
      v19[22] = v18[23];
      for ( v19[23] = v18[21]; v20 < v17; ++v21 )  //打乱了下加密字符串的顺序
      {
        v22 = 0i64;
        if ( v20 / 3 > 0 )
        {
          v23 = *v21;
          do
          {
            v23 ^= v19[v22++];
            *v21 = v23;
          }
          while ( v22 < v20 / 3 );
        }
        ++v20;
      }
      *(_QWORD *)&v29 = -4569681940847739698i64;
      v24 = v19 - (_BYTE *)&v29;
      *((_QWORD *)&v29 + 1) = 3819887636644928495i64;
      v25 = 0i64;
      v30 = -939386845;
      v31 = -95004953;
      do
      {
        if ( *((_BYTE *)&v29 + v25) != *((_BYTE *)&v29 + v25 + v24) )   //比较是否正确
          _exit(v7 * v7);
        ++v7;
        ++v25;
      }
      while ( v25 < 24 );
      v26 = sub_7FF65D451620(std::cout, "You win!");
      std::basic_ostream<char,std::char_traits<char>>::operator<<(v26, sub_7FF65D4517F0);
      return 0i64;
    }
    

    思路;

    先找到最终正确的加密字符串
    逆向那个异或的算法
    再移位回来
    再xxtea的解密,
    得出flag
    

    在这里插入图片描述
    然后写脚本逆向回去就好了。

    import struct
    _DELTA = 0x9E3779B9
    def _long2str(v, w):
        n = (len(v) - 1) << 2
        if w:
            m = v[-1]
            if (m < n - 3) or (m > n): return ''
            n = m
        s = struct.pack('<%iL' % len(v), *v)
        return s[0:n] if w else s
    
    
    def _str2long(s, w):
        n = len(s)
        m = (4 - (n & 3) & 3) + n
        s = s.ljust(m, "")
        v = list(struct.unpack('<%iL' % (m >> 2), s))
        if w: v.append(n)
        return v
    
    
    def encrypt(str, key):
        if str == '': return str
        v = _str2long(str, True)
        k = _str2long(key.ljust(16, ""), False)
        n = len(v) - 1
        z = v[n]
        y = v[0]
        sum = 0
        q = 6 + 52 // (n + 1)
        while q > 0:
            sum = (sum + _DELTA) & 0xffffffff
            e = sum >> 2 & 3
            for p in range(n):
                y = v[p + 1]
                v[p] = (v[p] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
                z = v[p]
            y = v[0]
            v[n] = (v[n] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[n & 3 ^ e] ^ z))) & 0xffffffff
            z = v[n]
            q -= 1
        return _long2str(v, False)
    
    
    def decrypt(str, key):
        if str == '': return str
        v = _str2long(str, False)
        k = _str2long(key.ljust(16, ""), False)
        n = len(v) - 1
        z = v[n]
        y = v[0]
        q = 6 + 52 // (n + 1)
        sum = (q * _DELTA) & 0xffffffff
        while (sum != 0):
            e = sum >> 2 & 3
            for p in range(n, 0, -1):
                z = v[p - 1]
                v[p] = (v[p] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
                y = v[p]
            z = v[n]
            v[0] = (v[0] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[0 & 3 ^ e] ^ z))) & 0xffffffff
            y = v[0]
            sum = (sum - _DELTA) & 0xffffffff
        return _long2str(v, True)
    
    res=[0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B, 0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8, 0xE7, 0x56, 0x56,0xFA]
    dec=""
    for i in range(7,-1,-1):
        a=""
        for j in range(3):
            tmp=res[i*3+j]
            for w in range(i):
                tmp^=res[w]
            a+=chr(tmp)
        dec=a+dec
    print(dec)
    key="flag"+"x00"*12
    num=[2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]
    n=[0 for i in range(24)]
    for i in range(24):
        n[num[i]]=dec[i]
    dec2="".join(n)
    dec3=decrypt(dec2,key)
    print(dec3)
    
    
    
  • 相关阅读:
    C#泛型集合之——链表
    C#泛型集合之——列表
    C#泛型集合之——哈希集合
    gRPC asp.net core自定义策略认证
    asp.net core mvc中自定义ActionResult
    当职责链遇到DI
    开发一个带UI的库(asp.net core 3.0)
    两个集合对比
    对日编程的一些小知识点
    基于aws api gateway的asp.net core验证
  • 原文地址:https://www.cnblogs.com/YenKoc/p/12779897.html
Copyright © 2011-2022 走看看