File Integrity Checker

So, I was perusing the internet for some side project ideas, and one that stuck out to me as interesting/useful as well as not too difficult was a file integrity checker.

The idea involved checking the hash of a known, good .bashrc file and comparing it against the current one on the system. From there e-mail alerts could be sent, the file could be reverted, etc.

I decided to give this a whirl in Python, and ended up making it a bit more generic so that any file could be verified. The code is below, and the only real requirements are hosing the known, good file somewhere, having an e-mail address that supports SMTP, and having the configuration options in a file/hard-coded into the actual application.

import difflib
import getpass
import hashlib
import os
from os.path import basename
import requests
import shutil
import smtplib
from urlparse import urlparse

def calculateOriginalValues(fileUrl, tempFile):
    r = requests.get(fileUrl)
    with open(tempFile, "w") as f:
    with open(tempFile, "rb") as f:
        return hashlib.md5(
def compareHashes(originalHash, originalFile, fileName):
    with open(fileName, "rb") as f:
        calculated_md5 = hashlib.md5(

    if originalHash == calculated_md5:
        print "MD5 verified."
        return None
        print "MD5 verification failed!"
        file1 = open(fileName, "rb").readlines()
        file2 = open(originalFile, "rb").readlines()

        diff = difflib.ndiff(file1, file2)

        if not os.path.exists("modified"):

        os.rename(fileName, "modified/"+fileName+"_modified")
        os.rename(originalFile, fileName)

        differences = ""
            while 1:
                diff_string =
                if not (diff_string[0] == " "):
                    differences += diff_string + "\r\n"
            if diff is None:
        return differences

def sendEmail(configFile, diffString, isSSL, hasAuth):
    config = {}
    execfile(configFile, config) 

    sender = config["sender"]
    recipient = config["recipient"]
    subject = config["subject"]
    body = diffString

    headers = ["From: " + sender,
           "Subject: " + subject,
           "To: " + recipient,
           "MIME-Version: 1.0",
           "Content-Type: text/plain"]
    headers = "\r\n".join(headers)

    server = smtplib.SMTP(config["server"], config["serverPort"])
    if isSSL:
    if hasAuth:
        password = getpass.getpass("Enter the password for " + sender + ": ")
        server.login(sender, password)
    server.sendmail(sender, recipient, headers + "\r\n\r\n" + body)

def main():
    fileUrl = (""
    tempFile = "temp.txt"
    fileName = basename(urlparse(fileUrl).path)
    originalHash = calculateOriginalValues(fileUrl, tempFile)
    diffString = compareHashes(originalHash, tempFile, fileName)
    if diffString is not None:
        sendEmail("email.conf", diffString, True, True)
        if os.path.isfile(tempFile):

if __name__ == '__main__':

After reading some more comments and ideas on the thread, I believe it would be useful to add watchers for users (/etc/passwd would be easy enough) as well as the init.d directory.

(Code and updates available at its Github page.)

doyler on Githubdoyler on Twitter
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

As an Amazon Associate I earn from qualifying purchases.

Common passed on this blog, I made it to a jam.

Leave a Comment

Filed under Security Not Included

Leave a Reply

Your email address will not be published. Required fields are marked *

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

This site uses Akismet to reduce spam. Learn how your comment data is processed.