# picoCTF vault-door (1-8) WriteUp
就自己紀錄一下,寫的很爛別太在意.w.
## valut-door-1
題目標籤: Medium, Reverse Engineering

### 題目解釋
裡面是一個JAVA檔,這部分的內容大概就是在 "picoCTF{" 後面會接一坨東西那就是flag。

往下看去會看到一個 checkPassword 他會回傳一個32個長度的東東,按順序組起來後會得到 "d35cr4mbl3_tH3_cH4r4cT3r5_f6daf4" 這一串,將其組起來後,就變成 picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_f6daf4},這就是最終答案

### FLAG
picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_f6daf4}
## vault-door-3
題目標籤: Medium, Reverse Engineering

### 題目解釋
前面的部分都大同小異就跳過了,直接看到重點,他是由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}"

### FLAG
picoCTF{jU5t_a_s1mpl3_an4gr4m_4_u_79958f}
## vault-door-4
題目標籤: Medium, Reverse Engineering

### 題目解釋
可以 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"

### FLAG
picoCTF{jU5t_4_bUnCh_0f_bYt3s_c194f7458e}
## vault-door-5
題目標籤: Medium, Reverse Engineering

### 題目解釋
可以看到 myBytes 有許多的十六進制,在下面是一個 32 次的 for 迴圈,對每一個與 0x55 做 XOR 運算,因此得到 "n0t_mUcH_h4rD3r_tH4n_x0r_3ce2919" 即為解答

### FLAG
picoCTF{n0t_mUcH_h4rD3r_tH4n_x0r_3ce2919}
## vault-door-7
題目標籤: Hard, Reverse

### 題目解釋
打開之後我們可以先偷看一下提示,簡單來說,就是今天有一串數字你可以先將他變成二進制,這時就會剛好符合 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 的陣列。

#### 第一步驟
先將圖片內的這八個 x\[0] 至 x\[7] 轉換為二進制,這部分可以用程式也可以手動,我比較懶,就直接手動了。

轉換過後變成這樣,記得要將沒有 32 長度的在最前面補上 0 這樣才會是正確的。

#### 第二步驟
接著根據前面所述,將 8 個分成一組,每個都拆成 4 份,這邊就直接用程式跑,簡單暴力的小程式,最後再自己調整一下就會得到我們的 flag 了。

### 程式碼
```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

### 題目解釋
#### 第一步驟
拿到題目後我們發現裡面十分混亂,因此稍微去整理一下讓此程式比較好看懂

整理後:
```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 的位置調換,對就是那麼直白。

#### 第三步驟
因此看回去到 scramble 的部分,我們稍微整理一下這 8 次交換,可以發現是在做下圖的事情,不過要注意的是在逆推時需要將其順序反過來,不然答案會是錯的。

透過程式,我們就可以將裡面的內容寫成程式運行,就可以得到我們的 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}