# 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.
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
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.
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!
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