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, ¶ms[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