---
# System prepended metadata

title: Write-up Eschaton CTF 2026 ( REV)

---

# Write-up Eschaton CTF 2026 ( REV)
# Retro
- Chạy thử chương trình:
![image](https://hackmd.io/_uploads/BkXc8BjL-e.png)
- Không thao tác được gì, mở ghidra lên thử.
- Kiểm tra các hàm, ta thấy hàm `FUN_022e`:
- ![image](https://hackmd.io/_uploads/B1TsdSsUZg.png)
- Như vậy chương trình sẽ kiểm tra `DAT_c000` xem có bằng 0  hay 1 hay 2 không để in ra cái gì đấy. Chương trình khi khởi động sẽ mặc định là 0 nên sẽ in ra màn hình trên ![image](https://hackmd.io/_uploads/HkiWiSjIZx.png)
=> dùng hxd fix lại giá trị của `DAT_c000` thử .  Ta sẽ sửa ở đây, đổi 0x0 thành 0x1 và 0x2 ![image](https://hackmd.io/_uploads/rkfI1Uo8Ze.png)

- `DAT_c000` = 0x1:![image](https://hackmd.io/_uploads/BJwqiSsU-e.png)
-`DAT_c000` = 0x2 :![image](https://hackmd.io/_uploads/By5U3BoL-e.png)

# Key1
![image](https://hackmd.io/_uploads/rJalGOiLWl.png)
- Chương trình sẽ nhận 1 username sau đó sẽ gen ra 1 key, ta phải nhập đúng 5 key từ 5 username ngẫu nhiên từ server.
Mở ida, ta có hàm tạo key sau:
```cpp=
__int64 __fastcall proc_a(unsigned __int8 *a1, _BYTE *pass)
{
  unsigned __int8 *username; // rbx
  __int64 len_user; // r12
  _QWORD *v4; // rax
  __int64 v5; // r8
  _QWORD *v6; // r9
  unsigned __int8 *v7; // rax
  __int64 v8; // rcx
  __int64 v9; // rax
  __int64 v10; // r8
  _QWORD *v11; // r9
  _DWORD *v13; // r11
  _WORD *v14; // r10
  int passs; // eax
  unsigned __int8 *v16; // rax
  __int16 v17; // dx
  unsigned __int16 v18; // ax
  __int16 v19; // si
  __int16 v20; // ax
  __int16 v21; // dx
  __int16 v22; // cx
  __int64 v23; // rax
  __int64 v24; // [rsp+8h] [rbp-50h]
  _WORD *v25; // [rsp+8h] [rbp-50h]
  _QWORD *v26; // [rsp+10h] [rbp-48h]
  _DWORD *v27; // [rsp+10h] [rbp-48h]
  _QWORD *v28; // [rsp+18h] [rbp-40h]
  _BYTE v29[8]; // [rsp+20h] [rbp-38h] BYREF
  char v30; // [rsp+28h] [rbp-30h] BYREF
  int v31; // [rsp+30h] [rbp-28h] BYREF
  _WORD v32[18]; // [rsp+34h] [rbp-24h] BYREF

  username = a1;
  len_user = j_strlen((__int64)a1);
  if ( (unsigned __int64)(len_user - 4) <= 12 )
  {
    v4 = (_QWORD *)_ctype_b_loc();
    v5 = *v4;
    v6 = v4;
    v7 = a1;
    while ( 1 )
    {
      v8 = *v7;
      if ( (*(_BYTE *)(v5 + 2 * v8) & 8) == 0 && (_BYTE)v8 != '_' )
        break;
      if ( ++v7 == &a1[len_user] )
      {
        v26 = v6;
        v24 = v5;
        v9 = j_strlen((__int64)pass);
        v10 = v24;
        v11 = v26;
        if ( v9 == 19 && pass[4] == '-' && pass[9] == '-' && pass[14] == '-' )
        {
          v13 = pass;
          v14 = v29;
LABEL_12:
          passs = *v13;
          LOBYTE(v32[0]) = 0;
          v31 = passs;
          v16 = (unsigned __int8 *)&v31;
          while ( (*(_BYTE *)(v10 + 2LL * *v16 + 1) & 0x10) != 0 )
          {
            if ( v32 == (_WORD *)++v16 )
            {
              v25 = v14;
              v28 = v11;
              v27 = v13;
              *v14 = _isoc23_strtoul(&v31, 0, 16);
              v14 = v25 + 1;
              if ( &v30 != (char *)(v25 + 1) )
              {
                v11 = v28;
                v13 = (_DWORD *)((char *)v27 + 5);
                v10 = *v28;
                goto LABEL_12;
              }
              v17 = *a1;
              v18 = 31279;
              if ( (_BYTE)v17 )
              {
                do
                {
                  ++username;
                  v18 = v17 + 33 * v18;
                  v17 = *username;
                }
                while ( (_BYTE)v17 );
                v19 = v18 ^ 0x9C3E;
                v20 = (8 * v18) ^ (v18 >> 5) ^ 0xB7A1;
                v21 = (v19 + v20) ^ 0xE4D2;
                v22 = (v19 + v20) ^ v20 ^ 0x78EC;
              }
              else
              {
                v21 = -20533;
                v22 = 22269;
                v20 = 25864;
                v19 = -6639;
              }
              LOWORD(v31) = v19;
              v32[0] = v21;
              v32[1] = v22;
              HIWORD(v31) = v20;
              v23 = 0;
              while ( *(_WORD *)&v29[v23 * 2] == v32[v23 - 2] )
              {
                if ( ++v23 == 4 )
                  return 1;
              }
              return 0;
            }
          }
        }
        return 0;
      }
    }
  }
  return 0;
}
```
Phân tích:
+ Username phải từ 4-16 kí tự.
+ Key phải đúng 19 kí tự mà mỗi 4 kí tự có "-".
+ Có thể thấy chương trình sẽ khởi tạo key từ username được nhập
+ Ta có seed : `v18 = 31279`
```cpp=
               do
                {
                  ++username;
                  v18 = v17 + 33 * v18;
                  v17 = *username;
                }
                while ( (_BYTE)v17 );
```
- Chương trình sẽ lấy từng kí tự của username nhân `v18` rồi  cộng lại, cuối cùng lưu vào `v18`. Sau đó từng phần của key sẽ được tính toán như sau.
- Part 1 :
`v19 = v18 ^ 0x9C3E;`
- Part 2 : 
`v20 = (8 * v18) ^ (v18 >> 5) ^ 0xB7A1`
- Part 3 : 
`v21 = (v19 + v20) ^ 0xE4D2`
- Part 4 : 
`v22 = (v19 + v20) ^ v20 ^ 0x78EC`
Cuối cùng chuyển các part sang mã hex và ghép lại:
`*v14 = _isoc23_strtoul(&v31, 0, 16); `
=> Viết được script sau:
```python=
from pwn import *

def gen_key(username: str) -> str:
    v18 = 31279
    for c in username:
        v18 = (ord(c) + 33 * v18) & 0xFFFF

    part1 = (v18 ^ 0x9C3E) & 0xFFFF
    part2 = ((v18 * 8) ^ (v18 >> 5) ^ 0xB7A1) & 0xFFFF
    part3 = ((part1 + part2) ^ 0xE4D2) & 0xFFFF
    part4 = ((part1 + part2) ^ part2 ^ 0x78EC) & 0xFFFF

    return f"{part1:04X}-{part2:04X}-{part3:04X}-{part4:04X}"

def main():
    context.log_level = "info"

    host = "node-2.mcsc.space"
    port = 12141

    p = remote(host, port)

    for i in range(1, 6):
        log.info (f" Dang giai bai {i}/5")
        p.recvuntil(b"Username: ")
        username = p.recvline().strip().decode()
        key = gen_key(username)                     
        p.sendlineafter(b"Enter key: ", key.encode())

    p.interactive()

if __name__ == "__main__":
    main()

```
![image](https://hackmd.io/_uploads/HJJH9YoIZx.png)

# Key 2
- tương tự bài trên nhưng bây giờ có thêm hwid. ![image](https://hackmd.io/_uploads/ByYnOB3Lbx.png)
- Load vào ida, xem thử.
```cpp=
 if ( a1 != 4 )
  {
    v2 = sub_458470(&unk_5C3A80, "Usage: ");
    v3 = sub_458470(v2, *a2);
    sub_458470(v3, " <username> <hwid> <key>\n");
    sub_458470(&unk_5C3A80, "  username: 4-20 alphanumeric characters\n");
    sub_458470(&unk_5C3A80, "  hwid: 8-character hex string\n");
    sub_458470(&unk_5C3A80, "  key: A1B2-XXXX-XXXX-XXXX-CCCC format\n");
    return 1;
  }
  sub_405980(Key, a2[3], &v32);
  sub_405980(hwid, a2[2], &v31);
  sub_405980(&username, a2[1], &v30);
  if ( (unsigned __int64)(len_user - 4) <= 16 )
  {
    v6 = username;
    v7 = &username[len_user];
    if ( username == &username[len_user] )
    {
LABEL_12:
      if ( hwid[1] == 8 )
      {
        v10 = hwid[0];
        v11 = 0;
        while ( (unsigned int)sub_4C5BE0(*(unsigned __int8 *)(v10 + v11)) )
        {
          if ( ++v11 == 8 )
          {
            v12 = sub_4D6710(v10, 0, 16);       //  chuyen hwid vao day va doi no thanh so
            if ( Key[1] == 24
              && *(_BYTE *)(Key[0] + 4LL) == '-'
              && *(_BYTE *)(Key[0] + 9LL) == '-'
              && *(_BYTE *)(Key[0] + 14LL) == '-'
              && *(_BYTE *)(Key[0] + 19LL) == '-' )
            {
              v13 = (char *)&v42;
              sub_4625A0(&v42, Key, 0, 4);      // lay 4 ki tu dau ghi vao v42
              if ( v43 != (_QWORD *)4 )
              {
LABEL_22:
                sub_45EB00((__int64 *)&v42);
                break;
              }
              v14 = *v42;
              sub_45EB00((__int64 *)&v42);
              if ( v14 == 843198785 )           // 4 ki tu dau
              {
                v15 = 0;     
                v37[0] = 0xA00000005LL;      // cắt chuỗi tại vị trí các offset
                v37[1] = 0x140000000FLL;
                while ( 1 )
                {
                  sub_4625A0(&v42, Key, *((int *)v37 + v15), 4);// Lay cum XXXX của input
                  v16 = v42;
                  v17 = (unsigned __int8 *)v42;
                  v18 = (unsigned __int8 *)v43 + (_QWORD)v42;
                  while ( v18 != v17 )
                  {
                    v29 = v17;
                    v19 = sub_4C5BE0(*v17);
                    v17 = v29 + 1;
                    if ( !v19 )
                      goto LABEL_22;
                  }
                  if ( v15 == 3 )   // lấy 3 lần XXXX
                    break;
                  *(&v35 + v15++) = sub_4D6710(v16, 0, 16);// bien hex thanh so nguyen
                  sub_45EB00((__int64 *)&v42);
                }
                v20 = sub_4D6710(v16, 0, 16);  // CCCC của người dùng
                sub_45EB00((__int64 *)&v42);
                v21 = sub_405900((__int64)username, len_user) ^ v12;// Lay seed
                v22 = (_QWORD *)sub_406820(8);   // xin 8 bytes
                *v22 = off_56A4A0;              // part2 ( gán địa chỉ hàm ảo)
                v42 = v22;
                v23 = (_QWORD *)sub_406820(8);
                *v23 = off_56A4C8;           // part 3
                v43 = v23;
                v24 = (_QWORD *)sub_406820(8);
                *v24 = off_56A4F0;              // part4
                v44 = v24;
                v25 = (_QWORD *)sub_406820(8);
                *v25 = off_56A518;              
                v26 = v25;
                v27 = 0;
                v45 = v25;
                do
                {
                  v28 = (*(__int64 (__fastcall **)(_DWORD *, _QWORD))(*(_QWORD *)(&v42)[v27] + 16LL))((&v42)[v27], v21);// goi ham tai offset +16
                  *((_WORD *)v37 + v27++) = v28; // ép kiểu các part(XXXX) sang 2 bytes
                  v21 = v28;                    // cap nhat seed
                }
                while ( v27 != 3 );
                (*(void (__fastcall **)(_QWORD *, _QWORD))(*v26 + 16LL))(v26, v28);
                do
                {
                  if ( *(_QWORD *)v13 )
                    (*(void (__fastcall **)(_QWORD))(**(_QWORD **)v13 + 8LL))(*(_QWORD *)v13);
                  v13 += 8;
                }
                while ( &v46 != v13 );
                if ( LOWORD(v37[0]) == v35 && v36 == *(_DWORD *)((char *)v37 + 2) )
                {
                  v34 = HIWORD(v36);
                  v33 = LOBYTE(v37[0]) | ((BYTE1(v37[0]) | (WORD1(v37[0]) << 8)) << 8);
                  v5 = ((unsigned __int16)sub_405900((__int64)&v33, 6) ^ 0x52B1) == v20;
                  goto LABEL_6;
                }
              }
            }
            break;
          }
        }
      }
    }
    else
    {
      while ( 1 )
      {
        v8 = *v6;
        v9 = sub_4C5AA0();
        if ( v8 != 95 && !v9 )
          break;
        if ( v7 == ++v6 )
          goto LABEL_12;
      }
    }
  }
  v5 = 0;
LABEL_6:
  sub_45EB00((__int64 *)&username);
  sub_45EB00(hwid);
  sub_45EB00(Key);
  if ( !v5 )
  {
    sub_458470(&unk_5C3BA0, "Invalid!\n");
    return 1;
  }
  sub_458470(&unk_5C3BA0, "Valid!\n");
  return 0;
}
```
- Chương trình đã bị stripped, không có các hàm hay gặp nữa, gây khó khăn trong việc hiểu chương trình làm gì.
- Ta có: ` v12 = sub_4D6710(v10, 0, 16);` sẽ chuyển hwid từ hex sang int .
- `sub_4625A0(&v42, Key, 0, 4);` : tách 4 ký tự đầu Key,  `v14 == 843198785 ` sẽ là 4 ký tự đầu của key : `843198785` là `A1B2`.
```cpp=
while ( 1 )
                {
                  sub_4625A0(&v42, Key, *((int *)v37 + v15), 4);
                  ...
                  if ( v15 == 3 ) 
                   break;
```
- đoạn while trên sẽ tách 3 phần XXXX từ key.
- ` v21 = sub_405900((__int64)username, len_user) ^ v12;` : đây sẽ là đoạn tính seed để tính toán các part.
- Bên trong hàm `sub_405900`:
```cpp=
_int64 __fastcall sub_405900(__int64 a1, __int64 a2)
{
  __int64 v4; // rdi
  __int64 result; // rax
  char v6; // cl
  int v7; // esi
  int v8; // esi

  if ( !a2 )
    return 1316956697;
  v4 = 0;
  LODWORD(result) = 1316956697;
  do
  {
    v6 = v4;
    v7 = *(unsigned __int8 *)(a1 + v4++);       // Lay tung ki tu tu username
    v8 = __ROL4__(result ^ (v7 << (8 * (v6 & 3))), 5);
    result = (unsigned int)(v8 + 1016194743) ^ __ROR4__(v8 + 1016194743, 11);
  }
  while ( a2 != v4 );
  return result;
}
```
- Giải thích : lấy từng kí tự của username , dịch trái ( 8 * (index & 3))   rồi XOR với result ( result ban đầu là 1316956697) rồi xoay đi 5 bit rồi lưu vào v8
- Tiếp theo result sẽ bằng `( v8+ 1016194743)` rồi XOR với `v8 + 1016194743` xoay phải đi 11 bit. Kết quả result phải là trong  khoảng số unsigned int.
- Cuối cùng seed sẽ bằng result XOR với v12( hwid đã chuyển thành int ) ![image](https://hackmd.io/_uploads/HypyAToIbx.png)

Tiếp tục, ta có đoạn sau : 
```cpp=
 v28 = (*(__int64 (__fastcall **)(_DWORD *, _QWORD))(*(_QWORD *)(&v42)[v27] + 16LL))((&v42)[v27], v21);// goi ham tai offset +16
                  *((_WORD *)v37 + v27++) = v28;
                  v21 = v28;   
```
- Gọi hàm ảo tại offset +16 của đối tượng hiện tại rồi lưu kết quả tính toán vào mảng `v37` cuối cùng cập nhật seed mới bằng kết quả vừa tính ( là các part luôn ).
- Chương trình được lặp lại 3 lần tương đương với part 2, part 3, part 4 của key.
**Các đoạn tính toán các part:**
Part 2 :  
- ![image](https://hackmd.io/_uploads/HkAs5jsU-e.png)
- Lấy seed  xoay trái 7 bit rồi XOR với 0x8D2F5A1C;

Part 3 :![image](https://hackmd.io/_uploads/HJgdhjjIbx.png)
- Lấy 16 bit cao của part2 rồi XOR với `0x1FA9` kết hợp với part2 XOR `0x6B3Eu` bị dịch trái 16 bit ( đây là phép SWAP (đảo vị trí). 16 bit cao mới được tạo từ 16 bit thấp cũ, và ngược lại. )

Part 4 :
![image](https://hackmd.io/_uploads/ByKHTjiLWx.png)
- xoay phải part3 đi 13 bit rồi + 1204305198 rồi ép kiểu thành số dương 32 bit
=> Cuối cùng các part trên sẽ được ép kiểu thành 16 bit để hiển thị lên màn hình như phía trên đã chú thích.
### Kiểm tra kết quả
- `if ( LOWORD(v37[0]) == v35 && v36 == *(_DWORD *)((char *)v37 + 2) )` : So sánh 3 part của mình với giá trị của chương trình đưa ra.
`v33 = LOBYTE(v37[0]) | ((BYTE1(v37[0]) | (WORD1(v37[0]) << 8)) << 8);` và
`v5 = ((unsigned __int16)sub_405900(&v33, 6) ^ 0x52B1) == v20;` : gộp 3 part của mình thành 1 dữ liệu 6 bytes, gọi lại hàm `sub_4059000` rồi XOR với `0x52B1` và so sánh kết quả cuối cùng với cụm CCCC (biến v20) trong Key của người dùng.

Tóm tắt luồng :
- nhận username và hwid.
- Seed = Hash(Username) ^ Int(HWID)
- part1 = A1B2
- Part2 = Func1(Seed)
- Part3 = Func2(Part2)
- Part4 = Funct(Part3)
- ghép part 2, 3, 4 vào với nhau thành buffer
- Part5 = Hash(Buffer) ^ 0x52B1
- Chuyển các giá trị Part 2, 3, 4, 5 thành hex.
- Ghép lại A1B2-Part2-Part3-Part4-Part5
- Nếu đúng in ra valid, ngược lại invalid
### Script
```python=
import sys
from pwn import *
import re 


HOST = 'node-3.mcsc.space' 
PORT = 35435

# --- Các hàm hỗ trợ Bitwise ---
def rol(val, shift, width=32):
    shift %= width
    return ((val << shift) & (2**width - 1)) | (val >> (width - shift))

def ror(val, shift, width=32):
    shift %= width
    return (val >> shift) | ((val << (width - shift)) & (2**width - 1))
    
def sub_405900(data_bytes):
    seed = 1316956697
    CONST = 1016194743
    v4 = 0
    for char in data_bytes:
        shift = (v4 & 3) * 8
        temp = (char << shift) ^ seed
        v8 = rol(temp & 0xFFFFFFFF, 5)
        temp_sum = (v8 + CONST) & 0xFFFFFFFF
        seed = temp_sum ^ ror(temp_sum, 11)
        v4 += 1
    return seed & 0xFFFFFFFF

def tao_key(username, hwid_hex):
    user_seed = sub_405900(username.encode('ascii'))
    hwid_int = int(hwid_hex, 16)
    
    cur_seed = user_seed ^ hwid_int
    
 #    ---- --- part2-------
    cur_seed = (rol(cur_seed, 7) ^ 0x8D2F5A1C) & 0xFFFFFFFF  
    part2 =  cur_seed & 0xFFFF  
    
    #------------part3---------
    old_low = cur_seed & 0xFFFF
    old_high = (cur_seed >> 16) & 0xFFFF
    
    new_high = old_low ^ 0x6B3E
    new_low = old_high ^ 0x1FA9
    
    cur_seed = (new_high << 16) | new_low
    part3 = cur_seed & 0xFFFF  
    
    #---------part4 ------------
    cur_seed = (ror(cur_seed, 13) + 1204305198) & 0xFFFFFFFF
    part4 = cur_seed & 0xFFFF  
    
    
    # ------------ Tính CCCC --------------
    buffer = bytearray()
    buffer.extend(part2.to_bytes(2, 'little'))
    buffer.extend(part3.to_bytes(2, 'little'))
    buffer.extend(part4.to_bytes(2, 'little'))
    
    checksum_hash = sub_405900(buffer)
    checksum = (checksum_hash ^ 0x52B1) & 0xFFFF
    
    return f"A1B2-{part2:04X}-{part3:04X}-{part4:04X}-{checksum:04X}"
    
    
def solve():
    context.log_level = 'info' 
    r = remote(HOST, PORT)
        # Vòng lặp giải 5 vòng
    for i in range(5):
        print(f"\n[*] === Round {i+1} ===")
            
            # Đọc đến khi server yêu cầu nhập key
        output = r.recvuntil(b'Enter key: ', drop=False).decode()
            
            # Regex lấy Username và HWID
            # Username có thể chứa ký tự đặc biệt, nên dùng \S+
        username_match = re.search(r'Username:\s*(\S+)', output)
        hwid_match = re.search(r'HWID:\s*([0-9a-fA-F]+)', output)
            
        if username_match and hwid_match:
           user = username_match.group(1).strip()
           hwid = hwid_match.group(1).strip()
                
                # Tính Key
           key = tao_key(user, hwid)
                
                # Gửi Key
           r.sendline(key.encode())
                
                # Đọc kết quả 
           response = r.recvline().decode()
           print(f"[Server]: {response.strip()}")
    r.interactive()
if __name__ == "__main__":
    solve()
```
![image](https://hackmd.io/_uploads/SJvQBDhUbx.png)

# Textmorph
![image](https://hackmd.io/_uploads/HJn_vYJvbe.png)
- Có vẻ chương trình muốn ta nhập gì đó để có được flag.
- Kiểm tra thử thì thấy nó bị pack bằng PyInstaller. ![image](https://hackmd.io/_uploads/rJfpQK1D-e.png)
Sau khi unpack bằng  lệnh `python3 pyinstxtractor.py textmorph`, ta được ![image](https://hackmd.io/_uploads/Byw-_FJDbg.png)
- Thấy file textmorph_embedded.pyc.
- Thử strings `strings -n 10 textmorph_embedded.pyc
` ta có mấy các fake flag : ![image](https://hackmd.io/_uploads/Hk_fI51vZg.png)
![image](https://hackmd.io/_uploads/BySQLckwWg.png)
![image](https://hackmd.io/_uploads/SkgNU9kvbg.png)
và 1 đống gì đó giống base64.![image](https://hackmd.io/_uploads/rJphUqyPWx.png)
- Chú ý đoạn  `eNrc` , đây là header đặc trưng của zlib file, viết 1 script python để extract được đoạn base64  này.
```python=
import re
import base64

with open("textmorph_embedded.pyc", "rb") as f:
    content = f.read()
    match = re.search(rb'([A-Za-z0-9+/=]{100,})', content)
    base64_bytes = match.group(1) 
    file_data = base64.b64decode(base64_bytes)          
    with open("extracted_data.bin", "wb") as f_out:
         f_out.write(file_data)
```
- script để giải nén file zlib trên.
```python=
import zlib
data = open("extracted_data.bin","rb").read()
out = zlib.decompress(data)
with open("output_file", "wb") as f_out:
        f_out.write(out)
```
- Nhận được 1 file gif chứa flag .
![image](https://hackmd.io/_uploads/ry1Vki1DWx.png)

# key3
![image](https://hackmd.io/_uploads/SJnZbiJwbl.png)
![image](https://hackmd.io/_uploads/By7a4kWPWl.png)
- Chương trình được viết bằng ngôn ngữ rust và bị stripped tương tự như bài key2.
- Chương trình lần này bắt ta tạo key từ username, hwid, timestamp, tier.
- Mở thử trong ida, ta tìm được hàm chính sau:
```cpp=
int64 sub_2480()
{
  _QWORD *v0; // rbx
  _BYTE *v1; // rcx
  unsigned __int64 v2; // rsi
  bool v3; // cf
  int v4; // eax
  __int64 v5; // rax
  unsigned __int64 v6; // r15
  unsigned int v7; // edx
  _BYTE *v8; // rcx
  unsigned __int64 v9; // rdx
  __int64 v10; // rax
  int v11; // edx
  __int64 v12; // rdi
  unsigned int v13; // edx
  __int64 v14; // r15
  __int64 v15; // rdx
  unsigned __int8 v16; // si
  unsigned int v17; // r13d
  unsigned __int8 v18; // r13
  unsigned __int8 *v19; // rsi
  __int64 v20; // r14
  __int64 v21; // rbx
  unsigned __int8 *v22; // rdx
  int v23; // edi
  int v24; // r8d
  int v25; // r10d
  int v26; // r9d
  void *v27; // r12
  size_t v28; // rbp
  int v29; // edx
  _BYTE *v30; // rax
  _BOOL8 v31; // rdx
  __int64 v32; // rcx
  _BYTE *v33; // rax
  __int64 v34; // rdx
  unsigned int v35; // r14d
  unsigned int v36; // edi
  unsigned int v37; // esi
  _BYTE *v38; // rax
  _BOOL8 v39; // rdx
  __int64 v40; // rcx
  _BYTE *v41; // rax
  __int64 v42; // rdx
  __int64 v43; // r12
  unsigned int v44; // edi
  unsigned int v45; // esi
  _BYTE *v46; // rax
  _BOOL8 v47; // rdx
  __int64 v48; // rcx
  _BYTE *v49; // rax
  __int64 v50; // rdx
  unsigned int v51; // ebx
  unsigned int v52; // edi
  unsigned int v53; // esi
  _BYTE *v54; // rax
  _BOOL8 v55; // rdx
  __int64 v56; // rcx
  _BYTE *v57; // rax
  __int64 v58; // rdx
  __int64 v59; // rbp
  unsigned int v60; // edi
  unsigned int v61; // esi
  _DWORD *v62; // rcx
  bool v63; // al
  char v64; // cl
  __int64 v65; // rsi
  char v66; // al
  unsigned int v67; // r8d
  size_t v68; // rdx
  size_t v69; // rdx
  unsigned __int64 v70; // rax
  char *v71; // rcx
  _BYTE *v72; // rdi
  size_t v73; // rdx
  size_t v74; // rax
  char *v75; // rsi
  size_t v76; // rdx
  size_t v77; // rax
  unsigned __int8 v78; // al
  size_t v79; // r15
  int v80; // r15d
  unsigned __int64 v81; // r13
  unsigned __int32 v82; // r13d
  unsigned __int32 v83; // r15d
  int v84; // eax
  unsigned __int32 v85; // r13d
  int v86; // ecx
  int v87; // r13d
  int v88; // esi
  int v89; // edi
  unsigned __int32 v90; // r15d
  int v91; // edx
  int v92; // r15d
  int v93; // ecx
  int v94; // edi
  int v95; // r8d
  int v96; // ecx
  int v97; // esi
  int v98; // r9d
  int v99; // edx
  int v100; // edi
  int v101; // r8d
  int v102; // r10d
  int v103; // esi
  int v104; // r10d
  int v105; // edi
  int v106; // r9d
  int v107; // ecx
  int v108; // edx
  int v109; // ecx
  unsigned int v110; // r15d
  int v111; // r8d
  int v112; // esi
  int v113; // r13d
  int v114; // edi
  __int64 v115; // rax
  int v116; // edx
  unsigned int v117; // esi
  __int64 v118; // r15
  __int64 v119; // rbp
  __int64 v120; // r12
  size_t v121; // rdx
  unsigned __int64 v122; // r13
  __int64 v123; // r14
  unsigned __int64 v124; // rbp
  size_t v125; // r12
  unsigned __int64 v126; // r14
  unsigned __int64 v127; // r13
  _QWORD *v128; // rbx
  __int64 v129; // r14
  _QWORD *v130; // r15
  __int64 v131; // rsi
  __int64 result; // rax
  __int64 v133; // rsi
  void *v134; // rdi
  size_t n; // [rsp+0h] [rbp-238h]
  size_t nb; // [rsp+0h] [rbp-238h]
  size_t na; // [rsp+0h] [rbp-238h]
  char *nc; // [rsp+0h] [rbp-238h]
  unsigned __int32 nd; // [rsp+0h] [rbp-238h]
  unsigned __int8 *src; // [rsp+8h] [rbp-230h]
  char *srca; // [rsp+8h] [rbp-230h]
  unsigned __int32 srcb; // [rsp+8h] [rbp-230h]
  __int128 v143; // [rsp+10h] [rbp-228h] BYREF
  __m256i v144; // [rsp+20h] [rbp-218h] BYREF
  __int128 v145; // [rsp+40h] [rbp-1F8h]
  __int128 v146; // [rsp+50h] [rbp-1E8h]
  __int128 v147; // [rsp+60h] [rbp-1D8h]
  unsigned __int64 v148; // [rsp+70h] [rbp-1C8h]
  unsigned __int8 v149; // [rsp+78h] [rbp-1C0h]
  int v150; // [rsp+79h] [rbp-1BFh]
  __int16 v151; // [rsp+7Dh] [rbp-1BBh]
  char v152; // [rsp+7Fh] [rbp-1B9h]
  size_t v153; // [rsp+80h] [rbp-1B8h]
  void *v154; // [rsp+88h] [rbp-1B0h]
  __int128 v155; // [rsp+90h] [rbp-1A8h] BYREF
  __int128 v156; // [rsp+A0h] [rbp-198h]
  _BYTE dest[72]; // [rsp+B0h] [rbp-188h] BYREF
  char v158; // [rsp+F8h] [rbp-140h]
  int v159; // [rsp+F9h] [rbp-13Fh]
  __int16 v160; // [rsp+FDh] [rbp-13Bh]
  char v161; // [rsp+FFh] [rbp-139h]
  __int64 v162; // [rsp+108h] [rbp-130h]
  __int64 v163; // [rsp+110h] [rbp-128h] BYREF
  _QWORD *v164; // [rsp+118h] [rbp-120h]
  __int64 v165; // [rsp+120h] [rbp-118h]
  _QWORD *v166; // [rsp+128h] [rbp-110h]
  __int64 v167; // [rsp+130h] [rbp-108h] BYREF
  _QWORD *v168; // [rsp+138h] [rbp-100h]
  __int64 v169; // [rsp+140h] [rbp-F8h]
  __int64 v170; // [rsp+148h] [rbp-F0h] BYREF
  __int64 v171; // [rsp+150h] [rbp-E8h]
  __int64 v172; // [rsp+158h] [rbp-E0h]
  _OWORD v173[3]; // [rsp+160h] [rbp-D8h] BYREF
  __int64 v174; // [rsp+190h] [rbp-A8h]
  unsigned __int64 v175; // [rsp+198h] [rbp-A0h]
  _QWORD v176[7]; // [rsp+1A0h] [rbp-98h] BYREF
  char v177; // [rsp+1D8h] [rbp-60h]
  __int16 v178; // [rsp+1E0h] [rbp-58h]
  _BYTE v179[80]; // [rsp+1E8h] [rbp-50h] BYREF

  sub_22B30(v179);
  sub_3570(&v163, v179, &off_659E8);
  if ( v165 != 6 )                              // so luong tham so
  {
    if ( !v165 )
      sub_1F15(0, 0, &off_65A20);
    *(_QWORD *)&v155 = v164;
    *((_QWORD *)&v155 + 1) = sub_2430;
    *(_QWORD *)&v143 = &off_65A38;
    *((_QWORD *)&v143 + 1) = 2;
    v144.m256i_i64[0] = (__int64)&v155;
    *(_OWORD *)&v144.m256i_u64[1] = 1u;
    sub_24820(&v143);
    *(_QWORD *)&v143 = &off_65A58;
    *((_QWORD *)&v143 + 1) = 1;
    v144.m256i_i64[0] = 8;
    *(_OWORD *)&v144.m256i_u64[1] = 0;
    sub_24820(&v143);
    *(_QWORD *)&v143 = &off_65A68;
    *((_QWORD *)&v143 + 1) = 1;
    v144.m256i_i64[0] = 8;
    *(_OWORD *)&v144.m256i_u64[1] = 0;
    sub_24820(&v143);
    *(_QWORD *)&v143 = &off_65A78;
    *((_QWORD *)&v143 + 1) = 1;
    v144.m256i_i64[0] = 8;
    *(_OWORD *)&v144.m256i_u64[1] = 0;
    sub_24820(&v143);
    *(_QWORD *)&v143 = &off_65A88;
    *((_QWORD *)&v143 + 1) = 1;
    v144.m256i_i64[0] = 8;
    *(_OWORD *)&v144.m256i_u64[1] = 0;
    sub_24820(&v143);
    *(_QWORD *)&v143 = &off_65A98;
    *((_QWORD *)&v143 + 1) = 1;
    v144.m256i_i64[0] = 8;
    *(_OWORD *)&v144.m256i_u64[1] = 0;
    sub_24820(&v143);
    sub_26FD0(1);
  }
  v0 = v164;
  sub_41B80(&v170, v164[7], v164[8]);
  v1 = (_BYTE *)v0[10];                         // timestamp
  v2 = v0[11];                                  
  if ( v2 == 1 )
  {
    v4 = (unsigned __int8)*v1;
    if ( v4 == 43 )
      goto LABEL_132;
    v2 = 1;
    if ( v4 == 45 )
      goto LABEL_132;
    goto LABEL_11;
  }
  if ( !v2 )
    goto LABEL_132;
  if ( *v1 != 43 )
  {
    if ( v2 >= 0x11 )
      goto LABEL_22;
LABEL_11:
    v5 = 0;
    v6 = 0;                      // timestamp
    while ( 1 )
    {
      v7 = (unsigned __int8)v1[v5] - 48;
      if ( v7 > 9 )
        goto LABEL_132;
      v6 = v7 + 10 * v6;                        // Chuyển đổi timestamp thành số nguyên.
      if ( v2 == ++v5 )
        goto LABEL_14;
    }
  }
  ++v1;
  v3 = v2-- < 0x12;
  if ( v3 )
    goto LABEL_11;
LABEL_22:
  v12 = 0;
  v6 = 0;
  while ( v2 != v12 )
  {
    v13 = (unsigned __int8)v1[v12] - 48;
    if ( v13 <= 9 && is_mul_ok(0xAu, v6) )
    {
      v14 = 10 * v6;
      ++v12;
      v3 = __CFADD__(v13, v14);
      v6 = v13 + v14;
      if ( !v3 )
        continue;
    }
    goto LABEL_132;
  }
LABEL_14:
  v8 = (_BYTE *)v0[13];                         // lay chuoi tier
  v9 = v0[14];                              // độ dài tier
  if ( v9 == 1 )
  {
    v11 = (unsigned __int8)*v8;
    if ( v11 == 43 )
      goto LABEL_132;
    v10 = 1;
    if ( v11 == 45 )
      goto LABEL_132;
    goto LABEL_29;
  }
  if ( !v9 )
    goto LABEL_132;
  if ( *v8 != 43 )
  {
    v10 = 2;
    if ( v9 >= 3 )
      goto LABEL_85;
LABEL_29:
    v15 = 0;
    v16 = 0;
    while ( 1 )
    {
      v17 = (unsigned __int8)v8[v15] - 48;
      if ( v17 > 9 )
        goto LABEL_132;
      v18 = 10 * v16 + v17;                     // chuyen tier thanh so
      ++v15;
      v16 = v18;
      if ( v10 == v15 )
        goto LABEL_32;
    }
  }
  ++v8;
  v10 = v9 - 1;
  v3 = v9-- < 4;
  if ( v3 )
    goto LABEL_29;
LABEL_85:
  v65 = 0;
  v18 = 0;
  while ( v9 != v65 )
  {
    v66 = 10 * v18;
    v67 = (unsigned __int8)v8[v65] - 48;
    if ( v67 <= 9 && is_mul_ok(0xAu, v18) )
    {
      ++v65;
      v18 = v67 + v66;
      if ( !__CFADD__((_BYTE)v67, v66) )
        continue;
    }
    goto LABEL_132;
  }
LABEL_32:
  n = v0[5];
  if ( n - 33 < 0xFFFFFFFFFFFFFFE3LL )
    goto LABEL_132;
  v19 = (unsigned __int8 *)v0[4];   // trỏ tới chuỗi username
  v20 = v0[16];
  v21 = v0[17];
  v22 = &v19[n];
  src = v19;                         // src chứa username
  while ( v19 != v22 )
  {
    v23 = *v19;
    if ( (v23 & 0x80u) == 0 )
    {
      ++v19;
    }
    else
    {
      v24 = v23 & 0x1F;
      v25 = v19[1] & 0x3F;
      if ( (unsigned __int8)v23 <= 0xDFu )
      {
        v19 += 2;
        v23 = v25 | (v24 << 6);
      }
      else
      {
        v26 = (v25 << 6) | v19[2] & 0x3F;
        if ( (unsigned __int8)v23 < 0xF0u )
        {
          v19 += 3;
          v23 = (v24 << 12) | v26;
        }
        else
        {
          v23 = ((v23 & 7) << 18) | (v26 << 6) | v19[3] & 0x3F;
          if ( v23 == 1114112 )
            break;
          v19 += 4;
        }
      }
    }
    if ( (unsigned int)(v23 - 32) >= 0x5F )
      goto LABEL_132;
  }
  if ( v172 != 16 )
    goto LABEL_132;
  LODWORD(v173[0]) = 3;
  *(_QWORD *)&v143 = v171;
  *((_QWORD *)&v143 + 1) = 16;
  *(_OWORD *)v144.m256i_i8 = 2u;
  v144.m256i_i64[2] = (__int64)v173;
  sub_3A10(&v155, &v143, &off_65AD8);
  if ( LODWORD(v173[0]) != 3 )
  {
    v133 = v155;
    if ( (_QWORD)v155 )
    {
      v134 = (void *)*((_QWORD *)&v155 + 1);
LABEL_131:
      sub_3CE0(v134, v133, 1);
    }
LABEL_132:
    *(_QWORD *)&v143 = &off_65A00;
    *((_QWORD *)&v143 + 1) = 1;
    v144.m256i_i64[0] = 8;
    *(_OWORD *)&v144.m256i_u64[1] = 0;
    sub_24730(&v143);
    sub_26FD0(1);
  }
  if ( __OFSUB__(-(__int64)v155, 1) )
    goto LABEL_132;
  v27 = (void *)*((_QWORD *)&v155 + 1);
  v162 = v155;
  if ( (unsigned __int8)(v18 - 4) < 0xFDu )
    goto LABEL_129;
  v28 = v156;
  *(_QWORD *)&v173[0] = sub_27350();  // lấy hwid từ input
  DWORD2(v173[0]) = v29;
  sub_27360(&v143, v173, 0, 0);  // hàm chuyển dổi
  if ( (_DWORD)v143 == 1 )
  {
    *(_QWORD *)&v155 = *((_QWORD *)&v143 + 1);
    DWORD2(v155) = v144.m256i_i32[0];
    sub_2120("called `Result::unwrap()` on an `Err` valueSystemTimeError", 43, &v155, &unk_65990, &off_659D0);
  }
  v153 = v28;
  if ( *((_QWORD *)&v143 + 1) + 86400LL < v6    // kiem tra thoi gian ( sai lệch không quá 24h)
    || v21 != 46
    || *((_QWORD *)&v143 + 1) - 86400LL > v6 && *((_QWORD *)&v143 + 1) >= 0x15181u )
  {
    goto LABEL_129;
  }
  v154 = v27;
  v176[0] = 0;
  v176[1] = 46;
  v176[2] = v20;
  v176[3] = 46;
  v176[4] = 0;
  v176[5] = 46;
  v176[6] = 0x2D0000002DLL;
  v177 = 1;
  v178 = 1;
  sub_3890(&v167, v176, &off_659E8);
  if ( v169 != 6
    || v168[1] != 5
    || *(_DWORD *)*v168 ^ 0x4949474B | *(unsigned __int8 *)(*v168 + 4LL) ^ 0x49// phan 1 KGIII
    || v168[3] != 8 )
  {
    goto LABEL_126;
  }
  v30 = (_BYTE *)v168[2];     // chứa part 2
  v31 = *v30 == 43;
  v32 = 8 - v31;              
  v33 = &v30[v31];
  v34 = 0;
  v35 = 0;                                      // phan 2
  do
  {
    v36 = (unsigned __int8)v33[v34];
    v37 = v36 - 48;
    if ( v36 >= 0x3A )
      v37 = ((v36 - 65) & 0xFFFFFFDF) + 10;
    if ( v37 > 0xF )
      goto LABEL_126;
    v35 = v37 | (16 * v35);      // Hex String to Integer 
    ++v34;
  }
  while ( v32 != v34 );
  if ( v168[5] != 8 )         // độ dài part 3
    goto LABEL_126;
  v38 = (_BYTE *)v168[4];    // chứa part 3
  v39 = *v38 == 43;
  v40 = 8 - v39;
  v41 = &v38[v39];
  v42 = 0;
  LODWORD(v43) = 0;                   // biến lưu giá trị part 3         
  do
  {
    v44 = (unsigned __int8)v41[v42];
    v45 = v44 - 48;
    if ( v44 >= 0x3A )
      v45 = ((v44 - 65) & 0xFFFFFFDF) + 10;
    if ( v45 > 0xF )
      goto LABEL_126;
    v43 = v45 | (16 * (_DWORD)v43);
    ++v42;
  }
  while ( v40 != v42 );
  if ( v168[7] != 8 )  // độ dài part 4
    goto LABEL_126;
  v46 = (_BYTE *)v168[6];
  v47 = *v46 == 43;
  v48 = 8 - v47;
  v49 = &v46[v47];
  v50 = 0;
  v51 = 0;                                      // part 4
  do
  {
    v52 = (unsigned __int8)v49[v50];
    v53 = v52 - 48;
    if ( v52 >= 0x3A )
      v53 = ((v52 - 65) & 0xFFFFFFDF) + 10;
    if ( v53 > 0xF )
      goto LABEL_126;
    v51 = v53 | (16 * v51);
    ++v50;
  }
  while ( v48 != v50 );
  if ( v168[9] != 8 )     // độ dài part 5
    goto LABEL_126;
  v54 = (_BYTE *)v168[8];
  v55 = *v54 == 43;
  v56 = 8 - v55;
  v57 = &v54[v55];
  v58 = 0;
  LODWORD(v59) = 0;                             // part 5
  do
  {
    v60 = (unsigned __int8)v57[v58];
    v61 = v60 - 48;
    if ( v60 >= 0x3A )
      v61 = ((v60 - 65) & 0xFFFFFFDF) + 10;
    if ( v61 > 0xF )
      goto LABEL_126;
    v59 = v61 | (16 * (_DWORD)v59);
    ++v58;
  }
  while ( v56 != v58 );
  if ( v168[11] != 4 )
    goto LABEL_126;
  v62 = (_DWORD *)v168[10];                     // phan cuoi cua key
  if ( *v62 == 1515082306 )                     // tier 1 bronze ( BRNZ)
  {
    v64 = 1;
  }
  else if ( *v62 == 1381387347 )                // // tier 2 sliver (slvr)
  {
    v64 = 2;
  }
  else
  {
    v63 = *v62 == 1145851719;                   // tier 3 gold
    v64 = 3;
    if ( !v63 )
      goto LABEL_126;
  }
  if ( v64 != v18 )
  {
LABEL_126:
    if ( v167 )
      sub_3CE0(v168, 16 * v167, 8);
    v27 = v154;
LABEL_129:
    v133 = v162;
    if ( !v162 )
      goto LABEL_132;
    v134 = v27;
    goto LABEL_131;
  }
  v166 = v168;
  v158 = 0;
  v155 = xmmword_4F130;
  v156 = xmmword_4F140;
  memset(dest, 0, sizeof(dest));
  v68 = n;
  if ( n >= 0x40 )
  {
    sub_4190(&v155, src, 0);             // đưa username vào trước
    v68 = n;
  }
  memcpy(&dest[8], src, v68);                   // copy username vao dest (buffer)
  v158 = n;
  v69 = v153;
  if ( v153 >= 64 - n )
  {
    v71 = (char *)v154;
    if ( n )
    {
      srca = (char *)v154 + 64 - n;
      v72 = &dest[n + 8];
      v73 = 64 - n;
      nb = v153 - (64 - n);
      memcpy(v72, v154, v73);
      ++*(_QWORD *)dest;
      sub_4190(&v155, &dest[8], 1);
      v71 = srca;
      v69 = nb;
    }
    v74 = v69 & 0x3F;
    v75 = &v71[v69 & 0xFFFFFFFFFFFFFFC0LL];
    na = v74;
    if ( v69 >= 0x40 )
    {
      v76 = v69 >> 6;
      *(_QWORD *)dest += v76;
      sub_4190(&v155, v71, v76);
      v74 = na;
    }
    memcpy(&dest[8], v75, v74);
    v70 = na;
  }
  else
  {
    memcpy(&dest[n + 8], v154, v153);
    v70 = v153 + n;
  }
  v158 = v70;
  *(_QWORD *)&v143 = v6;
  if ( v70 >= 0x38 )
  {
    nc = (char *)&v143 + 64 - v70;
    v79 = v70 - 56;
    memcpy(&dest[v70 + 8], &v143, 64 - v70);
    ++*(_QWORD *)dest;
    sub_4190(&v155, &dest[8], 1);
    memcpy(&dest[8], nc, v79);
    v77 = v79;
    goto LABEL_106;
  }
  *(_QWORD *)&dest[v70 + 8] = v6;               // copy timestamp vao ngay sau username
  v77 = v70 + 8;
  v158 = v77;
  if ( v77 != 63 )
  {
LABEL_106:
    dest[v77 + 8] = v18;                        // chuyển tier vào buffer 
    v78 = v77 + 1;
    goto LABEL_107;
  }
  dest[71] = v18;
  ++*(_QWORD *)dest;
  sub_4190(&v155, &dest[8], 1);
  v78 = 0;
LABEL_107:
  v158 = v78;
  v148 = *(_QWORD *)&dest[64];
  v149 = v78;
  v150 = v159;
  v151 = v160;
  v152 = v161;
  *(_OWORD *)&v144.m256i_u64[2] = *(_OWORD *)dest;
  v147 = *(_OWORD *)&dest[48];
  v146 = *(_OWORD *)&dest[32];
  v145 = *(_OWORD *)&dest[16];
  *(_OWORD *)v144.m256i_i8 = v156;
  v143 = v155;
  v80 = v78;
  v81 = _byteswap_uint64((*(_QWORD *)dest << 9) | (8 * (unsigned int)v78));
  v144.m256i_i8[v78 + 24] = 0x80;
  if ( v78 == 63 || (memset((char *)&v144.m256i_u64[3] + v78 + 1, 0, v78 ^ 0x3FLL), (v80 ^ 0x38u) <= 7) )
  {
    sub_4190(&v143, &v144.m256i_u64[3], 1);
    memset(v173, 0, sizeof(v173));
    v174 = 0;
    v175 = v81;
    sub_4190(&v143, v173, 1);
  }
  else
  {
    v148 = v81;
    sub_4190(&v143, &v144.m256i_u64[3], 1);
  }
  srcb = _byteswap_ulong(v143);                //h0
  v82 = _byteswap_ulong(DWORD1(v143));         // h1
  nd = _byteswap_ulong(DWORD2(v143));          // h2
  v83 = _byteswap_ulong(HIDWORD(v143));        // h3
  v84 = sub_3F00(v154, v153);                  // mã hóa crc32 
  v85 = (v84 ^ srcb) + v82;
  v86 = __ROL4__(v85, 25);
  v87 = nd ^ __ROL4__(v85, 4);
  v88 = __ROL4__(v84, 3);
  v89 = v88 ^ v87 ^ 0x5F8C2E7A;
  v90 = v89 + (v84 ^ srcb ^ (v83 - (v87 ^ 0x5F8C2E7A)));
  v91 = __ROL4__(v90, 25);
  v92 = v84 ^ srcb ^ __ROL4__(v90, 4);
  v93 = v89 ^ (v86 - (v92 ^ 0x5F8C2E7A));
  v94 = __ROL4__(v84, 6);
  v95 = v94 ^ v92 ^ 0x5F8C2E7A;
  v96 = v95 + v93;
  v97 = __ROL4__(v96, 4) ^ v87 ^ v88;
  v98 = v97 ^ __ROL4__(v84, 9);
  v99 = v98 + (v95 ^ (v91 - v97));
  v100 = __ROL4__(v99, 4) ^ v92 ^ v94;
  v101 = v100 ^ __ROL4__(v84, 12);
  v102 = v101 + (v98 ^ (__ROL4__(v96, 25) - v100));
  v103 = __ROL4__(v102, 25);
  v104 = v98 ^ __ROL4__(v102, 4);
  v105 = __ROL4__(v84, 15);
  v106 = v105 ^ v104 ^ 0x5F8C2E7A;
  v107 = v106 + (v101 ^ (__ROL4__(v99, 25) - (v104 ^ 0x5F8C2E7A)));
  v108 = __ROL4__(v107, 25);
  v109 = v101 ^ __ROL4__(v107, 4);
  v110 = __ROL4__(v84, 18);
  v111 = v110 ^ v109 ^ 0x5F8C2E7A;
  v112 = v111 + (v106 ^ (v103 - (v109 ^ 0x5F8C2E7A)));
  v113 = __ROL4__(v112, 25);
  v114 = __ROL4__(v112, 4) ^ v104 ^ v105;
  v115 = (unsigned int)v114 ^ __ROL4__(v84, 21);
  v116 = v115 + (v111 ^ (v108 - v114));
  v117 = __ROL4__(v116, 25);
  v118 = __ROL4__(v116, 4) ^ v109 ^ v110;
  v119 = v59 << 32;
  v120 = v43 << 32;
  v121 = v35;
  v122 = (unsigned __int64)((unsigned int)v115 ^ (v113 - (_DWORD)v118)) << 32;
  if ( v167 )
  {
    v153 = v35;
    v123 = v115;
    sub_3CE0(v166, 16 * v167, 8);
    v121 = v153;
    v115 = v123;
  }
  v124 = v51 | (unsigned __int64)v119;
  v125 = v121 | v120;                           // ghep cac phan da tinh toan
  v126 = v115 | ((unsigned __int64)v117 << 32);
  v127 = v118 | v122;
  if ( v162 )
    sub_3CE0(v154, v162, 1);
  if ( v127 ^ v125 | v126 ^ v124 )
    goto LABEL_132;
  *(_QWORD *)&v143 = &off_65A10;
  *((_QWORD *)&v143 + 1) = 1;
  v144.m256i_i64[0] = 8;
  *(_OWORD *)&v144.m256i_u64[1] = 0;
  sub_24730(&v143);
  if ( v170 )
    sub_3CE0(v171, v170, 1);
  v128 = v164;
  v129 = v165;
  if ( v165 )
  {
    v130 = v164 + 1;
    do
    {
      v131 = *(v130 - 1);
      if ( v131 )
        sub_3CE0(*v130, v131, 1);
      v130 += 3;
      --v129;
    }
    while ( v129 );
  }
  result = v163;
  if ( v163 )
    return sub_3CE0(v128, 24 * v163, 8);
  return result;
}
```
## Các đoạn xử lí dữ liệu:
+ Username giữ nguyên.
+ hwid được chuyển sang số int ( vd: ABCD => 0xAB, 0xCD).
+ Timestamp được truyền theo little edian.
+ Tier thành 1 bytes số nguyên, ( vd: 1 => 0x01).
=> nhét vào 1 buffer.
## Mã hóa
- Ta có hàm hash sha-256 sau: ` sub_4190(&v155, src, 0);`( nhận biết qua các đoạn như `sha256rnds2`, `sha256msg1`) ở đây dữ liệu được đưa vào là buffer chứa `username + hwid (bytes) + timestamp(little edian) + tier` như đã chú thích bên trên.
<details>
<summary>sub_4190(sha-256)</summary>
_int64 __fastcall sub_4190(__m128i *a1, const __m128i *a2, __int64 a3)
{
  __int64 result; // rax
  __int64 v4; // rbx
  __m128i v5; // xmm0
  __m128i v6; // xmm3
  __m128i v8; // xmm3
  const __m128i *v9; // rdx
  __m128i si128; // xmm4
  __m128i v85; // xmm0
  __m128i v86; // xmm1

  result = (unsigned __int8)byte_69000;
  if ( byte_69000 != 1 )
  {
    if ( (unsigned __int8)byte_69000 != 255 )
      return sub_45F0(a1, a2, a3);
    v4 = a3;
    result = sub_530();
    a3 = v4;
    if ( !(_BYTE)result )
      return sub_45F0(a1, a2, a3);
  }
  v5 = _mm_shuffle_epi32(_mm_loadu_si128(a1), 177);
  v6 = _mm_shuffle_epi32(_mm_loadu_si128(a1 + 1), 27);
  _XMM7 = _mm_alignr_epi8(v5, v6, 8);
  v8 = _mm_blend_epi16(v6, v5, 240);
  if ( a3 )
  {
    v9 = &a2[4 * a3];
    si128 = _mm_load_si128((const __m128i *)&xmmword_4EC60);
    _XMM14 = v8;
    _XMM2 = _XMM7;
    do
    {
      _XMM13 = _mm_shuffle_epi8(_mm_loadu_si128(a2), si128);
      __asm { sha256rnds2 xmm14, xmm7, xmm0 }
      _XMM6 = _mm_shuffle_epi8(_mm_loadu_si128(a2 + 1), si128);
      __asm { sha256rnds2 xmm2, xmm14, xmm0 }
      __asm { sha256rnds2 xmm14, xmm2, xmm0 }
      _XMM5 = _mm_shuffle_epi8(_mm_loadu_si128(a2 + 2), si128);
      __asm { sha256rnds2 xmm2, xmm14, xmm0 }
      __asm { sha256rnds2 xmm14, xmm2, xmm0 }
      __asm { sha256rnds2 xmm2, xmm14, xmm0 }
      _XMM1 = _mm_shuffle_epi8(_mm_loadu_si128(a2 + 3), si128);
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm13, xmm6
      }
      _XMM12 = _mm_add_epi32(_mm_alignr_epi8(_XMM1, _XMM5, 4), _XMM13);
      __asm
      {
        sha256msg2 xmm12, xmm1
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm6, xmm5
      }
      _XMM13 = _mm_add_epi32(_mm_alignr_epi8(_XMM12, _XMM1, 4), _XMM6);
      __asm
      {
        sha256msg2 xmm13, xmm12
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm5, xmm1
      }
      _XMM15 = _mm_add_epi32(_mm_alignr_epi8(_XMM13, _XMM12, 4), _XMM5);
      __asm
      {
        sha256msg2 xmm15, xmm13
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm1, xmm12
      }
      _XMM5 = _mm_add_epi32(_mm_alignr_epi8(_XMM15, _XMM13, 4), _XMM1);
      __asm
      {
        sha256msg2 xmm5, xmm15
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm12, xmm13
      }
      _XMM6 = _mm_add_epi32(_mm_alignr_epi8(_XMM5, _XMM15, 4), _XMM12);
      __asm
      {
        sha256msg2 xmm6, xmm5
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm13, xmm15
      }
      _XMM1 = _mm_add_epi32(_mm_alignr_epi8(_XMM6, _XMM5, 4), _XMM13);
      __asm
      {
        sha256msg2 xmm1, xmm6
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm15, xmm5
      }
      _XMM13 = _mm_add_epi32(_mm_alignr_epi8(_XMM1, _XMM6, 4), _XMM15);
      __asm
      {
        sha256msg2 xmm13, xmm1
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg1 xmm5, xmm6
      }
      _XMM12 = _mm_add_epi32(_mm_alignr_epi8(_XMM13, _XMM1, 4), _XMM5);
      __asm
      {
        sha256msg2 xmm12, xmm13
        sha256rnds2 xmm2, xmm14, xmm0
      }
      __asm { sha256msg1 xmm6, xmm1 }
      _XMM5 = _mm_add_epi32(_mm_alignr_epi8(_XMM12, _XMM13, 4), _XMM6);
      __asm
      {
        sha256rnds2 xmm14, xmm2, xmm0
        sha256msg2 xmm5, xmm12
        sha256msg1 xmm1, xmm13
      }
      _XMM6 = _mm_add_epi32(_mm_alignr_epi8(_XMM5, _XMM12, 4), _XMM1);
      __asm
      {
        sha256rnds2 xmm2, xmm14, xmm0
        sha256msg2 xmm6, xmm5
        sha256msg1 xmm13, xmm12
      }
      __asm { sha256msg1 xmm12, xmm5 }
      __asm { sha256rnds2 xmm14, xmm2, xmm0 }
      __asm { sha256rnds2 xmm2, xmm14, xmm0 }
      _XMM15 = _mm_add_epi32(_mm_alignr_epi8(_XMM6, _XMM5, 4), _XMM13);
      __asm { sha256msg2 xmm15, xmm6 }
      __asm { sha256rnds2 xmm14, xmm2, xmm0 }
      __asm { sha256rnds2 xmm2, xmm14, xmm0 }
      _XMM1 = _mm_add_epi32(_mm_alignr_epi8(_XMM15, _XMM6, 4), _XMM12);
      __asm { sha256msg2 xmm1, xmm15 }
      __asm { sha256rnds2 xmm14, xmm2, xmm0 }
      __asm { sha256rnds2 xmm2, xmm14, xmm0 }
      __asm { sha256rnds2 xmm14, xmm2, xmm0 }
      __asm { sha256rnds2 xmm2, xmm14, xmm0 }
      _XMM14 = _mm_add_epi32(_XMM14, v8);
      _XMM2 = _mm_add_epi32(_XMM2, _XMM7);
      a2 += 4;
      _XMM7 = _XMM2;
      v8 = _XMM14;
    }
    while ( a2 != v9 );
  }
  else
  {
    _XMM14 = v8;
    _XMM2 = _XMM7;
  }
  v85 = _mm_shuffle_epi32(_XMM2, 27);
  v86 = _mm_shuffle_epi32(_XMM14, 177);
  *a1 = _mm_blend_epi16(v85, v86, 240);
  a1[1] = _mm_alignr_epi8(v86, v85, 8);
  return result;
}
</details>

- Sau khi đã hash xong, chương trình lấy 16 bytes đầu tiên làm các biến khởi tạo cho thuận toán trộn.
```cpp=
srcb = _byteswap_ulong(v143);                 // h0
  v82 = _byteswap_ulong(DWORD1(v143));          // h1
  nd = _byteswap_ulong(DWORD2(v143));           // h2
  v83 = _byteswap_ulong(HIDWORD(v143));         // h3
```
Lưu ý: `_byteswap_ulong` được sử dụng vì SHA-256 tính toán theo Big Endian, nhưng kiến trúc x86 (và thuật toán trộn sau đó) sử dụng Little Endian.
`v84 = sub_3F00(v154, v153);` : Chương trình sẽ tính CRC32 với chỉ lệnh `PCLMULQDQ`( `nhận biết qua __asm { pclmulqdq xmm1, xmm0, 1 }`)với input là hwid đã parse rồi lưu vào v84.
<details>
<summary>sub_3F00(CRC32)</summary>
__int64 __fastcall sub_3F00(const __m128i *a1, unsigned __int64 a2)
{
  unsigned __int64 v2; // rdx
  char v4; // al
  __int16 v5; // ax
  __int64 v6; // rdi
  const __m128i *v7; // rsi
  unsigned __int64 v9; // r14
  __m128i v43; // xmm1
  __m128i v49; // xmm0
  __m128i v53; // xmm0

  v2 = a2;
  v4 = qword_69178[0];
  if ( !qword_69178[0] )
  {
    v4 = sub_1630();
    v2 = a2;
  }
  if ( (v4 & 2) == 0 )
    return sub_3D20(0, a1, v2);
  v5 = qword_69178[0];
  if ( !qword_69178[0] )
  {
    v9 = v2;
    v5 = sub_1630();
    v2 = v9;
  }
  if ( (v5 & 0x400) == 0 )
    return sub_3D20(0, a1, v2);
  v6 = 0;
  v7 = a1;
  if ( v2 < 0x80 )
    return sub_3D20(v6, v7, v2);
  _XMM3 = _mm_loadu_si128(a1 + 1);
  _XMM2 = _mm_loadu_si128(a1 + 2);
  _XMM1 = _mm_loadu_si128(a1 + 3);
  _XMM0 = _mm_xor_si128(_mm_cvtsi32_si128(0xFFFFFFFF), _mm_loadu_si128(a1));
  v7 = a1 + 4;
  v2 -= 64LL;
  _XMM4 = 0x154442BD4uLL;
  _XMM5 = _mm_load_si128(xmmword_4EC30);
  do
  {
    _XMM6 = _XMM0;
    __asm { pclmulqdq xmm6, xmm4, 0 }
    _XMM7 = _XMM0;
    __asm { pclmulqdq xmm7, xmm5, 11h }
    _XMM0 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128(v7), _XMM6), _XMM7);
    _XMM9 = _XMM3;
    __asm { pclmulqdq xmm9, xmm4, 0 }
    __asm { pclmulqdq xmm3, xmm5, 11h }
    _XMM3 = _mm_xor_si128(_XMM3, _mm_xor_si128(_XMM9, _mm_loadu_si128(v7 + 1)));
    _XMM6 = _XMM2;
    __asm { pclmulqdq xmm6, xmm4, 0 }
    __asm { pclmulqdq xmm2, xmm5, 11h }
    _XMM2 = _mm_xor_si128(_XMM2, _mm_xor_si128(_XMM6, _mm_loadu_si128(v7 + 2)));
    _XMM6 = _XMM1;
    __asm { pclmulqdq xmm6, xmm4, 0 }
    __asm { pclmulqdq xmm1, xmm5, 11h }
    _XMM1 = _mm_xor_si128(_XMM1, _mm_xor_si128(_XMM6, _mm_loadu_si128(v7 + 3)));
    v7 += 4;
    v2 -= 64LL;
  }
  while ( v2 > 0x3F );
  _XMM4 = 0x1751997D0uLL;
  _XMM6 = _XMM0;
  __asm { pclmulqdq xmm6, xmm4, 0 }
  _XMM5 = _mm_cvtepu32_epi64((__m64)0xCCAA009ECCAA009ELL);
  __asm { pclmulqdq xmm0, xmm5, 11h }
  _XMM0 = _mm_xor_si128(_mm_xor_si128(_XMM0, _XMM6), _XMM3);
  _XMM3 = _XMM0;
  __asm
  {
    pclmulqdq xmm3, xmm4, 0
    pclmulqdq xmm0, xmm5, 11h
  }
  _XMM0 = _mm_xor_si128(_mm_xor_si128(_XMM0, _XMM3), _XMM2);
  _XMM2 = _XMM0;
  __asm
  {
    pclmulqdq xmm2, xmm4, 0
    pclmulqdq xmm0, xmm5, 11h
  }
  _XMM0 = _mm_xor_si128(_mm_xor_si128(_XMM0, _XMM2), _XMM1);
  if ( v2 >= 0x10 )
  {
    do
    {
      v43 = _mm_loadu_si128(v7);
      v2 -= 16LL;
      ++v7;
      _XMM2 = _XMM0;
      __asm { pclmulqdq xmm2, xmm4, 0 }
      __asm { pclmulqdq xmm0, xmm5, 11h }
      _XMM0 = _mm_xor_si128(_XMM0, _mm_xor_si128(_XMM2, v43));
    }
    while ( v2 > 0xF );
  }
  _XMM1 = _mm_cvtepu32_epi64((__m64)0xCCAA009ECCAA009ELL);
  __asm { pclmulqdq xmm1, xmm0, 1 }
  v49 = _mm_xor_si128(_mm_srli_si128(_XMM0, 8), _XMM1);
  _XMM2 = _mm_blend_epi16((__m128i)0LL, v49, 3);
  _XMM3 = 0x163CD6124uLL;
  __asm { pclmulqdq xmm3, xmm2, 0 }
  v53 = _mm_xor_si128(_mm_srli_si128(v49, 4), _XMM3);
  _XMM2 = _mm_blend_epi16((__m128i)0LL, v53, 3);
  __asm { pclmulqdq xmm2, cs:xmmword_4EC50, 10h }
  _XMM2 = _mm_blend_epi16(_XMM2, (__m128i)0LL, 252);
  _XMM1 = 0x1DB710641uLL;
  __asm { pclmulqdq xmm1, xmm2, 0 }
  v6 = (unsigned int)~_mm_extract_epi32(_mm_xor_si128(_XMM1, v53), 1);
  if ( v2 )
    return sub_3D20(v6, v7, v2);
  else
    return (unsigned int)v6;
}
</details>

- Sau đó chương trình sẽ xử lí đoạn thuật toán sau với `v84` và các biến từ sha-256 => Ra được các part của key.
```cpp=
  v85 = (v84 ^ srcb) + v82;
  v86 = __ROL4__(v85, 25);
  v87 = nd ^ __ROL4__(v85, 4);
  v88 = __ROL4__(v84, 3);
  v89 = v88 ^ v87 ^ 0x5F8C2E7A;
  v90 = v89 + (v84 ^ srcb ^ (v83 - (v87 ^ 0x5F8C2E7A)));
  v91 = __ROL4__(v90, 25);
  v92 = v84 ^ srcb ^ __ROL4__(v90, 4);
  v93 = v89 ^ (v86 - (v92 ^ 0x5F8C2E7A));
  v94 = __ROL4__(v84, 6);
  v95 = v94 ^ v92 ^ 0x5F8C2E7A;
  v96 = v95 + v93;
  v97 = __ROL4__(v96, 4) ^ v87 ^ v88;
  v98 = v97 ^ __ROL4__(v84, 9);
  v99 = v98 + (v95 ^ (v91 - v97));
  v100 = __ROL4__(v99, 4) ^ v92 ^ v94;
  v101 = v100 ^ __ROL4__(v84, 12);
  v102 = v101 + (v98 ^ (__ROL4__(v96, 25) - v100));
  v103 = __ROL4__(v102, 25);
  v104 = v98 ^ __ROL4__(v102, 4);
  v105 = __ROL4__(v84, 15);
  v106 = v105 ^ v104 ^ 0x5F8C2E7A;
  v107 = v106 + (v101 ^ (__ROL4__(v99, 25) - (v104 ^ 0x5F8C2E7A)));
  v108 = __ROL4__(v107, 25);
  v109 = v101 ^ __ROL4__(v107, 4);
  v110 = __ROL4__(v84, 18);
  v111 = v110 ^ v109 ^ 0x5F8C2E7A;
  v112 = v111 + (v106 ^ (v103 - (v109 ^ 0x5F8C2E7A)));
  v113 = __ROL4__(v112, 25);
  v114 = __ROL4__(v112, 4) ^ v104 ^ v105;
  v115 = (unsigned int)v114 ^ __ROL4__(v84, 21);
  v116 = v115 + (v111 ^ (v108 - v114));
  v117 = __ROL4__(v116, 25);
  v118 = __ROL4__(v116, 4) ^ v109 ^ v110;
  v119 = v59 << 32;   //  ( part 5)
  v120 = v43 << 32;   // ( part 3) 
  v121 = v35;         // ( part 2)
  v122 = (unsigned __int64)((unsigned int)v115 ^ (v113 - (_DWORD)v118)) << 32;
```
- Trong đoạn code, biến v84 được xoay trái với các giá trị tăng dần theo cấp số cộng của 3 => Tổng cộng qua 8 lần vòng lặp, với magic const = `0x5F8C2E7A`, qua các phép tính mã hóa.
=> Kết quả của thuật toán là 4 số nguyên 32-bit, tương ứng với các part 2,3,4,5 của Key
Cuối cùng sẽ kiểm tra kết quả:
```cpp=
v124 = v51 | (unsigned __int64)v119;          // ghep phan 4 va 5 do ng nhap
  v125 = v121 | v120;                           // ghep phan 2 va 3 do ng nhap
  v126 = v115 | ((unsigned __int64)v117 << 32); // key do may tao
  v127 = v118 | v122;                           // key do may tao
if ( v127 ^ v125 | v126 ^ v124 )   // so sánh 
  goto LABEL_132; 
```
## Script
```python=
import hashlib
import struct
import binascii

# --- CÁC HÀM BỔ TRỢ ---
def rol32(val, r_bits):
    """Rotate Left 32-bit"""
    return ((val << r_bits) & 0xFFFFFFFF) | (val >> (32 - r_bits))

def crc32_func(data):
    """Standard CRC32"""
    return binascii.crc32(data) & 0xFFFFFFFF

# --- LOGIC CHÍNH ---
def generate_key(username, hwid_hex, timestamp, tier_int):
    # 1. Xử lý Input
    # Parse HWID từ Hex string (16 chars) sang 8 bytes raw
    try:
        hwid_bytes = binascii.unhexlify(hwid_hex)
    except:
        print("Lỗi: HWID phải là chuỗi Hex hợp lệ (độ dài chẵn, 0-9, A-F).")
        return

    # Map Tier sang chuỗi
    tier_map = {1: "BRNZ", 2: "SLVR", 3: "GOLD"}
    suffix = tier_map.get(tier_int, "UNK")

    # 2. Tạo SHA-256 Hash Buffer
    # Buffer = Username + HWID_Bytes + Timestamp(Little-Endian u64) + Tier(u8)
    # - "le64(timestamp) || u8(tier)"
    buffer = username.encode() + hwid_bytes + struct.pack('<Q', timestamp) + struct.pack('B', tier_int)
    
    sha_hash = hashlib.sha256(buffer).digest()

    # 3. Trích xuất h0-h3 (QUAN TRỌNG: LITTLE ENDIAN)

    h0, h1, h2, h3 = struct.unpack('<IIII', sha_hash[:16])

    # 4. Tính CRC32 của HWID Bytes
    c = crc32_func(hwid_bytes)

    # 5. Thuật toán 8 Vòng.
    MAGIC = 0x5f8c2e7a

    # Setup
    a = (h0 ^ c) & 0xFFFFFFFF
    b = (h1 + a) & 0xFFFFFFFF

    # Round 1
    b4 = rol32(b, 4) ^ h2
    x1 = b4 ^ MAGIC
    c3 = rol32(c, 3)
    y1 = x1 ^ c3
    # Phép trừ/cộng phải mask 0xFFFFFFFF để mô phỏng tràn số 32-bit
    d  = (((h3 - x1) & 0xFFFFFFFF) ^ a) + y1
    d  &= 0xFFFFFFFF 
    d4 = rol32(d, 4) ^ a

    # Round 2
    x2 = d4 ^ MAGIC
    c6 = rol32(c, 6)
    y2 = x2 ^ c6
    e  = (((rol32(b, 25) - x2) & 0xFFFFFFFF) ^ y1) + y2
    e  &= 0xFFFFFFFF

    # Round 3
    f1 = c3 ^ b4 ^ rol32(e, 4)
    c9 = rol32(c, 9)
    g1 = c9 ^ f1
    h_val = (((rol32(d, 25) - f1) & 0xFFFFFFFF) ^ y2) + g1
    h_val &= 0xFFFFFFFF

    # Round 4
    f2 = c6 ^ d4 ^ rol32(h_val, 4)
    c12 = rol32(c, 12)
    g2 = c12 ^ f2
    j  = (((rol32(e, 25) - f2) & 0xFFFFFFFF) ^ g1) + g2
    j  &= 0xFFFFFFFF

    # Round 5
    j4 = rol32(j, 4) ^ g1
    x5 = j4 ^ MAGIC
    c15 = rol32(c, 15)
    y5 = x5 ^ c15
    k  = (((rol32(h_val, 25) - x5) & 0xFFFFFFFF) ^ g2) + y5
    k  &= 0xFFFFFFFF

    # Round 6
    k4 = rol32(k, 4) ^ g2
    x6 = k4 ^ MAGIC
    c18 = rol32(c, 18)
    y6 = x6 ^ c18
    m  = (((rol32(j, 25) - x6) & 0xFFFFFFFF) ^ y5) + y6
    m  &= 0xFFFFFFFF

    # Round 7
    f7 = c15 ^ j4 ^ rol32(m, 4)
    c21 = rol32(c, 21)
    n  = c21 ^ f7
    p  = (((rol32(k, 25) - f7) & 0xFFFFFFFF) ^ y6) + n
    p  &= 0xFFFFFFFF

    # Round 8
    r_val = c18 ^ k4 ^ rol32(p, 4)

    # Final key parts
    key2 = r_val & 0xFFFFFFFF
    key3 = ((rol32(m, 25) - r_val) & 0xFFFFFFFF) ^ n
    key4 = n & 0xFFFFFFFF
    key5 = rol32(p, 25)
    final_key = f"KGIII-{key2:08X}-{key3:08X}-{key4:08X}-{key5:08X}-{suffix}"
    print(f"KEY:{final_key}")

generate_key("subscriber_silver", "DEAD5678FACE1234", 1770302143, 2) #( thay username, hwid, timestamp, tier vào đây).
```
- Nhập thử
![image](https://hackmd.io/_uploads/SyOfiQGDWx.png)
