reversing.kr
Vậy là mình đã kết thúc năm 3 đại học. Đúng là thời gian không chờ đợi một ai …
reversing.kr
1. Replace ~ 150 points
1.1. Overview
Một bài yêu cầu nhập password chính xác. Khi click check, chương trình chạy một lúc và tự thoát ngay sau đó.

1.2. Static Analysis
Đây là mã giả của chương trình khi được phân tích trong IDAPRO32.

Lời gọi hàm sub_40466F()
dẫn tới lệnh call $+5
rất lạ. Mình đặt breakpoint ngay chỗ này và debug để xem nó đang làm gì.
1.3. Dynamic Analysis
Quan sát kỹ càng, nhận thấy rằng giá trị dword_4084D0
chính là giá trị hexacimal của input.

Tiếp tục debug sâu vào từng dòng lệnh, giá trị dword_4084D0
lần lượt được cộng thêm các giá trị: 2, 0x601605C7, 2. Chạy hết chương trình, xuất hiện cửa sổ lỗi như sau:

Instruction tham chiếu một địa chỉ không hợp lệ 0x60160A9D. Đây cũng chính là kết quả của dword_4084D0
|
|
1.4. Solving
Vậy nhiệm vụ lúc này là chỉ cần đưa dword_4084D0
trỏ về đoạn code correct
. Giá trị input thỏa mãn là:
|
|
Do kết quả âm nên phải & 0xFFFFFFFF
2. ImagePrc ~ 120 points
2.1. Overview
Chương trình cho người chơi vẽ hình bất kỳ và có nút check kết quả.

Với dạng bài này, khả năng cao chương trình sẽ so sánh hình chúng ta vẽ với dữ liệu đã có sẵn.
2.2. Static Analysis
Chương trình đăng ký lớp cửa sổ với các thuộc tính: Background, Cursor, Icon, … Sau đó tính toán vị trí để cửa sổ ở giữa màn hình, tạo cửa sổ và hiển thị.

Hàm xử lý logic chính của chương trình chính là sub_401130()
. Trước tiên, nó tạo một bitmap có kích thước 200x150.

Tiếp theo, gọi các hàm FindResourceA()
, LoadResource()
, LockResource()
để tải tài nguyên có sẵn lên rồi đem đi so sánh với dữ liệu mình vẽ.

2.3. Solving
Sử dụng tool Paint, tạo ra một bức ảnh có kích thước 200x150, lưu dưới dạng BMP picture.

Copy toàn bộ tài nguyên bằng tool Resource Hacker, tiếp tục dùng tool HxD để paste chúng vào ảnh ở trên. Phần được select là phần được giữ lại của BMP picture.

Save lại và mở ra, ta có được đáp án thử thách.

3. Music Player ~ 150 points
3.1. Overview
Chạy một đoạn nhạc mp3 có độ dài > 60s, một message box hiện lên với nội dung khá khó hiểu “????”.

Thử thách còn cung cấp một file ReadMe.txt
với nội dung:
|
|
Đọc qua, chúng ta có thể hình dung được nhiệm vụ sẽ phải đi bypass những đoạn check “1-minute” có trong chương trình.
3.2. Static Analysis
Chương trình được viết bởi ngôn ngữ Visual Basic, thực sự các hàm được IDAPRO tạo ra đều không đem lại giá trị quá nhiều. Mình bắt đầu đi tìm những đoạn code có liên quan tới việc hiển thị Message Box.
Kiểm tra ở tab Import, ta thấy __imp_rtcMsgBox
giúp gợi nhớ tới Message Box và được gọi ở 2 hàm sub_4038D0()
và sub_4044C0()
.

Ở sub_4038D0()
, hàm __imp_rtcMsgBox
được gọi khá nhiều nhưng mình không tìm thấy đoạn code nào có kiểm tra độ dài thời gian file mp3.

Ở sub_4044C0
, ta tìm được đoạn check thời gian ngay tại đây

