Skip to content

curranj2/brute_campbell

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code
This branch is 10 commits ahead of CUEH:master.

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Course work 1, brute force

Introduction

Welcome to the documentation of brute_cambell, here you'll find out how to use the tool for cracking binaries.

There are with three distinct files:

  1. Basic
  2. Intermediate
  3. Hard

Each one uses their own custom algorithm for cracking of which I will go into details later.

For basic pin based passwords with a fixed length of 3, basic can be used.

Intermediate reads from a dictinary, and converts it to eilite speak (thats is words like, cool becoming c00l), adding 1-9 to the end, and using the regular password against the selected file.

Lastly, hard will be using what's known as a timmed attack (explained in the algorythims part in more detailed), of from a password of unknown length.

User guide

Start

Start by setting up a python3 enviorment, (this will be useful for using test later)

python3 -m venv venv
. ./venv/bin/activate
pip install -r requirements.txt

If pip fails, try running as sudo:

sudo pip install -r requirements.txt

To the neccisary binaries we want to crack, it will populate the targets folder,

./download.sh

Basic

Starting with, brute_basic.py. This will crack any basic file that you select.

To launch the script, run the following commands

python3 src/brute_basic.py

Note, cd into the src directory will break the code You now have access to the brute forcing options,

Screenshot 2020-10-29 at 21.48.51.png

Slecting an option not on the list will then close the script, and you would need to rerun.

Selecting the option you would want, will then compute the three didgit pin and return result as shown bellow:

Screenshot 2020-10-29 at 22.02.56.png

Testing the file out by
./targets/basic3

Upon this prompt enter the above guess, and:

Screenshot 2020-10-29 at 22.06.16.png

Success

Intermediate

Going back to the src directory, we can now launch the intermediate brute forcer. This cracks passwords using a dictinary, then adding numbers 0-9 to the end of the word and will convert the plain words to elliet speak (test t35t) Running:

python3 src/brute_basic.py

Will give you access to,

Screenshot 2020-10-29 at 23.59.03.png

Selecting an input that doesnt excist closes the code, However selecting 2 will start the cracking for intermediate3,where we get the output below.

Screenshot 2020-10-30 at 00.03.16.png

Testing the guess against the file, we get:

Screenshot 2020-10-30 at 03.43.38.png

Success

Advanced

This script takes advantage of the time differnce for correct characters, to incorrect ones.

To start, run the following command:

python3 src/brute_basic.py

Upon running the script youre introduced to the menue, as seen bellow.

Screenshot 2020-10-30 at 08.10.26.png

Upon running the target you'd like to bruteforce, the script will start attempting to crack. Bellow shows the sucessful outcome of 0, Screenshot 2020-10-30 at 08.11.39.png Running the file, with the password shown result in the password being correct. Screenshot 2020-10-30 at 08.12.38.png

Success

Unit Tests

To start testing, run the command bellow:

pytest -v ./tests/

test_basic.py

Function Test Expected Result
test_unsuccessful() Run against a file it cant crack None
test_guessGenerator() Length of the reurn 10000

intermediate_basic.py

Function Test Expected Result
test_unsuccessful() Run against a file it cant crack None
test_blankdict() Run against a file it can crack with an empty dictionary None
test_correctcrack() Run against a file it can crack with a correct dictionary String

Algorithms

In this program, I needed to develop three Algorithms:

  • Creating a list of three pins
  • Creating a list of passwords via dictionary manlipulation
  • Cracking a password via timming attack

Bellow is where I will go into further details on each task:

Creating a list of three pins,

By cycling through 0-1000, we generate all the codes that's required. Then by checking for the numbers less then 10, we add 00 to the start, less than 100 we then add 0 to the start. Thus we get all three didgit passcodes. With this generated list, we can now attack the binary with each nermircal pin! (though I would prefer a function within three while loops where it would return once you get a code which is more efficent in python) note by now I have ran out of time to develop for the advance module, though there is some error detection code within it.

Creating a list of passwords via dictionary manlipulation,

Firstly, we generate the list of words from the text file. Cycling through, 1-9 we add this to the end of each word, then assign it to a copy of the orginal list. We then take each word in the original list of words, splitting them into character. Then with each character we compair it to the eilite speak equivent then. Once the character loop is complete we have a new word that then gets added to that previous temp list. We coninue to loop untill all words in the dictionary is converted then attack the binary.

Source code

brute_basic.py

#!python3
from brutus import Binary

# This is a starting-point for your project
# Most of the work is done for the basic task
# Intermediate will require reading from a dictionary file and creating guesses based on the contents
# For the advanced task, see the supporting module "brute_time"



