14 May 2017
•
Tutorials
WhizKID's Crackme Challenge 8
Hôm nay, tôi sẽ hướng dẫn một vài phương pháp để giải một bài crackme. Tôi sử dụng WhizKID's Crackme Challenge 8 (HERE). Tôi sử dụng máy ảo VMware và thử chạy crackme này. Crackme hoạt động hoàn toàn bình thường.
Thử kiểm tra ứng dụng với chương trình PEiD, ta có kết quả như sau:
Chương trình này được viết bằng Visual Basic. Để đơn giản, tôi sử dụng VB Decompiler thử dịch ngược chương trình. Thử mở form của chương trình, có thể nhận thấy chương trình có 7 nút "Check key" khác nhau nhưng được đặt ở cùng một vị trí. Mỗi khi lựa chọn một option( Easy serial, Harder Serial, ...) thì nút tương ứng sẽ được hiển thị ( thuộc tính Visible được thiết lập bằng True).
Easy Serial
Khi chọn tùy chọn "Easy Serial", chương trình sẽ hiển thị nút ứng với Command1.
Mở đoạn code tương ứng với "Easy Serial", có thể nhận thấy khi nhập serial là 23784628356267, chương trình sẽ hiển thị "Easy Serial Part Completed..." và qua được thử thách này.
Private Sub Command1_Click() '40E890
Dim var_1C As Variant
loc_0040E8B5: var_8 = &H401188
loc_0040E8F8: Set var_1C = Me
loc_0040E907: var_18 = Text1.Text
loc_0040E911: If var_18 >= 0 Then GoTo loc_0040E929
loc_0040E962: If (var_18 = "23784628356267") = 0 Then GoTo loc_0040EA0D
loc_0040E9A9: var_18 = Me.BackColor
loc_0040E9CA: var_4C = 10
loc_0040E9D0: var_54 = 80020004h
loc_0040E9D3: var_34 = var_18
loc_0040E9D6: var_44 = 80020004h
loc_0040E9E7: var_3C = 8
loc_0040E9EA: var_64 = "Failed Easy Serial Part..."
loc_0040E9F1: var_6C = 8
loc_0040E9F4: var_2C = "Failed Easy Serial Part..."
loc_0040EA08: GoTo loc_0040EAAD
loc_0040EA4E: var_18 = Me.BackColor
loc_0040EA6C: var_5C = 10
loc_0040EA6F: var_4C = 10
loc_0040EA75: var_54 = 80020004h
loc_0040EA78: var_34 = var_18
loc_0040EA7B: var_44 = 80020004h
loc_0040EA8C: var_3C = 8
loc_0040EA8F: var_64 = "Easy Serial Part Completed..."
loc_0040EA96: var_6C = 8
loc_0040EAAD:
loc_0040EAB1: MsgBox "Easy Serial Part Completed...", 64, var_18
loc_0040EAE3: GoTo loc_0040EB13
loc_0040EB12: Exit Sub
loc_0040EB13: Exit Sub
End Sub
Harder Serial
Tương tự phần trước, phần 2 cũng so sánh chuỗi nhập vào với một xâu cố định. Nhưng khác so với phần trước, xâu cố định phải tính toán qua hàm _vbaStrR8 . Để đơn giản, có thể sử dụng OllyDbg để đặt breakpoint tại địa chỉ 0x40EC42.
Có thể thấy serial phù hợp là ADUJSDMD8387079498SOPEMNSD
Name/Serial
Phần này khó hơn các phần trước do cần 2 yếu tố để xác thực. Chương trình yêu cầu người dùng nhập tên và serial, Serial đúng sẽ được tính toán dựa trên name. Kiểm tra Command3:
Có thể thấy rằng serial được tính thông qua hàm MakeKey ( địa chỉ 0x0040EE80) sau đó tính toán và trả về một số tương ứng. số này là serial. VB Decompiler gần như không có tác dụng gì khi decompiler hàm này. Kết quả sai hoàn toàn.
Trong tình huống này, tôi sử dụng IDA. Tôi đọc nội dung của hàm MakeKey và hiểu thuật toán sinh serial của hàm. Hàm này có thể viết một đoạn giả mã như sau:
def serial(name):
return ((ord(name[-1]) * 13 + (483 / 3)) ** 2) * 154
Matrix Part
Bài này đơn giản hơn, có lẽ do có bug. Chỉ cần tick tất cả các checkbox là xong.
Key File
Phần này thì đơn giản hơn, KeyFile ứng với Option4. Mở nội dung của hàm này bằng VB decompiler thì sẽ không thấy phần kiểm tra file để active chương trình đâu cả. Vấn đề này luôn xảy ra do VB Decompiler có lúc sai. Chúng ta xem kĩ hàm này bằng IDA. Địa chỉ hàm là 0x4118A0:
Sau khi kiểm tra hàm một lượt, tôi phát hiện hàm gọi tới địa chỉ 0x40F4B0 để check file.
Phân tích hàm này bằng VB Decompiler, Có thể thấy rằng: Nếu ta đặt 1 file cùng thư mục với Crackme và có tên là wk.dat, nội dung của file là "Easy, eh?", ta sẽ qua được phần kiểm tra.
NAG
Phần này có lẽ nên patch chương trình, vì nó không có gì thú vị cả. Nhảy tới địa chỉ 0x00412B5E, và patch các lệnh NOP mã 0x90 tới địa chỉ 0x412B6F. Để đơn giản, có thể convert địa chỉ 0x00412B5E thành offset trên file : 0x00012B5E và patch 18 byte NOP.
cripple
Phần này cũng chả có gì để bàn. Nút disable thực chất chỉ hiển thị đúng một messagebox có chữ "Cripple Part Completed..."
07 May 2017
•
Tutorials
Trong khi phân tích hành vi của mã độc (malware), người phân tích luôn gặp một số tình huống khó chịu như: mã độc cần có kết nối tới server điều khiển, hoặc mã độc sẽ kiểm tra kết nối tới một số server trước khi thực hiện hành vi độc hại. Việc kiểm tra những đoạn mã liên quan tới kết nối và giao tiếp với server thật sự rất khó khăn. Do đó, tôi nghĩ tới một phương pháp có thể giám sát và kiểm tra tất cả hành vi của mã độc mà có dữ liệu được gửi tới server và đưa chúng vào database. Bằng phương pháp này, chúng ta có thể biết được chính xác thứ malware gửi ra ngoài nhưng không cần thiết phải dịch ngược (reverse engineering) quá nhiều.
Cài đặt môi trường phân tích
Tôi dùng VMware để xây dựng hệ thống phân tích của mình. VirtualBox và các loại máy ảo khác có lẽ cùng dùng được. Cần tối thiểu hai máy tính, một máy windows và một máy linux. Hai máy này kết nối được với nhau.
Tôi tạo thêm một card mạng ảo để 2 máy có thể giao tiếp với nhau qua một mạng ảo:
Tôi thêm card mạng ảo đó vào cả hai máy.
Cài đặt gateway
Tôi sử dụng hệ điều hành Ubuntu và cấu hình nó thành một gateway. Có thể sử dụng bất cứ một hệ điều hành nào khác thuộc họ unix cũng được: Centos,Debian,...Đâykhông phải là một gateway thật sự nhưng nó có nhiệm vụ nhận mọi gói tin được gửi tới mọi địa chỉ có thể được.
Tôi có 2 card mạng, ens33 để tôi có thể sử dụng SSH và ens38 để nhận các gói tin từ máy tính phân tích malware gửi tới.
root@ubuntu:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:b5:d2:bf brd ff:ff:ff:ff:ff:ff
inet 192.168.66.201/24 brd 192.168.66.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feb5:d2bf/64 scope link
valid_lft forever preferred_lft forever
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:b5:d2:c9 brd ff:ff:ff:ff:ff:ff
inet 192.168.171.10/24 brd 192.168.171.255 scope global ens38
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feb5:d2c9/64 scope link
valid_lft forever preferred_lft forever
Tôi cấu hình iptables để chuyển hướng toàn bộ kết nối từ bất cứ một cổng nào tới một cổng cố định, ví dụ như 9999.
iptables -t nat -A PREROUTING -i ens38 -p tcp --dport 1:65535 -j LOG --log-prefix "INPUT:SINKHOLE:" --log-level 6
iptables -t nat -A PREROUTING -i ens38 -p tcp --dport 1:65535 -j REDIRECT --to-ports 9999
Sau đó, tôi lại chuyển toàn bộ log của iptables về server của tôi để xử lý ở bước sau. Tôi tạo một file mới trong thư mục /etc/rsyslog.d/. Làm giống nhưu ví dụ trong file 20-ufw.conf, tôi tạo một file có tên /etc/rsyslog.d/00-sinkhole.conf và chứa nội dung như sau:
:msg, contains, "INPUT:SINKHOLE:" @@127.0.0.1:10514
& ~
lưu ý rằng tên file khá quan trọng, do hệ thống sẽ sắp xếp các luật trong file theo tên file. Với tên file bắt đầu là 00, hệ thống sẽ lấy luật trong file này và đặt trước luật trong tên file bắt đầu là 01.
Syslog server, sinkhole server
Trong server này, tôi tích hợp 3 module khác nhau, được xây dựng dựa trên thư viện twisted.
- DNSServerFactory: một dns server và luôn trả về địa chỉ của sinkhole server cho bất cứ domain nào. Truy vấn DNS sẽ được lưu vào database.
- SyslogdProtocol: một server có nhiệm vụ nhận và xử lý log từ rsyslog gửi tới. Đó là các log sinh ra trong quá trình chuyển hướng kết nối của iptables. Kết quả là địa chỉ IP và cổng khởi tạo kết nối sẽ được lưu lại. Bằng cách này, ta có thể biết chính xác client nào gửi dữ liệu gì.
- SinkholeServer: một server có nhiệm vụ nhận tất cả dữ liệu mà malware gửi tới và ghi vào database.
- DatabaseConnector: nhằm giao tiếp với cơ sở dữ liệu mysql.
Tôi cài đặt thêm một số gói cần thiết trước khi chạy server:
apt-get install python python-dev python-pip libmysqlclient-dev mysql-client
pip install twisted MySQL-python
Sau đó, chúng ta chạy sinkhole server (sinkhole.py) và kiểm tra database. Trong lần chạy đầu tiên, bạn nên có tham số -i để khởi tạo database:
python sinkhole.py -i
Cuối cùng, tôi khởi dộng lại dịch vụ rsyslog. rsyslog sẽ chuyển mọi dòng log có chứa "INPUT:SINKHOLE:" tới server của tôi.
service rsyslog restart
Lưu ý: Vì cổng 53 là một "privileged" port, có nghĩa là bạn cần chạy server với quyền root thì mới có thể lắng nghe ở cổng 53. Nếu không muốn dùng quyền root, bạn nên để cổng DNS là một cổng khác và dùng iptables để chuyển hướng kết nối.
Kết quả
Tôi tiến hành cấu hình địa chỉ IP trên máy windows như sau:
Và tôi dùng một công cụ đơn giản để gửi một request tới địa chỉ google.com:80. Có thể dùng nc nhưng tôi lại thích màu mè.
Sau đó, kiểm tra trong cơ sở dữ liệu:
Bạn có thể thấy chúng ta nhận được lệnh truy vấn dns để phân giải tên miền google.com
Sau đó là một kết nối được mở tới server giả của tôi:
Cuối cùng là nội dung mà client đã gửi đi Hello, World!:
Code của dự án: https://github.com/quangnh89/sinkhole-gateway
Kết luận
Bài này viết đã cho các bạn một chút hình dung về phương pháp phân tích hành vi độc hại của mã độc. Bạn có thể cài đặt một phòng lab nhỏ ở nhà để tự minh thử nghiệm. Trong thời gian tới, tôi sẽ viết một số bài viết liên quan tới các kinh nghiệm trong việc xử lý những tình huống mã độc cụ thể trong thực tế, cũng như cung cấp một bức tranh toàn diện hơn về những hành vi thực sự của mã độc và cách để giảm thiểu chúng.
Tham chiếu
https://superuser.com/questions/440324/iptables-how-to-forward-all-external-ports-to-one-local-port
http://fibrevillage.com/sysadmin/202-enable-linux-iptables-logging
https://askubuntu.com/questions/348439/where-can-i-find-the-iptables-log-file-and-how-can-i-change-its-location
http://stackoverflow.com/questions/37034439/rsyslog-filtering-and-forwarding
http://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged-ports-on-linux