2021 莲城杯 Reverse WP

作者cxing,转载请注明出处。

baby_rust

不知道用了什么算法,生成了一张256个字节的表,动态生成了一系列的索引(似乎是用随机数种子)取表中的值。我们取32个值即可,然后与加密数据异或即可得到flag,但奇怪的是题目自身无法验证通过。

enc = [
    0xDE, 0xA5, 0x70, 0x9D, 0x74, 0xD0, 0x20, 0xA9, 0x60, 0xE8,
    0xA5, 0xF7, 0x3F, 0xE9, 0x1E, 0x2A, 0xB0, 0x45, 0xB5, 0x39,
    0xC1, 0x80, 0x26, 0xDF, 0xB7, 0xA7, 0x94, 0xE0, 0x9B, 0x03,
    0xD2, 0x3A
]
table = [0xE9,0x9C,0x40,0xF9,0x47,0xE2,0x19,0xCC,0x06,0xDB,0x97,0xC6,0x0E,0xDD,0x2A,0x4F,0xD3,0x71,0x81,0x5F,0xF2,0xB7,0x42,0xEE,0x8F,0x9E,0xA5,0xD9,0xF9,0x37,0xE3,0x02]
for i in range(len(enc)):
    enc[i] ^= table[i]
print(''.join(map(chr,enc))) #790d329ef321144ec44f37d18919b418

babybf

brainfuck用脚本解析出C语言代码,运行即可。

