這題我感覺我做的有問題,最後雖然答案是勉強湊出來了
題目給了3個附件
cipher1:
2 0 LOAD_CONST 1 ('')
2 STORE_FAST 1 (ret_text)
3 4 LOAD_GLOBAL 0 (list)
6 LOAD_FAST 0 (text)
8 CALL_FUNCTION 1
10 GET_ITER
>> 12 FOR_ITER 42 (to 56)
14 STORE_FAST 2 (i)
4 16 LOAD_FAST 0 (text)
18 LOAD_METHOD 1 (count)
20 LOAD_FAST 2 (i)
22 CALL_METHOD 1
24 STORE_FAST 3 (counter)
5 26 LOAD_FAST 1 (ret_text)
28 LOAD_GLOBAL 2 (chr)
30 LOAD_CONST 2 (2)
32 LOAD_GLOBAL 3 (ord)
34 LOAD_FAST 2 (i)
36 CALL_FUNCTION 1
38 BINARY_MULTIPLY
40 LOAD_GLOBAL 4 (len)
42 LOAD_FAST 0 (text)
44 CALL_FUNCTION 1
46 BINARY_SUBTRACT
48 CALL_FUNCTION 1
50 INPLACE_ADD
52 STORE_FAST 1 (ret_text)
54 JUMP_ABSOLUTE 12
6 >> 56 LOAD_FAST 1 (ret_text)
58 RETURN_VALUE
cipher2:
3 0 LOAD_CONST 1 ('S')
2 STORE_FAST 1 (xorKey)
4 4 LOAD_GLOBAL 0 (len)
6 LOAD_FAST 0 (inpString)
8 CALL_FUNCTION 1
10 STORE_FAST 2 (length)
5 12 LOAD_GLOBAL 1 (range)
14 LOAD_FAST 2 (length)
16 CALL_FUNCTION 1
18 GET_ITER
>> 20 FOR_ITER 56 (to 78)
22 STORE_FAST 3 (i)
6 24 LOAD_FAST 0 (inpString)
26 LOAD_CONST 0 (None)
28 LOAD_FAST 3 (i)
30 BUILD_SLICE 2
32 BINARY_SUBSCR
34 LOAD_GLOBAL 2 (chr)
36 LOAD_GLOBAL 3 (ord)
38 LOAD_FAST 0 (inpString)
40 LOAD_FAST 3 (i)
42 BINARY_SUBSCR
44 CALL_FUNCTION 1
46 LOAD_GLOBAL 3 (ord)
48 LOAD_FAST 1 (xorKey)
50 CALL_FUNCTION 1
52 BINARY_XOR
54 CALL_FUNCTION 1
56 BINARY_ADD
58 LOAD_FAST 0 (inpString)
60 LOAD_FAST 3 (i)
62 LOAD_CONST 2 (1)
64 BINARY_ADD
66 LOAD_CONST 0 (None)
68 BUILD_SLICE 2
70 BINARY_SUBSCR
72 BINARY_ADD
74 STORE_FAST 0 (inpString)
76 JUMP_ABSOLUTE 20
9 >> 78 LOAD_FAST 0 (inpString)
80 RETURN_VALUE
encodedflag:
根據題目很容易想到python的dis庫
具體的分析方法可以直接使用搜尋引擎一鍵傳送到學習區,這裡不細講了
随着我一陣摸索+亂湊,終于把python代碼完整的還原出來了
import dis
def cipher1(text):
ret_text = ''
for i in list(text):
counter = text.count(i)
ret_text += chr(2 * ord(i) - len(text))
return ret_text
print(dis.dis(cipher1))
def cipher2(inpString):
xorKey = 'S'
length = len(inpString)
for i in range(length):
inpString = inpString[:i] + chr(ord(inpString[i]) ^ ord(xorKey)) + inpString[i + 1:]
return inpString
print(dis.dis(cipher2))
可以看到運作出來列印的和附件給的幾乎一模一樣,是以我們有把握認為加密代碼就是我還原出來的
然後就是寫逆向代碼了,結果。。。
#include <iostream>
using namespace std;
int main()
{
unsigned char flag[58] = {
0xC2, 0xA4, 0xC3, 0x84, 0xC2, 0xB0, 0xC2, 0xA4, 0xC3, 0x86, 0xC2, 0xAA, 0xC3, 0x94, 0xC2, 0x86,
0x24, 0xC2, 0xA0, 0x34, 0xC2, 0x9C, 0xC3, 0x8C, 0x60, 0x48, 0xC2, 0x9C, 0xC2, 0xAC, 0x3E, 0xC2,
0xBC, 0x66, 0xC2, 0x9C, 0xC2, 0xA6, 0x40, 0x48, 0x48, 0xC2, 0xA0, 0xC2, 0x84, 0xC2, 0xA8, 0xC2,
0x9A, 0xC2, 0x9A, 0xC2, 0xA2, 0x76, 0xC3, 0x90, 0xC3, 0x98
};
for (size_t i = 0; i < 58; i++)
{
flag[i] += 34;
flag[i] /= 2;
}
cout << (char*)flag << endl;
}
不要問我為什麼長度是58而加的是34,不要問我為什麼沒有異或,不要問我為什麼這答案看起來這麼怪… 因為是錯的
但是如果老老實實按照代碼去還原,輸出的是亂碼 =_=
初步懷疑可能是WinHex的問題或者是python編碼的問題?因為按理來說加密後的每個位元組要麼全是奇數要麼全是偶數,我在WinHex裡看到的又有奇數又有偶數…
是以,如果你用其他的二進制編輯工具能夠正确提取密文的話,這道題應該就很簡單了
在這裡我記錄一下我自己當時做題的過程
觀察到0xc2和0xc3反複出現,出現的位置往往是上面圖中的r字元,是以全部去掉,去掉之後長度就是34了。去掉之後,看起來有點像flag了,但是還是不對
然後我根據上面的 cSicTf[xxx] 與其他題目的 csictf{xxx} 發現了一個規律,對應字元的原位置的前面如果是0xc3的,要變成小寫/大括号
改完以後是這樣
csictf{T#a+_wA5_g0oD_d155aSe^^bLy}
嗯,這個終于對了 (lll¬ω¬)