PicoCTF - OTP Implementation
Source code
:::spoiler IDA Main Function
1 |
|
:::
:::spoiler IDA Jumble Function
1 |
|
::: :::spoiler IDA Valid Function
1 |
|
:::
Recon
這一題頗難,我寫的script也沒有很好,readability頗低,但我就爛,懶得優化了
- 這一題簡單來說就是把我們輸入的key做一些操作,然後把它和
bajbgfa...
做比較,如果對了我們就可以直接和他提供的flag進行xor,然後轉換成ASCII - 有幾個重點,首先透過valid_char function可以知道我們輸入的key一定介於[0-9a-f]之間(這是個伏筆,因為他最後會直接和他提供的ciphertext進行xor,所以其實就是hex字元)
- 接著可以從後面推回來,第一個flag做了一些操作,之後就直接加上0x61,再和
bajbgfa...
做比較,所以我們先減回去 :::spoiler tmp_key[1, 0, 9, 1, 6, 5, 0, 15, 1, 2, 2, 11, 6, 14, 4, 9, 6, 15, 0, 10, 12, 3, 8, 11, 0, 11, 15, 14, 12, 5, 3, 11, 10, 13, 6, 10, 7, 0, 11, 9, 11, 2, 15, 10, 9, 6, 13, 3, 11, 6, 12, 15, 3, 6, 12, 13, 12, 4, 15, 5, 8, 10, 0, 13, 4, 15, 14, 15, 1, 0, 15, 5, 10, 3, 6, 11, 4, 8, 11, 7, 10, 5, 6, 8, 11, 6, 0, 1, 11, 3, 14, 5, 1, 2, 0, 4, 3, 6, 5, 4]
::: - 接著我們分析jumble function在幹嘛,簡單來說,如果傳入的是
- ‘0’-‘9’$\to$return 0 2 4 6 8 10 12 14 17 19
- ‘a’-‘f’$\to$return 21 23 25 27 29 31
- 跟著if statement走
tmp_key[0] = jumble(input_key[0]) % 16;
我們知道tmp_key[0]=0x1
(因為key的第一個字元是b
$\to$0x62
,減掉0x61=0x1
),所以仔細推敲jumble(input_key[0])的return value是0 2 4 6 8 10 12 14 1 3 5 7 9 11 13 15
(對應到的是[0-9a-f]),所以代表0x1在經過mod運算是0x11(要+16),而正確的key就是對應到的8 - 接著換下一個字元,先破哏,if statement裡面的v6基本上是零,畢竟右移那麼多次,也不知道作者設計這個有甚麼用,可能是混淆逆向的?!但反正
1
2
3
4v4 -> jumble(tmp_key[i-1])([0 2 4 6 8 10 12 14 , .... , 31]) v5 -> [0-15]+v4 v6 -> v5 >> 59 (基本上是0) tmp_key[i] = v5 & 0xf
可以看到tmp_key[i]是v5和0xf做and operation,意思是他只會保留一個byte的後四個bits,跟一下gdb會發現前四bits,有可能存在,所以我們可以透過v5-v4是正還是負判斷前四bits有沒有數值,舉個例子,tmp_key[1]是0,而要判斷v5是0x0還是0x10可以透過減掉tmp_key[0]=1來決定,當結果是負的,就要加0x10,所以v5是0x10,v4是0xf,此時會發現沒有相對應的數值可以轉換,因為jumble function的return value並不包含0xf,所以我們要再加上0x10=0x1f,因為其實v5真正的數值是0x20才對,有了v4=31,就可以知道key[1]=’f’
- 就這樣不斷做下去,就能拿到key了,開寫script
Exploit
1 |
|
Flag: picoCTF{cust0m_jumbl3s_4r3nt_4_g0Od_1d3A_42dad069}