Dưới đây là chall Forensic của SVATTT 2024. Tác giả: bquanman

image-20241019215932448

Chall cho ta 2 file:

  • file process dump
  • file pcapng lưu lượng mạng

1. Kiểm tra file process dump

Load vào windbg

Dùng command lm để check các module:

image-20241019220138144

Nhận thấy chỉ có module OneDrive là không có symbols.

Kiểm tra module này, bằng lệnh lmDvmOneDrive

image-20241019220239946

Thấy file thực thi được tải về từ Internet tại Downloads.

Địa chỉ trong memory từ 0x7ff620ae0000 đến 0x7ff620afe000

thực hiện dump đoạn memory này ra file bằng lệnh

.writemem C:\TEMP\OneDrive.dmp 00007ff6`20ae0000 00007ff6`20afe000

Tuy nhiên, báo lỗi không access được dữ liệu tại 0x7ff620afe000

image-20241019220535183

Mình mới thực hiện phân tích lại !analyze -v (không cần thiết)

Sau đó chỉ dump đến 0x7ff620afdf00, bỏ 0x100 bytes cuối đi (đoán)

.writemem C:\TEMP\OneDrive.dmp 00007ff6`20ae0000 00007ff6`20afdf00

Thì dump thành công, Windows Defender check và báo mã độc Havoc.C

image-20241019220802676

Tìm kiếm một hồi về các bài phân tích Havoc C2, mình tìm được 2 link này:

https://github.com/Immersive-Labs-Sec/HavocC2-Forensics

https://www.immersivelabs.com/blog/havoc-c2-framework-a-defensive-operators-guide/

và link tàu này:

https://www.51cto.com/article/767998.html

(Có sẵn PDF cùng folder)

Phát hiện, cấu trúc KEY_MAKER của Havoc C2 như sau:

signatures = {
    'havoc_key_marker': """rule havoc_aes_marker
                                {
                                strings:
                                  $AES_KEY_MARKER = { 00 00 ?? ?? de ad be ef ?? ?? ?? ?? 00 00 00 63 00 00 00 00 }
                                condition:
                                  $AES_KEY_MARKER
                                }"""
}

Đoạn code detect AES Key và IV, agent ID như sau:

 rules = yara.compile(sources = signatures)
 ....
 for offset, rule_name, _name, _value in layer.scan(context = self.context,
                                                             scanner = yarascan.YaraScanner(rules = rules),
                                                             sections = vadyarascan.VadYaraScan.get_vad_maps(proc)):

                if rule_name == 'havoc_aes_marker':
                    # Read 1024 bytes from the layer at the offset and try to parse out some values. 
                    raw_data = layer.read(offset, 1024, False)
                    vollog.debug(f'Found AES Key Marker at {hex(offset)} in {process_name}\n')
                    vollog.debug(f'Raw Data: {raw_data}\n')

                    agent_id = raw_data[8:12].hex()
                    vollog.debug(f'Agent ID: {agent_id}\n')
                    aes_key = raw_data[20:52].hex()
                    vollog.debug(f'AES Key: {aes_key}\n')
                    aes_iv = raw_data[52:68].hex()
                    vollog.debug(f'AES IV: {aes_iv}\n')
 

Có thể thấy AES Key ở offset [20:52], AES IV ở offset [52:68] và Agent ID ở [8:12] tại vị trí tìm ra signature.

Do đó, mình nhanh chóng thu được key, iv và agent id từ file dump process.

image-20241019222043248

Như vậy:

image-20241019222351896

Thu được:

agent id:
2a c0 84 1e

aes key: [20:52]
D4 DC 20 98 7E EC 20 02 E0 46 D0 D0 3C BC C2 9A 88 96 44 34 D0 42 90 12 66 BA 98 1C E0 48 98 1E

aes iv: [52:68]
DC DA C0 90 F6 5E A6 76 FC 72 8E 08 54 66 40 30

Như vậy, mình đã nghĩ đến đây là xong. Mình chỉ mất khoảng 1 tiếng để tìm được đến đây.

