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 Principal Penetration Testing Consultant for Secureworks. His previous position was a Senior Penetration Tester for a major financial institution.

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.

Leave a Comment

Filed under Security Not Included

Leave a Reply

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


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