Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write byte at address (hexedit/modify binary from the command line)

Is there any straightforward way to modify a binary from the commandline?

Let's say I know that my binary contains 1234ABCD and I want to change it to 12FFABCD or FFFFABCD or maybe even FF34FFABC0 (you get the idea) :-)

How might I achieve that without using any special purpose tools like Swiss File Knife or similar?

It would be great to do it just from the command line with only standard Linux tools.

Or maybe even better, instead for searching for the hexadecimal string I want to replace directly writing FF at offset 0x10000, 12 at offset 0x100001 and so on.

It should be scriptable and run directly from the command line. I am looking for something like "binary-which-is-included-in-the-distro --write AB --at-offset 100000 --file thebinary.bin". I am quite sure that it is possible with dd, but I wasn't able to wrap my head around the man page.

like image 359
Josh Avatar asked Jan 24 '11 15:01

Josh


7 Answers

printf '\x31\xc0\xc3' | dd of=test_blob bs=1 seek=100 count=3 conv=notrunc

dd arguments:

  • of | file to patch
  • bs | 1 byte at a time please
  • seek | go to position 100 (decimal)
  • conv=notrunc | don't truncate the output after the edit (which dd does by default)

One Josh looking out for another ;)

like image 112
Josh Avatar answered Oct 02 '22 13:10

Josh


Here's a Bash function replaceByte, which takes the following parameters:

  • the name of the file,
  • an offset of the byte in the file to rewrite, and
  • the new value of the byte (a number).
#!/bin/bash

# param 1: file
# param 2: offset
# param 3: value
function replaceByte() {
    printf "$(printf '\\x%02X' $3)" | dd of="$1" bs=1 seek=$2 count=1 conv=notrunc &> /dev/null
}

# Usage:
# replaceByte 'thefile' $offset 95
like image 41
sinharaj Avatar answered Oct 02 '22 13:10

sinharaj


The printf + dd based solutions do not seem to work for writing out zeros. Here is a generic solution in Python 3 (included in all modern distributions) which should work for all byte values...

#!/usr/bin/env python3
#file: set-byte

import sys

fileName = sys.argv[1]
offset = int(sys.argv[2], 0)
byte = int(sys.argv[3], 0)

with open(fileName, "r+b") as fh:
    fh.seek(offset)
    fh.write(bytes([byte]))

Usage...

set-byte eeprom_bad.bin 0x7D00 0
set-byte eeprom_bad.bin 1000 0xff

Note: This code can handle input numbers both in hexadecimal (prefixed by 0x) and decimal (no prefix).

like image 45
Autodidact Avatar answered Oct 02 '22 12:10

Autodidact


The xxd tool, which comes with Vim (and thus is quite likely to be available) allows to hex dump a binary file and construct a new binary file from a modified hex dump.

like image 33
SK-logic Avatar answered Oct 02 '22 11:10

SK-logic


Writing the same byte at two different positions in the same file with a one liner.

printf '\x00'| tee >(dd of=filename bs=1 count=1 seek=692 conv=notrunc status=none) \
    >(dd of=filename bs=1 count=1 seek=624 conv=notrunc status=none)

status=none very useful when you don't want any statistics out of dd.

like image 29
memscan Avatar answered Oct 02 '22 13:10

memscan


Some alternatives:

  • HexAlter (open source compiled tool)
  • ucon64 --nbak --poke=OFF:V FILE (meant for ROM dumps, should work with any binary file, but no inplace editing)
  • printf '\x31' | dd of=FILE bs=1 seek=OFFSET count=1 conv=notrunc (wrapped in a shellscript like this that also allows reading)
like image 27
eadmaster Avatar answered Oct 02 '22 11:10

eadmaster


If you don't need it to be scriptable, you could try the hexedit utility. It is available in many Linux distributions (if not installed by default, it can usually be found in the distribution's package repository).

If your distribution doesn't have it, you can build and install it from source.

like image 30
Dan Moulding Avatar answered Oct 02 '22 11:10

Dan Moulding