Как я могу использовать Bash, чтобы найти 2 байта в двоичном файле, увеличить их значения и заменить?

8

Я пытаюсь найти два байта внутри двоичного файла, затем увеличить значение этих двух байтов и заменить их внутри файла. Эти два байта находятся на позициях 0x82-0x83. На данный момент я успешно извлек эти два байта, используя это:

#!/usr/bin/env bash
BYTES=$(tail -c +131 "$1" | head -c 2)

Эти байты имеют значение: 1B 1F. Я застрял с:

  1. Как преобразовать байты в целое число? Это должно быть 6943десятичным.
  2. Как добавить / отразить двоичные данные в файл
  3. Как записать увеличенные байты внутри файла на позиции 0x82-0x83. Я мог бы использовать head -c 130 original.bin >> new_file.bin && magic_command_writing_bytes_to_file >> new_file.bin && tail -c +133 original.bin, но должен быть лучший способ.

Я мог бы сделать это в PHP, это должно быть проще, но мне интересно, как это сделать в bash.

piotrekkr
источник

Ответы:

5

Тестирование с этим файлом:

$ echo hello world > test.txt
$ echo -n $'\x1b\x1f' >> test.txt
$ echo whatever >> test.txt
$ hexdump -C test.txt 
00000000  68 65 6c 6c 6f 20 77 6f  72 6c 64 0a 1b 1f 77 68  |hello world...wh|
00000010  61 74 65 76 65 72 0a                              |atever.|
$ grep -a -b --only-matching $'\x1b\x1f' test.txt 
12:

Так что в этом случае 1B 1Fэто на месте 12.

  • Преобразовать в целое число (возможно, есть более простой способ)

    $ echo 'ibase=16; '`xxd -u -ps -l 2 -s 12 test.txt`  | bc
    6943
    
  • И наоборот:

    $ printf '%04X' 6943 | xxd -r -ps | hexdump -C
    00000000  1b 1f                                             |..|
    $ printf '%04X' 4242 | xxd -r -ps | hexdump -C
    00000000  10 92                                             |..|
    
  • И положить его обратно в файл:

    $ printf '%04X' 4242 | xxd -r -ps | dd of=test.txt bs=1 count=2 seek=12 conv=notrunc
    2+0 records in
    2+0 records out
    2 bytes (2 B) copied, 5.0241e-05 s, 39.8 kB/s
    
  • Результат:

    $ hexdump -C test.txt
    00000000  68 65 6c 6c 6f 20 77 6f  72 6c 64 0a 10 92 77 68  |hello world...wh|
    00000010  61 74 65 76 65 72 0a                              |atever.|
    
frostschutz
источник
Да, это именно то, что я искал. Спасибо.
piotrekkr
@frostschutz: \xво второй строке вашего примера кода есть ошибка, которая отсутствует . Так и должно быть echo -n $'\x1b\x1f' >> test.txt.
Эрик
1
Преобразовать в целое число (возможно, есть более простой способ). О, да! :) Эрик выбрал лучшую команду, так что я просто адаптирую его линию к вашей: printf "%d" 0x1B1Fотлично выполнит работу, чтобы получить ваш 6943результат; Исходя из этого, вы можете использовать значительно более умную линию, как printf "%d" $(xxd -u -ps -l 2 -s 12 test.txt)вместо этого, и вам больше не понадобится bc.
синтаксическая ошибка
2

Ой, извини. Этот ответ устарел, потому что я думал, что в вашем файле есть шестнадцатеричные значения, записанные как ascii.


Вы можете преобразовать шестнадцатеричные числа в десятичную систему через printf "%d" 0x1B1F.

Если вы сохранили байты в переменной, BYTES=1B1Fвы получите результат с помощью printf "%d" 0x$BYTES.

Итак, если вы хотите увеличить число, сделайте

$ echo $(($(printf "%d" 0x$BYTES) +1))
6944

Тогда конвертируй обратно

printf '%X' $(($(printf "%d" 0x$BYTES) +1))
1B20
Erik
источник