HackTheBox-Challenges SPG Writeup

kazma 成大資安社 創辦人/社長

Exploitation

首先題目附給我們 source.py 以及 output.txt,其中程式的主邏輯如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import random
import string
from base64 import b64encode
from hashlib import sha256

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from secret import FLAG, MASTER_KEY

ALPHABET = string.ascii_letters + string.digits + "~!@#$%^&*"


def generate_password():
master_key = int.from_bytes(MASTER_KEY, "little")
password = ""

while master_key:
bit = master_key & 1
if bit:
password += random.choice(ALPHABET[: len(ALPHABET) // 2])
else:
password += random.choice(ALPHABET[len(ALPHABET) // 2 :])
master_key >>= 1

return password


def main():
password = generate_password()
encryption_key = sha256(MASTER_KEY).digest()
cipher = AES.new(encryption_key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(FLAG, 16))

with open("output.txt", "w") as f:
f.write(
f"Your Password : {password}\nEncrypted Flag : {b64encode(ciphertext).decode()}"
)


if __name__ == "__main__":
main()

我們來分析一下上面做了些什麼,首先他有一個 generate_password() 的函式把引入的 MASTER_KEY 來生成一組密碼。他先把 MASTER_KEY 用 little_endian 的格式轉成整數,接著從最低位開始若 bit 為 1 則從自定義的字母表前半部分挑一個字符加入 password,反之,若 bit 為 0 就從後半部挑一個字符,然後往高位移動一個重複前面的操作。再來 main 使用 MASTER_KEY 通過 SHA-256 雜湊算法生成加密金鑰 encryption_key,sha256(MASTER_KEY).digest() 會產生一個 256 位的摘要,這會用於之後 AES 加密的密鑰。
接著我們會使用生成的 encryption_key 初始化 AES 加密器,並選擇 ECB 模式。然後把 flag padding 到 16 位確保 AES 可以正常運作,然後執行加密後輸出 password 跟 flag。

那分析完後首先我們會想先想辦法得到 master_key,那根據他字母表的建立方式我們可以知道前半跟後半分別是:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*,所以我們可以透過 password 的每一位在前半或是後半知道 master_key 的每一個 bit 是 0 還是 1 如此就可以得到 master_key,接著就是正常的 AES 操作。

Exploit

最後按照剛剛的邏輯把腳本實現如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import string
from base64 import b64decode
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes
from Crypto.Util.Padding import unpad

alph = string.ascii_letters + string.digits + "~!@#$%^&*"
first_half, second_half = set(alph[:len(alph) // 2]), set(alph[len(alph) // 2:])

def load_data():
with open("output.txt") as f:
password = f.readline().split(" : ")[1].strip()
enc_flag = b64decode(f.readline().split(" : ")[1].strip())
return password, enc_flag

def recover_master_key(password):
bits = ['1' if p in first_half else '0' for p in password]
return int(''.join(bits[::-1]), 2)

def decrypt_flag(master_key, enc_flag):
encryption_key = sha256(long_to_bytes(master_key)[::-1]).digest()
cipher = AES.new(encryption_key, AES.MODE_ECB)
return unpad(cipher.decrypt(enc_flag), 16).decode()

def pwn():
password, enc_flag = load_data()
master_key = recover_master_key(password)
flag = decrypt_flag(master_key, enc_flag)
print(f"Decrypted FLAG: {flag}")

pwn()
1
2
╰─ python solve.py                                      ─╯
Decrypted FLAG: HTB{m4ll34bl3_p4ssw0rd_g3n3r4t0r!}

Pwned !!!

pwn

References

  • Title: HackTheBox-Challenges SPG Writeup
  • Author: kazma
  • Created at : 2024-11-01 18:03:28
  • Updated at : 2024-11-01 20:09:01
  • Link: https://kazma.tw/2024/11/01/HackTheBox-Challenges-SPG-Writeup/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
HackTheBox-Challenges SPG Writeup