- Đâ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

# 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.

- 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.

- 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.

- Dưới đây là hàm RC4_init() cùng với key đã bđ v6~map ntn:

- Đối với hàm createFake(), fake_flag sẽ được tạo ra từ map.

=> 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:


- 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++!`.

- 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ì.

=> 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.