CTF-RE: STL逆向 [NewStarCTF 2023 公开赛道 STL] WP

多看看STL题就会了,很简单

c 复制代码
int __fastcall main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbx
  __int64 v4; // rax
  char v5; // bl
  _BYTE *v6; // rax
  _QWORD *v7; // rax
  __int64 v8; // rax
  __int64 v9; // rax
  int i; // [rsp+0h] [rbp-250h]
  int j; // [rsp+4h] [rbp-24Ch]
  char v13[32]; // [rsp+10h] [rbp-240h] BYREF
  char v14[32]; // [rsp+30h] [rbp-220h] BYREF
  __int64 v15[64]; // [rsp+50h] [rbp-200h] BYREF

  v15[61] = __readfsqword(0x28u);
  std::string::basic_string(v13, argv, envp);
  memset(v15, 0, 480);
  v15[0] = 0x2882D802120ELL;
  v15[1] = 0x28529A05954LL;
  v15[2] = 0x486088C03LL;
  v15[3] = 0xC0FB3B55754LL;
  v15[4] = 0xC2B9B7F8651LL;
  v15[5] = 0xAE83FB054CLL;
  v15[6] = 0x29ABF6DDCB15LL;
  v15[7] = 0x10E261FC807LL;
  v15[8] = 0x2A82FE86D707LL;
  v15[9] = 0xE0CB79A5706LL;
  v15[10] = 0x330560890D06LL;
  std::operator<<<std::char_traits<char>>(&std::cout, "Input Your flag:");
  std::operator>><char>(&std::cin, v13);
  if ( std::string::length(v13) != 44 )
    exit(0);
  v3 = std::string::end(v13);
  v4 = std::string::begin(v13);
  std::reverse<__gnu_cxx::__normal_iterator<char *,std::string>>(v4, v3);
  for ( i = 0; i < (unsigned __int64)(std::string::size(v13) - 1); ++i )
  {
    v5 = *(_BYTE *)std::string::operator[](v13, i + 1);
    v6 = (_BYTE *)std::string::operator[](v13, i);
    *v6 ^= v5;
  }
  for ( j = 0; j < (unsigned __int64)std::string::size(v13) >> 2; ++j )
  {
    std::string::substr(v14, v13, 4 * j, 4LL);
    v7 = (_QWORD *)std::string::operator[](v14, 0LL);
    if ( (((unsigned __int64)(unsigned int)*v7 << 15) ^ (unsigned int)*v7) != v15[j] )
    {
      v8 = std::operator<<<std::char_traits<char>>(&std::cout, "Wrong!!");
      std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
      exit(0);
    }
    std::string::~string(v14);
  }
  v9 = std::operator<<<std::char_traits<char>>(&std::cout, "Right!!");
  std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);
  std::string::~string(v13);
  return 0;
}

加注释

c 复制代码
int __fastcall main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbx
  __int64 v4; // rax
  char v5; // bl
  _BYTE *v6; // rax
  _QWORD *v7; // rax
  __int64 v8; // rax
  __int64 v9; // rax
  int i; // [rsp+0h] [rbp-250h]
  int j; // [rsp+4h] [rbp-24Ch]
  char input[32]; // [rsp+10h] [rbp-240h] BYREF
  char v14[32]; // [rsp+30h] [rbp-220h] BYREF
  __int64 v15[64]; // [rsp+50h] [rbp-200h] BYREF

  v15[61] = __readfsqword(0x28u);
  std::string::basic_string(input, argv, envp);
  memset(v15, 0, 480);
  v15[0] = 0x2882D802120ELL;
  v15[1] = 0x28529A05954LL;
  v15[2] = 0x486088C03LL;
  v15[3] = 0xC0FB3B55754LL;
  v15[4] = 0xC2B9B7F8651LL;
  v15[5] = 0xAE83FB054CLL;
  v15[6] = 0x29ABF6DDCB15LL;
  v15[7] = 0x10E261FC807LL;
  v15[8] = 0x2A82FE86D707LL;
  v15[9] = 0xE0CB79A5706LL;
  v15[10] = 0x330560890D06LL;
  std::operator<<<std::char_traits<char>>(&std::cout, "Input Your flag:");// 输出
  std::operator>><char>(&std::cin, input);      // 输入
  if ( std::string::length(input) != 44 )       // 检查输入长度是否为44
    exit(0);
  v3 = std::string::end(input);                 // 返回字符串最后一个之后的
  v4 = std::string::begin(input);               // 返回第一个
  std::reverse<__gnu_cxx::__normal_iterator<char *,std::string>>(v4, v3);// std::reverse反转字符串
  for ( i = 0; i < (unsigned __int64)(std::string::size(input) - 1); ++i )
  {
    v5 = *(_BYTE *)std::string::operator[](input, i + 1);// v5 = input[i+1]
    v6 = (_BYTE *)std::string::operator[](input, i);// v6 = input[i]
    *v6 ^= v5;                                  // input[i] = input[i] ^ input[i+1]
  }
  for ( j = 0; j < (unsigned __int64)std::string::size(input) >> 2; ++j )// for(j=0;j < len(input)/4 ; j++)
  {
    std::string::substr(v14, input, 4 * j, 4LL);// 四个一组提取到v14
    v7 = (_QWORD *)std::string::operator[](v14, 0LL);// v7 = v14[0]
    if ( (((unsigned __int64)(unsigned int)*v7 << 15) ^ (unsigned int)*v7) != v15[j] )// int32强制转64,解密时候要转回来
                                                // (x << 15) ^ x = y
                                                // v15
                                                // unsigned long data[11] = {
                                                //     0x00002882D802120E, 0x0000028529A05954, 0x0000000486088C03, 0x00000C0FB3B55754, 
                                                //     0x00000C2B9B7F8651, 0x000000AE83FB054C, 0x000029ABF6DDCB15, 0x0000010E261FC807, 
                                                //     0x00002A82FE86D707, 0x00000E0CB79A5706, 0x0000330560890D06
                                                // };
    {
      v8 = std::operator<<<std::char_traits<char>>(&std::cout, "Wrong!!");
      std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
      exit(0);
    }
    std::string::~string(v14);
  }
  v9 = std::operator<<<std::char_traits<char>>(&std::cout, "Right!!");
  std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);
  std::string::~string(input);
  return 0;
}

