# DreamHack's Rev_basic (0-9) Rev-basic 0 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_140001190("Input : ", argv, envp); sub_1400011F0("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_14001000` ```c _BOOL8 __fastcall sub_140001000(const char *Str1) { return strcmp(Str1, "Compar3_the_str1ng") == 0; } ``` --> `strcmp` so sánh 2 chuỗi `Str1` và `"Compar3_the_str1ng"` nếu giống thì trả về 0 Flag: DH{Compar3_the_str1ng} --- Rev-basic 1 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400013E0("Input : ", argv, envp); sub_140001440("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_14001000` ```c= like_BOOL8 __fastcall sub_140001000(_BYTE *a1) { if ( *a1 != 67 ) //C return 0LL; if ( a1[1] != 111 ) //o return 0LL; if ( a1[2] != 109 ) //m return 0LL; if ( a1[3] != 112 ) //p return 0LL; if ( a1[4] != 97 ) //a return 0LL; if ( a1[5] != 114 ) //r return 0LL; if ( a1[6] != 51 ) //3 return 0LL; if ( a1[7] != 95 ) //_ return 0LL; if ( a1[8] != 116 ) //t return 0LL; if ( a1[9] != 104 ) //h return 0LL; if ( a1[10] != 101 ) //e return 0LL; if ( a1[11] != 95 ) //_ return 0LL; if ( a1[12] != 99 ) //c return 0LL; if ( a1[13] != 104 ) //h return 0LL; if ( a1[14] != 52 ) //4 return 0LL; if ( a1[15] != 114 ) //r return 0LL; if ( a1[16] != 97 ) //a return 0LL; if ( a1[17] != 99 ) //c return 0LL; if ( a1[18] != 116 ) //t return 0LL; if ( a1[19] != 51 ) //3 return 0LL; if ( a1[20] == 114 ) //r return a1[21] == 0; return 0LL; } ``` --> Hàm kiểm tra lần lượt vị trí của chuỗi `a1` theo kí tự ASCII để trả về "Correct" Flag: DH{Compar3_the_ch4ract3r} --- Rev-basic 2 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400011B0((__int64)"Input : ", argv, envp); sub_140001210("%256s", buf); if ( (unsigned int)sub_140001000((__int64)buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_14001000` ```c= __int64 __fastcall sub_140001000(__int64 buf) { int i; // [rsp+0h] [rbp-18h] for ( i = 0; (unsigned __int64)i < 0x12; ++i ) { if ( *(_DWORD *)&aC[4 * i] != *(unsigned __int8 *)(buf + i) )// "C" return 0LL; } return 1LL; } ``` --> Hàm `sub_140001000` so sánh 18 byte đầu của input với mảng hằng `aC`. Mỗi byte input được so sánh trực tiếp với một giá trị cố định. Do đó chỉ cần dump `aC` là có thể khôi phục input hợp lệ. --> Ta nhìn qua assembly code ![image](https://hackmd.io/_uploads/B1ch0PG4We.png) - Kiểm tra thanh stack chứa địa chỉ aC và thấy được flag ![image](https://hackmd.io/_uploads/Bk0a0PzV-l.png) Flag: DH{Comp4re_the_arr4y} --- Rev-basic 3 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```cpp= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400011B0("Input : ", argv, envp); sub_140001210("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_14001000` ```cpp= __int64 __fastcall sub_140001000(__int64 a1) { int i; // [rsp+0h] [rbp-18h] for ( i = 0; (unsigned __int64)i < 0x18; ++i ) { if ( byte_140003000[i] != (i ^ *(unsigned __int8 *)(a1 + i)) + 2 * i ) return 0LL; } return 1LL; } ``` Ta hiểu hàm trên muốn làm như sau: `byte_1400300[i]= i ^ s[i] + 2 * index --> s[i] = (byte_1400300 - 2 * index) ^ index` - `byte_1400300[i]` ![image](https://hackmd.io/_uploads/HJF_qYfV-x.png) ` --> Tiến hành dịch ngược để lấy flag: ```cpp= #include <bits/stdc++.h> #define ll long long #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl '\n' using namespace std; const ll Nmax=1e6+5; int main() { fastio; int byte_1400300[] = { 0x49, 0x60, 0x67, 0x74, 0x63, 0x67, 0x42, 0x66, 0x80, 0x78, 0x69, 0x69, 0x7B, 0x99, 0x6D, 0x88, 0x68, 0x94, 0x9F, 0x8D, 0x4D, 0xA5, 0x9D, 0x45 }; string s; for(ll i=0; i<0x18; i++){ s+= ( byte_1400300[i] -2*i ) ^ i; } cout<<s; //I_am_X0_xo_Xor_eXcit1ng } ``` Flag: DH{I_am_X0_xo_Xor_eXcit1ng} --- Rev-basic 4 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```cpp= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400011C0("Input : ", argv, envp); sub_140001220("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_140001000` ```cpp= __int64 __fastcall sub_140001000(__int64 a1) { int i; // [rsp+0h] [rbp-18h] for ( i = 0; (unsigned __int64)i < 0x1C; ++i ) { if ( ((unsigned __int8)(16 * *(_BYTE *)(a1 + i)) | ((int)*(unsigned __int8 *)(a1 + i) >> 4)) != byte_140003000[i] ) return 0LL; } return 1LL; } ``` - Ta hiểu hàm trên muốn làm như sau: byte140003000[i] = s[i] << 4 | s[i] >>4 - Nhận thấy đây là kĩ thuật ``[swap 2 nibbles in a byte]`` nên mình sẽ tiến hành swap lại thêm một lần nữa -- Ví dụ ta có : AB(plaintext) -> BA(encrypted text) -> AB - Decrypted Code: ```c= #include <bits/stdc++.h> #define ll long long #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl '\n' using namespace std; const ll Nmax=1e6+5; int main() { fastio; int byte_1400300[] = { 0x24, 0x27, 0x13, 0xC6, 0xC6, 0x13, 0x16, 0xE6, 0x47, 0xF5, 0x26, 0x96, 0x47, 0xF5, 0x46, 0x27, 0x13, 0x26, 0x26, 0xC6, 0x56, 0xF5, 0xC3, 0xC3, 0xF5, 0xE3, 0xE3 }; string s; for(ll i=0; i<0x1C; i++){ s+= (byte_1400300[i] << 4 | byte_1400300[i] >> 4 ) & 0xFF; } cout<<s; } ``` Flag: DH{Br1ll1ant_bit_dr1bble_<<_>>} --- Rev-basic 5 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400011C0("Input : ", argv, envp); sub_140001220("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_14001000` ```c= __int64 __fastcall sub_140001000(__int64 a1) { int i; // [rsp+0h] [rbp-18h] for ( i = 0; (unsigned __int64)i < 0x18; ++i ) { if ( *(unsigned __int8 *)(a1 + i + 1) + *(unsigned __int8 *)(a1 + i) != byte_140003000[i] ) return 0LL; } return 1LL; } ``` - Hàm trên tiến hành như sau: -- `byte_140003000[i] = s[i] + s[i+1] --> s[i]= byte_140003000[i] - s[i+1]` Nhưng vì byte_140003000[i] - s[i+1] là không logic vì chưa biết được kí tự s[i+1] nên không suy ra được s[i] Ví dụ: ```c= byte[0] = s[0] + s[1] byte[1] = s[1] + s[2] byte[2] = s[2] + s[3] s[0]=byte[0]-s[1] s[1]=byte[1]-s[2] s[2]=byte[2]-s[3] ``` -->Không biết `s[3]` thì không thể dịch ngược về được Nên mình có hướng giải quyết như sau: ```c= #include <bits/stdc++.h> #define ll long long #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl '\n' using namespace std; const ll Nmax=1e6+5; int main() { fastio; int byte_1400300[] = { 0xAD, 0xD8, 0xCB, 0xCB, 0x9D, 0x97, 0xCB, 0xC4, 0x92, 0xA1, 0xD2, 0xD7, 0xD2, 0xD6, 0xA8, 0xA5, 0xDC, 0xC7, 0xAD, 0xA3, 0xA1, 0x98, 0x4C }; char s[25]; s[24]='}'; //DH{...} for(ll i=0x18; i>=0; i--){ s[i]=char(byte_1400300[i]-s[i+1]); } cout<<s; } ``` Flag: DH{All_l1fe_3nds_w1th_NULL} --- Rev-basic 6 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400011B0("Input : ", argv, envp); sub_140001210("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_140001000` ```c= __int64 __fastcall sub_140001000(__int64 a1) { int i; // [rsp+0h] [rbp-18h] for ( i = 0; (unsigned __int64)i < 0x12; ++i ) { if ( byte_140003020[*(unsigned __int8 *)(a1 + i)] != byte_140003000[i] ) return 0LL; } return 1LL; } ``` - Hàm trên tiến hành như sau: `byte_140003000[i] = byte_140003020[s[i]] --> s[i] = inv_byte_140003020[byte_140003000[i]]` - Nhận xét: hàm trên sử dụng kĩ thuật `AES Inverse S-box` nên mình có decrypted code như sau: ```c= #include <bits/stdc++.h> #define ll long long #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl '\n' using namespace std; const ll Nmax=1e6+5; int main() { string s; int inv_byte14003020[256]; fastio; int byte_14003020[] = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; int byte_14003000[] = { 0x0,0x4D, 0x51, 0x50, 0xEF, 0xFB, 0xC3, 0xCF, 0x92, 0x45, 0x4D, 0xCF, 0xF5, 0x04, 0x40, 0x50, 0x43, 0x63 }; for (int i = 0; i < 256; i++) inv_byte14003020[byte_14003020[i]] = i; for(ll i=0;i<0x12; i++){ s+=char(inv_byte14003020[byte_14003000[i]]); } cout<<s; } ``` Flag: DH{Replac3_the_w0rld} --- Rev-basic 7 --- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= -int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_140001120("Input : ", argv, envp); sub_1400011B0("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm `sub_140001000` ```c= __int64 __fastcall sub_140001000(__int64 a1) { int i; // [rsp+0h] [rbp-18h] for ( i = 0; (unsigned __int64)i < 0x1F; ++i ) { if ( (i ^ (unsigned __int8)__ROL1__(*(_BYTE *)(a1 + i), i & 7)) != byte_140003000[i] ) return 0LL; } return 1LL; } ``` - Hàm trên tiến hành như sau: `byte_140003000[i]= i ^ ROL1(s[i], i & 7 ) --> s[i]= ROR1(byte_140003000[i] ^ i, i & 7 )` - byte_140003000[i] ![image](https://hackmd.io/_uploads/ByI9uafEbx.png) -- Đến đây mình chỉ cần dịch ngược lại thôi: ```c= #include <bits/stdc++.h> #define ll long long #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl '\n' using namespace std; const ll Nmax=1e6+5; ll ROR(int x, int y){ return ( x >> y | x << (8- y)); } int main() { string s; fastio; int byte_14003000[] = { 0x52,0xDF,0xB3,0x60,0xF1,0x8B,0x1C,0xB5, 0x57,0xD1,0x9F,0x38,0x4B,0x29,0xD9,0x26, 0x7F,0xC9,0xA3,0xE9,0x53,0x18,0x4F,0xB8, 0x6A,0xCB,0x87,0x58,0x5B,0x39,0x1E }; for(ll i=0 ;i<0x1F;i++){ s+= (ROR(byte_14003000[i]^ i ,i&7)); } cout<<s; } ``` Flag: DH{Roll_the_left!_Roll_the_right!} --- Rev-basic 8 ---- Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400011B0("Input : ", argv, envp); sub_140001210("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai - Hàm sub_14001000 ```c= __int64 __fastcall sub_140001000(__int64 a1) { int i; // [rsp+0h] [rbp-18h] for ( i = 0; (unsigned __int64)i < 0x15; ++i ) { if ( (unsigned __int8)(-5 * *(_BYTE *)(a1 + i)) != byte_140003000[i] ) return 0LL; } return 1LL; } ``` - Hàm trên thực hiện cụ thể như sau: `byte_140003000[i]= s[i]* (unsigned_int8)-5` - Do kết quả của phép nhân được ép kiểu về unsigned_int8, nên mọi phép toán đều được thực hiện trong modulo 256. Khi đó, biểu thức trên tương đương với: `byte_140003000[i] ≡ -5 × s[i] (mod 256)` - Để khôi phục lại giá trị s[i], mình cần đảo ngược phép nhân trên trong modulo 256. Tuy nhiên, không thể sử dụng phép chia thông thường, mà phải dùng nghịch đảo modulo -Reversed code: ```c= #include <bits/stdc++.h> #define ll long long #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl '\n' using namespace std; const ll Nmax=1e6+5; int main() { // freopen("liq.inp","r",stdin); // freopen("liq.out","w",stdout); fastio; int byte_14001000[] = { 0xAC, 0xF3, 0x0C, 0x25, 0xA3, 0x10, 0xB7, 0x25, 0x16, 0xC6, 0xB7, 0xBC, 0x07, 0x25, 0x02, 0xD5, 0xC6, 0x11, 0x07, 0xC5, }; string s; for(ll i=0;i<0x15;i++){ s+= (byte_14001000[i]*51) & 0xFF; } cout<<s; } ``` Flag: DH{Did_y0u_brute_force?} --- Rev-basic 9 --- Đây là bài cuối cùng trong chuỗi bài Rev-basic của mình rồi, cảm ơn các bạn vì đã đọc đến tận đây!! Đề bài cho chúng ta một file thực thi `(.exe)`, tìm và debug binary trong hàm `main()` để dịch ngược ra flag - Hàm main ```c= int __fastcall main(int argc, const char **argv, const char **envp) { char buf[256]; // [rsp+20h] [rbp-118h] BYREF memset(buf, 0, sizeof(buf)); sub_1400012E0("Input : ", argv, envp); sub_140001340("%256s", buf); if ( (unsigned int)sub_140001000(buf) ) puts("Correct"); else puts("Wrong"); return 0; } ``` - Chúng ta thấy rằng chương trình bắt nhập một chuỗi string sau đó trả về "Correct" nếu hàm `sub_14001000` đúng và "Wrong" nếu hàm sai -Hàm sub_140001000 ```c= _BOOL8 __fastcall sub_140001000(const char *Buf1) { int i; // [rsp+20h] [rbp-18h] int v3; // [rsp+24h] [rbp-14h] v3 = strlen(Buf1); if ( (v3 + 1) % 8 ) return 0LL; for ( i = 0; i < v3 + 1; i += 8 ) sub_1400010A0(&Buf1[i]); return memcmp(Buf1, &Buf2_, 0x19uLL) == 0; } ``` - Nhìn vào đoạn code trên, mình thấy để trả về flag phải gọi thêm 1 hàm nữa, vậy hãy kiểm tra hết tất cả hàm 1 lượt nhé - Hàm `sub_1400010A0` ```c= __int64 __fastcall sub_1400010A0(unsigned __int8 *a1) { __int64 result; // rax unsigned __int8 v2; // [rsp+0h] [rbp-48h] int j; // [rsp+4h] [rbp-44h] int i; // [rsp+8h] [rbp-40h] char I_am_KEY[16]; // [rsp+10h] [rbp-38h] BYREF strcpy(I_am_KEY, "I_am_KEY"); result = *a1; v2 = *a1; for ( i = 0; i < 16; ++i ) { for ( j = 0; j < 8; ++j ) { v2 = __ROR1__(a1[((_BYTE)j + 1) & 7] + byte_140004020[(unsigned __int8)I_am_KEY[j] ^ v2], 5); a1[((_BYTE)j + 1) & 7] = v2; } result = (unsigned int)(i + 1); } return result; } ``` - Hàm `sub_1400010A0` thực hiện như sau: ```c= answer[i]==ROR(a1[((j+1)&7)] + byte_140004020[key[j]^ v2],5) a1[((j+1)&7)] + byte_140004020[key[j] ^ v2]==ROL(answer[i],5) a1[((j+1)&7)]==ROL(answer[i],5)−byte_14004020[key[j] ^ v2] //lệnh sau khi đã chuyển đổi ``` Nói tóm gọn : 2 hàm trên thực hiện mã hóa từng block 8 byte bằng phép XOR với khóa, tra bảng hằng, cộng và dịch vòng bit (ROL/ROR), sau đó so sánh kết quả với một giá trị cố định để xác thực input. -Code reversed của mình: ```c= #include <bits/stdc++.h> using namespace std; int v5[8] = { 'I','_','a','m','_','K','E','Y' }; /* AES S-box */ int byte_140004020[256] = { 99,124,119,123,242,107,111,197,48,1, 103,43,254,215,171,118,202,130,201,125, 250,89,71,240,173,212,162,175,156,164, 114,192,183,253,147,38,54,63,247,204, 52,165,229,241,113,216,49,21,4,199, 35,195,24,150,5,154,7,18,128,226, 235,39,178,117,9,131,44,26,27,110, 90,160,82,59,214,179,41,227,47,132, 83,209,0,237,32,252,177,91,106,203, 190,57,74,76,88,207,208,239,170,251, 67,77,51,133,69,249,2,127,80,60, 159,168,81,163,64,143,146,157,56,245, 188,182,218,33,16,255,243,210,205,12, 19,236,95,151,68,23,196,167,126,61, 100,93,25,115,96,129,79,220,34,42, 144,136,70,238,184,20,222,94,11,219, 224,50,58,10,73,6,36,92,194,211, 172,98,145,149,228,121,231,200,55,109, 141,213,78,169,108,86,244,234,101,122, 174,8,186,120,37,46,28,166,180,198, 232,221,116,31,75,189,139,138,112,62, 181,102,72,3,246,14,97,53,87,185, 134,193,29,158,225,248,152,17,105,217, 142,148,155,30,135,233,206,85,40,223, 140,161,137,13,191,230,66,104,65,153, 45,15,176,84,187,22 }; uint8_t unk_140004000[32] = { 0x7E,0x7D,0x9A,0x8B,0x25,0x2D,0xD5,0x3D, 0x03,0x2B,0x38,0x98,0x27,0x9F,0x4F,0xBC, 0x2A,0x79,0x00,0x7D,0xC4,0x2A,0x4F,0x58, 0,0,0,0,0,0,0,0 }; int ROL(int x, int n) { return (x << n) | (x >> (8 - n)); } /* answer[i]==ROR(a1[((j+1)&7)] + byte_140004020[key[j]⊕v2],5) a1[((j+1)&7)] + byte_140004020[key[j]⊕v2]==ROL(answer[i],5) a1[((j+1)&7)]==ROL(answer[i],5)−byte_14004020[key[j]⊕v2] */ void solve(uint8_t a[8]) { for (int i = 0; i < 16; i++) { for (int j = 7; j >= 0; j--) { uint8_t v2 = a[(j + 1) & 7]; a[(j + 1) & 7] = (ROL(v2, 5) - byte_140004020[v5[j] ^ a[j & 7]])& 0xFF ; } } } int main() { for (int off = 0; off < 24; off += 8) { solve(unk_140004000 + off); } for (int i = 0; i < 24; i++) { cout << (char)unk_140004000[i]; } cout << endl; } ``` Flag: DH{Reverse__your__brain_;)}