天天看點

【CSICTF】pydis2ctf WriteUp

【CSICTF】pydis2ctf WriteUp

這題我感覺我做的有問題,最後雖然答案是勉強湊出來了

題目給了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:

【CSICTF】pydis2ctf WriteUp

根據題目很容易想到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))
           

可以看到運作出來列印的和附件給的幾乎一模一樣,是以我們有把握認為加密代碼就是我還原出來的

【CSICTF】pydis2ctf WriteUp

然後就是寫逆向代碼了,結果。。。

#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;
}
           
【CSICTF】pydis2ctf WriteUp

不要問我為什麼長度是58而加的是34,不要問我為什麼沒有異或,不要問我為什麼這答案看起來這麼怪… 因為是錯的

但是如果老老實實按照代碼去還原,輸出的是亂碼 =_=

初步懷疑可能是WinHex的問題或者是python編碼的問題?因為按理來說加密後的每個位元組要麼全是奇數要麼全是偶數,我在WinHex裡看到的又有奇數又有偶數…

是以,如果你用其他的二進制編輯工具能夠正确提取密文的話,這道題應該就很簡單了

在這裡我記錄一下我自己當時做題的過程

觀察到0xc2和0xc3反複出現,出現的位置往往是上面圖中的r字元,是以全部去掉,去掉之後長度就是34了。去掉之後,看起來有點像flag了,但是還是不對

【CSICTF】pydis2ctf WriteUp

然後我根據上面的 cSicTf[xxx] 與其他題目的 csictf{xxx} 發現了一個規律,對應字元的原位置的前面如果是0xc3的,要變成小寫/大括号

改完以後是這樣

csictf{T#a+_wA5_g0oD_d155aSe^^bLy}

嗯,這個終于對了 (lll¬ω¬)

ctf