How to execute JS like a binary
There are dozens of binary file formats that supported by operating systems thatwe use. Binary format is standard that helps operating system to determine howto execute file: read content, load part of them into a memory, extract additional data etc.
How operating system determines how it should execute one or the other binary file? There are several ways to do that: one of that is to look at file extension. For example if you use Windows operating system, you can easily rename any text file to add
.exe-extension and after that it will be looks like executable file, but, for sure, it cannot be executed because it doesn't follow structure of standard executable file for Windows.
Other way to determine that some file can be executed is read several first bytes of file. This first bytes called magic number. For example, in UNIX-like operating system, ELF file format, which is being commonly used, has magic number that consists of hexadecimal number
0x7F and followed by
ELF string. More interesting that Java class file and Mach-O file format, which is executable format for MacOS, have the same magic number:
CAFEBABE. Creator of Java, James Gosling, even explained why he chose this magic number and if it has common with Mach-O executable file format.
If you are using UNIX-like operating system, you can easily check content of any files in your system on byte-level, i.e. using program
hexdump. There is four bytes of executable
hexdump on my MacBook that were represented by hexadecimal numbers:
~ hexdump -n 4 /usr/bin/hexdump
0000000 ca fe ba be
In linux executable file is executed by kernel and format of executable is determinated using either magic numbers or file extension. Built-in module binfmt is responsible for this process. In linux 5.9 you can find seven file formats that kernel supports out of box. And, surprisingly, one of the format is shebang scripts — scripts, that start with
#! symbol combination. Thus, if you run, using your favorite shell program, script, which has permission to be executed, kernel will decide what to do with your script.
But the most interesting part of this mechanism that you can easily extend itusing custom binary formats. By default, your distribution has mounted folder
~ ls /proc/sys/fs/binfmt_misc
.js extension with
node program in the future:
# echo ":nodejs:E::js::/usr/bin/node:" > \
There are list of parameters, which delimited from each other using colons, that we specified in string: nodejs — name of executable format;
E— specify that we use file extension to determine file format. Other possible value of this parameter is M, which means that we should determinefile format by magic number;
js— value of target extension;
/usr/bin/node— path to executable that will be used for executing of file.
After that file nodejs should appears in the /proc/sys/fs/binfmt_misc folder:
~ ls /proc/sys/fs/binfmt_misc
nodejs register status
~ echo "console.log('Hello, world!')" > index.js
~ chmod +x ./index.js # Add permission to execute file