Tags: trustzone 

Rating:

The next task is a little harder than the previous. Open task2 in IDA and see that file not stripped, cool!
```C
int __cdecl main(int argc, const char **argv, const char **envp)
{
const char *v3; // r3
char *v4; // r2
int v7; // r0
int v8; // r1
_WORD *v9; // r4
const char *v10; // r4
int v11; // r7
int v12; // r0
int v13; // r6
size_t size; // r7
void *key_der; // r4
size_t v16; // r0
int mode; // r3
int file; // [sp+0h] [bp-40h]
char ses; // [sp+4h] [bp-3Ch]
char v21; // [sp+14h] [bp-2Ch]

v3 = "SUPERSECRETSTRING";
v4 = &v2;;
do... // cp v3 to v21
*v9 = *(_WORD *)v3;
if ( argc != 3
|| (v10 = argv[1], v11 = strcmp(argv[1], "decrypt"), v12 = strcmp(v10, "encrypt"), v13 = v12, v11) && v12 )
{
puts("Usage task2 <encrypt/decrypt> <name file>");
exit(0);
}
size = read_file(&file, (int)argv[2]);
prepare_tee_session(&ses);
key_der = malloc(0x20u);
memset(key_der, 173, 0x20u);
v16 = strlen(&v21);
memcpy(key_der, &v21, v16);
mode = v13;
if ( v13 )
mode = 1;
derive_key((int)&ses, (int)key_der, 0x20, mode);
finalize_op(&ses, &file, size);
if ( v13 )
printf("Your FLAG %s\n", "Hello_world");
save_file((const void **)&file, (int)argv[2], size);
terminate_tee_session(&ses);
free(key_der);
return 0;
}
```
We see that there is a certain derive of a key and the finalize op of the decryption or encryption operation. The key is derive on the basis of the SUPERSECRETSTRING string padded to length with 32 bytes `0xad`. In func `read_file` seen that file will padding with zero bytes to length multiple 16. When a file is encrypted / decrypted, it is saved to the same file. Ok, lets check func `derive_key` and `finalize_op`.
```C
nt __fastcall derive_key(int *ses, int key, int key_len, int mode)
{
int result; // r0
int v9; // [sp+0h] [bp-58h]
TEEC_Operation op; // [sp+4h] [bp-54h]

memset(&op, 0, 0x3Cu);
op.paramTypes = 21;
op.params[0].tmpref = key;
op.params[1].tmpref = key_len;
op.params[3].tmpref = mode;
result = TEEC_InvokeCommand(ses + 2, 1, &op, &v9;;
if ( result )
errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x", result, v9);
return result;
}
```
```C
void __fastcall finalize_op(int ses, void **file, size_t size)
{
void *out_buf; // r6
int v7; // r2
int v8; // [sp+0h] [bp-58h]
TEEC_Operation s; // [sp+4h] [bp-54h]

memset(&s, 0, 0x3Cu);
out_buf = malloc(size);
s.paramTypes = 101;
s.params[0].tmpref = (uint32_t)*file;
s.params[1].tmpref = size;
s.params[3].tmpref = (uint32_t)out_buf;
s.imp = size;
v7 = TEEC_InvokeCommand(ses + 8, 2, &s, &v8;;
if ( v7 )
errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x", v7, v8);
free(*file);
*file = out_buf;
}
```
`derive_key` sends key and mode (dec / enc),` finalize_op` sends input data and output buffer to TA. There is nothing to watch now, close client and open TA same way as in first task.Find `TA_InvokeCommandEntryPoint` function by xrefs to same string. Found 2 supported command is finalize_op, and derive_key named by the same names in client.
```C
int __fastcall TA_InvokeCommandEntryPoint(int sessionContext, int commandID, int paramTypes, int params)
{
if ( commandID == 1 )
return derive_key((_DWORD *)sessionContext, paramTypes, (int *)params);
if ( commandID == 2 )
return finalize_op(sessionContext, paramTypes, params);
sub_5DA("TA_InvokeCommandEntryPoint", 213, 1, 1, "Command ID 0x%x is not supported", commandID, params, paramTypes);
return 0xFFFF000A;
}
signed int __fastcall derive_key(_DWORD *sessionContext, int paramTypes, TEEC_Parameter *params)
{
int xor_key; // [sp+18h] [bp+8h]
int v8; // [sp+1Ch] [bp+Ch]
int size; // [sp+28h] [bp+18h]
int key; // [sp+2Ch] [bp+1Ch]
int v12; // [sp+34h] [bp+24h]
int i; // [sp+38h] [bp+28h]
int v14; // [sp+3Ch] [bp+2Ch]

v12 = 21;
if ( paramTypes != 21 )
return 0xFFFF0006;
*sessionContext = params[2].tmpref;
if...
v14 = allocate_operation(sessionContext + 1, 0x10000110u, *sessionContext, 0x100u);// TEE_ALG_AES_CBC_NOPAD
if ( v14 )
{
sub_5DA("derive_key", 44, 1, 1, "Failed to allocate operation");
sessionContext[1] = 0;
}
else
{
key = params->tmpref;
size = params[1].tmpref;
getprop(0xFFFFFFFF, "unictf.2020.data.key", &xor_key);// 0x41
for ( i = 0; i <= 15; ++i )
*(_BYTE *)(i + key) ^= (_BYTE)i + (_BYTE)xor_key;
v14 = allocate_transient_object(0xA0000010, 256, sessionContext + 2);// TEE_TYPE_AES
if ( v14 )
{
sub_5DA("derive_key", 63, 1, 1, "Failed to allocate transient object");
sessionContext[2] = 0;
}
else
{
sub_1140E((int)&v8, 0xC0000000, key, size);// secret value
v14 = TEE_PopulateTransientObject(sessionContext[2], &v8, 1);
if ( !v14 )
return 0;
sub_5DA("derive_key", 72, 1, 1, "TEE_PopulateTransientObject failed, %x", v14);
}
}
if...
sessionContext[1] = 0;
if...
sessionContext[2] = 0;
return v14;
}
```

