Software Wrangling – Challenge 1

 

For this challenge we were presented with a short python programme (below) which was designed to produce a one-time passcode based on an account number and the current time.  We were asked what the passcode would be for a given account and a time a few weeks in the past.

Firstly, we had to add the required date and time rather than real time by modifying either line 20 or 24 to generate the correct value of BigNumber.  The only remaining problem was to disable the IntegrityChecker by commenting out line 5 and the integrity check itself starting at line 63.

The key message to take from this exercise is that software running on client machines can never be trusted.  This was a trivial example, but even signed compiled software can be manipulated by a clever adversary, particularly where it has to run on generic computers over which you have no control.

[codesyntax lang=”python” lines=”normal” title=”Passcode Generator”]

# Secure One-Time PassCode Generator, written by Budget Coding Ltd for BigBank PLC

import datetime
import base64
import IntegrityChecker

def getAccntNumber():
    AccntNumber = []

    while len(AccntNumber) != 8 or not AccntNumber.isdigit():
        AccntNumber = (raw_input('Please enter your 8-digit Account Number: '))
        if len(AccntNumber) != 8 or not AccntNumber.isdigit():
            print("Not a valid account number. Please Try again...")
            print("")
    
    return AccntNumber

def getPassCode(AccntNumber):
    # Get Current Time
    TimeNow = str(datetime.datetime.now().strftime('%Y,%m,%d,%H,%M'))

    # Extract numbers and combine together
    [Year,Month,Day,Hour,Minute] = TimeNow.split(',')
    BigNumber = ((int(Year) * int(Month) * int(Day)) + (int(Hour) * int(Minute))) ** 2

    # Create two sets of interleaving numbers and combine to get another Big Number
    NumberSetA = int(str(BigNumber)[0::2])
    NumberSetB = int(str(BigNumber)[1::2])

    NewBigNumber = NumberSetA * NumberSetB

    # Do some clever maths
    if BigNumber > NewBigNumber:
        SmallerNumber = BigNumber - NewBigNumber
    elif NewBigNumber > BigNumber:
        SmallerNumber = NewBigNumber - BigNumber
    else:
        SmallerNumber = BigNumber / 2

    # Do some maths with the Account Number
    EvenBiggerNumber = SmallerNumber * int(AccntNumber)

    # Pad number to fixed size
    PaddedEvenBiggerNumber = str(EvenBiggerNumber).ljust(20,"0")

    PassCode = []

    # Take chunks from padded number and average to get passcode
    for N in range(0,4):
        Chunk = PaddedEvenBiggerNumber[N::5]
        SplitChunk = Chunk[0:3]
        y = 0
        for x in SplitChunk:
            y = y + int(x)
        PassCode.append(int(y/4))
    
    return PassCode

###### Core Code ######

# Check file hasn't been tampered with

if IntegrityChecker.CheckIntegrityOfFile() is False:
	print("This File Has Been Tampered With!! Exiting...")
	exit()

PassWord = raw_input("Please Enter your Password: ")

PassWordHash = base64.b64encode(PassWord)

CorrectHash = "aG9yc2ViYXR0ZXJ5c3RhcGxl"

if PassWordHash == CorrectHash:
    print("Your PassCode is: %s") % getPassCode(getAccntNumber())
    print("")
    print("This PassCode will expire in less than a minute. Please re-run to get a new code if it has expired.")

else:
    print "Password Incorrect..."

[/codesyntax]