wannaShare | Writeup Google Capture The Flag 2021 | WEATHER – Reversing

PHAPHA_JIàN
14:36 21/07/2021

Nhóm Wanna.One chia sẻ một số Challenges giải được và việc chia sẻ writeup nhằm mục đích giao lưu học thuật. Mọi đóng-góp ý-kiến bọn mình luôn-luôn tiếp nhận qua mail: wannaone.uit@gmail.com

Mochi Nishi - PwN3v3rY7h1nG

Challenge

Entry point

File: weather

Disclaimer:

Bài này lúc thi mình không giải ra, vì lúc đầu mình đã có một vài nhận xét sai nên nghĩ rằng không làm được. Nhưng trước khi kết thúc kì thi khoảng 6 tiếng thì mình có xem lại bài và phát hiện là những nhận xét của mình có phần sai sót. Sau khi đánh giải lại thì mình thấy mình có thể làm được bài này, nhưng không còn thời gian để giải trong lúc thi nữa. Bài này mình giải được sau khi thi 2 ngày, nhưng mình khá tự hào vì đã tự giải quyết nó mà không có sự trợ giúp từ bên ngoài.

Solve:

Bài này đòi hỏi một vài kiến thức khá mới lạ so với những WriteUp trước đó mình viết, nên mình sẽ nói về những kiến thức đó trong bài này:

Hàm init

Nếu như chúng ta để ý hàm __libc_start_main() thì ngoài trừ tham số là hàm main, còn có một hàm đáng được quan tâm là hàm init.
Hàm init là một constructor trước khi vô hàm main. Hay nói nôm na dễ hiểu là hàm init sẽ được chạy đầu tiên rồi sau đó mới đến hàm main.
Như vậy chuyện tác giả có thể giấu code trong hàm init là một điều hoàn toàn khả thi. Và trong bài này tác giả đã làm như thế. Ta thử xem sơ qua hàm init:

Entry point

Đây là một câu trúc chung của hàm init trong các chương trình ELF. Trong hình ta thấy có biến funcs_2701. Đó là biến con trỏ, sẽ trỏ tới các chương trình con nó sẽ gọi để khởi tạo chương trình. Ta vô xem thử thì thấy có 2 chương trình con:

Entry point

Thường thì chương trình đầu tiên là của hệ thống nên ta không quan tâm. Nhưng chương trình con thứ 2 (nếu xuất hiện) thường sẽ là của tác giả, nên ta vô xem hàm này:

Entry point

Và ... có một đống hàm register_printf_function...

Custom printf

Hàm printf được dùng để xuất kết quả ra chương trình, tuy nhiên hàm đòi hỏi một tham số khá quan trọng, đó là tham số format, mính sẽ không nói chi tiết printf hoạt động như thế nào, các bạn có thể lên google tra thử.
Thì như tiêu đề, tham số format hoàn toàn có thể custom được, hay nói cách khác, ta có thể tạo ra một (format) mới theo ý của riêng ta.
Để giúp đỡ chúng ta trong việc tạo format mới, hàm register_printf_function được ra đời. Lên mạng đọc về hàm này thì mình sẽ tóm tắt lại một số điều quan trọng của hàm như sau:

Entry point

Ở hàm này, nếu như mình thực hiện lệnh printf('%W'); thì hàm func sẽ được gọi để xử lí chương trình.Chi tiết các bạn có thể tham khảo ở https://www.gnu.org/software/libc/manual/html_node/Registering-New-Conversions.html

Ok, giờ là chương trình chính:

Entry point

Entry point

Mình để ý ngay đến dòng cuối, nó sẽ in ra flag tuỳ vào input ta nhập. Mình xem thử hàm xử lí foramt %F

Entry point

Nó sẽ gọi cho %C, ta xem tiếp %C nó làm gì:

Entry point

Hmmmmmm, nhìn khá phức tạp. Nếu như tham khảo tài liệu kĩ hơn thì ta sẽ hiểu ngoài format ra ta còn có những tham số truyền vào format, ví dụ như %+12.45llF. Ở đây có 4 phần: Dấu +, số 12, số 45 và kí hiệu ll
Những phần này sẽ quyết định các tham số và 'opcode' của chương trình. Đúng vậy, đây là một bài Virtual Machine.Lúc này mình debug để hiểu thêm và phát hiện có 3 phase chính:

Bài này mình có viết script để dịch opcode cho dễ hiểu, nhưng script mình viết chỉ có một mình bản thân mình hiểu nên mình không dám đưa script lên :p, tuy nhiên script không quá khó, các bạn có thể debug để hiểu thêm và viết script cho bản thân.
Mình đã nhảy sang Phase 3 để mình tìm các tham số và viết một chương trình để decrypt lại tìm input phù hợp:

script.py

li = [161, 51, 163, 51, 173, 51, 185, 51, 193, 51, 203, 51, 211, 51, 235, 51, 241, 51, 253, 51, 1, 52, 15, 52, 19, 52, 25, 52, 27, 52, 55, 52, 69, 52, 85, 52, 87, 52, 99, 52, 105, 52, 109, 52, 129, 52, 139, 52, 145, 52, 151, 52, 157, 52, 165, 52, 175, 52, 187, 52, 201, 52, 211, 52, 225, 52, 241, 52, 255, 52, 9, 53, 23, 53, 29, 53]char = [0xf5, 0xcc, 0xcf, 0xf9, 0xa9, 0xc4, 0xa5, 0x8a, 0xa3, 0xa0, 0x57, 0x6f, 0x88, 0x86, 0x79, 0x79, 0x48, 0x15, 0x53, 0xd, 0x31, 0x28, 0xf6, 0xe6, 0x15, 0x2, 0x68, 0xe8]import stringfor i in range(len(char)):    e = li[i * 2]    cou = 0    if (i != 0):        num = i + 1        cou = 0        while (num != 1):            cou += 1            if (num % 2 == 0): num //= 2            else: num = (num * 3) + 1    val = (char[i] - cou) & 255    val ^= e    print(chr(val), end = "")print()

Entry point

Đưa kết quả vào chương trình:

Entry point

TIN LIÊN QUAN
✨ Bạn là sinh viên mới vào trường, bạn có niềm đam mê đặc biệt đối với bảo mật và an ninh mạng, bạn muốn thử sức mình với những thử thách khó nhằn, vậy thì đây là cuộc thi dành cho bạn. 🔥 𝐖𝐀𝐍𝐍𝐀𝐆𝐀𝐌𝐄 𝐅𝐑𝐄𝐒𝐇𝐌𝐀𝐍 𝟐𝟎𝟐𝟑 là một cuộc...
Chào các bạn yêu thích nghiên cứu và công nghệ thông tin! Sau sự thành công của WannaResearch Episode 06, chúng tôi xin trân trọng thông báo về sự trở lại của chuỗi sự kiện nghiên cứu uy tín với Episode 07: "Audio Deepfake Detection." Buổi seminar này sẽ mang...
CLB An toàn Thông tin Wanna.W^n chia sẻ một số Challenges giải được và việc chia sẻ writeup nhằm mục đích giao lưu học thuật. Mọi đóng-góp ý-kiến bọn mình luôn-luôn tiếp nhận qua mail: wannaone.uit@gmail.com hoặc inseclab@uit.edu.vn và fanpage: fb.com/inseclab Cám ơn các thành viên Wanna.W^N @InSecLab đã đóng...