RootOfTheNull

Flattened Base64 Recovery

Feb 20th, 2019
385
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python2
  2. # Author: Caleb Stewart
  3. # Date: January 20th, 2019
  4. # This code, given a lowercased Base64 string, will determine the correct and original Base64 encoding
  5.  
  6. from pwn import *
  7. import sys
  8. import argparse
  9.  
  10. def all_case_combos(inp):
  11.     n = len(inp)
  12.    
  13.     # Number of permutations is 2^n
  14.     mx = 1 << n
  15.    
  16.     # Converting string to lower case
  17.     inp = inp.lower()
  18.  
  19.      # Using all subsequences and permuting them
  20.     i = long(0)
  21.     while i < mx:
  22.         # If j-th bit is set, we convert it to upper case
  23.         combination = [k for k in inp]
  24.         for j in xrange(n):
  25.             if (((i >> j) & 1) == 1):
  26.                 combination[j] = inp[j].upper()
  27.    
  28.         temp = ""
  29.         # Printing current combination
  30.         for j in combination:
  31.             temp += j
  32.         i += 1
  33.         yield temp
  34.  
  35. def count_printable(s):
  36.     n = len([c for c in s if ord(c) >= 32 and ord(c) <= 126])
  37.     return n
  38.  
  39. def base64_pad(s):
  40.     if (len(s)%4) == 0:
  41.         return s
  42.     return s.ljust(len(s)+3-(int((len(s)/4)*3)%3), '=')
  43.  
  44. def bruteforce_base64(flat):
  45.     # The entire result in the correct case
  46.     result = ''
  47.  
  48.     # Iterate through each 4 character (3 byte) chunkk
  49.     for i in range(0, len(flat), 4):
  50.         p = log.progress('bruteforcing chunk[{0}:{1}]'.format(i,i+4))
  51.  
  52.         # Indicates whether the next loop failed
  53.         found = 0
  54.  
  55.         # Iterate all cases of this chunk
  56.         for option in all_case_combos(flat[i:i+4]):
  57.             # Make sure the padding is right
  58.             option = base64_pad(option)
  59.            
  60.             p.status('trying case {0}'.format(option))
  61.  
  62.             # Decode the data
  63.             data = option.decode('base64')
  64.  
  65.             # Count the printable characters
  66.             nprint = count_printable(data)
  67.  
  68.             # We consider is success if it is all ascii printable
  69.             if nprint == len(data):
  70.                 p.success("correct case is {0}".format(option))
  71.                 result += option.replace('=', '')
  72.                 found = 1
  73.                 break
  74.  
  75.         # Make sure the last loop succeeded. If not, we have completely failed
  76.         if found == 0:
  77.             p.failure('unable to find correct case')
  78.             return None
  79.  
  80.     # We found it
  81.     return result
  82.  
  83. # Parse arguments
  84. parser = argparse.ArgumentParser(description='bruteforce base64 case')
  85. parser.add_argument('base64', help='the base64 input you want to bruteforce')
  86. args = parser.parse_args()
  87.  
  88. # Padding
  89. args.base64 = base64_pad(args.base64)
  90.  
  91. # Loop condition
  92. cont = 'y'
  93.  
  94. # Loop forever
  95. while cont.upper() == 'Y':
  96.     log.info('bruteforcing case of {0}'.format(args.base64))
  97.  
  98.     # Brute force it!
  99.     result = base64_pad(bruteforce_base64(args.base64))
  100.  
  101.     # Check if we failed
  102.     if result == None:
  103.         log.error('failed to bruteforce {0}!'.format(args.base64))
  104.         sys.exit(1)
  105.  
  106.     # Should we continue?
  107.     log.info('the correct case is {0}'.format(result))
  108.     log.info('the decoded output is: {0}'.format(result.decode('base64')))
  109.     # loop till they listen
  110.     cont = ''
  111.     while cont.upper() != 'Y' and cont.upper() != 'N':
  112.         cont = raw_input('should we continue? (y/n) ').rstrip()
  113.  
  114.     # If we continue, the result is now our target
  115.     args.base64 = result.decode('base64')
RAW Paste Data