diff --git a/.gitignore b/.gitignore index 0d7bd4e..6c632d6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ /brute_venv/ /html/ /src/__pycache__/ +/test/__pycache__/ +#*# +/targets/* diff --git a/Makefile b/Makefile index 7fbfccb..dc4a981 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ test/testbin: test/testbin.c $(CC) -o test/testbin test/testbin.c test: FORCE venvcheck test/testbin - py.test -v tests/ + py.test -v test/ diff --git a/download_targets.sh b/download_targets.sh new file mode 100755 index 0000000..1b844c3 --- /dev/null +++ b/download_targets.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +bins=(basic1 basic2 basic3 intermediate1) + +rm -f targets/* + +for b in "${bins[@]}" +do + curl -o targets/$b "https://github.coventry.ac.uk/pages/csx239/naturan_demanto/bins/$b" +done + +chmod u+x targets/* diff --git a/src/brute_basic.py b/src/brute_basic.py new file mode 100644 index 0000000..473d0f4 --- /dev/null +++ b/src/brute_basic.py @@ -0,0 +1,72 @@ +#!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 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""" + + + #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 + guesses=["000","001","002","003","004"] + + + + + 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: + 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__": + + + # 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","PW:", "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") diff --git a/src/brutus.py b/src/brutus.py index f24999d..ad64136 100644 --- a/src/brutus.py +++ b/src/brutus.py @@ -1,3 +1,8 @@ +""" Brutus: A simple password-protected password brute-force support tool + +Brutus provides a simple interface for you to run a binary or script and test a password, simplifying the task of breaking passwords with brute force. + +""" import pexpect class Binary: @@ -22,10 +27,16 @@ class Binary: Returns: None: if there is no data A String: containing the next line of output if available.""" - if self.proc.eof(): - return None - return self.proc.readline() + self.proc.expect(prompt) + self.proc.send(data+"\n") + try: + self.proc.expect(fail, timeout=2) + return False + except pexpect.exceptions.EOF: + return True + + def attempt(self,prompt,data, fail): """ Make a guess at a password, when the expected prompt is found Args: diff --git a/targets/.placeholder b/targets/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/test/test_brutus.py b/test/test_brutus.py index 6dfcd9e..f240510 100644 --- a/test/test_brutus.py +++ b/test/test_brutus.py @@ -2,7 +2,23 @@ import pytest import sys sys.path.append("./src/") +#Here the tests are all around the "brutus" module that assists in brute-forcing +#You will need to write tests for your own functions + import brutus -# You can import your source files here, too -# So you can test the functions you create + +def test_incorrect(): + bad_guesses=["","NO","123","aejfhskdjfhkjsdfh","-1","Swordfish", " swordfish", "swordfish "] + for guess in bad_guesses: + b=brutus.Binary("./test/testbin") + b.run() + result=b.attempt("password:",guess,"Password Incorrect") + assert result==False, f"'{guess}' worked as a guess, but shouldn't have" + + +def test_correct(): + b=brutus.Binary("./test/testbin") + b.run() + result=b.attempt("password:","swordfish","Password Incorrect") + assert result==True, "The correct password was used, but brutus reported it incorrect"