week1--RE--刷题记录
week1 刷题
1. [GXYCTF2019]simple CPP
IDA载入直接分析,这个程序的主要加密逻辑有几块:

第一块是一个异或,和key进行异或

第二部分是将8个字符拼成一个QWORD,然后存放到v20当中

最后就是将v20的值拿出来计算然后进行比较判断。在最后这个加密当中,运用了一大堆的运算,那么z3是最好的方式,直接z3求解即可。
这里有一个注意的地方是,我们并不知道输入有多长,只知道最后比较的长度是32字节,所以这里的z3需要从分组之后开始求解。求解出来后再回推input。这里试了一下从开头写z3到结尾会导致解出来的值不太一样。
- exp:
from z3 import*
f1, f2, f3, f4 = BitVecs('f1 f2 f3 f4', 64)
s = Solver()
s.add(f3 & (~f1) == 0x11204161012)
s.add((f3 & (~f2)) & f1 | f3 & ((f2 & f1) | f2 & (~f1) | (~(f2 | f1))) == 0x8020717153E3013)
s.add((f3 & ~f1) | (f2 & f1) | (f3 & (~f2)) | (f1 & ~f2) == 0x3E3A4717373E7F1F)
s.add((((f3 & (~f1)) | (f2 & f1) | (f3 & (~f2)) | (f1 & ~f2)) ^ f4) == 0x3E3A4717050F791F)
s.add((((f3 & (~f1)) | (f2 & f1) | f2 & f3)) == (~f1 & f3 | 0xC00020130082C0C))
print(s.check())
d2 = []
d = s.model()
flag1 = hex(d[f1].as_long())[2:].rjust(16, "0")
flag2 = hex(d[f2].as_long())[2:].rjust(16, "0")
flag3 = hex(d[f3].as_long())[2:].rjust(16, "0")
flag4 = hex(d[f4].as_long())[2:-2]
def decode(flag, d):
le = len(flag)
for i in range(0, le, 2):
if flag[i:i+2] != "":
d.append(int(flag[i:i+2], 16))
decode(flag1, d2)
decode(flag2, d2)
decode(flag3, d2)
decode(flag4, d2)
key = 'i_will_check_is_debug_or_not'
fake_flag = ""
for i in range(len(d2)):
fake_flag += chr(ord(key[i]) ^ d2[i])
print(fake_flag)
# We1l_D0ndeajoa_Slgebra_am_i
right_flag = ''
right_flag += fake_flag[:8]
right_flag += 'e!P0or_a' # 多解,比赛的时候hint需要将这个替换上去
right_flag += fake_flag[16:]
print(right_flag)
# flag{We1l_D0ne!P0or_algebra_am_i}
2. [网鼎杯 2020 青龙组]singal
非常基础的一道vm题,直接ida分析:

使用idapython将code字节码抓出来:
start = 0x403040
print("[")
for i in range(455):
print(ida_bytes.get_byte(start+i), end=", ")
print("\n]")