getflag

c 复制代码
#include <cstdio>

/*
 * 根据给定的 y 和 n 计算出 x
 * (x << n) ^ x = y
 */
template<typename T>
T left_Solve_x_correct(T y, unsigned int n) {
    T x = 0; // 初始化 x 为 0
    unsigned int total_bits = sizeof(T) * 8; // 数据类型的总位数

    for (unsigned int i = 0; i < total_bits; ++i) {
        T y_i = (y >> i) & 1; // 提取 y 的第 i 位
        T x_i;
        if (i < n) {
            x_i = y_i; // 当 i < n 时,x_i = y_i
        } else {
            T x_prev = (x >> (i - n)) & 1; // 获取 x 中第 (i - n) 位
            x_i = y_i ^ x_prev; // x_i = y_i ^ x_{i - n}
        }
        x |= (x_i << i); // 将计算得到的 x_i 放回 x 中
    }

    return x;
}

int main() {
    unsigned long long data[11] = {
            0x00002882D802120E, 0x0000028529A05954, 0x0000000486088C03, 0x00000C0FB3B55754,
            0x00000C2B9B7F8651, 0x000000AE83FB054C, 0x000029ABF6DDCB15, 0x0000010E261FC807,
            0x00002A82FE86D707, 0x00000E0CB79A5706, 0x0000330560890D06
    };

    // 先求解第一层
    int i;
    for(i=0;i<11;i++)
        data[i] = left_Solve_x_correct(data[i], 15);
    for(i=0;i<11;i++)
        printf("0x%x,", data[i]);// 要从64转32,直接打印出来用python接着写了就不用转换了,比较方便
    printf("\n");
}

用python求解第二层

python 复制代码
import struct

# 输入的整数数组
a = [0x5105120e, 0x50a5954, 0x90c03, 0x181f5754, 0x18570651, 0x15d054c, 0x53574b15, 0x21c4807, 0x55055707, 0x1c195706, 0x660a0d06]

# 创建一个空字节数组
byte_array = bytearray()

# 将每个整数转换为字节并按小端序添加到字节数组中
for number in a:
    byte_array.extend(struct.pack('<I', number))  # '<I'表示小端序的4字节无符号整数

# 输出结果
print(list(byte_array))  # 以列表形式输出字节数组
# 数组从0开始到43!
for i in range((len(byte_array) - 1)):
    j = 42 - i
    byte_array[j] = byte_array[j] ^ byte_array[j + 1]

flag = ''
for i in byte_array:
    flag += chr(i)

print(flag[::-1]) # 反转
相关推荐
网安加社区4 小时前
国内外网络安全政策动态(2024年12月)
网络安全·政策动态
肾透侧视攻城狮4 小时前
基于华为ENSP的OSPF不规则区域划分深入浅出(5)
网络·网络协议·网络安全·华为·信息与通信·ospf·多进程双向重发布
肾透侧视攻城狮5 小时前
基于华为ENSP的OSPF状态机、工作过程、配置保姆级别详解(2)
网络·网络协议·安全·网络安全·华为·信息与通信·ospf
城主科技8 小时前
从零部署【国际互联网、ISP骨干网、互联网数据中心、企业数据中心、企业私网】组成的大型综合型网络环境部署。
网络·网络安全·华为·智能路由器
Andya_net12 小时前
网络安全 | WAF防护开通流程与技术原理详解
安全·web安全·网络安全
打工人你好13 小时前
d2j-dex2jar classes.dex 执行报错:not support version 问题解决
逆向
Eastmount13 小时前
[论文阅读] (35)TIFS24 MEGR-APT:基于攻击表示学习的高效内存APT猎杀系统
论文阅读·网络安全·apt攻击·威胁检测·溯源图
网络安全成叔1 天前
【入门级】计算机网络学习
学习·计算机网络·web安全·计算机·网络安全·编程
Orig1nal1 天前
VSCode配置php开发环境
网络安全