Задать вопрос
@Drovosek01

Какой есть универсальный и надежный способ замены байт в файле?

Для определенных задач мне нужно менять байты в файлах в UNIX-подобных системах. В основном в macOS и в основном в бинарных файлах.

Чаще всего я это делаю с помощью утилиты perl, например с помощью:
perl -pi -e 's/\x01\x02\x03/\x04\x05\x06/g' file

Но эта команда не всегда работает. Вот пример - https://qna.habr.com/q/1208282
Как я понял из ответа к тому вопросу, если в файле встречается код переноса строки (а именно \x0A), то указанный выше perl скрипт прерывает работу.
Чтобы он не прерывал работу, нужно -pi заменить на -0pi, но в таком случае я не смогу использовать значения \x00 в паттерне.

Как мне быть, если в файле могут встречаться символы \x0A и в паттерне у меня есть \x00?

Я не могу знать заранее в каком файле будут меняться байты (в текстовом или в бинарном) и будут ли в нем значения переноса строки, поэтому хочу найти какой-то универсальный вариант команды, которая будет весь файл рассматривать как один сплошной поток байт и не будет прерывать выполнение на символах переноса строки. То есть я хочу задать паттерн поиска и замены байт и чтобы если такой набор байт находится в файле, чтобы он был 100% заменен на указанные байты.

С помощью какой команды такое можно сделать?
  • Вопрос задан
  • 558 просмотров
Подписаться 2 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 5
hint000
@hint000
у админа три руки
Меня интересует способ решить проблему, используя только встроенные в систему (в основном речь идет о macOS) утилиты
там есть dd?
echo -ne "\x04\x05\x06" | dd of=filename bs=1 seek=`grep -aboP "\x01\x02\x03" filename | cut -d ":" -f 1 | head -c -1`

Монструозненько получилось (неравный бой с выводом grep). :) Если заглянет xotkot, то придумает, как оптимизировать, у него чёрный пояс по таким вещам.
Ответ написан
Комментировать
shabelski89
@shabelski89
engineer
Файл конечно нужно читать не как строковый, а как бинарный, уверен Perl умеет такое :)
Вот пример на питоне.

import os

print('Start')
file = r"C:\Users\ashab\Downloads\libbinaryninjacore.1.dylib\libbinaryninjacore.1.dylib"

