Tiếp tục là 1 task của a mochi và bài lần này không khó nhưng nó khá là thú vị ở cách mình tiếp cận. Đây sẽ là wu nhỏ nói sơ về quá trình mình làm trong lúc mình không có bất kì gợi ý nào.
Okay như mọi bài khác, mình check xem nó là file gì:
Mình thấy nó khá là bình thường, thử chạy và sau đó load vào IDA, nó là Password checker:
Đây là hàm main và nó sử dụng exe_start
, bên trong nó tiếp tục sử dụng execute
và …
Vấn đề ở đây là mình sẽ rất khó tìm được đoạn check nếu cứ trace mãi như thế.
Hướng tiếp cận này mình thấy không khả thi và mình chắc chắn đây khong phải là intended.
Okay, tới đây mình chỉ mới nghi ngờ đó là 1 file dotnet. Nhưng cho tới khi mình load vào dnspy thì ko có gì đặt biệt.
Quay trở lại với IDA (hơi oằn tà là vằn), thì mình nhận ra mình có thể dùng attach process trong lúc chương trình đợi mình nhập password sau đó mình có thể quay về user code và tiếp tục vừa debug vừa phân tích:
Mình theo hướng này một lúc và mình thấy khá là ổn, tuy nhiên có 1 vài lưu ý cho các bạn mới:
Mặc định khi attach vào 1 process đang đợi input, nó sẽ brk tại lib, nên là các bạn cần chọn Thread về Vault.exe và bấm (Ctrl + F7, step out) cho nó chạy tiếp đoạn code sau khi nhập input.
Usercode:
Mình debug khá là bình thường, thậm chí mình còn thấy nó gọi 1 hàm checkinput của mình sau đó test eax, eax
để check return value, nếu không đúng thì nó sẽ jump tới nhánh in ra There's no way that's correct!
, và ngược lại.
Tuy nhiên, trong lúc debug mình thấy có 1 vài hàm có tên khá là lạ:
Search thử thì nó là của .NET, tới đây mình biết mình thiếu cái gì rồi, mình đổi hướng ngay lập tức.
Nguyên nhân chính mà dnspy không nhận diện được .NET là do đây là .NET embbeded, nên mình phải dùng dotpeek để xem, đây cũng không phải là lần đầu mình gặp dạng này nhưng mà lần cuối là cách đây khá lâu nên mình không nhớ rõ:V
Okay, có dotpeek, mọi thứ clear hơn rất nhiều:
Tuy nhiên nếu cách bạn chỉ xem ở dotpeek và rev thì cũng hơi khó bởi vì vốn dĩ đây là obfuscated .NET. Cho nên mình tìm cách extract file này ra từ file gốc (Vault.exe).
Thật ra ban đầu mình copy ra ngoài xong đổi tên lại và refactor lại cho gọn (bởi vì hàm khá ngắn), sau đó mọi thứ khá là clear, chỉ là aes đơn giản:
Tuy nhiên mình lay hoay mãi mơi lấy được mấy cái bytes ra bởi vì mình không biết nó để ở đâu.
Tiện thể mình sẽ nói luôn cách deobfuscate cái này:
Okay đây là file .NET cần tìm, giờ sẽ lấy cái này ra và ghi vào 1 file.
Sau đó mình dùng de4dot (.NET deobfuscate khá là hiệu quả) để deobfuscate file này:
(Từ wtf.dll -> wtf-cleaned.dll)
Load file cleaned vào dnspy:
Very clean…
Nếu cách bạn rev thì sẽ thấy nó load 3 bytes array từ class5
1 là dòng chữ Checking...
11 kí tự
64 bytes của encrypted flag
16 bytes của aes key.
Tới đây thì mình dựa trên File offset của nó và lấy ra.
Full script:
from Crypto.Cipher import AES
with open('wtf-cleaned.dll','rb') as f:
f.seek(0x4a0)
encrypted = f.read(64)
f.seek(0x4e0)
key = f.read(16)
aes = AES.new(key,AES.MODE_ECB)
print(aes.decrypt(encrypted)) #b'MetaCTF{1ac1f0606afb5567d1a25d70f2f8fd809427ff083}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e'
## extract
# with open('Vault.exe','rb') as f:
# f.seek(0x3ef0000)
# d = f.read()
# with open('wtf.exe','wb') as wf:
# wf.write(d)