12

It is to my understanding that in /bin we have some binary executables that are just compiled C programs. Out of curiosity, I decided to play with them and I opened ls with sudo privileges using nano, and added the character 0 at the beginning. I saved the file and, to my amusement, I checked that indeed, executing the ls command in a terminal does not work.

What I did not expect is that after deleting this character I had added, the ls command still does not work and segfaults.

If the files contained in /bin are nothing but machine code with ones and zeros, why does deleting a character that we have previously added not yield a program that works?

3 Answers3

27

Editing a binary file with an editor meant for text may or may not work - in practice it usually won't. The editor might make various changes like fixing line endings (e.g., if a sequence of bytes in the file contained \r\n, the editor might "fix" that to \n, or fix occurrences of just \n to \r\n), adding a trailing newline if file didn't end with one, etc. There's a high likelihood that the ls binary did get corrupted by some of such changes. You can compare the output of od -c or hexdump on the original and modified files to see what changed, exactly. And consider using a hex editor in future (Please recommend a hex editor for shell) for editing non-text files.

Raffa
  • 34,963
muru
  • 207,228
23

Repeating your experiment and then comparing with the original using binwalk shows that the reason is indeed the conversion of 0x0D (CR) to 0x0A (LF) character:

$ binwalk -Wi test /bin/ls

OFFSET test /bin/ls

0x00000190 02 00 00 00 06 00 00 00 58 0D 02 00 00 00 00 00 |........X.......| \ 02 00 00 00 06 00 00 00 58 0A 02 00 00 00 00 00 |........X.......|

0x000015B0 01 00 0D 00 03 00 03 00 03 00 03 00 03 00 03 00 |................| / 01 00 0A 00 03 00 03 00 03 00 03 00 03 00 03 00 |................|

0x00001660 43 05 00 00 10 00 00 00 94 91 96 06 00 00 0D 00 |C...............| \ 43 05 00 00 10 00 00 00 94 91 96 06 00 00 0A 00 |C...............|

Likely one of these bytes was part of a memory address or an instruction involved in creating an address. Invalid memory address then results in the segmentation fault.

When you open the file, nano informs of this as (Converted from Mac format).

You can disable this conversion and the addition of a trailing newline by giving the command line options nano -LN. With these options the result is identical to the original, but editing binary files in this way is still prone to corruption.

jpa
  • 1,595
0

When doing that, you basically change the file type. To demonstrate, a quick. experiment:

cd /bin
sudo cp ls ls_copy  #ensure not to play around with binaries needed by the system
file ls_copy

The last commend will generate an output similar to the following:

ls_copy: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=36b86f957a1be53733633d184c3a3354f3fc7b12, for GNU/Linux 3.2.0, stripped

Now open ls_copy with Nano using root privileges:

sudo nano ls_copy

What happens here is that Nano opens the binary file ls_copy in text mode. You will see characters which most doesn't seem to make any sense. Add a character like a 0 at the beginning or any other position and save the file pressing STRG+o to write out the file. Now run

file ls_copy

again and you will get an output similar to

ls_copy: data

So obviously, ls_copy is not an executable binary anymore, but some kind of text-type file. Running

ls_copy

while result in an error like

-bash: /usr/bin/ls_copy: cannot execute binary file: Exec format error

due to that.

To edit binary file, you need to use a binary editor, not a text editor.

noisefloor
  • 1,769