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.