Chính đoạn check đó sẽ đưa chương trình vào nhánh sai (màu đỏ). Vì vậy, tôi sẽ dùng plugin KeyPatch để thay đổi từ lệnh jl
thành jmp
(nhảy trực tiếp) tới vị trí 0x004045FE.

Apply patch, save và chạy lại chương trình. Một lỗi khác lại xuất hiện “Run-time error”.

Sau khi quan sát toàn bộ các hàm bên nhánh đúng, tôi đã đi hỏi ChatGPT về các hàm có thể gây lỗi. Tôi đã quyết định sửa jge
thành jmp
để nó bỏ qua hàm __imp___vbaHresultCheckObj()
đầu tiên.

Lưu lại chương trình, ta thu được flag ở thanh tiêu đề chương trình.

4. Easy Crack ~ 100 points
Hàm check input rất rõ ràng như sau

Ghép nối các đoạn check lại, ta thu được flag “Ea5yR3versing”.
5. Position ~ 160 points
5.1. Overview
Chương trình là một bài keygen thuần túy.

Khi chạy chương trình, máy mình thông báo thiếu msvcr100.dll và mfc100u.dll. Lên mạng download các dll còn thiếu về rồi paste vào thư mục challenge để fix các lỗi.
Ngoài ra, còn có một file README.txt.
có nội dung như sau:
|
|
Từ đó, ta có thể hình dung được phải đi tìm name
có tận cùng là chữ p
và thỏa mãn serial bằng 76876-77776
.
5.2. Static Analysis
Sau khi tìm kiếm các hàm trong IDAPRO, ta dễ dàng nhận biết được sub_DD1740()
chính là hàm check input.

Về cơ bản, hàm này sẽ
- Kiểm tra độ dài
name
có bằng 4 hay không? - Kiểm tra các ký tự trong
name
có thuộc khoảng [a-z] không? - Kiểm tra các ký tự trong
name
có trùng lặp hay không? - Kiểm tra độ dài
serial
có bằng 11 hay không? Ký tự thứ 6 (serial[5]) có phải là dấu-
hay không? - Tạo ra các giá trị trung gian dựa trên biến
name
rồi đem đi so sánh vớiserial
.
5.3. Solving
Do name
có 4 ký tự, ký tự cuối cùng là p
nên ta chỉ cần brute-force 3 ký tự còn lại là tìm ra kết quả.
|
|
6. Direct3D FPS ~ 140 points
6.1. Overview
Một tựa game bắn súng fps. Nhiệm vụ của player sẽ phải đi bắn chết toàn bộ quái đang xuất hiện. Mình có thử bắn một vài con quái nhưng tất cả đều không khả thi.

6.2. Static Analysis
Sau khi trace các hàm với string “Game Clear!”, ta đi tới được hàm sub_4039C0()
.

Chuỗi szCkfkbuliLEEZF
được chú ý tới vì đây là thông điệp được hiển thị bởi Message Box. Có vẻ chuỗi đã bị mã hóa nên ta cần xref để xem chuỗi này còn được xuất hiện ở đoạn code nào nữa.

Tại hàm sub_403400()
, chuỗi szCkfkbuliLEEZF
được xor với các giá trị ở mảng byte_409184[]
.

6.2. Dynamic Analysis
Bật debug lên để lấy các giá trị của mảng byte_409184[]
. Nhìn vào kết quả, có thể dự đoán được giá trị của mảng sẽ là: 0, 4, 8, 12, 16, …

Khi debug động, mảng được xor là
byte_389184[]
chứ lại không phảibyte_409184[]
. Mình không rõ là tại sao lại bị thay đổi như vậy nhưng không sao cả, chuỗiszCkfkbuliLEEZF
vẫn được xor với 1 mảng như đã phân tích ban đầu.
6.3. Solving
Dump toàn bộ giá trị của chuỗi szCkfkbuliLEEZF
và xor ngược lại với mảng ở trên sẽ thu được flag bài toán.
|
|