Expletive
© 2015 Russ Olsen
Expletive is a simple pair of utilities that allow you to dump a file -- presumably a binary file -- into a plain text format that you can edit. The trick is that as long as you follow the expletive conventions as you edit you can turn your plain text back into a binary file. So expletive has all the charm of your typical hex editor, without having to learn a new editor. Just use vim or emacs or lightTable or any other editor of your choice.
And the name... Well typically by the time I come to having to edit a binary file I'm usually muttering some bad words.
Installation
Add this line to your application's Gemfile:
gem 'expletive'
And then execute:
$ bundle
Or install it yourself as:
$ gem install expletive
Usage
Expletive is really just two commands, exdump
and exundump
. The exdump
command will take your binary file and
turn it into something you can edit with an ordinary text editor. For example, if I wanted to
edit the ls
command, I would do something like:
$ exdump < /bin/ls >ls.dump
What you will end up with in ls.dump
will be plain text, albeit somewhat intimidating plain text:
\cf\fa\ed\fe\07\00\00\01\03\00\00\80\02\00\00\00\13\00\00\00\18
\07\00\00\85\00 \00\00\00\00\00\19\00\00\00H\00\00\00__PAGEZE
RO\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01\00
\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00
\00\00\00\00\00\00\00\00\00\00\00\00\00\19\00\00\00(\02\00\00
__TEXT\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00
You can then edit the ls.dump
file, making any changes you desire. Once you are
done you can turn your modified text back into binary with exundump
.
$ exundump < ls.dump > ls.new
The Dump File Format
The format of the dumped files is as simple as my small mind can make it:
-
Backslashes get converted to double backslashes, so \ becomes \\.
-
Newlines get converted to \n - that's a backslash character followed by an "n".
-
Any byte that looks like a simple, human readable single byte character is written as is.
-
Otherwise the byte is written as a backslash followed by a two digit hex number. Note that this number is zero filled: It's always \03, never \3.
-
The
exdump
command will periodically insert actual newlines into the output to make it more readable. Actual newlines are ignored byexundump
.
That's it!
An Example
Have you ever noticed that when you do ls -l
in your terminal, ls
prints
the total number of bytes at the top of the output?
~/projects/ruby/expletive: ls -l
total 304
-rw-r--r-- 1 russolsen staff 347 Jun 10 08:56 CHANGELOG.md
-rw-r--r-- 1 russolsen staff 55 Jun 10 09:20 Gemfile
-rw-r--r-- 1 russolsen staff 672 Jun 10 08:56 Gemfile.lock
-rw-r--r-- 1 russolsen staff 1067 Jun 10 08:56 LICENSE
...
Now imagine that for some obscure reason you wanted to make that
total show up as YOOO!. Nothing to it. First dump the contents
of the (very binary) ls
command to some file:
exdump </bin/ls >ls.dump
Then edit the resulting dump file with the editor of your choice:
vi ls.dump
And look for the string total. Here is what I see when I do that:
llu\00%lu\00printscol\00/SourceCache/file_cmds/file_cmds-242/
ls/print.c\00dp\00total %qu\n\00%*llu \00%*qu \00%s%s %*u \00
%s%s %*u %-*s \00%s%s %*u %-*s %-*s \00%-*s \00%3d, 0x%08x
\00%3d, %3d \00%*s%*qu \00, \00printcol\00dp->list\00base <·
Notice the total on the second line. Now all you need to do is change total to YOOO! or some other amusing string:
llu\00%lu\00printscol\00/SourceCache/file_cmds/file_cmds-242/
ls/print.c\00dp\00YOOO! %qu\n\00%*llu \00%*qu \00%s%s %*u \00
%s%s %*u %-*s \00%s%s %*u %-*s %-*s \00%-*s \00%3d, 0x%08x
\00%3d, %3d \00%*s%*qu \00, \00printcol\00dp->list\00base <·
Note that you need to make sure that your new string is the same length as the old one (e.g. total) because executables contain counts and offsets that you don't want to mess up.
Having made your change, you just need to convert your dump file back
to a binary. But don't overwrite your system's ls
command!
exundump <ls.dump >ls.new
Make your new ls.new
file executable:
chmod +x ls.new
And run your hacked binary:
./ls.new -l
YOOO! 312
-rw-r--r-- 1 russolsen staff 347 Jun 10 08:56 CHANGELOG.md
-rw-r--r-- 1 russolsen staff 55 Jun 10 09:20 Gemfile
-rw-r--r-- 1 russolsen staff 672 Jun 10 08:56 Gemfile.lock
One final note: With the power to edit binaries, easily and with your favorite text editor, comes great responsibility.
Contributors
- Russ Olsen (@russolsen)
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request