Script to get checksum of itself

is there a way to get a script to do a checksum on itself?

something like this:

#!/bin/sh

myexpectedsig=$(cksum $0 | awk '{print $1}')
if [ ${myexpectedsig} -ne 83373373737 ] ; then
     exit
else
   who
   uptime
   date
fi

im looking for something that would always represent the running script, which is why im using "$0" above. but $0 may not be reliable. as in, it may not always refer to the running script file.

If you want to prevent that someone changes this script, that person can also just comment those lines.
Maybe an IDS (Intrusion Detection System) like Tripewire etc. is the better choice to watch files.

1 Like

If you update the file to insert the correct checksum, then that will change the checksum for the next run. You would be extremely unlikely to ever be able to guess the checksum and be able to put it in the script.

You could consider:-

  • Change the permissions
  • Have the script read a file holding the checksum
  • Use and IDS as zaxxon suggests
  • Regularly checksum your code and compare to the previous run

Of course, all of these can be bypassed by someone with appropriate authority, so it comes down to a question of who is trusted and only granting access to those you can trust. A script that can be read can be copied and adjusted before running the local copy anyway, if the user has the authority to do so, so you should be thinking of denying all access except where you are comfortable granting it.

Making the scripts' permissions as rwx --- --- and having a sudo rule to allow specific people to execute it may be the way to go.

I hope that this gives you some ideas to ponder further.
Robin

1 Like

Hi.

Perhaps use the calculated checksum as the name of the file. That way the checksum is outside the content of the file, yet is still associated with it.

Just a thought experiment.

Best wishes ... cheers, drl

1 Like

What is your operating system ?

On Linux systems, use inotifywatch on that file to check if it's modified and take appropriate action.

Upon modify action (or any action you require supported by inotify subsystem), take action to prevent unwanted behavior.
chown a monitored file not to execute, mv a monitored file ,check the PID with fuser, run an antivirus check on monitored file etc.
This can be done from screen session, crontab or as a background job in while loop.

Check if script unchanged from script itself makes no sense whatsoever, as zaxxon mentioned.
It should be an external script/utility/software.

I have found that a lot of software actually uses inotify subsystem builtin, like clamav for instance.

On other OS-es you can use audit systems (perhaps overhead for one script/file), or script from cron using while loop and cksum (or equivalent tool) with a bit logic.

Hope that helps
Regards
Peasant.

1 Like

thank you all. I really appreciate the thoughtful and detailed responses provided. i'll mull them over.

thanks again.

Hi.

Here is a brief example of a self-checksumming, creation and verification script on file s1 :

#!/usr/bin/env bash

# @(#) (calculated)     Demonstrate checksum as script name.

LC_ALL=C ; LANG=C ; export LC_ALL LANG
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
em() { pe "$*" >&2 ; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
# C=$HOME/bin/context && [ -f $C ] && $C

# Calculate checksum, compare with name.
program=$( basename $0 )
checksum=$( cksum < $0 )
name=$( echo "$checksum" | sed 's/ /_/' )

# Intermediate output if debugging.
db " program name        = $program"
db " calculated checksum = $name"

if [ "$name" != "$program" ]
then
  db " Checksums [ $name | $program ] do not match, aborting."
  em " Checksums [ $name | $program ] do not match, aborting."
  exit 1
else
  db " Checksums [$name] match, continuing."
fi

echo ""
echo " Hello, world from $program."

exit 0

Running it as is will fail, but produce a checksum:

$ ./s1
 Checksums [ 2207913779_881 | s1 ] do not match, aborting.

Now we can copy the script to a a filename that is the string of the checksum:

cp s1 2207913779_881

And now run the code from the new filename:

$ ./2207913779_881 

 Hello, world from 2207913779_881.

Testing to see if the checksum works by changing the period at the end of the comment:

# @(#) (calculated) Demonstrate checksum as script name;

and re-running the script:

$ ./2207913779_881 
 Checksums [ 1941515329_881 | 2207913779_881 ] do not match, aborting.

See man pages for details.

Best wishes ... cheers, drl

1 Like