RCTF Rev复现

Push uself

Posted by Aaron on July 30, 2024

2048

用脚本一直梭哈跑到100w分得到flag

from pwn import *

#io = process('./2048')
io=remote('1.94.104.104',10088)
io.recvuntil(b'score: ')
score = (io.recvuntil(b'\n'))[:-1]
print(score)
print("##########")
for i in range(10000000000):
    io.sendline(b'1')
    io.sendline(score)
    io.sendline(
        b'ssassassassdssdssdssassassassdssdssdssassassassdssdssdssassass......')
    io.recvuntil(b'win')
    io.recvline()
    io.recvuntil(b'score: ')
    score = (io.recvuntil(b'\n'))[:-1]
    print(score)
    s = int(score.decode())
    if (s > 1000000):
        io.sendline(b'3')
        a=io.recv(numb=4096000000)
        b=io.recvall()
        print(b)
        break

image-20240730172436817

PPTT

进入main函数动调观察数据

image-20240730195022953

在执行完以上代码后返回的是中序遍历后的数据 由于是进行二叉树遍历,所以需要不重复的元素进行调试才能体现

以下是实现二叉树的遍历:

class TreeNode:
    def __init__(self, value=0, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right


def build_tree(data):
    nodes = [TreeNode(char) for char in data]
    for i in range(len(nodes) // 2):
        if 2 * i + 1 < len(nodes):
            nodes[i].left = nodes[2 * i + 1]
        if 2 * i + 2 < len(nodes):
            nodes[i].right = nodes[2 * i + 2]
    return nodes[0] if nodes else None


def preorder_traversal(root):
    result = []

    def traverse(node):
        if not node:
            return
        result.append(node.value)
        traverse(node.left)
        traverse(node.right)

    traverse(root)
    return result


def inorder_traversal(root):
    result = []

    def traverse(node):
        if not node:
            return
        traverse(node.left)
        result.append(node.value)
        traverse(node.right)

    traverse(root)
    return result


# 示例用法
if __name__ == "__main__":
    data = "abcdefghijklmnopqrstuvwx"
    root = build_tree(data)

    print("先序遍历结果:", "".join(preorder_traversal(root)))
    print("中序遍历结果:", "".join(inorder_traversal(root)))

执行完遍历下方有数据交换的流程

image-20240730200308132

我们可以下断点查看运行完之后的数据为: qopmukwlfcrveisaxbtdjgnh

image-20240730200356672

然后是将数据合成为64位int

image-20240730201153178

解析如下

unsigned int v23[6]; // 至少包含6个元素
unsigned int v29[24]; // 至少包含24个元素
unsigned long long v6;
unsigned long long v7;
int i, j;

LODWORDHIDWORD宏分别获取64位整数的低32位和高32位

__PAIR64__ 宏用于构建64位整数

for (i = 0; i < 3; ++i) {
    for (j = 0; j < 8; ++j) {
        // 取v23数组的两个元素,并合并为64位整数
        LODWORD(v6) = *(&v23 + 2 * i);
        HIDWORD(v6) = *(&v23 + 2 * i + 1);
        
        // 左移8位
        v6 <<= 8;
        
        // 将结果分解回v23数组的两个元素中
        *(&v23 + 2 * i) = v6;
        *(&v23 + 2 * i + 1) = HIDWORD(v6);
        
        // 将当前64位整数与v29中的一个值相加
        v7 = __PAIR64__(*(&v23 + 2 * i + 1), *(&v23 + 2 * i)) + v29[8 * i + 7 - j];
        
        // 将结果分解回v23数组的两个元素中
        *(&v23 + 2 * i) = v7;
        *(&v23 + 2 * i + 1) = HIDWORD(v7);
    }
}

最后对以下条件进行约束求解

image-20240730205001225

还原得到

from Crypto.Util.number import long_to_bytes as l2b
import claripy

inp = [claripy.BVS(f"inp_{i}", 64) for i in range(3)]

v23 = inp[0]
v24 = inp[1]
v25 = inp[2]
v20 = (v24 & v23)
v19 = ((v24 & v23 | v25 & v23) + 65670)
v18 = ((v25 & v23 ^ v25 & v24) - 1131796)
v17 = (v24 & v23 ^ v25 & v23)

s = claripy.Solver()
s.add((v23 ^ (v20 & ~v18 | v20 & ~v19 | v17 & v19 | v25 & v23 & ~v18))== 0x400010000622000)
s.add((v18 ^ (v19 - v20)) == 0x2100A0203EFBB8B)
s.add((v17 ^ v19 ^ v20) == 0x4083102108E)
s.add((v19 ^ v17) - v18 == 0x1551566F3C6485ED)
s.add((v18 ^ v19 ^ v25 & v24) == 0x40836ECAB9A)
s.add((v17 ^ v20) - v18 == 0x3E51566F3C718563)
s.add((v23 - v24) == 0x1AEFF6FDFC121BF1)
s.add((v25 + v24 + v23) % 10 == 8)

for i in range(len(inp)):
    for j in range(8):
        s.add((inp[i] >> (j*8)) & 0xff <= 125)
        s.add((inp[i] >> (j*8)) & 0xff >= 65)

print(s.check_satisfiability())


def rev(s):
    inp = "abcdefghijklmnopqrstuvwx"
    inp_tree2_pos = "qopmukwlfcrveisaxbtdjgnh"
    flag = [0]*len(s)
    for i in range(len(s)):
        flag[inp.index(inp_tree2_pos[i])] = ord(s[i])
    return bytes(flag)


for i in s.batch_eval(inp, 2000):
    s = ""
    for ii in i:
        s += (l2b(ii)[::-1].decode())
    res = rev(s).decode()
    if res.startswith("RCTF{") and res.endswith("}"):
        print(res)
  • –> RCTF{sjknwemqspsdaqtyua}

image-20240730205137839

Bloker_vm

一共三个操作:异或 移位 rc4

image-20240731110751985

直接将rc4的代码复制出来逐步还原

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<string>
#include<cstring>
#include<list>
#include<stdlib.h>
using namespace std;
typedef int status;
typedef int selemtype;

/*
_______
___    |_____ ____________________
__  /| |  __ `/_  ___/  __ \_  __ \
_  ___ / /_/ /_  /   / /_/ /  / / /
/_/  |_\__,_/ /_/    \____//_/ /_/

*/

int rc4(unsigned char* a1, int a2, char* a3, int a4)
{
  int result; // eax
  char v5; // [esp+D3h] [ebp-155h]
  char v6; // [esp+D3h] [ebp-155h]
  int v7; // [esp+F4h] [ebp-134h]
  int i; // [esp+100h] [ebp-128h]
  int j; // [esp+100h] [ebp-128h]
  int k; // [esp+100h] [ebp-128h]
  unsigned __int8 v11; // [esp+10Fh] [ebp-119h]
  unsigned __int8 v12; // [esp+11Bh] [ebp-10Dh]
  char v13[260]; // [esp+124h] [ebp-104h]

  for ( i = 0; i < 256; ++i )
    v13[i] = i;
  v7 = 0;
  for ( j = 0; j < 256; ++j )
  {
    v7 = (*(unsigned __int8 *)(a3 + j % a4) + v7 + (unsigned __int8)v13[j]) % 256;
    v5 = v13[j];
    v13[j] = v13[v7];
    v13[v7] = v5;
  }
  v12 = 0;
  v11 = 0;
  for ( k = 0; ; k = (k + 1) )
  {
    result = k;
    if ( (int)k >= a2 )
      break;
    v11 += v13[++v12];
    v6 = v13[v12];
    v13[v12] = v13[v11];
    v13[v11] = v6;
    *(k + a1) ^= v13[((unsigned __int8)v13[v11] + (unsigned __int8)v13[v12]) % 256];
  }
  return result;
}

int main()
{
    unsigned char enc[] =
    {
        0x80, 0x05, 0xE3, 0x2F, 0x18, 0x2F, 0xC5, 0x8C, 0x25, 0x70,
        0xBC, 0x05, 0x1C, 0x4F, 0xF2, 0x02, 0xE5, 0x3E, 0x02, 0x2F,
        0xE5, 0x11, 0xA3, 0xC0
    };
    char key[] = "thisisyoursecretkey";


    rc4(enc, 24, key, 18);

    for(int i = 0; i < 24; i++)
    {
        enc[i] = (enc[i] << 2)  | (enc[i] >> 6) & 0xff;
        enc[i] ^= 0x7D;
        printf("%c", enc[i]);
    }

    return 0;
}
//RCTF{a_baby_debug_bloker