Okey general key derive is:
```python
key = list(b"SUPERSECRETSTRING"+b"\xad"*(32-17))
for i in range(16):
key[i]^=(0x41+i)
```
check finalyze func to get iv
```C
signed int __fastcall finalize_op(int *session, int paramtypes, TEEC_Parameter *params)
{
int v6; // r3
char iv[16]; // [sp+1Ch] [bp+8h]
int v10; // [sp+2Ch] [bp+18h]
int v12; // [sp+34h] [bp+20h]

v12 = 101;
if ( paramtypes != 101 )
return 0xFFFF0006;
v10 = TEE_SetOperationKey(session[1], session[2]);
if ( v10 )
{
sub_5DA("finalize_op", 107, 1, 1, "TEE_SetOperationKey failed %x", v10);
if ( session[1] )
sub_340A(session[1]);
session[1] = 0;
if ( session[2] )
sub_111F6(session[2]);
session[2] = 0;
v6 = v10;
}
else
{
memset((int)iv, 0, 0x10);
sub_3CBA(session[1], iv, 0x10);
v6 = sub_4062(session[1], params->tmpref, params[1].tmpref, params[2].tmpref, &params[3].tmpref);
}
return v6;
}
```
Now try decrypt with this key flag
```Python
from Crypto.Cipher import AES

flag=open("flag.enc","rb").read()
key = list(b"SUPERSECRETSTRING"+b"\xad"*(32-17))
for i in range(16):
key[i]^=(0x41+i)
key_b=b""
for i in key:
key_b+=i.to_bytes(1,"little")
cipher = AES.new(key_b, AES.MODE_CBC, b"\x00"*16)
cipher.decrypt(flag)
>>> b'unictf{A4@1n_F1l3_ENCRYPTION}\n\x00\x00'
```
Decrypt private.enc
```python
private = open("Private.enc","rb").read()
cipher = AES.new(key_b, AES.MODE_CBC, b"\x00"*16)
private = cipher.decrypt(private)
with open("private.der","wb") as f:
f.write(private)
```
And lets try to solve next task