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\n");
    _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, "\0")
    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, "\0"), 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, "\0"), 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)


posted @ 2020-04-04 19:47  YenKoc  阅读(245)  评论(0编辑  收藏  举报