我必须测试哈希函数,并且只想更改特定文件的一位。
我尝试使用 dd 命令。这可行,但我只能更改整个字节而不是一点点。
sudo dd if=/dev/zero of=/file.bin bs=1 seek=10 count=1 conv=notrunc
我还尝试了带有正则表达式的 sed 命令,但由于我不知道文件的内容,所以我不能只将“a”更改为“b”。
有谁知道执行此操作的命令?
答案1
由于文件可能包含空值,因此面向文本的过滤器sed
将失败。但是您可以使用可以处理空值的编程语言,例如perl
或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
。下面的示例翻转最后一个字节中的最低有效位文件.bin。
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