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: dataThat 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.pngHmm, 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.pngas a binary:vi -b test.pngShow 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!