更改许多文件中的某些字节

更改许多文件中的某些字节

我需要大量损坏的.png文件来测试我的项目。为此,我需要将从第 0x054 到第 0xa00 的所有字节设置为 0。

.png文件包含带有校验和的块,我想更改图像数据块(IDAT),而不更新校验和。此外,我想损坏大量字节,以便在显示图像时出现可见(黑色)区域(假设查看程序忽略校验和不匹配)。

这是我到目前为止所得到的:

#!/bin/sh

# This script reads all .png or .PNG files in the current folder,
# sets all bytes at offsets [0x054, 0xa00] to 0
# and overwrites the files back.

temp_file_ascii=outfile.txt
temp_file_bin=outfile.png
target_dir=.
start_bytes=0x054
stop_bytes=0xa00
len_bytes=$stop_bytes-$start_bytes

for file in $(find "$target_dir" -name "*.png")         #TODO: -name "*.PNG")
do
    # Copy first part of the file unchanged.
    xxd -p -s $start_bytes "$file" > $temp_file_ascii

    # Create some zero bytes, followed by 'a',
    # because I don't know how to add just zeroes.
    echo "$len_bytes: 41" | xxd -r >> $temp_file_ascii

    # Copy the rest of the input file.
    # ??

    mv outfile.png "$file"
done

编辑:完成的脚本,使用接受的答案:

#!/bin/sh

if [ "$#" != 3 ]
then
    echo "Usage: "
    echo "break_png.sh <target_dir> <start_offset> <num_zeroed_bytes>"
    exit
fi

for file in $(find "$1" -name "*.png")
do
    dd if=/dev/zero of=$file bs=1 seek=$(($2)) count=$(($3)) conv=notrunc
done

答案1

你可以用以下方法做一些更简单的事情dd

dd if=/dev/zero \
   of="$your_target_file" \
   bs=1 \
   seek="$((start_offset))" \
   count="$((num_zeros))" \
   conv=notrunc

作为$start_offset要清零的字节范围的开始(从零开始,如从第 n 个字节开始擦除使用 n-1),以及$num_zeros该范围的长度。将$((...))负责将十六进制转换为十进制。

(您可以运行的其他测试是设置if/dev/urandom而不是/dev/zero,或者也用随机数据覆盖校验和。)

答案2

ksh93

 PATH=/opt/ast/bin:$PATH find "$targetdir" -name '*.png' -type f -exec ksh93 -c '
   for file do
      head -c "$((0xa00 - 0x54 + 1))" < /dev/zero 1<> "$file" >#((0x54 - 1))
   done' ksh {} +

>#((...))是 中的查找运算符ksh93。这是相对高效的,因为它运行尽可能少的 ksh93 并且所有命令都是内置的。

使用最新版本zsh

find "$targetdir" -name '*.png' -type f -exec zsh -c '
  zmodload zsh/system
  z=${(pl:0xa00-0x54+1::\0:)}
  for file do
    {sysseek -u1 0x54-1 && print -rn $z} 1<> $file
  done' zsh {} +

它们将第 0x54 个字节更改为第 0xa00 个字节(2477 个字节)。看起来你实际上想将第 0x55 个更改为第 0xa00 个。如果是这种情况,只需删除上面代码中的+ 1s 和s 即可。- 1

相关内容