---
# System prepended metadata

title: DreamHack's Rev_basic (0-9)

---

# 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_;)}