re学习(25)i春秋-re-basebasebase(base64+函数构造)

参考文章:re学习笔记(22)爱春秋CTF答题夺旗赛(第四季)-re-basebasebase_ctfbase~base_Forgo7ten的博客-CSDN博

总结:1.flag——→base64加密(自定义)——→与3异或——→加密后数据(对比,相等成功)

re学习(25)i春秋-re-basebasebase(base64+函数构造)_第1张图片

          2.关键代码?构造函数(P键)?

re学习(25)i春秋-re-basebasebase(base64+函数构造)_第2张图片

3.为什么要进行栈指针的调整?那个快捷键进行栈指针调整?如何打开栈指针?

re学习(25)i春秋-re-basebasebase(base64+函数构造)_第3张图片

Alt+K键(调整栈指针)

4.base64解密

       自定义base64编码表   

       转义字符串

       加密解密字符串的长度关系

题解:
构造函数后发现的函数:
 

int __usercall sub_40103B@(int a1@)
{
  *(_DWORD *)(a1 - 132) = 0;
  *(_BYTE *)(a1 - 40) = 89;
  *(_BYTE *)(a1 - 39) = 110;
  *(_BYTE *)(a1 - 38) = 123;
  *(_BYTE *)(a1 - 37) = 107;
  *(_BYTE *)(a1 - 36) = 89;
  *(_BYTE *)(a1 - 35) = 32;
  *(_BYTE *)(a1 - 34) = 119;
  *(_BYTE *)(a1 - 33) = 106;
  *(_BYTE *)(a1 - 32) = 90;
  *(_BYTE *)(a1 - 31) = 91;
  *(_BYTE *)(a1 - 30) = 77;
  *(_BYTE *)(a1 - 29) = 111;
  *(_BYTE *)(a1 - 28) = 91;
  *(_BYTE *)(a1 - 27) = 67;
  *(_BYTE *)(a1 - 26) = 90;
  *(_BYTE *)(a1 - 25) = 42;
  *(_BYTE *)(a1 - 24) = 90;
  *(_BYTE *)(a1 - 23) = 67;
  *(_BYTE *)(a1 - 22) = 119;
  *(_BYTE *)(a1 - 21) = 101;
  *(_BYTE *)(a1 - 20) = 86;
  *(_BYTE *)(a1 - 19) = 110;
  *(_BYTE *)(a1 - 18) = 85;
  *(_BYTE *)(a1 - 17) = 67;
  *(_BYTE *)(a1 - 16) = 89;
  *(_BYTE *)(a1 - 15) = 91;
  *(_BYTE *)(a1 - 14) = 73;
  *(_BYTE *)(a1 - 13) = 121;
  *(_BYTE *)(a1 - 12) = 89;
  *(_BYTE *)(a1 - 11) = 91;
  *(_BYTE *)(a1 - 10) = 42;
  *(_BYTE *)(a1 - 9) = 41;
  *(_BYTE *)(a1 - 8) = 3;
  printf("Give Me Flag:");
  *(_BYTE *)(a1 - 76) = 0;
  *(_DWORD *)(a1 - 75) = 0;
  *(_DWORD *)(a1 - 71) = 0;
  *(_DWORD *)(a1 - 67) = 0;
  *(_DWORD *)(a1 - 63) = 0;
  *(_DWORD *)(a1 - 59) = 0;
  *(_DWORD *)(a1 - 55) = 0;
  *(_DWORD *)(a1 - 51) = 0;
  *(_DWORD *)(a1 - 47) = 0;
  scanf("%s", a1 - 76);                         // a1-76为用户的输入
  *(_DWORD *)(a1 - 128) = a1 - 76;              // a1-128  是一个指针,指向用户输入
  *(_DWORD *)(a1 - 144) = *(_DWORD *)(a1 - 128) + 1;// a1-144存储用户输入第二个字符
  do
    *(_BYTE *)(a1 - 113) = *(_BYTE *)(*(_DWORD *)(a1 - 128))++;
  while ( *(_BYTE *)(a1 - 113) );
  *(_DWORD *)(a1 - 140) = *(_DWORD *)(a1 - 128) - *(_DWORD *)(a1 - 144);
  *(_DWORD *)(a1 - 148) = base64((char *)(a1 - 76), *(_DWORD *)(a1 - 140), (int *)(a1 - 136));// a1-140  为编码之前的长度
                                                // a1-136  为base64编码后的长度
  for ( *(_DWORD *)(a1 - 124) = 0; *(int *)(a1 - 124) < 33; ++*(_DWORD *)(a1 - 124) )// a1-124 为计数器   <33   33位
    *(_BYTE *)(a1 + *(_DWORD *)(a1 - 124) - 112) = *(_BYTE *)(*(_DWORD *)(a1 - 124) + *(_DWORD *)(a1 - 148)) ^ 3;// base64编码后与3异或
                                                //  赋给a1-112
  for ( *(_DWORD *)(a1 - 120) = 0; *(_DWORD *)(a1 - 120) < *(_DWORD *)(a1 - 136); ++*(_DWORD *)(a1 - 120) )
  {                                             // a1-120为计数器,循环次数为base64编码后的长度
    if ( *(char *)(a1 + *(_DWORD *)(a1 - 120) - 112) != *(char *)(a1 + *(_DWORD *)(a1 - 120) - 40) )// a1-40上面有数据
    {                                           // base64编码后,再与3异或,然后与a1-40比较
      printf(&byte_40302C);
      exit(0);
    }
    ++*(_DWORD *)(a1 - 132);                    // 如果不相等,a1-132就不加,不加的话,下面判断就会失败
  }
  if ( *(_DWORD *)(a1 - 132) == *(_DWORD *)(a1 - 136) )
    printf("Successful!\n");
  return 0;
}

全程指针操作

上解密脚本:
 

import base64
text = [89,110,123,107,89,32,119,106,90,91,77,111,91,67,90,42,90,67,119,101,86,110,85,67,89,91,73,121,89,91,42,41,3]
for i in range(len(text)):
    text[i] ^= 3
    text[i] = chr(text[i])
text = ''.join(text)
text += "==="
print(base64.b64decode(text.translate(str.maketrans("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz)!@#$%^&*(+/","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")).encode('utf-8')))
#b'flag{base_f4ck_Reverse}<' 在Python中,前缀"b"表示一个字节字符串(bytes)
#当您使用base64.b64decode()函数解码Base64编码的数据时,返回的结果是字节字符串。
# 字节字符串是由原始字节组成的,每个字节对应一个ASCII字符或二进制数据。

你可能感兴趣的:(#,每天一个CTF,网络安全)