然后直接将vm逻辑用python抄出来,z3配合直接求解出来:
from z3 import *
s = Solver()
x = [BitVec(f"x{i}",8) for i in range(15)]
opcode = [
10, 0, 0, 0, 4, 0, 0, 0, 16, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, 11, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 81, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 36, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 37, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 54, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 65, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 37, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 65, 0, 0, 0, 8, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 63, 0, 0, 0, 7, 0, 0, 0, 52, 0, 0, 0, 7, 0, 0, 0, 50, 0, 0, 0, 7, 0, 0, 0, 114, 0, 0, 0, 7, 0, 0, 0, 51, 0, 0, 0, 7, 0, 0, 0, 24, 0, 0, 0, 7, 0, 0, 0, 167, 255, 255, 255, 7, 0, 0, 0, 49, 0, 0, 0, 7, 0, 0, 0, 241, 255, 255, 255, 7, 0, 0, 0, 40, 0, 0, 0, 7, 0, 0, 0, 132, 255, 255, 255, 7, 0, 0, 0, 193, 255, 255, 255, 7, 0, 0, 0, 30, 0, 0, 0, 7, 0, 0, 0, 122, 0, 0, 0, 0
]
v9 = 0
Str = [0] * 1000
end = 114
v8 = 0
v7 = 0
v6 = 0
v5 = 0
v4 = 0
while v9 < end:
op = opcode[v9 * 4]
if op == 1:
Str[v6+100]=v4
v9 += 1
v6 += 1
v8 += 1
elif op == 2:
v4 = Str[v8] + opcode[(v9 + 1)*4]
v9 += 2
elif op == 3:
v4 = Str[v8] - opcode[(v9 + 1)*4]
v9 += 2
elif op == 4:
v4 = opcode[(v9 + 1)*4] ^ Str[v8]
v9 += 2
elif op == 5:
v4 = opcode[(v9 + 1)*4] * Str[v8]
v9 += 2
elif op == 6:
v9 += 1
elif op == 7:
print(Str[v7 + 100])
s.add(Str[v7 + 100] == opcode[(v9 + 1)*4])
v9 += 2
v7 += 1
elif op == 8:
Str[v5] = v4
v9 += 1
v5 += 1
elif op == 10:
print("Read input")
for i, v in enumerate(x):
Str[i] = v
v9 += 1
elif op == 11:
v4 = Str[v8] - 1
v9 += 1
elif op == 12:
v4 = Str[v8] + 1
v9 += 1
else:
print(f"unknown insn {op}")
print(s.check())
if s.check():
m = s.model()
for i in x:
val = m.eval(i, model_completion=True)
print(chr(val.as_long()), end="")
from z3 import *
s = Solver()
x = [BitVec(f"x{i}",8) for i in range(15)]
opcode = [
10, 0, 0, 0, 4, 0, 0, 0, 16, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, 11, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 81, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 36, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 37, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 54, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 65, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 37, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 65, 0, 0, 0, 8, 0, 0, 0, 12, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 34, 0, 0, 0, 7, 0, 0, 0, 63, 0, 0, 0, 7, 0, 0, 0, 52, 0, 0, 0, 7, 0, 0, 0, 50, 0, 0, 0, 7, 0, 0, 0, 114, 0, 0, 0, 7, 0, 0, 0, 51, 0, 0, 0, 7, 0, 0, 0, 24, 0, 0, 0, 7, 0, 0, 0, 167, 255, 255, 255, 7, 0, 0, 0, 49, 0, 0, 0, 7, 0, 0, 0, 241, 255, 255, 255, 7, 0, 0, 0, 40, 0, 0, 0, 7, 0, 0, 0, 132, 255, 255, 255, 7, 0, 0, 0, 193, 255, 255, 255, 7, 0, 0, 0, 30, 0, 0, 0, 7, 0, 0, 0, 122, 0, 0, 0, 0
]
v9 = 0
Str = [0] * 1000
end = 114
v8 = 0
v7 = 0
v6 = 0
v5 = 0
v4 = 0
while v9 < end:
op = opcode[v9 * 4]
if op == 1:
Str[v6+100]=v4
v9 += 1
v6 += 1
v8 += 1
elif op == 2:
v4 = Str[v8] + opcode[(v9 + 1)*4]
v9 += 2
elif op == 3:
v4 = Str[v8] - opcode[(v9 + 1)*4]
v9 += 2
elif op == 4:
v4 = opcode[(v9 + 1)*4] ^ Str[v8]
v9 += 2
elif op == 5:
v4 = opcode[(v9 + 1)*4] * Str[v8]
v9 += 2
elif op == 6:
v9 += 1
elif op == 7:
print(Str[v7 + 100])
s.add(Str[v7 + 100] == opcode[(v9 + 1)*4])
v9 += 2
v7 += 1
elif op == 8:
Str[v5] = v4
v9 += 1
v5 += 1
elif op == 10:
print("Read input")
for i, v in enumerate(x):
Str[i] = v
v9 += 1
elif op == 11:
v4 = Str[v8] - 1
v9 += 1
elif op == 12:
v4 = Str[v8] + 1
v9 += 1
else:
print(f"unknown insn {op}")
print(s.check())
if s.check():
m = s.model()
for i in x:
val = m.eval(i, model_completion=True)
print(chr(val.as_long()), end="")
# Read input
# (16 ^ x0) - 5
# 3*(32 ^ x1)
# x2 - 2 - 1
# 4 ^ x3 + 1
# 3*x4 - 33
# x5 - 1 - 1
# (9 ^ x6) - 32
# 36 ^ x7 + 81
# x8 + 1 - 1
# 2*x9 + 37
# 65 ^ x10 + 54
# 1*(x11 + 32)
# 3*x12 + 37
# (9 ^ x13) - 32
# x14 + 65 + 1
# sat
# 757515121f3d478 <-- flag
3. [buuctf]firmware
这个是个路由器的固件题,有点misc的味道。下载题目之后是一个.bin文件,丢虚拟机用binwalk看看是个什么玩意。看起来有不少东西

使用binwalk直接将文件拆开:
binwalk -e 51475f91-7b90-41dd-81a3-8b82df4f29d0.bin

整出来之后发现文件夹当中有一个.squashfs的文件,这个文件是一种只读的压缩文件系统。可以使用firmware-mod-kit工具来获取解压缩,这里可以直接去github中将源码下载下来,然后丢到虚拟机,在src文件夹make一下,就可以使用了:
unsquashfs_all.sh 120200.squashfs
然后就能够发现多了一个root-1的文件夹,最后在这个文件夹当中/tmp找到了一个backdoor的文件,复制出来丢die看看有没有壳,发现有一个upx,直接工具脱一下壳,然后丢ida里面,字符串查找就能够发现有一个邮箱的字符串了:

