많은 파일에서 일부 바이트 변경

많은 파일에서 일부 바이트 변경

.png내 프로젝트를 테스트하려면 손상된 파일이 많이 필요합니다 . 이렇게 하려면 0x054th부터 0xa00th까지의 모든 바이트를 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지울 바이트 범위의 시작(0부터 시작, 예를 들어 n번째 바이트부터 지우기 , n -1 사용) 및 $num_zeros범위의 길이. $((...))16진수를 10진수로 변환하는 일을 담당합니다 .

(실행할 수 있는 다른 테스트는 대신 으로 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바이트)으로 변경합니다. 실제로 0x55th를 0xa00th로 변경하려는 것 같습니다. 이 경우 위 코드에서 s와 s를 제거하면 됩니다 + 1.- 1

관련 정보