Home > Back-end >  what is the quickest command to reverse bits in file using bash
what is the quickest command to reverse bits in file using bash

Time:04-15

I want to write a bash script that changes bits in file. I created txt file then used md5 and now I want to change one or two bits ( I made a command to run okteta and change there but I want to try without it )to run md5 on updated file and see if hashes are different

#!/bin/bash
echo "input file:"
read file_input
echo "choose algorythm ( md5(1) or sha256(2) )"
read choice
if [ $choice -eq 1 ]
then
    echo "running md5"
    openssl dgst -md5 $file_input > md5.txt
    FILENAME=/home/lukasz/$file_input
    FILESIZE=$(stat -c%s "$FILENAME")
    echo "size of the input file : $FILESIZE"
    hexdump -C $file_input
    echo "process of changing bits..."
    echo "how many bit do u want to change?"
    read num
    while [ $num -gt 0 ]
    do
        echo "which bit do u want to change?"
        read number
        # no idea 
        num=$(( $num - 1 ))
   done
   # okteta $file_input > testowyMD5.    
   cmp -l md5.txt md5PO.txt | grep "" -c

else
   echo 'hello'
fi

CodePudding user response:

Would you please try the following bash script. It inverts the bit'th bit of the pos'th byte in file. It will be easy to embed the commands in your bash script. Please note you need to assign pos to some value even if you don't intend to let the user input it.

#!/bin/bash

# these values are for demonstration
pos=16                  # position (address) of the byte to modify. 0 <= $pos <= filesize - 1
bit=2                   # bit slice to flip. 0 <= $bit <= 7
file="thisfile"         # filename to modify

int=$(( 16#$(dd if="$file" bs=1 skip="$pos" count=1 2> /dev/null | xxd -p) ))
(( mask = 1 << bit ))
(( int = int ^ mask ))
printf "x" "$int" | xxd -r -p | dd of="$file" bs=1 seek="$pos" conv=notrunc 2> /dev/null
  • dd if="$file" bs=1 skip="$pos" count=1 reads a byte of the specified address.
  • xxd -p converts the byte (character) to the hexadecimal string.
  • 16#$( commands above ) converts the hex string into integer value between 0 and 255.
  • (( mask = 1 << bit )) generates a bitmask to invert the specified bit.
  • (( int = int ^ mask )) inverts the bit.
  • The final printf ... writes the byte in the reversed procedures.

[EDIT]
Here is the functionalized version for easy handling:

#!/bin/bash

# usage: bitflip filename pos bit ...
#        bit is variable length arguments and can be put as many as you want
bitflip() {
    local file=$1; shift        # 1st argument
    local pos=$1; shift         # 2nd argument
    local -a bits=("$@")        # 3rd and remaining arguments (if any)

    local int mask bit

    int=$(( 16#$(dd if="$file" bs=1 skip="$pos" count=1 2> /dev/null | xxd -p) ))
    for bit in "${bits[@]}"; do
        (( mask = 1 << bit ))
        (( int = int ^ mask ))
    done
    printf "x" "$int" | xxd -r -p | dd of="$file" bs=1 seek="$pos" conv=notrunc 2> /dev/null
}

# demonstration of simple usage
bitflip thisfile 16 2

# multiple bit parameters to invert 0th and 2nd bit at once
bitflip thisfile 16 0 2

# you can also call it multiple times in a loop
for i in 0 2; do
    bitflip thisfile 16 "$i"
done

Then your main code will look like:

echo "how many bits do you want to change"
read NUMBER
while (( NUMBER-- > 0 ))
do
    echo "put the number of the byte in which you want to change a bit ( 0 <= X <= $MAX_VALUE)"
    read BYTE_NUMBER
    echo "now choose the bit you want to reverse ( 0 <= X <= 7 )"
    read BIT_NUMBER
    bitflip "copy_org.txt" "$BYTE_NUMBER" "$BIT_NUMBER"
done

Please note it always overwrites the file. You may need to make a backup in advance, if needed.

  • Related