def generateGuesses():
    """ Creates a list of PIN guesses. Needs finishing, testing and documenting... """
    #Here, the guesses are listed explicitly.  We *could* write out
    #1000 guesses, but the point is to use the computer to do the
    #brute force work, not our fingers

    #For the basic task, the only functionality you need is to replace
    #the line below with code that can generate all the potential
    #guesses
    output=[]
    for x in range(1000):
        if x< 10:
        #Checks for digits 1-9
            output.append("00"+str(x))
        elif x< 100:
        #checks for diget 10-99
            output.append("0"+str(x))
        else:
        #three digits now, so no need for further checks
            output.append(str(x))
    return output



def breakBinary(target, promptText, failText):
    """" Break into the given target binary.
    Assumes "basic" level binary, with PIN codes of 000-999
    Args:
        target: path to the binary. e.g. "./bins/basic1"
        promptText: text to look for in the output that signals a password is required. e.g. "Password:"
        failText: text that indicates an attempt failed. e.g. "Password Incorrect"
    Returns:
        None: if no successful attempt was made
        string: a successful password"""


    guesses=generateGuesses()

    
    
    for g in guesses:        

        #The actual attempt
        b=Binary(target)
        b.run()
        success=b.attempt(promptText,g, failText)

        
        if success:
            print(f"The Guess '{g}' appears to be correct")
            return g #Return the answer. No need to "break" because the return exits the function
        else:
            pass
             #rint(f"guess: {g} - Password incorrect!")
    return None #If we get here, it means we didn't return earlier in the loop with a successful guess

    
if __name__=="__main__":


    # Create a simple menu system to pick the binary we want to force
    targets=[]
    targets.append(["targets/basic1","Password:", "Password Incorrect"])
    targets.append(["targets/basic2","Enter the secret code:", "ACCESS DENIED"])
    targets.append(["targets/basic3","Got the PIN?", "NO"])


    print("Basic Binary Breaker")
    print("Which binary do you want to brute force?")

    for c in range(len(targets)):
        print(f"{c}: {targets[c][0]}")

    selection=int(input("Enter the number of the binary to be forced: "))

    if 0 <= selection < len(targets):
        target=targets[selection]
        breakBinary(target[0],target[1],target[2])
    else:
        print("Invalid selection")

brute_intermediate.py

#!python3
from brutus import Binary

def wordsFromFile(filePath):
   """ Read lines from a file containing one word per line and return a list of the words
   Args:
       filePath: the absolute or relative path of the file to be read
   Returns:
       a list of the words from the file, stripped of whitespace
   """
   f=open(filePath,"r")
   out=[]
   for l in f.readlines():
       w=l.strip()
       if len(w)>0:
           out.append(w.lower())
   f.close()
   return out

def breakBinary(target, promptText, failText, guesses):
   """" Break into the given target binary.
   Assumes "intermeduate level binary, with dictionary words
   Args:
       target: path to the binary. e.g. "./bins/basic1"
       promptText: text to look for in the output that signals a password is required. e.g. "Password:"
       failText: text that indicates an attempt failed. e.g. "Password Incorrect"
       guesses: list of words to try as passwords
   Returns:
       None: if no successful attempt was made
       string: a successful password""" 
   
   for g in guesses:        

       #The actual attempt
       b=Binary(target)
       b.run()
       success=b.attempt(promptText,g, failText)

       
       if success:
           print(f"The Guess '{g}' appears to be correct")
           return g #Return the answer. No need to "break" because the return exits the function
       else:
           pass
           #print(f"guess: {g} - Password incorrect!")
   return None #If we get here, it means we didn't return earlier in the loop with a successful guess

   
if __name__=="__main__":

   #Load the dictionary
   words=wordsFromFile("dictionaries/base.txt")
   
   ### YOUR CODE HERE
   ### Currently it passes in the plain words
   ### Change the line "words2=words" so that the list "words2" contains your guesses
   ### You need to create a word list that has the dictionary words in PLUS
   ### 1. Each word with all 0-9 digits appended (so 'swordfish' would be 'swordfish0', 'swordfish1' etc.
   ### 2. Each word turned into "l33t-5p34k"
   ###    Each o becomes 0, each i becomes 1, each a becomes 4, each s becomes 5, each e becomes 3
   ###    'swordfish' becomes '5w0rdf15h', for example
   ###    You can assume case (upper/lower) will not need to be changed
   tempWord =[]
   for word in words:
       #Gets each word from disctionary and makes it into a string
       for x in range(10):
           #Counts zero to nine
           tempWord.append(word+str(x))
           #then add that number to the end
       tester = list(word)
       #splits the word into characters
       newWord = ""
       #Creates a tempory string
       for character in tester:
           #Cycles through each letter, then converts to leet speak
           #would have prefered switch case, but you know. Python.
           if(character == 'e'):
               newWord+="3"
           elif(character == 'o'):
               newWord +="0"
           elif(character == 's'):
               newWord +="5"
           elif(character == 'i'):
               newWord += "1"
           elif(character =='a'):
               newWord += "4"
           else:
               newWord+=str(character)
       #Adds leet speak onto the end of the new list
       tempWord.append(newWord)
   
   words2=words+tempWord
   #Adds new dictionary to the old one
   
   # Create a simple menu system to pick the binary we want to force
   targets=[]
   targets.append(["targets/intermediate1","Password:", "Password Incorrect"])
   targets.append(["targets/intermediate2","Secret code:", "Auth Failure"])
   targets.append(["targets/intermediate3","Enter Credentials:", "Invalid Credentials"])

   print("Intermediate Binary Breaker")
   print("Which binary do you want to brute force?")

   for c in range(len(targets)):
       print(f"{c}: {targets[c][0]}")

   selection=int(input("Enter the number of the binary to be forced: "))

   if 0 <= selection < len(targets):
       target=targets[selection]
       breakBinary(target[0],target[1],target[2], words2)
   else:
       print("Invalid selection")

