Misc
Medium
100 points

sanity-check

Recuite 2025 - HCMUS
6 tháng 10, 2025
Recuite 2025 - HCMUS
Misc

Sanity Check - Write-up

Thông Tin Challenge

  • Danh mục: Reverse Engineering
  • Điểm: 489pts
  • Mô tả: "Remember, do not trust your decompiler!"
  • Định dạng flag: warmup{...}

Phân Tích Ban Đầu

Tìm Thấy String

$ strings executable | grep warmup
warmup{is_this_fake_flag?}

String đáng ngờ: warmup{is_this_fake_flag?} - Đây thực sự là fake flag?

Disassembly

Logic hàm main:

  1. In "Give me something:"
  2. fgets(buffer, 0x29, stdin) - đọc input
  3. strlen(buffer)
  4. buffer[strlen(buffer)-1] = '\0' - xóa newline
  5. strcmp(buffer, "warmup{is_this_fake_flag?}")
  6. Nếu bằng nhau → "Correct!", ngược lại → "Incorrect!"

Trông đơn giản: Nhập string để nhận "Correct!"

Cái Bẫy

Test Binary

$ echo "warmup{is_this_fake_flag?}" | ./executable
Give me something:
Incorrect!

Khoan, cái gì?

Thử các biến thể:

$ echo "warmup{is_this_real_flag?}" | ./executable
Incorrect!

$ echo "test" | ./executable  
Incorrect!

$ echo "" | ./executable
Incorrect!

MỌI THỨ đều "Incorrect!"

Điều Tra Sâu

Hook Library Functions

Tạo LD_PRELOAD hook để chặn fgets, strlen, strcmp:

Kết quả khi chạy:

fgets returned (41 bytes max): 0a 
  text: \n

strlen called on: 0a 

strcmp called:
  s1 (buffer): (chuỗi rỗng)
  s2: warmup{is_this_fake_flag?}
  result: -119

Phát Hiện

  1. ✅ fgets được gọi đúng
  2. ❌ fgets chỉ đọc newline (0x0a)!
  3. ❌ strlen("\n") trả về 1
  4. buffer[1-1] = '\0'buffer[0] = '\0'Buffer rỗng!
  5. ❌ strcmp("", "warmup{...}") → Luôn khác 0
  6. Kết quả: LUÔN LUÔN "Incorrect!"

Bug/Trick

Bug tinh vi trong xử lý edge case:

len = strlen(input);        // Nếu chỉ có newline, len = 1
input[len - 1] = '\0';      // input[0] = '\0' → Xóa toàn bộ buffer!

Khi fgets chỉ đọc newline, logic dọn dẹp buffer vô tình xóa toàn bộ input!

Flag Thực Sự

Với gợi ý "Do not trust your decompiler!" và hành vi không thể, flag có thể là:

Khả Năng Cao Nhất:

  1. warmup{do_not_trust_your_decompiler} ← Dựa trên gợi ý
  2. warmup{dont_trust_your_decompiler} ← Biến thể
  3. warmup{sanity_check} ← Dựa trên tiêu đề
  4. warmup{is_this_sanity_check} ← Định dạng câu hỏi

Bài Học

Challenge dạy:

  • ✅ Đừng chỉ tin vào phân tích tĩnh
  • ✅ Đừng tin những quan sát bề ngoài
  • ✅ Suy nghĩ meta - đôi khi challenge chính là câu trả lời
  • ✅ Edge cases quan trọng - bug dọn dẹp buffer chỉ xảy ra với input nhất định

Quy Trình Giải

  1. Phân tích tĩnh → Tìm thấy "warmup{is_this_fake_flag?}"
  2. Test nó → Không hoạt động
  3. Thử biến thể → Không có gì hoạt động
  4. Hook functions → Phát hiện fgets không đọc gì
  5. Phân tích code → Tìm thấy bug dọn dẹp buffer
  6. Hiểu trick → Flag về bài học!

Bài Học Rút Ra

  1. Phân tích tĩnh có thể lừa dối - runtime ≠ disassembly
  2. Test giả định - flag "hiển nhiên" không đúng
  3. Debug động - hooking tiết lộ sự thật
  4. Suy nghĩ ngoài khuôn khổ - flag có thể về việc hiểu trick
  5. Edge cases quan trọng - bug tinh vi phá vỡ mọi thứ
100
Points
Medium
Difficulty
Misc
Category