Last active
May 15, 2019 20:14
-
-
Save Sparrow1029/07bdd84e4e4e558a77a640a76f351d87 to your computer and use it in GitHub Desktop.
Script that uses python 3 multiprocessing module to attempt brute-force of RC4-encrypted strings.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# This script requires the chardet library for python3 | |
# the RC4 implementation used in this script is attributed to Ryosuke Ito | |
# it (and installation instructions) can be found at https://github.com/manicmaniac/arc4.git | |
import sys | |
from arc4 import ARC4 | |
import chardet | |
from string import ascii_uppercase, ascii_lowercase, digits | |
from itertools import product | |
import binascii | |
from multiprocessing import Pool | |
print("""RC4 brute force""") | |
chars_dict = {1: ascii_uppercase, | |
2: ascii_lowercase, | |
3: ascii_uppercase + ascii_lowercase, | |
4: digits, | |
5: ascii_uppercase + digits, | |
6: ascii_lowercase + digits, | |
7: ascii_uppercase + ascii_lowercase + digits} | |
DICT_CHOICE = int(input(""" | |
What characters should we use? | |
1. ascii_uppercase | |
2. ascii_lowercase | |
4. digits | |
example: 3 (1 + 2) = ascii_uppercase + ascii_lowercase | |
6 (4 + 2) = ascii_lowercase + digits | |
7 (1 + 2 + 4) = All combinations | |
> """)) | |
CHAR_POOL = ''.join(chars_dict[DICT_CHOICE]) # set chars to pull from | |
KEY_LEN = int(input("What is the keylength? (0 if unknown)> ")) | |
if KEY_LEN == 0: | |
print(""" | |
**WARNING** If you used more than one set of characters, this will probably | |
take a VERY long time, and not be kind to your computer/VM. | |
""") | |
super_brute = True | |
else: | |
super_brute = False | |
DATA_TO_DECODE = input("Enter the encrypted data (string)> ") | |
encrypted = binascii.unhexlify(DATA_TO_DECODE) | |
def gen(): | |
""" | |
Iterate through CHAR_POOL one char at a time | |
""" | |
for i in CHAR_POOL: | |
yield tuple([i]) | |
def worker(base, enc_data=encrypted): | |
""" | |
Worker function to search key space | |
""" | |
for p in product(CHAR_POOL, repeat=KEY_LEN-len(base)): | |
key = ''.join(base + p) | |
decr = ARC4(key).decrypt(enc_data) | |
# Uncomment to print all keys to screen | |
print(key) | |
# Use the chardetect library to decide if the unencrypted data is a string | |
check = chardet.detect(decr) | |
if check['confidence'] >= 0.8 and check['encoding'] == 'ascii': | |
return f"\nFound it!\nKey:{key}\nString: {decr.decode('ascii')}\n" | |
return None | |
def parallel(): | |
""" | |
Starts a number of threads that search through the key space | |
""" | |
print("Working....") | |
with Pool() as pool: # Pool() uses number of system CPU cores by default | |
for i in pool.imap_unordered(worker, gen(), chunksize=1): | |
if i is not None: | |
pool.terminate() | |
print(i) | |
sys.exit(0) | |
sys.exit("\nNothing found.") | |
def serial(): | |
worker(tuple()) | |
if __name__ == "__main__": | |
# Replace parallel() with serial() if you want to use only one thread. | |
if super_brute: | |
for i in range(1, 7): # Default is to attempt iterations up to a key length of 6... | |
KEY_LEN = i | |
parallel() | |
else: | |
parallel() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment