Graverobber
5 minutos de lectura
Se nos proporciona un binario llamado robber
:
$ file pass
robber: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=972b4d1424b8cd4916e26b94ebb6257f970e4cbb, for GNU/Linux 4.4.0, not stripped
Si ejecutamos el programa, aparentemente no pasa nada:
$ ./robber
We took a wrong turning!
Descompilación
Si abrimos el binario en IDA, veremos la siguiente función main
:
int __fastcall main(int argc, const char** argv, const char** envp) {
unsigned int i; // [rsp+Ch] [rbp-E4h]
stat buf; // [rsp+10h] [rbp-E0h] BYREF
char file[8]; // [rsp+A0h] [rbp-50h] BYREF
__int64 v7; // [rsp+A8h] [rbp-48h]
__int64 v8; // [rsp+B0h] [rbp-40h]
__int64 v9; // [rsp+B8h] [rbp-38h]
__int64 v10; // [rsp+C0h] [rbp-30h]
__int64 v11; // [rsp+C8h] [rbp-28h]
__int64 v12; // [rsp+D0h] [rbp-20h]
__int64 v13; // [rsp+D8h] [rbp-18h]
int v14; // [rsp+E0h] [rbp-10h]
unsigned __int64 v15; // [rsp+E8h] [rbp-8h]
v15 = __readfsqword(0x28u);
*(_QWORD *)file = 0;
v7 = 0;
v8 = 0;
v9 = 0;
v10 = 0;
v11 = 0;
v12 = 0;
v13 = 0;
v14 = 0;
for (i = 0; i <= 0x1F; ++i) {
file[2 * i] = parts[i];
file[2 * i + 1] = '/';
if (stat(file, &buf)) {
puts("We took a wrong turning!");
return 1;
}
}
puts("We found the treasure! (I hope it's not cursed)");
return 0;
}
El programa toma caracteres de un array global llamado parts
y añade barras entre ellos. Una vez añadida una barra, llama a stat
para verificar si existe un archivo. Así es como se ve el array:
.data:0000000000004040 parts db 48h ; DATA XREF: main+7D↑o
.data:0000000000004041 db 0
.data:0000000000004042 db 0
.data:0000000000004043 db 0
.data:0000000000004044 db 54h ; T
.data:0000000000004045 db 0
.data:0000000000004046 db 0
.data:0000000000004047 db 0
.data:0000000000004048 db 42h ; B
.data:0000000000004049 db 0
.data:000000000000404A db 0
.data:000000000000404B db 0
.data:000000000000404C db 7Bh ; {
.data:000000000000404D db 0
.data:000000000000404E db 0
.data:000000000000404F db 0
.data:0000000000004050 db 62h ; b
.data:0000000000004051 db 0
.data:0000000000004052 db 0
.data:0000000000004053 db 0
.data:0000000000004054 db 72h ; r
.data:0000000000004055 db 0
.data:0000000000004056 db 0
.data:0000000000004057 db 0
.data:0000000000004058 db 33h ; 3
.data:0000000000004059 db 0
.data:000000000000405A db 0
.data:000000000000405B db 0
.data:000000000000405C db 34h ; 4
.data:000000000000405D db 0
.data:000000000000405E db 0
.data:000000000000405F db 0
.data:0000000000004060 db 6Bh ; k
.data:0000000000004061 db 0
.data:0000000000004062 db 0
.data:0000000000004063 db 0
.data:0000000000004064 db 31h ; 1
.data:0000000000004065 db 0
.data:0000000000004066 db 0
.data:0000000000004067 db 0
.data:0000000000004068 db 6Eh ; n
.data:0000000000004069 db 0
.data:000000000000406A db 0
.data:000000000000406B db 0
.data:000000000000406C db 39h ; 9
.data:000000000000406D db 0
.data:000000000000406E db 0
.data:000000000000406F db 0
.data:0000000000004070 db 5Fh ; _
.data:0000000000004071 db 0
.data:0000000000004072 db 0
.data:0000000000004073 db 0
.data:0000000000004074 db 64h ; d
.data:0000000000004075 db 0
.data:0000000000004076 db 0
.data:0000000000004077 db 0
.data:0000000000004078 db 30h ; 0
.data:0000000000004079 db 0
.data:000000000000407A db 0
.data:000000000000407B db 0
.data:000000000000407C db 77h ; w
.data:000000000000407D db 0
.data:000000000000407E db 0
.data:000000000000407F db 0
.data:0000000000004080 db 6Eh ; n
.data:0000000000004081 db 0
.data:0000000000004082 db 0
.data:0000000000004083 db 0
.data:0000000000004084 db 5Fh ; _
.data:0000000000004085 db 0
.data:0000000000004086 db 0
.data:0000000000004087 db 0
.data:0000000000004088 db 74h ; t
.data:0000000000004089 db 0
.data:000000000000408A db 0
.data:000000000000408B db 0
.data:000000000000408C db 68h ; h
.data:000000000000408D db 0
.data:000000000000408E db 0
.data:000000000000408F db 0
.data:0000000000004090 db 33h ; 3
.data:0000000000004091 db 0
.data:0000000000004092 db 0
.data:0000000000004093 db 0
.data:0000000000004094 db 5Fh ; _
.data:0000000000004095 db 0
.data:0000000000004096 db 0
.data:0000000000004097 db 0
.data:0000000000004098 db 73h ; s
.data:0000000000004099 db 0
.data:000000000000409A db 0
.data:000000000000409B db 0
.data:000000000000409C db 79h ; y
.data:000000000000409D db 0
.data:000000000000409E db 0
.data:000000000000409F db 0
.data:00000000000040A0 db 73h ; s
.data:00000000000040A1 db 0
.data:00000000000040A2 db 0
.data:00000000000040A3 db 0
.data:00000000000040A4 db 63h ; c
.data:00000000000040A5 db 0
.data:00000000000040A6 db 0
.data:00000000000040A7 db 0
.data:00000000000040A8 db 34h ; 4
.data:00000000000040A9 db 0
.data:00000000000040AA db 0
.data:00000000000040AB db 0
.data:00000000000040AC db 6Ch ; l
.data:00000000000040AD db 0
.data:00000000000040AE db 0
.data:00000000000040AF db 0
.data:00000000000040B0 db 6Ch ; l
.data:00000000000040B1 db 0
.data:00000000000040B2 db 0
.data:00000000000040B3 db 0
.data:00000000000040B4 db 35h ; 5
.data:00000000000040B5 db 0
.data:00000000000040B6 db 0
.data:00000000000040B7 db 0
.data:00000000000040B8 db 7Dh ; }
.data:00000000000040B9 db 0
.data:00000000000040BA db 0
.data:00000000000040BB db 0
.data:00000000000040BC db 0
.data:00000000000040BD db 0
.data:00000000000040BE db 0
.data:00000000000040BF db 0
.data:00000000000040BF _data ends
.data:00000000000040BF
Evidentemente, es la flag. Entonces, el programa está verificando si H
existe como un directorio, luego H/T
, luego H/T/B
, y así sucesivamente. Obviamente, esto es inútil, pero ya tenemos la flag.
Solución
La forma más directa de obtener la flag es manualmente. Pero hay formas más rápidas, como usar simplemente cat
sobre el binario, ya que los bytes de la flag están separados por bytes nulos, que no se imprimen:
$ catn robber
@@@@���yy ���-�=�=���-�=�=�888@xxxDDS�td888@P�tdX X X $$Q�tdR�td�-�=�=00/lib64/ld-linux-x86-64.so.20GNU����GNU�+M$��I�k��%�L�GNUs � � ."puts__stack_chk_failstat__libc_start_main__cxa_finalizelibc.so.6GLIBC_2.33GH��������H�U�dH+%(t���������H�H��We took a wrong turning!We found the treasure! (I hope it's not cursed);$�������@����zR�����&D$4h���@FJ ���H�E�H��H���:�����tH���H��H��?H��H�H��tH��.H����fD����=�/u3UH�=�.H��t
�?;*3$"\y���A�C
P=
l�����o���
�
�?H�� ������o����o���op���o�=6FV(@HTB{br34k1n9_d0wn_th3_sysc4ll5}GCC: (GNU) 14.2.1 20240805GCC: (GNU) 14.2.1 20240910����=X $�?:W � @s��@�l��@@�� @� ��(@� ��@�`&��@
Y�@ 6"Q
main.c_DYNAMIC__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE___libc_start_main@GLIBC_2.34_ITM_deregisterTMCloneTableputs@GLIBC_2.2.5_edata_fini__stack_chk_fail@GLIBC_2.4parts__data_start__gmon_start__stat@GLIBC_2.33__dso_handle_IO_stdin_used_end__bss_startmain__TMC_END___ITM_registerTMCloneTable__cxa_finalize@GLIBC_2.2.5_init.symtab.strtab.shstrtab.interp.note.gnu.property.note.gnu.build-id.note.ABI-tag.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.dynamic.got.got.plt.data.bss.comment#886xx$I�� W���o�a
��i���q���opp~���o������B���� @�``
0�06�0� �3W�4
También podemos usar objdump
para obtener la dirección del array global:
$ objdump -j .data -s robber
robber: file format elf64-x86-64
Contents of section .data:
4020 00000000 00000000 28400000 00000000 ........(@......
4030 00000000 00000000 00000000 00000000 ................
4040 48000000 54000000 42000000 7b000000 H...T...B...{...
4050 62000000 72000000 33000000 34000000 b...r...3...4...
4060 6b000000 31000000 6e000000 39000000 k...1...n...9...
4070 5f000000 64000000 30000000 77000000 _...d...0...w...
4080 6e000000 5f000000 74000000 68000000 n..._...t...h...
4090 33000000 5f000000 73000000 79000000 3..._...s...y...
40a0 73000000 63000000 34000000 6c000000 s...c...4...l...
40b0 6c000000 35000000 7d000000 00000000 l...5...}.......
Flag
Luego, podemos usar xxd
o dd
para tomar la flag desde esa dirección específica (menos 0x1000
):
$ xxd -s 0x3040 robber | head -8
00003040: 4800 0000 5400 0000 4200 0000 7b00 0000 H...T...B...{...
00003050: 6200 0000 7200 0000 3300 0000 3400 0000 b...r...3...4...
00003060: 6b00 0000 3100 0000 6e00 0000 3900 0000 k...1...n...9...
00003070: 5f00 0000 6400 0000 3000 0000 7700 0000 _...d...0...w...
00003080: 6e00 0000 5f00 0000 7400 0000 6800 0000 n..._...t...h...
00003090: 3300 0000 5f00 0000 7300 0000 7900 0000 3..._...s...y...
000030a0: 7300 0000 6300 0000 3400 0000 6c00 0000 s...c...4...l...
000030b0: 6c00 0000 3500 0000 7d00 0000 0000 0000 l...5...}.......
$ xxd -s 0x3040 robber | head -8 | xxd -r
HTB{br34k1n9_d0wn_th3_sysc4ll5}
$ dd if=./robber skip=$((0x3040)) count=$((0x30c0 - 0x3040)) bs=1 2>/dev/null
HTB{br34k1n9_d0wn_th3_sysc4ll5}