int main(_In_ int argc, _In_reads_(argc) _Pre_z_ char** argv, _In_z_ char** envp)
{

	uint8_t ptr[40] = { 0 };
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	while (ptr[1]) {
		ptr[0] += 10;
		ptr[1] -= 1;
	}
	while (ptr[0]) {
		ptr[0] -= 1;
		ptr[10] += 1;
		ptr[20] += 1;
	}
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	while (ptr[1]) {
		ptr[0] += 8;
		ptr[1] -= 1;
	}
	while (ptr[0]) {
		ptr[0] -= 1;
		ptr[2] += 1;
		ptr[3] += 1;
		ptr[5] += 1;
		ptr[7] += 1;
		ptr[30] += 1;
	}
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	while (ptr[1]) {
		ptr[0] += 9;
		ptr[1] -= 1;
	}
	while (ptr[0]) {
		ptr[0] -= 1;
		ptr[4] += 1;
		ptr[6] += 1;
		ptr[16] += 1;
		ptr[22] += 1;
		ptr[23] += 1;
		ptr[24] += 1;
	}
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	while (ptr[1]) {
		ptr[0] += 10;
		ptr[1] -= 1;
	}
	while (ptr[0]) {
		ptr[0] -= 1;
		ptr[9] += 1;
		ptr[11] += 1;
		ptr[12] += 1;
		ptr[13] += 1;
		ptr[14] += 1;
		ptr[17] += 1;
		ptr[18] += 1;
		ptr[19] += 1;
		ptr[21] += 1;
		ptr[25] += 1;
		ptr[28] += 1;
		ptr[29] += 1;
	}
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	ptr[1] += 1;
	while (ptr[1]) {
		ptr[0] += 11;
		ptr[1] -= 1;
	}
	while (ptr[0]) {
		ptr[0] -= 1;
		ptr[8] += 1;
		ptr[15] += 1;
		ptr[26] += 1;
		ptr[27] += 1;
		ptr[31] += 1;
		ptr[32] += 1;
		ptr[33] += 1;
	}
	ptr[2] += 1;
	ptr[2] += 1;
	ptr[2] += 1;
	ptr[2] += 1;
	ptr[3] += 1;
	ptr[4] += 1;
	ptr[4] += 1;
	ptr[5] += 1;
	ptr[5] += 1;
	ptr[5] += 1;
	ptr[6] += 1;
	ptr[6] += 1;
	ptr[6] += 1;
	ptr[7] += 1;
	ptr[7] += 1;
	ptr[7] += 1;
	ptr[7] += 1;
	ptr[7] += 1;
	ptr[7] += 1;
	ptr[8] += 1;
	ptr[8] += 1;
	ptr[9] -= 1;
	ptr[9] -= 1;
	ptr[10] += 1;
	ptr[11] -= 1;
	ptr[11] -= 1;
	ptr[11] -= 1;
	ptr[12] += 1;
	ptr[12] += 1;
	ptr[12] += 1;
	ptr[12] += 1;
	ptr[12] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[13] += 1;
	ptr[14] += 1;
	ptr[14] += 1;
	ptr[15] -= 1;
	ptr[15] -= 1;
	ptr[15] -= 1;
	ptr[15] -= 1;
	ptr[16] += 1;
	ptr[16] += 1;
	ptr[16] += 1;
	ptr[16] += 1;
	ptr[16] += 1;
	ptr[16] += 1;
	ptr[16] += 1;
	ptr[17] += 1;
	ptr[17] += 1;
	ptr[17] += 1;
	ptr[17] += 1;
	ptr[17] += 1;
	ptr[17] += 1;
	ptr[17] += 1;
	ptr[18] -= 1;
	ptr[18] -= 1;
	ptr[18] -= 1;
	ptr[18] -= 1;
	ptr[18] -= 1;
	ptr[19] += 1;
	ptr[19] += 1;
	ptr[19] += 1;
	ptr[19] += 1;
	ptr[19] += 1;
	ptr[20] += 1;
	ptr[20] += 1;
	ptr[20] += 1;
	ptr[21] -= 1;
	ptr[21] -= 1;
	ptr[21] -= 1;
	ptr[21] -= 1;
	ptr[21] -= 1;
	ptr[22] += 1;
	ptr[22] += 1;
	ptr[22] += 1;
	ptr[22] += 1;
	ptr[22] += 1;
	ptr[23] += 1;
	ptr[23] += 1;
	ptr[23] += 1;
	ptr[23] += 1;
	ptr[23] += 1;
	ptr[24] += 1;
	ptr[24] += 1;
	ptr[24] += 1;
	ptr[24] += 1;
	ptr[24] += 1;
	ptr[25] += 1;
	ptr[26] -= 1;
	ptr[26] -= 1;
	ptr[26] -= 1;
	ptr[26] -= 1;
	ptr[26] -= 1;
	ptr[26] -= 1;
	ptr[26] -= 1;
	ptr[28] -= 1;
	ptr[28] -= 1;
	ptr[28] -= 1;
	ptr[28] -= 1;
	ptr[28] -= 1;
	ptr[29] += 1;
	ptr[31] -= 1;
	ptr[31] -= 1;
	ptr[31] -= 1;
	ptr[31] -= 1;
	ptr[31] -= 1;
	ptr[31] -= 1;
	ptr[33] += 1;
	ptr[33] += 1;
	ptr[33] += 1;
	ptr[33] += 1;

	printf("%s", &ptr[2]); //DASCTF{b3ainfuXk_i5_VVVery_e@sy}

	return 0;
}

LongTime

go程序逆向,先patch Sleep函数。程序主要利用一个等式,v1 = i + 4 * v1 + 1取索引作为斐波那契数列的项数取余16作为16进制符号的索引,相当于有两层映射关系,第一层是一个等式,第二层斐波那契数列的值,最终从16进制字符串中取字符,一个32个。
处理数列相关的实际问题,通常是列出一些项来观察规律,因此可知斐波那契数列取余16的数列是在每隔24项重复。

因此等式产生的32个值就可以在24内取余,作为斐波那契数列的项数,第三层映射非常简单就不说了,因此问题就解决了。

def get_flag():
    table = "0123456789abcdef"
    fib = [0,1,1,2,3,5,8,13,5,2,7,9,0,9,9,2,11,13,8,5,13,2,15,1]
    idxs = []
    v0 = 0
    v1 = 1
    while v0 < 32:
        idxs.append(v1 % 24)
        v16 = v0
        v15 = v1
        v0 = v16 + 1
        v1 = v16 + 4 * v15 + 1
    for e in idxs:
        print(table[fib[e]],end='')
get_flag()  # 15f559713195b57dd1f9b91d3df55971
posted @ 2021-11-24 13:57  辰星-cxing  阅读(113)  评论(0编辑  收藏  举报