search_pattern = b'\xD6\x6C\x9E\xC8\xDC\x86\xF3\xDB\x68\xB2\xB8\xBF\x66\x05\x51\x63\x05\x27\xF4\xEC\x31\x19\x3B\x69\x74\x3E\xE1\xE6\x50\xAB\xB1\xA2\x27\x63\x61\xB0\x03\x83\xF2\x3D\x66\x68\x0A\x68\x1E\xB3\xB8\xDC\x4A\x7F\x91\x51\xE7\x32\xF6\xD4\xB7\x69\x63\xD1\x12\x2A\x8F\x58\x99\x73\x6B\xDE\x7B\x91\x1C\x9F\x2A\x55\xE4\x2D\xAA\x85\x66\xCB\xAD\x43\xBE\x68\x1B\x2F\x38\x15\x49\xC3\x42\xFC\x19\xF1\xF5\x93\xD2\x44\x54\x74\x1D\x17\xAD\xF2\x21\xF6\x33\xA5\xAC\x4D\xE8\x5E\xF6\x02\x36\x28\xF8\xF9\x36\x8C\x61\x6B\x19\x49\xD7\x02\xC4\x19\x5D\x41\x1D\xD5\x1A\x2F\x1B\x84\x59\x83\x22\x99\x03\x5E\xEF\x68\xBE\x1E\xE3\x7D\x92\xA4\xDF\x75\x8F\x58\x92\xC8\xAA\xF6\x35\xA4\x06\xA7\xAD\x4F\x9E\xBF\x03\xEB\x0E\x44\xDA\x48\x5B\xBB\xF0\x98\x3D\xF8\x39\x20\x42\x0A\xE8\x24\xF4\xDA\x3C\xC9\xD1\x69\x95\x35\x63\x5F\x71\x51\xB2\x79\xD2\x71\x44\xB8\xA2\x9A\x65\xB6\xE2\x8C\xCB\xAF\xFD\xDB\xAB\x3F\xDE\x84\xCB\xF0\xE1\xFF\x4E\x28\xAB\x65\x19\x7E\xC9\xFD\x02\x7D\xCD\x7A\xF5\x28\x80\xBF\x14\x32\x75\x78\x2F\x07\x82\xC3\x04\x3B\x47\x02\x04\xB6\x3C\x40\xFC\x7B\xAF\x33'
replace_bytes = b'\xD2\xBF\x80\x69\xB2\x98\x61\x8B\x54\x27\x2B\x13\xCE\x40\x2C\x37\x82\x6D\x90\x6F\xA0\xDB\x47\xC9\x16\xE3\x04\xD6\x1C\xFE\x84\x73\x06\xAD\x17\x63\xA3\x32\xA6\xFA\xCB\xEF\x13\x3D\xE5\xE6\x34\xB3\x33\x73\x9E\xFF\xFE\x9F\x75\x13\xF7\xC3\x8C\xDF\x4E\xB7\xCE\x27\xB5\x6B\x72\x84\x24\xF9\x41\x0D\xB4\xCD\x3A\xB3\x3D\x2A\x36\x71\x23\x47\x0D\x62\x32\x42\x11\x87\x6D\x83\xC1\x5B\x59\xFB\x7A\x4D\x5A\x74\xE5\x6F\x9E\x44\x3D\xBE\xFF\x30\x28\x9D\x3E\x4F\x84\xE5\x8E\x6A\xB2\x3A\xD4\xF4\x38\x70\x03\x46\x05\xE6\x8E\xDF\x1F\xF9\x02\x56\xAA\x02\x7C\x61\x02\x98\x1B\x8A\x77\x42\xC3\xDC\xFC\x53\x6A\x4D\x98\xC4\xE2\x27\x02\xF2\xBF\xFD\xE2\x98\x5E\x23\x2A\x24\x46\xD5\x75\x0E\x20\xED\xD2\x7E\x59\xFA\x24\x75\xCF\xF2\x88\x2C\xA3\x33\x47\x20\x9F\x62\xDE\xD6\x96\x5D\x85\xB0\x3B\xDE\x6E\x02\xB9\x9F\x68\x0F\x33\xB7\xDC\x08\xF8\x73\x0C\x0B\xCE\x62\x25\x6F\xCA\x56\x13\x21\x3A\x11\x82\xC0\x0A\x36\xA9\xD4\x96\x62\x9D\x15\xC1\xB6\x04\x55\x0F\x97\x38\x8C\x2D\xFD\x60\xCC\x8D\xC1\x5C\xF5\xD6\x1A\x82\x91\x67\xCE\x07\xF9\x79\x81\x68\xC9\x2D\x60\x37\x47'

with open(file, 'rb') as f:
    file_bytes = f.read()

position = file_bytes.find(search_pattern)

if position:
    print(f'Search pattern position - {position}')
    file_bytes.replace(search_pattern, replace_bytes)

    out_file_path = os.path.dirname(file)
    new_file_name = 'result.dylib'
    with open(os.path.join(out_file_path, new_file_name), 'wb') as f:
        f.write(file_bytes)
    print('File update success')
else:
    print('Pattern not found')

print('Exit')


сделать консольный на раз два - гугл argparse .
Ответ написан
mayton2019
@mayton2019
Bigdata Engineer
Не специалист в Perl. Но использовать awk-like replacements для работы с бинарниками - так себе идея.

У тебя в примере такой кейс. Дан двоичный файл и надо заменить в нем байты
01 02 03на байты 04 05 06. Ето один кейс? Или возможны другие? 3 на 2 байта можно менять?
В этом случае размер файла изменится. И нужно-ли сделать один реплейсмент? Или найти все возможные?

Я думаю что тебе надо найти сишника, поставить ему пиво и он тебе 1 раз напишет утилиту для патчей и будешь ей всегда пользоваться.

Или попробуй разберись вот как тут пишут https://stackoverflow.com/questions/2464334/how-ca...
Ответ написан
saboteur_kiev
@saboteur_kiev Куратор тега bash
software engineer
xxd (hexdump) обычно везде есть

Переводим bin в ascII дамп, с опцией -p будет сплошной поток. Затем тем же седом меняем, и конвертим ascII дамп назад в бинарник.
Плюс можно смело менять размер файла.

xxd -p file.original | sed 's/\x01\x02\x03/\x04\x05\x06/g' | xxd -p -r > file.updated
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы