SECATHON 2018 – RVZT

Khoan hay nhắc đến tên đề bài này có nghĩa gì mà xem nó chạy ra cái gì.

secathon2018_RVZT_0

Chúng ta đi vào phân tích file ELF này qua IDA đã xem nó là gì. Flag được lưu trong mảng ptr

secathon2018_RVZT_1.png

Sau khi nhập liệu vào ptr, thực hiện một chuỗi các hàm kiểm tra với Flag. Đầu tiên Flag phải có 26 ký tự.

Hàm tạm đặt tên là Validate() sẽ kiểm tra giá trị một số ký tự thỏa mã các điều kiện như: Là chữ số, là chữ cái, là chữ viết thường, ….

secathon2018_RVZT_2.png

          Ta suy ra:

          Ptr[0->7] là chữ cái                                     Ptr[8] ko phải số hoặc chữ

          Ptr[9] là chữ hoa                                         Ptr[10] là chữ số

          Ptr[11] là chữ hoa                                       Ptr[12] là chữ cái

          Ptr[13] là chữ số                                         Prt[14] là chữ số

          Ptr[15] là chữ cái                                        Ptr[16] là chữ hoa

          Ptr[17] là chữ cái                                        Ptr[18] là chữ số

          Ptr[19] là chữ hoa                                       Ptr[20] là chữ số

          Ptr[21] là chữ số

          Ta gọi đây là điều kiện (1)

Sau đó là hàm W7G( ) kiểm tra ptr[10], ptr[12]

secathon2018_RVZT_3.png

Vì đây là hàm kiểm tra các phần tử nên ta dễ dàng viết brute force để tìm ra

          Suy ra Prt[10] = ‘3’ ; Ptr[12] = ‘n’

          Ta gọi là điều kiện (2)

Tiếp theo là hàm ZS1DDAW2B( )

secathon2018_RVZT_4.png

          Suy ra:

          Ptr[10] = Ptr[13] = Ptr[14] = Ptr[21] = Ptr[24]

          Ptr[12] = Ptr[22]

          Ta gọi là điều kiện (3)

Hàm ABWW7U9LE( )

secathon2018_RVZT_5.png

Ở đây sử dụng hàm NOIBSA5() để kiểm tra từng ký tự Ptr[15], Ptr[17], Ptr[18], Ptr[20], Ptr[23]

Trong đó hàm NOIBSA5( )

          secathon2018_RVZT_6.png

Tiếp tục brute force để tim ra các ký tự này:

          => Ptr[15] = d; Ptr[17] = p; Ptr[18] = 4;  Ptr[20] = 1; Ptr[23] = c

          Ta gọi là điều kiện (4)

Từ (1), (2), (3) và (4) ta có:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
S E C A T H O N { 3 n 3 3 d p 4 1 3 n c 3 }

Vậy là còn 4 vị trí nữa chưa xuất hiện trong phần kiểm tra ở trên mà sẽ được kiểm tra bằng hàm CRC32( ). Thực tế mình không thể tìm thấy hàm tương tự với 3 tham số như trong bài để brute force được nên cả buổi chiều giải không ra.

Trong hàm main( ) có đoạn kiểm tra Ptr[9] và Ptr[11] nên đã giới hạn được 1 phần:

          P<= Ptr[9], Ptr[11] << Z

Đây chính là lúc ta nhìn lại đề bài: Đề bài gồm 4 chữ cái viết hoa không có nghĩa gì “RVZT”. Và vấn đề bài toán còn 4 ký tự chưa biết. Thử thêm lần lượt các ký tự đề bài vào và kiểm tra.

secathon2018_RVZT_7.png

Flag: SECATHON{R3Vn33dZp4T23nc3}

Qua đây ta rút ra bài học: cần đọc kỹ đề trước khi làm bài.

SECATHON 2018 – DecryptFile

Bài này không phải khó nhưng nó yêu cầu kinh nghiệm làm nhiều CTF.

Đề bài có 2 file: 1 file thực thi và 1 file đã bị mã hóa

Chạy file thực thi thấy sinh ra 1 file: file_dec tuy nhiên file này không chạy được

Dùng IDA để xem code của file thực thi:

Đầu tiên, Key được sinh ra bởi hàm sub_4010A0( ) có 32 ký tự (giống mã md5) và chuỗi tham số nhập vào sau đó được đưa vào hàm giải mã sub_4017D0( )

secathon2018_decfile_1.png

Đọc vào hàm sub_4010A0( ) thấy có các con số lớn và lạ. Google thì biết đây là mảng tạo của thuật toán MD5.

secathon2018_decfile_0.png

Tại hàm giải mã sub_4017D0( ), thực hiện đọc file “file” sau đó lấy ra 8800 bytes để giải mã bằng Key rồi lưu vào file “file_dec”.

Phương thức giải mã được hiểu đơn giản là lấy các ký tự đọc được từ “file” nếu khác 0 thì xor với ký tự của Key.

secathon2018_decfile_2.png

Vậy thì vấn đề ở đây là nhập vào gì để sinh ra Key giải mã file ra được một file có nghĩa.

Mở “file” bằng 101 Editor thấy có những vùng toàn ký tự ‘\0x00’ rất giống với cấu trúc một file PE. Chúng ta đặt giả thiết: Nếu như “file_dec” là một file PE thì sẽ có e_magic ở DOS_HEADER là “MZ” và có một đặc trưng DOS stub sẽ không đổi ở mọi file là:

