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
PPTT
进入main函数动调观察数据
在执行完以上代码后返回的是中序遍历后的数据 由于是进行二叉树遍历,所以需要不重复的元素进行调试才能体现
以下是实现二叉树的遍历:
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)))
执行完遍历下方有数据交换的流程
我们可以下断点查看运行完之后的数据为: qopmukwlfcrveisaxbtdjgnh
然后是将数据合成为64位int
解析如下
unsigned int v23[6]; // 至少包含6个元素
unsigned int v29[24]; // 至少包含24个元素
unsigned long long v6;
unsigned long long v7;
int i, j;
LODWORD
和 HIDWORD
宏分别获取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);
}
}
最后对以下条件进行约束求解
还原得到
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}
Bloker_vm
一共三个操作:异或 移位 rc4
直接将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