ファイル内の1ビットのみ変更

ファイル内の1ビットのみ変更

ハッシュ関数をテストする必要がありますが、特定のファイルの1ビットだけを変更したいと思います。

ddコマンドを使ってみました。これはうまくいきますが、わずかではなくバイト全体のみを変更できます。

sudo dd if=/dev/zero of=/file.bin bs=1 seek=10 count=1 conv=notrunc

また、正規表現を使ってsedコマンドを試しましたが、ファイルの内容がわからないため、「a」を「b」に変更することはできません。

これを行うコマンドを知っている人はいますか?

答え1

sedファイルにヌル値を含めることができるため、テキスト指向フィルタは失敗します。ただし、perlまたはなどのNULL値を処理できるプログラミング言語を使用できますpython。これがPython 3ソリューションです。読みやすくするために必要なものよりも数行長くなります。

#!/usr/bin/env python3
"""Toggle the bit at the specified offset.
Syntax: <cmdname> filename bit-offset"""

import sys
fname = sys.argv[1]
# Convert bit offset to bytes + leftover bits
bitpos = int(sys.argv[2])
nbytes, nbits = divmod(bitpos, 8)

# Open in read+write, binary mode; read 1 byte 
fp = open(fname, "r+b")
fp.seek(nbytes, 0)
c = fp.read(1)

# Toggle bit at byte position `nbits`
toggled = bytes( [ ord(c)^(1<<nbits) ] ) 
# print(toggled) # diagnostic output

# Back up one byte, write out the modified byte
fp.seek(-1, 1)  # or absolute: fp.seek(nbytes, 0)
fp.write(toggled)
fp.close()

ファイル(たとえばbitflip)に保存して実行可能にし、変更したいファイル名とオフセットで実行します。ビット単位で。ファイルをその場で修正します。同じオフセットで2回実行すると、ファイルが回復します。

答え2

コツはないようです。以下は簡単なスクリプトです。 " flipbit"として保存してください。

#!/usr/bin/perl
# Arguments:   byte (starting from 0),  bit (0-7),  filename (otherwise stdin)
$byte = shift(@ARGV);
$bit = shift(@ARGV);
undef $/; 
$file=<>; 
substr($file,$byte,1) = substr($file,$byte,1) ^ chr(1<<$bit); 
print $file;

テスト:

$ echo abb | ~/bin/flip-bit.pl 2 0 | od -xa
0000000      6261    0a63                                                
       a   b   c  nl                                                

これにより、3番目の文字の下位ビット(0)が反転され、「b」が「c」に変わります。

1行のコマンドで:

perl -e '$byte=shift(@ARGV);$bit=shift(@ARGV);undef $/; $file=<>; substr($file,$byte,1) = substr($file,$byte,1) ^ chr(1<<$bit); print $file'

答え3

ついに解決策を見つけxxdましたdd

a=$(xxd -b -l 1 -seek 3 -p a.bin);b=1;echo -e "\x$((${a}^${b}))" | dd of=a.bin bs=1 seek=3 count=1 conv=notrunc

hexdump a.bin     v
0000000 61 39 73 36 36 64 66 38 61 39 73 64 35 36 66 35
0000010 37 61 73 64 37 66 74 75 61 67 73 0a 61 73 64 66

hexdump b.bin     v
0000000 61 39 73 37 36 64 66 38 61 39 73 64 35 36 66 35
0000010 37 61 73 64 37 66 74 75 61 67 73 0a 61 73 64 66

しかし、醜いです。

答え4

head、を使用したtail簡単なソリューションですxxd。次の例では、最後のバイトの最下位ビットを反転します。ファイル。空

head -c -1 file.bin > flipped.bin
LAST=`tail -c 1 file.bin | xxd -ps`
printf "%02X" $(( $((16#$LAST)) ^ 1 )) | xxd -r -ps >> flipped.bin

関連情報