secathon2018_decfile_3

Dựa vào giả thiết này, ta code thử xem sẽ giải mã ra gì:

secathon2018_decfile_4

Ta được mã “5c7ab41e37efc4e816ebfcbc70071aa2” nhưng khi decrypt bằng tool onlie thì không ra gì 😦

Và may mắn khi “file_dec” thật sự là một file PE nhưng chạy không được do lỗi config.

secathon2018_decfile_5.png

Mở “file_dec” bằng CFF explorer tìm đển Resource Editor để xem file cấu hình trong Configuration File thì nhìn thấy trong thư mục Bitmap có 1 ảnh bmp

secathon2018_decfile_6.png

Export file bitmap ra thì thấy ảnh này không đọc được ra gì cả. Mở file bằng 101Editor lên để xem. Đến đây nếu không kiên trì và thêm may mắn thì nhiều bạn sẽ bỏ cuộc và tìm hướng khác.

Dựa vào kinh nghiệm chơi CTF, ở phần kích thước của file, ta thay đổi thông tin của chiều dài và chiều rộng của ảnh thử xem có mang lại kết quả gì không. Thường thì sẽ là nhân chiều rộng với x thì sẽ chia chiều cao với x. Như vậy ảnh sẽ không bị lỗi. Thử tăng chiều rộng lên 2 lần và giảm chiều cao đi 2 lần thì thấy ảnh bắt đầu xuất hiện chữ nhưng chưa rõ ràng.

secathon2018_decfile_out.png

Tăng tiếp chiều rộng lên 2 lần và giảm chiều dài đi 2 lần nữa ta được flag 🙂

secathon2018_decfile_flag

 

 

 

Flare-on 2017 – Greek-to-me – Challenge 3

Chương trình: greek-to-me.exe

Phân tích

Đây là chương trình sử dụng socket để nhận dữ liệu từ máy khác đến. Nhìn vào giả mã ta có thể thấy được địa chỉ IP = ‘127.0.0.1’port = 0x8AE = 2222 của chương trình đang mở để lắng nghe. Buf nhận vào 4 bytes => len(data_send) <=4

flare-on-2017-greek-to-me-0.png

Sau khi nhận dữ liệu, chương trình đem Buf[0] để xor với các phần tử trong mảng dữ liệu loc_40107c[] rồi cộng thêm 22h rồi lưu lại vào mảng.

flare-on-2017-greek-to-me-1.png

Xét thấy phần dữ liệu nằm trong section code nhưng code lại bị thay đổi trong khi chạy => người lập trình chương trình muốn làm rối mã trong lúc dịch ngược.

Mảng sau khi thay đổi dùng để tính toàn để đưa ra flag hay không. Nếu đúng thì Congratulations!. Thêm vào đó các giá trị bị thay đổi chỉ phụ thuộc vào giá trị của Buf[0] nên ta chỉ cần gửi 1 ký tự để tìm ra flag 🙂 (không gian khóa chỉ còn 256) ==> brute force chương trình để tìm ra flag thôi 🙂

flare-on-2017-greek-to-me-2.png

Nhập vào ký tự có mã ASCII là 162 nhưng nhận được câu hỏi “where’s my flag?”. Tìm kiếm quan chương trình và khả nghi nhất vẫn là đoạn code bị thay đổi.

Dùng ollydbg để debug ta phát hiện code đã bị thay đổi thành chức năng thêm giá trị vào stack. Lấy giá trị đó ra ta được flag 🙂
flare-on-2017-greek-to-me-3.png

flag: et_tu_brute_force@flare-on.com

Flare-on 2017 – IgniteMe – Challenge 2

flare-on-2017-igniteme-0

Nhận xét

  • Chương trình yêu cầu nhận flag vào để kiểm tra.
  • Cấu trúc chương trình đơn giản, chỉ có 4 hàm nhỏ để thay đổi giá trị và kiểm tra giá trị.

Phân tích

flare-on-2017-igniteme-1

Hàm main( ) đưa ra yêu cầu nhập flag vào và gọi đến các hàm sub_4010F0( )sub_401050( ) để thay đổi giá trị và kiểm tra flag

flare-on-2017-igniteme-2

Hàm sub_4010F0( ) nhận giá trị flag nhập vào.  Hàm sub_401020( ) trả vê chiều dài của flag nhập vào. Sau đó flag được lưu vào mảng ký tự byte_403078[] nếu thỏa mãn buffer[i] != 10 and != 13 and != 0. Nhận thấy với đầu vào là flag luôn thỏa mãn điều kiện trên => byte_403078[] == buffer[] 

flare-on-2017-igniteme-4

Hàm sub_41000( ) luôn trả về eax = 4 ==> v4 = 4

flare-on-2017-igniteme-3.png

Hàm sub_401050( )  thực hiện xor v4 với byte_403078[i] lưu trong byte_403180[i] rồi cập nhật liên tục giá trị v4 = byte_403070[i]. Sau đó so sánh với mảng byte_43000[], nếu đúng thì đó là flag.  

Giải pháp

Cho mảng byte_43000[i] xor v4  = flag[i], cụ thể như sau:

flare-on-2017-igniteme-5

Flag: R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com