AIS3 IoT 檢測實務 Lab01~03 writeup

AIS3 沒能聽到IoT的課,好奇IoT在教什麼,就看講師簡報,試做課程 lab,目前只看到 lab3

Lab01

題目

給兩個檔案
image
取出存放在 /etc/shadow 中的 root 密碼

writeup

1
binwalk kkeps-3.5.bin -Me

成功解壓縮
image
image

1
2
3
4
unshadow _kkeps-3.5.bin.extracted/squashfs-root/etc/passwd _kkeps-3.5.bin.extracted/squashfs-root/etc/shadow > unshadow.txt
john --wordlist="password 字典檔.txt" --format="crypt" unshadow.txt

p9z34c (root)

Lab02

題目

觀察有/無加密韌體的 Entropy 差異
image

writeup

1
binwalk -E DIR882A1_encrypted.bin

有加密
image

1
binwalk -E rapa_vi-Merx-2.0b1_20180823_uncrypted.fw

無加密
image

Lab03

題目

撰寫解密工具並解密 DIR882A1_FW110B02.BIN

  • 找出 AES Key, IV, Internal AES Key
  • 並定位出檔案讀取的 offset

image
解密工具有模板可以參考

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
from Crypto.Cipher import AES
import binascii

Encrypted_key = bytes.fromhex('')
AES_internal_key = bytes.fromhex('')
AES_iv = bytes.fromhex('')

FIRMWARE_DATA_LENGTH_OFFSET = 0
FIRMWARE_DATA_IV_OFFSET = 0
FIRMWARE_DATA_OFFSET = 0

AES_Instance = AES.new(AES_internal_key, AES.MODE_CBC, AES_iv)
AES_ImageDecryptKey = AES_Instance.decrypt(Encrypted_key)
print( "Image Decrypt Key:" + binascii.hexlify(AES_ImageDecryptKey).decode() )

target_fw = "DIR882A1_FW110B02.BIN"
encrypted_fw_fd = open(target_fw, "rb")

# Read data length
encrypted_fw_fd.seek(FIRMWARE_DATA_LENGTH_OFFSET)
data_length = int.from_bytes(encrypted_fw_fd.read(4), byteorder='big', signed=False)

print("Image Data Length: " + str(data_length))

# read data iv
encrypted_fw_fd.seek(FIRMWARE_DATA_IV_OFFSET)
data_iv = encrypted_fw_fd.read(16)

print("Image Data IV: " + binascii.hexlify(data_iv).decode())


# read encrypted fw data
encrypted_fw_fd.seek(FIRMWARE_DATA_OFFSET)
encrypted_fw_data = encrypted_fw_fd.read(data_length)

AES_Instance_Fw = AES.new(AES_ImageDecryptKey, AES.MODE_CBC, data_iv)
with open(target_fw + "_decrypted.BIN", "wb") as f:
f.write( AES_Instance_Fw.decrypt( encrypted_fw_data ) )

writeup

1
binwalk -E DIR882A1_FW110B02.BIN

有加密
image
無法解壓縮
image

看 FW110B02 的 Release Notes ,發現有過度版本
image

1
binwalk -Me DIR882A1_FW104B02_Middle_FW_Unencrypt.bin

成功解壓縮過度版本
image
image
bin 底下找解密工具
image
用 Ghidra 開 imgdecrypt
image
先看 Imports、Exports、Functions
image

  • __uClibc_main
    嵌入式系統常用的 libc
  • AES_cbc_encrypt、AES_set_decrypt_key、AES_set_encrypt_key
    AES 家族的函數

image
(粉色沒有重新命名過,藍色部分有)

  • decrypt_firmare、encrypt_firmare
    程式本身提供加解密系統
  • entry
    程式進入點
  • main
    程式主函數

  • 先看 entry
    image
  • main
    image
  • decrypt_firmare
    (由於看不懂講師簡報上為什麼框選處範圍為關鍵程式碼,我把decrypt_firmare逆了一遍,這是已整理過的,以下其它截圖也都是我逆向過的)
    逆向過程大致是參考簡報+chatgpt
    這段關鍵程式碼是在用AES CBC解密東西,被解密的東西是別的解密函數的 Key,會被print出來
    image
  • to_AES_cbc_decrypt
    image
  • AES_cbc_decrypt
    image
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    AES_set_decrypt_key(const unsigned char *userKey, const int bits,  AES_KEY *key)
    設定解密用的Key
    userKey: 金鑰數值
    bits:密鑰長度,以bit為單位,如果密鑰數字是16個位元組,則此參數值應為128;
    key: AES_KEY物件指標
    傳回值: 0 成功, -1 userkey, key為空, -2 金鑰長度不是128,192,256

    AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc)
    AES加密/解密單一資料塊(16個位元組),CBC模式
    in: 需要加密/解密的資料
    out: 計算後輸出的資料
    length: 資料長度(不包含初始向量)
    key:金鑰
    ivec: 初始向量
    enc: AES_ENCRYPT(0) 代表加密, AES_DECRYPT(1) 代表解密
  • IV_PTR
    image
  • BYTE_00402e58
    取得 IV、Key、Data ,應該對應 IV, Internal AES Key, AES Key
    image
    image
  • 回到 decrypt_firmare
    image
    這段關鍵程式碼是真的在解密韌體,用的key是前面解密出來的data
  • decryt_firmware1
    image
    開加密韌體
    image
    取得加密韌體映射在記憶體中的起始位址
    image
    1
    2
    3
    4
    5
    6
    mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize)
    主要用途有三個:
    - 將一個普通檔案映射到記憶體中,通常在需要對檔案進行頻繁讀寫時使用,這樣用記憶體讀寫取代I/O讀寫,以獲得較高的效能;
    - 將特殊檔案進行匿名記憶體映射,可以為關聯進程提供共享記憶體空間;
    - 為無關聯的程序提供共享記憶體空間,一般也是將一個普通檔案映射到記憶體中
    若映射成功則傳回映射區的記憶體起始位址,否則回傳MAP_FAILED(-1)
    確認加密韌體的檔案標頭
    image
  • check_SHRS
    檢查加密韌體的前四 bytes 是不是 SHRS
    image
    DIR882A1_FW110B02.BIN 是符合的
    image
  • 定位出檔案讀取的 offset
    參考解密程式模板,要找出加密韌體檔案中的 DATA LENGTH OFFSET、
    DATA IV OFFSET、DATA OFFSET
    image
    1
    AES_cbc_decrypt(uchar *Data,uint Length,uchar *Key,undefined4 *IV,uchar *decrypt_data )
    所以Length對應uVar1,而uVar1是加密韌體映射在記憶體中的起始位址偏移 8
    DATA LENGTH OFFSET => 8
    加密韌體映射在記憶體中的起始位址偏移 0xc 是 IV
    DATA IV OFFSET => 0xc
    加密韌體映射在記憶體中的起始位址偏移 0x6dc 是 Data
    DATA OFFSET => 0x6dc

完成解密程式模板

1
2
3
4
5
6
7
Encrypted_key    = bytes.fromhex('c8d32f409cacb347c8d26fdcb9090b3c')
AES_internal_key = bytes.fromhex('358790034519f8c8235db6492839a73f')
AES_iv = bytes.fromhex('98c9d8f0133d0695e2a709c8b69682d4')

FIRMWARE_DATA_LENGTH_OFFSET = 8
FIRMWARE_DATA_IV_OFFSET = 12
FIRMWARE_DATA_OFFSET = 1756

image
image

1
binwalk -Me DIR882A1_FW110B02.BIN_decrypted.BIN

成功解壓縮
image