Skip to content

Commit f6fccf1

Browse files
committed
Add writeups from T0077
1 parent f7443c1 commit f6fccf1

File tree

3 files changed

+225
-0
lines changed

3 files changed

+225
-0
lines changed

ram/writeups/t0077/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# HKCERT CTF Challenge 2020 Writeup
2+
### Team: T0077 - HKUST
3+
### Challenge Name: RAM 拉姆 (Misc, 450 points)
4+
5+
Solved by _Vincent_
6+
7+
---
8+
9+
Objective: Get user passwords from `memory.dmp` of RAM image
10+
11+
Flag format: `hkcert20{(pw of flag01)_(pw of flag02)_(pw of flag03)_(pw of flag04)_(pw of flag05)}`
12+
13+
---
14+
15+
Reference: OtterCTF 2018 Memory Forensics Write-up (Part I)
16+
https://medium.com/@sbasu7241/otterctf-2018-memory-forensics-write-up-part-1-ea27a144a5d4
17+
18+
Simply follow the steps of the above write-up :)
19+
20+
1. Install `volatility`
21+
2. Identify the correct profile for the memory image using `imageinfo`, verify with `kdbgscan`
22+
23+
![](https://i.imgur.com/EgUAOCu.png)
24+
25+
![](https://i.imgur.com/mikpokj.png)
26+
27+
3. Get the passwords using `hashdump`
28+
29+
![](https://i.imgur.com/xPlTlLn.png)
30+
31+
We now have all the passwords, hashed:
32+
33+
```1
34+
flag01:1678ac6f5380c60363a91082d0699c74
35+
flag02:40e43aee94115e12541624221019423b
36+
flag03:186cb09181e2c2ecaac768c47c729904
37+
flag04:5c3b27ff63ae1e7e1b3221b19f00183c
38+
flag05:1597f8e3b872d5348767416f6921d346
39+
```
40+
41+
Final step: crack the hashes
42+
43+
![](https://i.imgur.com/OhE37Cw.png)
44+
45+
Flag: `hkcert20{this_is_a_MD5_challenge}`

tenet/writeups/t0077/README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# HKCERT CTF Challenge 2020 Writeup
2+
### Team: T0077 - HKUST
3+
### Challenge Name: Tenet 天能 (Crypto, 492 points)
4+
5+
Solved by _Vincent_
6+
#first_blood
7+
8+
---
9+
10+
Objective: Given encryption code, decipher this:
11+
`6255c24aa3dd8f58c5fcb41feb90f90e73e870db651d5a963498f062c2c1572430098acf05`
12+
13+
---
14+
15+
Observations:
16+
17+
1. AES Double-Key Encryption:
18+
$C=E(E(P, K_0, IV_0), K_1, IV_1)$
19+
$P=D(D(C, K_1, IV_1), K_0, IV_0)$
20+
$\Rightarrow$ Meet-in-the-middle attack?
21+
$D(C, K_1, IV_1)=E(P, K_0, IV_0)$
22+
2. The National Security Law in the near future requires first 13 bytes of keys to be zeros.
23+
`key1 = b'\0' * 13 + os.urandom(3)`
24+
`key2 = b'\0' * 13 + os.urandom(3)`
25+
$\Rightarrow$ Key search space = $2^{24}$
26+
3. Of course we don't know the whole plaintext, we just know it starts with `hkcert20{`. However, even having partial plaintext is useless for MiM attacks, unless...
27+
4. `mode=AES.MODE_CTR`
28+
29+
$C_i=(P_i \oplus E_{CTR}(IV_0+i, K_0)) \oplus E_{CTR}(IV_1+i, K_1)\\
30+
\ \ \ \ =P_i \oplus (E_{CTR}(IV_0+i, K_0) \oplus E_{CTR}(IV_1+i, K_1))$
31+
32+
$\Rightarrow P=C \oplus (E(\vec{0}, K_0, IV_0) \oplus E(\vec{0}, K_1, IV_1))$
33+
34+
---
35+
36+
Exhaust all $2^{24}$ keys, compute $E(\vec{0}, K, IV_0)$ and $E(\vec{0}, K, IV_1)$, label using the first 3 bytes of the keystreams.
37+
38+
Then $\forall K_0, K_1$ s.t. $E(E(P, K_0, IV_0), K_1, IV_1)$`[:3] == b'hkc'`, check if `[:9] == b'hkcert20{'`
39+
40+
---
41+
42+
```python=
43+
from Crypto.Cipher import AES
44+
from Crypto.Util import Counter
45+
from Crypto.Util.number import bytes_to_long, long_to_bytes
46+
import os
47+
48+
flaggie = b'hkcert20{'
49+
50+
ciphervalue = 0x6255c24aa3dd8f58c5fcb41feb90f90e73e870db651d5a963498f062c2c1572430098acf05
51+
ciphertext = long_to_bytes(ciphervalue)
52+
53+
head = bytes_to_long(flaggie[:3]) ^ bytes_to_long(ciphertext[:3])
54+
55+
# In the future, we have not only time inversion but also quantum computers.
56+
# So, we need to encrypt twice to double the key size.
57+
class TenetAES():
58+
def __init__(self, key0, key1):
59+
self.aes128_0 = AES.new(key=key0, mode=AES.MODE_CTR, counter=Counter.new(128, initial_value=1))
60+
self.aes128_01 = AES.new(key=key0, mode=AES.MODE_CTR, counter=Counter.new(128, initial_value=1))
61+
self.aes128_1 = AES.new(key=key1, mode=AES.MODE_CTR, counter=Counter.new(128, initial_value=129))
62+
self.aes128_11 = AES.new(key=key1, mode=AES.MODE_CTR, counter=Counter.new(128, initial_value=129))
63+
64+
def keystreams(self, n = 37):
65+
return self.aes128_0.encrypt(b'\0' * n), self.aes128_1.encrypt(b'\0' * n)
66+
67+
def encrypt(self, s):
68+
n = len(s)
69+
x = self.aes128_1.encrypt(self.aes128_0.encrypt(s))
70+
y = long_to_bytes(
71+
bytes_to_long(self.aes128_01.encrypt(b'\0' * n))
72+
^ bytes_to_long(self.aes128_11.encrypt(b'\0' * n))
73+
^ bytes_to_long(s)
74+
)
75+
assert x == y
76+
return x
77+
78+
def decrypt(self, data):
79+
n = len(data)
80+
x = self.aes128_0.decrypt(self.aes128_1.decrypt(data))
81+
y = long_to_bytes(
82+
bytes_to_long(self.aes128_01.encrypt(b'\0' * n))
83+
^ bytes_to_long(self.aes128_11.encrypt(b'\0' * n))
84+
^ bytes_to_long(data)
85+
)
86+
assert x == y
87+
return x
88+
89+
#with open('flag.txt') as f:
90+
# flag = f.read()
91+
92+
# The National Security Law in the near future requires first 13 bytes of
93+
# keys to be zeros.
94+
95+
#key1 = b'\0' * 13 + os.urandom(3)
96+
#key2 = b'\0' * 13 + os.urandom(3)
97+
98+
one = [[] for i in range(16777216)]
99+
two = [[] for i in range(16777216)]
100+
101+
for i in range(16777216):
102+
key1 = b'\0' * 13 + i.to_bytes(3, byteorder = 'big')
103+
key2 = b'\0' * 13 + i.to_bytes(3, byteorder = 'big')
104+
a, b = TenetAES(key1, key2).keystreams()
105+
one[bytes_to_long(a[:3])].append(i)
106+
two[bytes_to_long(b[:3])].append(i)
107+
108+
for i in range(16777216):
109+
for a in one[i]:
110+
for b in two[i ^ head]:
111+
key1 = b'\0' * 13 + a.to_bytes(3, byteorder = 'big')
112+
key2 = b'\0' * 13 + b.to_bytes(3, byteorder = 'big')
113+
aa, bb = TenetAES(key1, key2).keystreams()
114+
aa = bytes_to_long(aa)
115+
bb = bytes_to_long(bb)
116+
x = (aa ^ bb ^ ciphervalue).to_bytes(37, byteorder='big')
117+
assert x[:3] == b'hkc'
118+
if x[:9] == flaggie:
119+
print(key1)
120+
print(key2)
121+
print(x)
122+
```
123+
124+
```python
125+
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+!0'
126+
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x84\xd2'
127+
b'hkcert20{7h3_b361nn1n6_15_7h3_3nd1n6}'
128+
```
129+
130+
---
131+
132+
P.S.
133+
134+
![](https://i.imgur.com/39LHsr8.png)
135+
136+
P.P.S. Official Hint: (viewed after contest)
137+
In "Tenet", red team and blue team meet in the middle.
138+
139+
---
140+
141+
###### _In memory of Neil_
142+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# HKCERT CTF Challenge 2020 Writeup
2+
### Team: T0077 - HKUST
3+
### Challenge Name: Tuning Keyboard 通靈字盤 (Misc, 482 points)
4+
5+
Solved by _Vincent_
6+
Written by _Starry Miracle_
7+
8+
---
9+
10+
Flag format: `hkcert20{...}`
11+
12+
Description 描述:
13+
* Username: Guest 帳號: 訪客
14+
* Password: Guess 密碼: 猜測
15+
16+
---
17+
18+
Step 1. Look at the free hint! (isn't them cute?)
19+
20+
![](https://i.imgur.com/rd43vn3.jpg)
21+
22+
Step 2. Find out what is going on
23+
24+
- Unzip the file. You should find `0.jpg`, `1.jpg`, `flag.jpg` and `yaminogemu.html`.
25+
- Have a look at `yaminogemu.html` (after you find out that it is not a steganography challenge)
26+
- There is a comment in line 52, how about changing it to `q.innerText += ''+ok+''+dk+''+ek+''+ak+''+tk+''+hk;`
27+
- Some 1s and 0s shows up! Maybe this is the encoded flag?
28+
- However, after restarting and get the value of `q` again, the result changed...
29+
- It seems that `setTimeout` is not accurate enough to "get the frequency" of the challenge author
30+
31+
Step 3. Solving the challenge :)
32+
33+
- Write a solver that can simulate what the `setTimeout` in HTML
34+
![](https://imgur.com/RMxw4YU.jpg)
35+
- Since it is in group of 6, maybe the binarys are encoded in group of 6? (2^6 is ... 64!)
36+
Converting the binary to base64 we get`aGtjZXJ0MjB7SEEqTkEqU0V9`, and decoding this we get the flag.
37+
38+
Flag: `hkcert20{HA*NA*SE}`

0 commit comments

Comments
 (0)