Ghost Wrangler
4 minutos de lectura
Se nos proporciona un binario llamado ghost
:
$ file ghost
ghost: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=810d0f9271ec04d80a2eee6ff2afd9367da3c3dd, for GNU/Linux 3.2.0, not stripped
Ingeniería inversa
Si lo abrimos en Ghidra, veremos el código en C descompilado de la función main
:
int main() {
undefined8 flag;
flag = get_flag();
printf("%s\r|\x1b[4m%*.c\x1b[24m| I\'ve managed to trap the flag ghost in this box, but it\'s turn ed invisible!\nCan you figure out how to reveal them?\n", flag, 0x28, 0x5f);
return 0;
}
Esta llama a una función llamada get_flag
y muestra una cadena de texto que contiene la variable flag
. Ests es la función get_flag
:
void* get_flag() {
void* __s;
uint i;
__s = malloc(0x29);
memset(__s, 0, 0x29);
for (i = 0; i < 0x28; i = i + 1) {
*(byte *) ((long) __s + (long) (int) i) = _[(int) i] ^ 0x13;
}
return __s;
}
Cifrado XOR
Si miramos atentamente, está realizando una operación XOR usando 0x13
com clave y una variable global llamada _
como datos cifrados. En Ghidra, tenemos estos bytes asignados a _
:
_ XREF[3]: Entry Point(*),
get_flag:0010118f(*),
get_flag:00101196(R)
00102020 5b 47 51 undefine
68 7b 27
66 7d 67
00102020 5b undefined15Bh [0] XREF[3]: Entry Point(*),
get_flag:0010118f(*),
get_flag:00101196(R)
00102021 47 undefined147h [1]
00102022 51 undefined151h [2]
00102023 68 undefined168h [3]
00102024 7b undefined17Bh [4]
00102025 27 undefined127h [5]
00102026 66 undefined166h [6]
00102027 7d undefined17Dh [7]
00102028 67 undefined167h [8]
00102029 20 undefined120h [9]
0010202a 77 undefined177h [10]
0010202b 4c undefined14Ch [11]
0010202c 71 undefined171h [12]
0010202d 6a undefined16Ah [13]
0010202e 4c undefined14Ch [14]
0010202f 67 undefined167h [15]
00102030 7b undefined17Bh [16]
00102031 20 undefined120h [17]
00102032 4c undefined14Ch [18]
00102033 74 undefined174h [19]
00102034 7b undefined17Bh [20]
00102035 23 undefined123h [21]
00102036 60 undefined160h [22]
00102037 67 undefined167h [23]
00102038 26 undefined126h [24]
00102039 4c undefined14Ch [25]
0010203a 23 undefined123h [26]
0010203b 75 undefined175h [27]
0010203c 4c undefined14Ch [28]
0010203d 70 undefined170h [29]
0010203e 67 undefined167h [30]
0010203f 75 undefined175h [31]
00102040 26 undefined126h [32]
00102041 4c undefined14Ch [33]
00102042 63 undefined163h [34]
00102043 27 undefined127h [35]
00102044 26 undefined126h [36]
00102045 67 undefined167h [37]
00102046 32 undefined132h [38]
00102047 6e undefined16Eh [39]
Flag
En este punto, cogí estos bytes y realicé el mismo cifrado XOR que en get_flag
para ver la flag:
$ python3 -q
>>> data = bytes([
... 0x5b,
... 0x47,
... 0x51,
... 0x68,
... 0x7b,
... 0x27,
... 0x66,
... 0x7d,
... 0x67,
... 0x20,
... 0x77,
... 0x4c,
... 0x71,
... 0x6a,
... 0x4c,
... 0x67,
... 0x7b,
... 0x20,
... 0x4c,
... 0x74,
... 0x7b,
... 0x23,
... 0x60,
... 0x67,
... 0x26,
... 0x4c,
... 0x23,
... 0x75,
... 0x4c,
... 0x70,
... 0x67,
... 0x75,
... 0x26,
... 0x4c,
... 0x63,
... 0x27,
... 0x26,
... 0x67,
... 0x32,
... 0x6e,
... ])
>>> from pwn import xor
>>> xor(data, b'\x13')
b'HTB{h4unt3d_by_th3_gh0st5_0f_ctf5_p45t!}'
Otra manera de resolverlo es simplemente procesando la salida del binario con xxd
, head
o tr
:
$ ./ghost | xxd
00000000: 4854 427b 6834 756e 7433 645f 6279 5f74 HTB{h4unt3d_by_t
00000010: 6833 5f67 6830 7374 355f 3066 5f63 7466 h3_gh0st5_0f_ctf
00000020: 355f 7034 3574 217d 0d7c 1b5b 346d 2020 5_p45t!}.|.[4m
00000030: 2020 2020 2020 2020 2020 2020 2020 2020
00000040: 2020 2020 2020 2020 2020 2020 2020 2020
00000050: 2020 2020 205f 1b5b 3234 6d7c 2049 2776 _.[24m| I'v
00000060: 6520 6d61 6e61 6765 6420 746f 2074 7261 e managed to tra
00000070: 7020 7468 6520 666c 6167 2067 686f 7374 p the flag ghost
00000080: 2069 6e20 7468 6973 2062 6f78 2c20 6275 in this box, bu
00000090: 7420 6974 2773 2074 7572 6e65 6420 696e t it's turned in
000000a0: 7669 7369 626c 6521 0a43 616e 2079 6f75 visible!.Can you
000000b0: 2066 6967 7572 6520 6f75 7420 686f 7720 figure out how
000000c0: 746f 2072 6576 6561 6c20 7468 656d 3f0a to reveal them?.
$ ./ghost | head -c 40
HTB{h4unt3d_by_th3_gh0st5_0f_ctf5_p45t!}
$ ./ghost | tr -d '\r'
HTB{h4unt3d_by_th3_gh0st5_0f_ctf5_p45t!}| _| I've managed to trap the flag ghost in this box, but it's turned invisible!
Can you figure out how to reveal them?
El problema era un carácter de retorno de carro (\r
, \x0d
), que hace que los caracteres siguientes sobrescriban la flag.