Записать байт по адресу (hexedit/изменить двоичный файл из командной строки)
Есть ли простой способ изменить двоичный файл из командной строки?
Допустим, я знаю, что мой двоичный файл содержит 1234abcd, и я хочу изменить его на 12FFabcd или FFFFabcd или, возможно, даже FF34FFabc0 (вы поняли) :-)
Как я могу достичь этого, не используя специальные инструменты, такие как http://stahlworks.com/dev/swiss-file-knife.html или аналогичные.
Было бы здорово сделать это только из командной строки, используя только стандартные инструменты Linux.
Или, может быть, даже лучше вместо этого для поиска шестнадцатеричной строки, которую я хочу заменить непосредственно записывая FF со смещением 0x10000, 12 со смещением 0x100001 и так далее.
Он должен быть сценарием и запускаться непосредственно из командной строки. Я ищу что-то вроде "двоичный файл, который включен в дистрибутив --write AB - at-offset 100000 --file thebinary.bin". Я совершенно уверен, что это возможно с "dd", но я не смог обернуть голову вокруг страницы руководства.
Есть идеи?
Заранее спасибо!
Ответы
Ответ 1
printf '\x31\xc0\xc3' | dd of=test_blob bs=1 seek=100 count=3 conv=notrunc
аргументы dd:
- | файл для исправления
- bs | 1 байт за один раз.
- искать | перейдите в позицию 100 (десятичная).
- conv = notrunc | не усекайте результат после редактирования (что делает dd по умолчанию)
Один Джош смотрит на другого;)
Ответ 2
Решения на основе printf+dd
, похоже, не работают для написания нулей. Вот общее решение в python3 (входит во все современные дистрибутивы), которое должно работать для всех байтовых значений...
#!/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]))
Использование...
set-byte eeprom_bad.bin 0x7D00 0
set-byte eeprom_bad.bin 1000 0xff
Примечание. Этот код может обрабатывать номера ввода в шестнадцатеричном формате (префикс 0x) и dec (без префикса).
Ответ 3
Здесь Bash функция replaceByte
, которая принимает следующие параметры:
- имя файла,
- смещение байта в файле для перезаписи и
- новое значение байта (число).
#!/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
Ответ 4
Инструмент xxd, который поставляется с vim (и, следовательно, вполне вероятно, будет доступен), позволяет шестнадцатеричный дамп двоичного файла и построить новый двоичный файл из измененного шестнадцатеричного дампа.
Ответ 5
Запись одного и того же байта в двух разных позициях в одном и том же файле с одним вкладышем.
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 очень полезно, когда вам не нужна статистика из dd.
Ответ 6
Если вам не нужно писать сценарии, вы можете попробовать утилиту "hexedit". Он доступен во многих дистрибутивах Linux (если он не установлен по умолчанию, его обычно можно найти в репозитории дистрибутива).
Если ваш дистрибутив не имеет его, вы можете создать и установить его из источника.
Ответ 7
Некоторые альтернативы:
Ответ 8
Относительно ответа Джоша: Если вы хотите сделать это для определенного адреса
hexdump -C {file location}
с некоторым шестнадцатеричным значением вы могли бы попытаться добавить 0x, но это не получится:
dd: warning: ‘0x is a zero multiplier; use ‘00x if that is intended
Вы можете добиться этого, заключив его в $ (()), который терминал будет переводить как значение типа int:
mybinary={file location}
printf '\x31\xc0\xc3' | dd of=$mybinary bs=1 seek=$((0x100)) count=3 conv=notrunc