CTF, ELF binaries and magic bytes
Just a short blog on a fun CTF challenge I did related to ELF binaries.
ctfI had a spare weekend so I particiapated in a CTF competition conducted by my college’s CS club. In the event, one challenge really stood apart and hence I’m writing about it.
The challenge #
On the website, a ‘PNG’ file was provided initially, called
test.png
. This file was the only clue to the flag.
My approach #
Given the fact that only a file was provided as a clue, and that it wouldn’t
open using an image viewer. It was obvious what I needed to do first, and that
was the classic file
command.
$ file test.png
test.png: data
That is not how a PNG file looks like, so I went ahead with cat
.
$ cat test.png
�PNG>P@`9@8
���-�=�=HP�-�=�=����DDP�td8 8 8 <<Q�tdR�td�-�=�=/lib64/ld-linux-x86-64.so.2GNU Z��_���09�DfWͫ�w�GNU��e�m? [ j"printf__cxa_finalize__libc_start_mainlibc.so.6GLIBC_2.2.5_ITM_deregisterTMCloneTable__gmon_start___ITM_registerTMCloneTable)ui 3�0��((@�?�?�?�?�?@H�H��/H��t��H���5�/�%�/@�%�/h������%�/f�1�I��^3H�=��f/�DH�=�/H��/H9�tH�>/H��t �����H�=y/H�5r/H)�H��H��?H��H�H��tH�/H����fD���=9/u/UH�=�.H��t
H�=/�-����h����/]�����{���UH��H�jnjijajrjbjwjejnjsjyjejojjjhjtA�iA�w�e�n�oH�=������H�쀸��f.�@AWL�=?,AVI��AUI��ATA��UH�-0,SL)�H��3���H��t�L��L��D��A��H��H9�u�H�[]A\A]A^A_��H�H��flag{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}<�����������X�����h��������0zRx
����+zRx
$X��� FJ
X �?;*3$"DP��\-���]A�C
D|x���]B�I�E �E(�D0�H8�G@j8A0A(B BB�����0�)
������0
�
@P� ������op���o���o\���o�=6(@GCC: (Debian 10.2.1-6) 10.2.1 20210110��0�p �
P
@P 8 x �=�=�=�?@ @0@��
��!�70@C�=j0v�=������|!����=��=��=�8 �@�
f @,0@
3Fd @q �(@� ��]�8@jP+�0@�5]�0@� �"crtstuff.cderegister_tm_clones__do_global_dtors_auxcompleted.0__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entrytest.c__FRAME_END____init_array_end_DYNAMIC__init_array_start__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE___libc_csu_fini_ITM_deregisterTMCloneTable_edataprintf@GLIBC_2.2.5__libc_start_main@GLIBC_2.2.5__data_start__gmon_start____dso_handle_IO_stdin_used__libc_csu_init__bss_startmain__TMC_END___ITM_registerTMCloneTable__cxa_finalize@GLIBC_2.2.5.symtab.strtab.shstrtab.interp.note.gnu.build-id.note.ABI-tag.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.dynamic.got.plt.data.bss.comment�#��$6�� D��No
0V���^���o\\k���oppz���BP�� �PP�� � �8 8 <�x ������=�-��?��@� @ 0@0�000'X0- X6�V8%
The things which jump out at me from the above output are the following:
(@GCC: (Debian 10.2.1-6) 10.2.1
=/lib64/ld-linux-x86-64.so.2
They are something you normally won’t find in a PNG file. Instead, they’re
found in ELF binaries. To verify this, I compared the output of cat
with the
ls
binary. The output is a bit verbose so I’ll skip it here.
Now, we know that test.png
is actually a binary instead of an image, we can
go ahead and execute it.
$ chmod +x test.png
$ ./test.png
zsh: exec format error: ./test.png
Hmm, guess it won’t be that easy. Since file
was failing to detect test.png
as an ELF earlier, the error probably lies somewhere in the header bytes of the
ELF binary.
$ xxd test.png | head -n 1
00000000: 8950 4e47 0201 0100 0000 0000 0000 0000 .PNG............
$ xxd /bin/ls | head -n 1
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
We can see that the first 4 bytes in test.png
have been tampered with.
Therefore, we can fix the header bytes by correctly indicating that test.png
is actually and ELF binary.
I used vim
alongwith xxd
for editing the test.png
in hex.
Open
test.png
as a binary:vi -b test.png
Show the hexdump of the buffer:
:%!xxd
Fix the magic bytes
Reverse the hexdump into the buffer:
:%!xxd -r
Save contents of buffer as
test
::w test
After fixing the ELF magic bytes, we can see that file
properly detects the
file type for test
and that we can execute it to get the flag.
$ file test
test: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=205a03bd925f839ef43039d5446657cdabca7785, for GNU/Linux 3.2.0, not stripped
$ chmod +x test
$ ./test
flag{onewithjoeysnewbrain}%
Conclusion #
This was a fun exercise and I enjoyed dipping my finger into the guts of binaries.
Comments
iiit_first_year #
What about binwalk?
Anurag Kar #
Nice Work!