接着直接交叉引用到调用的位置,可以发现这个v3其实就是端口号,如果传入的字串有自己的端口就使用自己的端口,没有的话就使用36667端口

最后直接将echo.bytehost51.com:36667进行md5提交即可。
4. [2019红帽杯]xx
直接丢IDA看看反汇编,main函数看起来非常的乱。开头就是一个输入长度的判断,输入如果不等于19直接退出:

然后直接动调看看关键位置:

第一个关键位置就是这里,这里的v30其实是输入的前4字节,然后传入了这个sub_140001AB0函数当中,进去看了一下发现是一个xxtea加密,然后key就是输入的前四个字节了:

继续往下分析:

这里很明显就是一个乱序了,接着继续往下:

最后这里很明显能看出来是一个异或的加密,而且加密过程是这样的,如果索引值 / 3大于0的话就和从0开始的字符进行逐个异或加密,这里解密的时候需要倒过来。
最后这一块就是比较了:

这里的几块变量的内存都是连续的所以这个就是密文。那么大致的逻辑就是:输入 --> xxtea --> 乱序 ---> 异或 --> 比较可以直接写exp了:
#pragma once
#include <iostream>
#include <stdio.h>
#include <vector>
void decrypt_xor(unsigned char* enc)
{
for (int i = 23; i > 0; i--)
{
int j = 0;
if (i / 3 > 0)
{
do {
enc[i] ^= enc[j++];
} while (j < i / 3);
}
}
}
void sort(unsigned char* enc)
{
std::vector<unsigned char> v;
for (int i = 0; i < 24; i++)
{
v.push_back(enc[i]);
}
char index[] = { 2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21 };
for (int i = 0; i < 24; i++)
{
enc[index[i]] = v[i];
}
}
uint8_t* tea_decrypt(const uint8_t* cipher, uint64_t cipherlen, const uint8_t* key) {
if (!cipherlen || cipherlen < 4) return NULL;
// 去掉可能的结尾 0
uint64_t usable = cipherlen;
if (cipher[cipherlen - 1] == 0 && (cipherlen % 4) == 1) {
usable = cipherlen - 1;
}
if (usable % 4 != 0) return NULL;
size_t n = (size_t)(usable / 4);
// 组装 v
uint32_t* v = (uint32_t*)calloc(n, sizeof(uint32_t));
if (!v) return NULL;
for (uint64_t i = 0; i < usable; i++) {
size_t idx = (size_t)(i >> 2);
size_t shift = (size_t)((i & 3) * 8);
v[idx] |= ((uint32_t)cipher[i]) << shift;
}
// 组装 key
uint32_t k[4];
for (int j = 0; j < 4; j++) {
int base = j * 4;
k[j] = (uint32_t)key[base]
| ((uint32_t)key[base + 1] << 8)
| ((uint32_t)key[base + 2] << 16)
| ((uint32_t)key[base + 3] << 24);
}
// XXTEA 解密核心
if (n > 1) {
uint32_t delta = 0x9E3779B9;
size_t rounds = 6 + 52 / n;
uint32_t sum = (uint32_t)(rounds * delta);
uint32_t z, y;
while (sum) {
uint32_t e = (sum >> 2) & 3;
y = v[0];
for (size_t p = n - 1; p > 0; p--) {
z = v[p - 1];
v[p] -= (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)))
^ ((sum ^ y) + (k[(p & 3) ^ e] ^ z));
y = v[p];
}
z = v[n - 1];
v[0] -= (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)))
^ ((sum ^ y) + (k[(0 & 3) ^ e] ^ z));
sum -= delta;
}
}
// 恢复原始长度
uint32_t orig_len = v[n - 1];
uint64_t max_plain = (uint64_t)((n - 1) * 4);
if ((uint64_t)orig_len > max_plain) {
free(v);
return NULL;
}
// 导出明文
uint8_t* out = (uint8_t*)malloc((uint64_t)orig_len);
if (!out) {
free(v);
return NULL;
}
for (uint64_t i = 0; i < (uint64_t)orig_len; i++) {
out[i] = (uint8_t)(v[i >> 2] >> (8 * (i & 3)));
}
free(v);
return out;
}
void decrypt()
{
unsigned char enc[] =
{
0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B,
0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8,
0xE7, 0x56, 0x56, 0xFA
};
// 解密xor
decrypt_xor(enc);
printf("[*] : xor finish \r\n");
// 乱序
sort(enc);
printf("[*] : sort success\r\n");
// xxtea
char key[16] = { 'f','l','a','g'};
size_t size = 0;
uint8_t* decrpyt = tea_decrypt((const uint8_t*)enc,24,(uint8_t*)key);
printf("[*] : xxtea success\r\n");
for (int i = 0; i < 19; i++)
printf("%c", decrpyt[i]);
}
// flag{CXX_and_++tea}

浙公网安备 33010602011771号