test_intermediate.py

import pytest
import sys
sys.path.append("./src/")

import brute_intermediate

def test_blankDict():
   test= brute_intermediate.best_intermediate.py("./test/testbin","", "",[""])
   assert (isinstance(test, str) == False)

brute_advance.py

#!python3
from brutus import Binary


def maxPos(seq):
    """ Given a list of numbers, return the **position** of the largest
    Args:
       seq: the list to be searched
    Returns:
       an integer position of the largest number in `seq`
    """
    maxNum=seq[0]
    maxPos=0
    for i in range(len(seq)):
        if seq[i]>maxNum:
            maxNum=seq[i]
            maxPos=i
    return maxPos
            

# def averageTry(target, promptText, failText, guess, repeats=2):
#     # Provided to assist. If you use it, document it properly... :)
#     # Runs multiple attempts at cracking the binary, returning the
#     # success AND the average length of time each try took
#     results=[]
#     success=False
#     for i in range(repeats):
#         b=Binary(target)
#         b.run()
#         result=b.timedAttempt(promptText,guess, failText)
#         success=result[0]
#         results.append(result[1])
#     return (success,sum(results)/len(results))

def breakBinary(target, promptText, failText):


    #Your code here
    # Suggested algorithm:
    
    #1. Use an accumulator for the current guess
    #2. in a loop, try the current guess plus each letter of the alphabest and see which one takes longest
    #3. If it is the correct password, end
    #4. If not, add the current best letter to the guess and repeat...
    accumulator =0
    adverageTime=[]
    foundPass = False
    guess=""
    numberOfLoops =0
    while foundPass == False:
        for currentCharacter in range(97, 123):
            for trials in range(4):
                temp=guess+str(chr(currentCharacter))
                b=Binary(target)
                b.run()
                result=b.timedAttempt(promptText,temp, failText)
                foundPass= result[0]
                if (not foundPass):
                    if(numberOfLoops <20):
                        adverageTime.append(result[1])
                    else:
                        print("Password not found")
                        return False
                else:
                    print("Guessing the password is " +temp)
                    return True
        guess+=str(chr(96+sortTime(adverageTime)))
        adverageTime=[]
    return None        
def sortTime(someData):
    if(len(someData) == 104):
        currentLow=0.0
        foundIndex=0
        adverageTimePerChar=[]
        for index in range(104):
        #26*4+1 ammount of charaters in some data
            if (index+1) %4 == 0:
                totalAdv = (someData[index]+someData[index-1]+someData[index-2]+someData[index-3])/4
                pythonFunkyness= currentLow- totalAdv
                if(currentLow <totalAdv):
                    currentLow=totalAdv
                    
                    foundIndex=int((index+1)/4)

                
        return foundIndex
        #Gets the index of the fastest character   
    else:
        print(len(someData))
        return -1  
if __name__=="__main__":

        
    # Create a simple menu system to pick the binary we want to force
    targets=[]
    targets.append(["./targets/advanced1","Password:", "Password Incorrect"])
    targets.append(["./targets/advanced2","Password:", "Password Incorrect"])
    targets.append(["./targets/advanced3","Password:", "Password Incorrect"])

    print("Intermediate Binary Breaker")
    print("Which binary do you want to brute force?")

    for c in range(len(targets)):
        print(f"{c}: {targets[c][0]}")

    selection=int(input("Enter the number of the binary to be forced: "))

    if 0 <= selection < len(targets):
        target=targets[selection]
        breakBinary(target[0],target[1],target[2])
    else:
        print("Invalid selection")

test_basic.py

import pytest
import sys
sys.path.append("./src/")


#You will need to write tests for your own functions, or change tests for ones you modify

import brute_basic

def test_unsuccessful():
    test =(brute_basic.breakBinary("./test/testbin","",""))
    assert (isinstance(test, str) == False)


def  test_guessGenerator():
    #This definitely needs changing and expanding
    assert len(brute_basic.generateGuesses())==1000

About

Brute Campbell is a brute-force tool for accessing password-protected executable binaries

Resources

Stars

Watchers

Forks

Releases

No releases published

Languages

  • Python 98.8%
  • Other 1.2%