파일에서 한 비트만 변경

파일에서 한 비트만 변경

해시 함수를 테스트해야 하는데 특정 파일의 한 비트만 변경하고 싶습니다.

dd 명령을 사용해 보았습니다. 이것은 작동하지만 약간이 아닌 전체 바이트만 변경할 수 있습니다.

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

또한 정규식을 사용하여 sed 명령을 시도했지만 파일 내용을 모르기 때문에 "a"를 "b"로 변경할 수는 없습니다.

이 작업을 수행하는 명령을 아는 사람이 있습니까?

답변1

sed파일에 null 값이 포함될 수 있으므로 텍스트 지향 필터가 실패합니다. 그러나 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

요령은 없는 것 같아요. 다음은 간단한 스크립트입니다. " 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                                                

그러면 세 번째 문자의 하위 비트(0)가 반전되어 "b"가 "c"로 변경됩니다.

한 줄 명령으로:

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

관련 정보