# picoCTF vault-door (1-8) WriteUp 就自己紀錄一下,寫的很爛別太在意.w. ## valut-door-1 題目標籤: Medium, Reverse Engineering ![vault-door-1](https://hackmd.io/_uploads/BkOSVUMYJe.png) ### 題目解釋 裡面是一個JAVA檔,這部分的內容大概就是在 "picoCTF{" 後面會接一坨東西那就是flag。 ![vault-door-1_1](https://hackmd.io/_uploads/H11XBLGt1g.png) 往下看去會看到一個 checkPassword 他會回傳一個32個長度的東東,按順序組起來後會得到 "d35cr4mbl3_tH3_cH4r4cT3r5_f6daf4" 這一串,將其組起來後,就變成 picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_f6daf4},這就是最終答案 ![vault-door-1_2](https://hackmd.io/_uploads/rke46SDicJx.png) ### FLAG picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_f6daf4} ## vault-door-3 題目標籤: Medium, Reverse Engineering ![vault-door-3](https://hackmd.io/_uploads/BJlRrPi51e.png) ### 題目解釋 前面的部分都大同小異就跳過了,直接看到重點,他是由4個 for 迴圈組成,最後面有一個 "jU5t_a_sna_3lpm18g947\_u\_4\_m9r54f" 共有有32個字元。 ##### 第一個 for 迴圈 > 將 buffer 的 0-7 變成 "jU5t\_a\_s" 字串。 ##### 第二個 for 迴圈 > 將 burffer 的 8-15 變成倒過來的 "1mpl3\_an" 字串。 ##### 第三個 for 迴圈 > 將 16, 18, ... ,30 共8個位置變成 "4, r, m, 4, u, 7, 9, 8 " 這些字。 ##### 第四個 for 迴圈 > 將 31, 29, ... ,17 變成 "f, 5, 9, \_, \_, \_, 4, g" 這些字。 ##### 合併 最終全部組起來後變成 "picoCTF{jU5t_a_s1mpl3\_an4gr4m_4_u_79958f}" ![vault-door-3_1](https://hackmd.io/_uploads/HJSlLws5kl.png) ### FLAG picoCTF{jU5t_a_s1mpl3_an4gr4m_4_u_79958f} ## vault-door-4 題目標籤: Medium, Reverse Engineering ![vault-door-4](https://hackmd.io/_uploads/H11GIPo9Je.png) ### 題目解釋 可以 myBytes 是由4個部分組成 ##### 第一部分 > 106 , 85 , 53 , 116 , 95 , 52 , 95 , 98 > 這一段看起來像是 ascii 碼 > 轉換過後變成 "jU5t_4_b" ##### 第二部分 > 0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f > 這一段是一個[[進制轉換#十六進制|十六進制]] (Hex) > 轉換過後變成 "UnCh_0f_" ##### 第三部分 > 0142, 0131, 0164, 063 , 0163, 0137, 0143, 061 > 這一段是一個八進制 (Octal) > 轉換過後變成 "bYt3s_c1" ##### 第四部份 >'9' , '4' , 'f' , '7' , '4' , '5' , '8' , 'e' >本身就是文字 >因此合起來變成 "94f7458e" ![vault-door-4_1](https://hackmd.io/_uploads/BksM8Pi5kl.png) ### FLAG picoCTF{jU5t_4_bUnCh_0f_bYt3s_c194f7458e} ## vault-door-5 題目標籤: Medium, Reverse Engineering ![vault-door-5](https://hackmd.io/_uploads/SkmQIwscJg.png) ### 題目解釋 可以看到 myBytes 有許多的十六進制,在下面是一個 32 次的 for 迴圈,對每一個與 0x55 做 XOR 運算,因此得到 "n0t_mUcH_h4rD3r_tH4n_x0r_3ce2919" 即為解答 ![vault-door-5_1](https://hackmd.io/_uploads/H19Q8wi9kl.png) ### FLAG picoCTF{n0t_mUcH_h4rD3r_tH4n_x0r_3ce2919} ## vault-door-7 題目標籤: Hard, Reverse ![vault-door-7](https://hackmd.io/_uploads/ryPiUDjqye.png) ### 題目解釋 打開之後我們可以先偷看一下提示,簡單來說,就是今天有一串數字你可以先將他變成二進制,這時就會剛好符合 int 的長度 32 位元,我們可以將其拆分成四個部分並分別轉換回十進制,再轉換成 ASCII 就會得到 4 個字母。 ``` // Each character can be represented as a byte value using its // ASCII encoding. Each byte contains 8 bits, and an int contains // 32 bits, so we can "pack" 4 bytes into a single int. Here's an // example: if the hex string is "01ab", then those can be // represented as the bytes {0x30, 0x31, 0x61, 0x62}. When those // bytes are represented as binary, they are: // // 0x30: 00110000 // 0x31: 00110001 // 0x61: 01100001 // 0x62: 01100010 // // If we put those 4 binary numbers end to end, we end up with 32 // bits that can be interpreted as an int. // // 00110000001100010110000101100010 -> 808542562 // // Since 4 chars can be represented as 1 int, the 32 character password can // be represented as an array of 8 ints. // // - Minion #7816 ``` 或者也可以從這邊看出來,是將一組 hex 轉換成 8 個 int 的陣列。 ![vault-door-7_1](https://hackmd.io/_uploads/SkbnLws5kl.png) #### 第一步驟 先將圖片內的這八個 x\[0] 至 x\[7] 轉換為二進制,這部分可以用程式也可以手動,我比較懶,就直接手動了。 ![vault-door-7_2](https://hackmd.io/_uploads/SkK3Lwj9yg.png) 轉換過後變成這樣,記得要將沒有 32 長度的在最前面補上 0 這樣才會是正確的。 ![vault-door-7_3](https://hackmd.io/_uploads/rJIa8Dj5kg.png) #### 第二步驟 接著根據前面所述,將 8 個分成一組,每個都拆成 4 份,這邊就直接用程式跑,簡單暴力的小程式,最後再自己調整一下就會得到我們的 flag 了。 ![vault-door-7_4](https://hackmd.io/_uploads/BJap8DsqJg.png) ### 程式碼 ```py x1 = "01000001010111110110001000110001" x2 = "01110100010111110011000001100110" x3 = "01011111011000100011000101110100" x4 = "01011111011100110110100000110001" x5 = "01100110010101000110100101001110" x6 = "01100111010111110110010001100011" x7 = "00111000001100000110010100110010" x8 = "00111000001100010011001000110100" words = [] x = [x1, x2, x3, x4, x5, x6, x7, x8] for i in x:     for j in range(0, len(i), 8):         words.append(chr((int(i[j:j+8], 2)))) print(*words) ``` ### FLAG picoCTF{A_b1t_0f_b1t_sh1fTiNg_dc80e28124} ## vault-door-8 題目標籤: Hard, Reverse ![vault-door-8](https://hackmd.io/_uploads/HkjAUDiqkl.png) ### 題目解釋 #### 第一步驟 拿到題目後我們發現裡面十分混亂,因此稍微去整理一下讓此程式比較好看懂 ![vault-door-8_1](https://hackmd.io/_uploads/HkdyPwjc1l.png) 整理後: ```java // These pesky special agents keep reverse engineering our source code and then // breaking into our secret vaults. THIS will teach those sneaky sneaks a // lesson. // // -Minion #0891 import java.util.*; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.security.*; class VaultDoor8 { public static void main(String args[]) { Scanner b = new Scanner(System.in); System.out.print("Enter vault password: "); String c = b.next(); String f = c.substring(8,c.length()-1); VaultDoor8 a = new VaultDoor8(); if (a.checkPassword(f)) { System.out.println("Access granted."); } else { System.out.println("Access denied!"); } } public char[] scramble(String password) { /* Scramble a password by transposing pairs of bits. */ char[] a = password.toCharArray(); for (int b=0; b<a.length; b++) { char c = a[b]; c = switchBits(c,1,2); c = switchBits(c,0,3); /* c = switchBits(c,14,3); c = switchBits(c, 2, 0); */ c = switchBits(c,5,6); c = switchBits(c,4,7); c = switchBits(c,0,1); /* d = switchBits(d, 4, 5); e = switchBits(e, 5, 6); */ c = switchBits(c,3,4); c = switchBits(c,2,5); c = switchBits(c,6,7); a[b] = c; } return a; } public char switchBits(char c, int p1, int p2) { /* Move the bit in position p1 to position p2, and move the bit that was in position p2 to position p1. Precondition: p1 < p2 */ char mask1 = (char)(1 << p1); char mask2 = (char)(1 << p2); /* char mask3 = (char)(1<<p1<<p2); mask1++; mask1--; */ char bit1 = (char)(c & mask1); char bit2 = (char)(c & mask2); /* System.out.println("bit1 " + Integer.toBinaryString(bit1)); System.out.println("bit2 " + Integer.toBinaryString(bit2)); */ char rest = (char)(c & ~(mask1 | mask2)); char shift = (char)(p2 - p1); char result = (char)((bit1<<shift) | (bit2>>shift) | rest); return result; } public boolean checkPassword(String password) { char[] scrambled = scramble(password); char[] expected = { 0xF4, 0xC0, 0x97, 0xF0, 0x77, 0x97, 0xC0, 0xE4, 0xF0, 0x77, 0xA4, 0xD0, 0xC5, 0x77, 0xF4, 0x86, 0xD0, 0xA5, 0x45, 0x96, 0x27, 0xB5, 0x77, 0xE0, 0x95, 0xF1, 0xE1, 0xE0, 0xA4, 0xC0, 0x94, 0xA4 }; return Arrays.equals(scrambled, expected); } } ``` #### 第二步驟 先了解整個流程,在 checkPassword 的時候會將輸入值做 scramble 這個函數,也就是將每個字元做 8 次 switchBits 後,與 checkPassword 內的答案做對比,如果相同就是正確。 因此我們看到 swtichBits 的部分,一開始先對 1 進行左移 p1, p2 位,再存放在 mask 內。接著做 c & mask 也就是抓取 c 的第 mask 位的數值,並存放在 bit 內。最後三個 rest, shift, result 分別是,將 c 在 p1 和 p2 的位置清掉;接著藉由 p2 - p1 計算偏移量;講了那麼多廢話,其實就是將 p1 跟 p2 的位置調換,對就是那麼直白。 ![vault-door-8_2](https://hackmd.io/_uploads/BJI7PvsqJx.png) #### 第三步驟 因此看回去到 scramble 的部分,我們稍微整理一下這 8 次交換,可以發現是在做下圖的事情,不過要注意的是在逆推時需要將其順序反過來,不然答案會是錯的。 ![vault-door-8_3](https://hackmd.io/_uploads/ry2XPPi5ke.png) 透過程式,我們就可以將裡面的內容寫成程式運行,就可以得到我們的 flag 了。 ### 程式碼 ```py word = [0xF4, 0xC0, 0x97, 0xF0, 0x77, 0x97, 0xC0, 0xE4, 0xF0, 0x77, 0xA4, 0xD0, 0xC5, 0x77, 0xF4, 0x86, 0xD0, 0xA5, 0x45, 0x96, 0x27, 0xB5, 0x77, 0xE0, 0x95, 0xF1, 0xE1, 0xE0, 0xA4, 0xC0, 0x94, 0xA4] bin_word = [str(bin(i)[2:].zfill(8)) for i in word] ans = [] for i in bin_word: ans.append(chr(int((i[4:6] + i[0:2] + i[6:8] + i[2:4]), 2))) print(*ans) ``` ### FLAG picoCTF{s0m3_m0r3_b1t_sh1fTiNg_2e762b0ab}