Cryptohorrific
3 minutos de lectura
Se nos proporciona una aplicación de iOS. Dentro podemos encontrar un archivo llamado challenge.plist que no es legible.
Solución
Mediante una herramienta llamada plistutil, es posible extraer la información en formato XML:
$ plistutil -i hackthebox.app/challenge.plist -o challenge.plist.xml
$ cat challenge.plist.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>flag</key>
<string>Tq+CWzQS0wYzs2rJ+GNrPLP6qekDbwze6fIeRRwBK2WXHOhba7WR2OGNUFKoAvyW7njTCMlQzlwIRdJvaP2iYQ==</string>
<key>id</key>
<string>123</string>
<key>title</key>
<string>HackTheBoxIsCool</string>
</dict>
</array>
</plist>
La flag no solo está codificada en Base64, sino que también está cifrada:
$ echo Tq+CWzQS0wYzs2rJ+GNrPLP6qekDbwze6fIeRRwBK2WXHOhba7WR2OGNUFKoAvyW7njTCMlQzlwIRdJvaP2iYQ== | base64 -d | xxd
00000000: 4eaf 825b 3412 d306 33b3 6ac9 f863 6b3c N..[4...3.j..ck<
00000010: b3fa a9e9 036f 0cde e9f2 1e45 1c01 2b65 .....o.....E..+e
00000020: 971c e85b 6bb5 91d8 e18d 5052 a802 fc96 ...[k.....PR....
00000030: ee78 d308 c950 ce5c 0845 d26f 68fd a261 .x...P.\.E.oh..a
Usando Ghidra podemos analizar el contenido de la aplicación (llamada hackthebox, que es un binario MacOS X Mach-O). Hay una clase llamada ViewController que tiene una función SecretManager:key:iv:data::
ID ViewController::SecretManager:key:iv:data:(ID param_1, SEL param_2, unsigned int param_3, ID param_4, ID param_5, ID param_6) {
CCOperation op;
CCCryptorStatus CVar1;
undefined8 uVar2;
void *dataIn;
ID IVar3;
size_t local_b0;
void *local_a8;
size_t local_a0;
size_t local_98;
undefined8 local_90;
long local_88;
undefined8 local_80;
unsigned int local_74;
SEL local_70;
ID local_68;
undefined8 local_60;
undefined local_58[32];
undefined local_38[24];
long local_20;
local_20 = *(long *) __got::___stack_chk_guard;
local_80 = 0;
local_74 = param_3;
local_70 = param_2;
local_68 = param_1;
__stubs::_objc_storeStrong(&local_80, param_4);
local_88 = 0;
__stubs::_objc_storeStrong(&local_88, param_5);
local_90 = 0;
__stubs::_objc_storeStrong(&local_90);
__stubs::_memset(local_38, 0, 0x11);
__stubs::_objc_msgSend(local_80, "getCString:maxLength:encoding:", local_38, 0x11, 4);
__stubs::_memset(local_58, 0, 0x11);
if (local_88 != 0) {
__stubs::_objc_msgSend(local_88, "getCString:maxLength:encoding:", local_58, 0x11, 4);
}
local_98 = __stubs::_objc_msgSend(local_90, "length");
local_a0 = local_98 + 0x10;
local_a8 = __stubs::_malloc(local_a0);
op = local_74;
local_b0 = 0;
uVar2 = __stubs::_objc_retainAutorelease(local_90);
dataIn = (void *) __stubs::_objc_msgSend(uVar2);
CVar1 = __stubs::_CCCrypt(op, 0, 3, local_38, 0x10, local_58, dataIn, local_98, local_a8, local_a0, &local_b0);
if (CVar1 == 0) {
uVar2 = __stubs::_objc_msgSend(&_OBJC_CLASS_$_NSData, "dataWithBytesNoCopy:length:", local_a8, local_b0);
local_60 = __stubs::_objc_retainAutoreleasedReturnValue(uVar2);
} else {
__stubs::_free(local_a8);
local_60 = 0;
}
__stubs::_objc_storeStrong(&local_90, 0);
__stubs::_objc_storeStrong(&local_88, 0);
__stubs::_objc_storeStrong(&local_80, 0);
IVar3 = __stubs::_objc_autoreleaseReturnValue(local_60);
if (*(long *) __got::___stack_chk_guard == local_20) {
return IVar3;
}
/* WARNING: Subroutine does not return */
__stubs::___stack_chk_fail();
}
Está usando _CCCrypt para descifrar un texto cifrado. Según developer.apple.com, esta función se emplea para utilizar cifrados simétricos como AES.
La función anterior se llama desde viewDidLoad:
void ViewController::viewDidLoad(ID param_1, SEL param_2) {
undefined8 uVar1;
undefined8 uVar2;
undefined8 uVar3;
undefined8 uVar4;
undefined8 uVar5;
undefined8 uVar6;
undefined8 uVar7;
undefined8 uVar8;
ID IVar9;
ID IVar10;
ID local_28;
class_t *local_20;
SEL local_18;
ID local_10;
local_20 = &objc::class_t::ViewController;
local_28 = param_1;
local_18 = param_2;
local_10 = param_1;
__stubs::_objc_msgSendSuper2(&local_28, "viewDidLoad");
uVar1 = *(undefined8 *) (local_10 + l);
uVar2 = __stubs::_objc_msgSend(&_OBJC_CLASS_$_NSString, "alloc");
IVar10 = local_10;
uVar3 = __stubs::_objc_msgSend(&_OBJC_CLASS_$_NSData, "alloc");
uVar4 = __stubs::_objc_msgSend(&_OBJC_CLASS_$_NSArray, "alloc");
uVar5 = __stubs::_objc_msgSend(&_OBJC_CLASS_$_NSBundle, "mainBundle");
uVar5 = __stubs::_objc_retainAutoreleasedReturnValue(uVar5);
uVar6 = __stubs::_objc_msgSend(uVar5, "pathForResource:ofType:", &cf_challenge, &cf_plist);
uVar6 = __stubs::_objc_retainAutoreleasedReturnValue(uVar6);
uVar4 = __stubs::_objc_msgSend(uVar4, "initWithContentsOfFile:", uVar6);
uVar7 = __stubs::_objc_msgSend(uVar4, "objectAtIndex:", 0);
uVar7 = __stubs::_objc_retainAutoreleasedReturnValue(uVar7);
uVar8 = __stubs::_objc_msgSend(uVar7, "objectForKey:", &cf_flag);
uVar8 = __stubs::_objc_retainAutoreleasedReturnValue(uVar8);
IVar9 = __stubs::_objc_msgSend(uVar3, "initWithBase64EncodedString:options:", uVar8, 0);
IVar10 = SecretManager:key:iv:data:(IVar10, (SEL) "SecretManager:key:iv:data:", 1, (ID) "!A%D*G-KaPdSgVkY", (ID) "QfTjWnZq4t7w!z%C", IVar9);
uVar3 = __stubs::_objc_retainAutoreleasedReturnValue(IVar10);
uVar2 = __stubs::_objc_msgSend(uVar2, "initWithData:encoding:", uVar3, 4);
__stubs::_objc_msgSend(uVar1, "setText:", uVar2);
__stubs::_objc_release(uVar2);
__stubs::_objc_release(uVar3);
__stubs::_objc_release(IVar9);
__stubs::_objc_release(uVar8);
__stubs::_objc_release(uVar7);
__stubs::_objc_release(uVar4);
__stubs::_objc_release(uVar6);
__stubs::_objc_release(uVar5);
return;
}
Aquí vemos que la función coge la flag cifrada de challenge.plist y trata de descifrarla usando !A%D*G-KaPdSgVkY como clave y QfTjWnZq4t7w!z%C como IV.
Flag
Aunque tenemos un IV, el descifrado se hace con AES ECB, que no utiliza IV. La flag se puede capturar así:
$ python3 -q
>>> from Crypto.Cipher import AES
>>> from Crypto.Util.Padding import unpad
>>> from base64 import b64decode
>>> key = b'!A%D*G-KaPdSgVkY'
>>> ct = b64decode('Tq+CWzQS0wYzs2rJ+GNrPLP6qekDbwze6fIeRRwBK2WXHOhba7WR2OGNUFKoAvyW7njTCMlQzlwIRdJvaP2iYQ==')
>>> cipher = AES.new(key, AES.MODE_ECB)
>>> unpad(cipher.decrypt(ct), 16)
b'HTB{%SoC00l_H4ckTh3b0xbyBs3cur31stCh4ll3ng3!!Cr4zY%}'