- Đây là lần đầu tiên mình tham gia giải offline nên khá nhiều bỡ ngỡ và lo lắng, hơn thế nữa mình còn là newbie :> - Cảm ơn anh Sơn đã hỗ trợ e giải bài này ạ. # Overview ![image](https://hackmd.io/_uploads/S1SNDLDmR.png) # Solution - Mình cho vào IDA để debug rồi F5 xem mã giả. ``` int __cdecl main(int argc, const char **argv, const char **envp) { unsigned int v3; // eax unsigned int v4; // eax char v6[256]; // [rsp+30h] [rbp-D18h] BYREF char Str[1024]; // [rsp+130h] [rbp-C18h] BYREF CHAR fake[1024]; // [rsp+530h] [rbp-818h] BYREF CHAR input[1024]; // [rsp+930h] [rbp-418h] BYREF Str[0] = -33; Str[1] = 69; Str[2] = 67; Str[3] = 49; Str[4] = -122; Str[5] = 38; Str[6] = 116; Str[7] = -97; Str[8] = -87; Str[9] = 118; Str[10] = -115; Str[11] = -86; Str[12] = -108; Str[13] = 116; Str[14] = -73; Str[15] = 46; Str[16] = -98; Str[17] = -94; Str[18] = 20; Str[19] = 5; Str[20] = 109; Str[21] = -87; Str[22] = -34; Str[23] = -89; Str[24] = 80; Str[25] = 57; Str[26] = 17; memset(&Str[27], 0, 0x3E5ui64); printf("[+] Input flag: "); scanf("%s", input); v3 = strlen(Key); RC4_init(v6, Key, v3); v4 = strlen(Str); createFake(v6, Str, v4, fake); if ( lstrcmpA(input, fake) ) printf("\nWrong!"); else printf("Correct!"); return 0; } ``` - Mình đã thay đổi tên của vài hàm và biến cho dễ phân biệt bằng cách dùng `ctrl + N`. - Chương trình chỉ đơn giản là nó bắt bạn nhập 1 string rồi so với 1 string khác. - Bạn đặt bp rồi debug, sau khi chạy qua hàm creatFake, ta có thể thấy hàm createFake sẽ tạo 1 fake flag. ![image](https://hackmd.io/_uploads/H1Frw8D7A.png) - Fake flag được lưu trong rcx, bạn trỏ đến thanh ghi này, sẽ thấy. - Sau khi chạy qua mấy lệnh nữa, ta thấy hàm `lstrcmpA`. => Ban đầu mình tưởng đơn giản chỉ là hàm so sánh `strcmp` nhưng không, nó là 1 fake strcmp :> - Ta có thể dễ dàng nhập ra khi debug tiếp, nó sẽ chạy xuống và in `Correct`, dù nó là false. ![image](https://hackmd.io/_uploads/rkt8vUP70.png) - Mình bấm vào hàm ấy nó ra 1 cái địa chỉ. - Đây mới chương trình thật của nó ``` __int64 __fastcall sub_7FF668F31230(__int64 input_string, __int64 fake_flag) { int i; // [rsp+20h] [rbp-128h] char sus[128]; // [rsp+30h] [rbp-118h] BYREF char res[128]; // [rsp+B0h] [rbp-98h] BYREF qmemcpy(sus, "fM", 2); sus[2] = 12; sus[3] = -95; sus[4] = 86; sus[5] = 63; sus[6] = 43; sus[7] = -67; sus[8] = 78; sus[9] = 97; sus[10] = 106; sus[11] = -114; sus[12] = 73; sus[13] = 81; sus[14] = 61; sus[15] = -121; sus[16] = 114; sus[17] = 124; sus[18] = 54; sus[19] = -123; sus[20] = 69; sus[21] = 122; sus[22] = 104; sus[23] = -67; sus[24] = 75; sus[25] = 98; sus[26] = 62; sus[27] = -37; sus[28] = 114; sus[29] = 102; sus[30] = 58; sus[31] = -112; sus[32] = 72; sus[33] = 81; sus[34] = 1; sus[35] = -52; sus[36] = 115; sus[37] = 78; sus[38] = 31; sus[39] = -97; memset(&sus[40], 0, 0x58ui64); memset(res, 0, sizeof(res)); for ( i = 0; i < strlen(sus); ++i ) res[i] = *(_BYTE *)(fake_flag + i % 4) ^ sus[i]; return 0i64; } ``` - Mình đặt lại tên cho clean code cái. - Đọc sơ qua, mình có thể đoán đc, flag mình đang tìm chính là chuỗi res. - Nhưng khi mình chạy thử mấy vòng lặp XOR thì thấy nó không ra cái gì cả. - Quay lại hàm main(), mình thấy 1 thứ, đã bỏ quên là cái key `f@**!`, là thứ mã hóa v6~map. ![image](https://hackmd.io/_uploads/ryIOv8wQ0.png) - Dưới đây là hàm RC4_init() cùng với key đã bđ v6~map ntn: ![image](https://hackmd.io/_uploads/HJzXkwP7C.png) - Đối với hàm createFake(), fake_flag sẽ được tạo ra từ map. ![image](https://hackmd.io/_uploads/BJ6a08P7R.png) => Từ đó, mình phát hiện ra rằng v6~map là thứ sẽ qđ flag ra chuẩn hay không. - Bây giờ mình sẽ dùng xref, công dụng của nó là trỏ đến những hàm có sự xuất hiện của key. - Mình xref key thì ra hàm này: ![image](https://hackmd.io/_uploads/HJlKwUvQC.png) ![image](https://hackmd.io/_uploads/SkYFvLvQA.png) - Mình thử đặt bp tại đây và chạy thì nó luôn trỏ sang true => mình set ip hoặc đổi cờ ZF để nó sang false. - Cuối cùng key nó bị biến từ `f@**!` -> `fA++!`. ![image](https://hackmd.io/_uploads/H1SswIPQR.png) - Rồi ta chạy vào hàm fake strcmp rồi XOR lại với sus[], xem chuỗi res[] nó ra gì. ![image](https://hackmd.io/_uploads/SyCsPUP70.png) => flag: `KCSC{1t_co5ld_be_right7_fla9_here_^.^@@}` - Tóm lại, cái key đã làm cái v6 bị biến đổi, do đó, ta cần sửa key rồi truyền nó vào hàm createFake(), bên cạnh đó, xuất hiện 1 hàm fake strcmp(), bản chất nó là tạo flag chứ kp là so sánh.