1. 程式人生 > 其它 >2021 蓮城杯 Reverse WP

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
to be or not to be, is a question.