Với bài phân tích vừa rồi, mình đoán sẽ dùng AES decrypt giải mã pcapng để lấy flag.

Tuy nhiên, mọi chuyện không như là mơ.

2. Xử lý pcapng

Kiểm tra pcapng thì chỉ thấy có 2 IP 192.168.240.148 và 192.168.240.147.

Kiểm tra thì chỉ có 2 tcpstream là 0 và 1. là các request đến cổng 443 của IP:148. (attacker)

Như vậy, mình cần tìm các requests gửi dữ liệu lên máy chủ, decrypt là lấy được file.

Khó khăn từ đây (do mình dốt crypto :<)

Kiểm tra sơ sơ thì thấy có vài request POST send data rất lớn.

image-20241019222812163

Đến đây mình dùng Cyberchef để cố decrypt phần body request nhưng thử với tất cả các thuật toán đều không được, về sau phát hiện ra, Havoc dùng AES CTR mode.

Tuy nhiên, mình vẫn không decrypt được, mình có thử viết code python decrypt cũng không được. Mãi sau, mình mới đọc lại blog 51cto ở trên. Phát hiện phần body có cấu trúc. 20bytes đầu là các giá trị, sau đó là data bị mã hoá.

Data POST lên có cấu trúc như sau:

image-20241019223512913

Dó, lúc này mình mới nhận ra và bắt đầu đi lọc các POST request lớn, có Agent ID và check dữ liệu decrypt.

Mình thu được output command, khẳng định AES Key IV là đúng

image-20241019223631949

Sau đó mình tìm thấy một request có data decrypt có thứ rất quen thuộc, .rels và .xml. Với bản năng của 1 mal analysis, đây là docx mình cần!!!

image-20241019223758206

Mình thu được file docx sau khi chạy word recovery.

image-20241019223822777

flag 2:

Flag2: Th3_9r0unD_0b3y5_m3_0e2845b20c93546}

Mình bắt đầu hơi hụt hẫng, ủa flag1 đâu, hay trong request vẫn còn. Mình tiếp tục đi decrypt hết các POST data, thậm chí cả data trả về của Havoc C2 server ở IP:148.

Thu được, đoạn text flagpart1 ????

image-20241019224000465

Hay một số data có cấu trúc rất lạ, giống kiểu output của ascii graphic, mà mình không đoán ra ý nghĩa

image-20241019224110338

Data ec0 ec1 do server gửi đến

image-20241019224140615

image-20241019224159677

Nohope flag part 1 :<

Sau đó team có tìm thêm 1 số string trong file OneDrive.exe

image-20241019224232597

Nhưng có vẻ không khả quan lắm.

Cuối cùng mình định tạo lại lab Havoc nhưng đã quá muộn.

