C++ STL的逆向,理解该程序需要了解C++基础STL

静态分析

  for ( i = 0; i <= 15; ++i )
  {
    scanf("%d", &v25[i], v15);
    std::vector<int,std::allocator<int>>::push_back(&in_vec, &v25[i]);
  }
  for ( j = 0; j <= 15; ++j )
  {
    LODWORD(v24) = fib(j);
    std::vector<int,std::allocator<int>>::push_back(&fib_vec, &v24);
  }
  std::vector<int,std::allocator<int>>::push_back(&v20, v25);
  v4 = std::back_inserter<std::vector<int,std::allocator<int>>>(&v20);
  v2 = std::vector<int,std::allocator<int>>::end(&in_vec);
  v24 = std::vector<int,std::allocator<int>>::begin(&in_vec);
  v1 = __gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator+(&v24, 1LL);
  std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::back_insert_iterator<std::vector<int,std::allocator<int>>>,main::{lambda(int)#1}>(
    v1,
    v2,
    v4,
    (__int64)v25);

1、首先获取输入,为16个数字,保存至一个vector中。
2、生成斐波那契数列,同样保存至一个vector中。
接下来分析transform函数内部:

  v10 = a1;
  v9 = a2;
  v8 = a3;
  v7 = a4;
  v12 = __readfsqword(0x28u);
  while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int,std::allocator<int>>>(&v10, &v9) )
  {
    v4 = (int *)__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator*(&v10);
    v11 = main::{lambda(int)#1}::operator() const((_DWORD **)&v7, *v4);
    v5 = std::back_insert_iterator<std::vector<int,std::allocator<int>>>::operator*(&v8);
    std::back_insert_iterator<std::vector<int,std::allocator<int>>>::operator=(v5, &v11);
    __gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator++(&v10);
    std::back_insert_iterator<std::vector<int,std::allocator<int>>>::operator++(&v8);
  }
  return v8;

v10为迭代器begin + 1v9为迭代器endv7为输入的第一个值,匿名函数为简单的加法:

__int64 __fastcall main::{lambda(int)#1}::operator() const(_DWORD **a1, int a2)
{
  return (unsigned int)(**a1 + a2);
}

于是可以看出来transform的功能就是把输入的第一个值依次加到之后值上。
接下来是accumulate的分析:

  std::vector<int,std::allocator<int>>::vector((__int64)&v23);
  v7 = std::vector<int,std::allocator<int>>::end(&v20);
  v8 = std::vector<int,std::allocator<int>>::begin(&v20);
  std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::vector<int,std::allocator<int>>,main::{lambda(std::vector<int,std::allocator<int>>,int)#2}>(
    (__int64)&v24,
    v8,
    v7,
    (__int64)&v23,
    v9,
    v10,
    v3);

根据以下代码,v11beginv10endv7为每个元素的值。

  v12 = a1;
  v11 = a2;
  v10 = a3;
  v9 = a4;
  v15 = __readfsqword(0x28u);
  while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int,std::allocator<int>>>(&v11, &v10) )
  {
    v7 = *(_DWORD *)__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator*(&v11);
    std::vector<int,std::allocator<int>>::vector(&v13, v9);
    main::{lambda(std::vector<int,std::allocator<int>>,int)#2}::operator() const(
      (__int64)&v14,
      (__int64)&a7,
      (__int64)&v13,
      v7);
    std::vector<int,std::allocator<int>>::operator=(v9, &v14);
    std::vector<int,std::allocator<int>>::~vector(&v14);
    std::vector<int,std::allocator<int>>::~vector(&v13);
    __gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator++(&v11);
  }
  std::vector<int,std::allocator<int>>::vector(v12, v9);
  return v12;
}

接下来看匿名函数:

  v11 = a1;
  v10 = a2;
  v9 = a3;
  v8 = a4;
  v12 = __readfsqword(0x28u);
  std::vector<int,std::allocator<int>>::vector(a1);
  std::vector<int,std::allocator<int>>::push_back(a1, &v8);
  v4 = std::back_inserter<std::vector<int,std::allocator<int>>>(v11);
  v5 = std::vector<int,std::allocator<int>>::end(v9);
  v6 = std::vector<int,std::allocator<int>>::begin(v9);
  std::copy<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::back_insert_iterator<std::vector<int,std::allocator<int>>>>(
    v6,
    v5,
    v4);
  return v11;

看到匿名函数把参数v7放入acumulatev4队尾。
于是在acumulate中一个遍历下来便是逆序操作。

动态调试验证

exp.py

#! /usr/bin/python
from pwn import *
io = process("./easyCpp")

def fib(n):
    result = [1,1]
    if n <= 1:
        return result
    for i in range(2,n+1):
        result.append(result[i-1]+result[i-2])
    return result

fib_list = fib(15)[::-1]
key = [fib_list[0]]
for i in range(1, 16):
    key.append(fib_list[i]-fib_list[0])
for i in range(16):
    io.sendline(str(key[i]))
print io.recv()
# You win!
# Your flag is:flag{987-377-843-953-979-985}