END GAME lần xxx :((((


Bonus, phần flagpart1, sau khi có WU của tác giả

Đúng như dự đoán, phần dữ liệu được server gửi đến máy nạn nhân sẽ là 1 object BOF để thực thi,

Hãy quan sát 1 response

image-20241025091533354

Như trên, khi server response theo cấu trúc chunk, ta sẽ chỉ quan tâm phần Chunk data.

phần Chunk Data này sẽ cấu trúc như sau:

12 bytes đầu (HEADER) | Sau là data

Trong HEADER: 2 bytes đầu là Command ID (ở Little edians) => 0x0A00 = 2560 => BOF objects

image-20241025092132656

Như vậy, decrypt ra sẽ được BOF object.

Tuy nhiên, BOF có signature là bắt đầu bằng bytes

0x64 0x86 cho 64 bit và 0x4C 0x01 (chữ dt và L.) như ảnh (Phần File Header của NTHeader)

image-20241025095220385

với 32bit

image-20241025095309081

Thì trong BOF sẽ như này

image-20241025095352467

Ném vào IDA, phân tích, bấm mặc định, nó sẽ ra được

image-20241025095431383

Như vậy, sau khi decrypt BOF bằng AES-CTR mode, ta sẽ phải xoá đi 16bytes đầu để bắt đầu bằng signature BOF.

Kiểm tra hết các BOF, thấy có BOF để thực thi adduser mà không cần dùng command adduser của windows. Đó là user flagpart1

Vì vậy, ta cần đi tìm data của câu lệnh này ở đâu trong BOF object này.

Phần ảo: Tìm data của BOF object này

Theo cấu trúc của havoc C2 BOF, thì các BOF sẽ được tạo sẵn , phần data sẽ nối ở phía sau BOF.

Nhưng các thức chúng được mã hoá AES lại khác nhau

như sau:

DataChunk = 12bytes HEADER + AES-CTF_Encrypt( 16bytes + BOF object ) + DATA_sau_BOF

Mở rộng nhanh, thực tế phần data sau BOF object có 12 bytes là: TaskID, Command,Executable, packed data length nên:

DATA_sau_BOF = 12 bytes + AES-CTF_Encrypt( Dữ liệu parametter của BOF )

Nghĩa phần data được mã hoá riêng rẽ chứ không mã hoá chung 1 lần với BOF object.

Mà AES-CTR mode sẽ mã hoá 1bytes thành 1 bytes (tương đương)

Nên chỉ cần lấy độ dài dữ liệu của data chunk post - độ dài BOF objects sau giải mã - 16bytes đầu

sẽ ra được độ dài phần data bị mã hoá.

Vậy làm sao biết đc BOF object dài bao nhiêu.

https://github.com/HavocFramework/Modules/blob/main/RemoteOps/bin/adduser.x64.o

Các BOF object là pre-built

Vì vậy, chỉ cần tải file adduser.x64.o cho khớp với BOF trong decrypted data, ta sẽ có được length.

image-20241025111130741

Ở đây, object BOF Adduser kết thúc ở length 3583, tận cùng là byte 0x00

Vì vậy, với phần data encrypted ở Data chunk

image-20241025111336351

Phần này cấu trúc như đã nói, toàn bộ Data Chunk có length 3776.

  • Xoá 12bytes đầu header Được BOF encrypted + data encrypted Tuy nhiên BOF encrypted này có chứa 16bytes đầu là bytes gì đó, trước khi đến được đoạn signature BOF.

  • Xoá 16bytes đầu của BOF để ra đc signature dt

  • Xoá tiếp 3583 bytes BOF object

  • Ta thu được phần data BOF encrypted.

    image-20241025114037572

    Tuy nhiên, phần data BOF encrypted này cũng có cấu trúc là 12 bytes: TaskID, Command,Executable, packed data length rồi mới đến AES-CTR_Encrypted(Data của BOF)

  • Xoá 12 bytes đầu

  • Thực hiện decrypt AES-CTR, Decode UTF-16 LE

Thu được đoạn bytes (153 bytes):

3b 53 9a a6 93 b6 31 3a cf 25 d6 fa bd b3 ac 98 
69 84 ad 7b 25 94 0e ab 5c 3c ec 4b da ea 98 e8 
5e b5 c2 5a 8e 37 fa f8 83 eb c4 34 c4 d2 9c e0 
67 a6 b5 c0 a3 98 57 3e 29 35 f9 aa 5d 25 1d 44 
4d 3e 8d 15 f8 a0 ba 5b 12 a5 55 55 f4 d9 d4 85 
b7 f4 1d 6d 8d 7b 4a b9 b0 ca 3e 4d 7b 45 75 4d 
ff fd 43 74 34 28 b9 d4 3e 14 1b b3 df 7b b6 7a 
3c 86 23 7f 82 12 04 a7 5e 62 14 00 00 00 13 d0 
c5 8f 13 00 00 00 64 09 97 a7 9e d9 31 8d f7 fd 
4d a6 8d be ad 98 0f 84 ad

Decrypt bằng AES-CTR và Decode UTF-16 LE:

image-20241025134833400

Vậy flag1 :

ASCIS{C@nt_k3Ep_m3_1n_7hE_9r0uNd_