source: bin/bletchley-analyze @ 17

Last change on this file since 17 was 13, checked in by tmorgan, 12 years ago

added block size and encoding chain options

  • Property svn:executable set to *
File size: 4.7 KB
RevLine 
[1]1#!/usr/bin/env python
2
3# Requires Python 2.7+
4
5'''
6Simple script to leverage some of the blobtools features
7
8Copyright (C) 2011-2012 Virtual Security Research, LLC
9Author: Timothy D. Morgan
10
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU Lesser General Public License, version 3,
13 as published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program.  If not, see <http://www.gnu.org/licenses/>.
22'''
23
24
25import sys
26import argparse
27import binascii
28from bletchley import blobtools,buffertools
29
30
31parser = argparse.ArgumentParser(description='Analyzes samples of encrypted data in an attempt to decode samples to binary and identify patterns useful in cryptanalysis.')
32parser.add_argument('input_file', nargs='?', default=None,
33                    help='File containing encrypted blobs to analyze, one per line. Omit to read from stdin.')
[13]34parser.add_argument('-e', dest='encoding_chain', type=str, default=None,
35                    help='Comma-separated sequence of formats used to encode the tokens, beginning with the last one applied. (default: auto-detect)')
36parser.add_argument('-b', dest='block_size', type=int, default=8,
37                    help='The block size displayed and used in highlighting (default: 8)')
[1]38parser.add_argument('-p', dest='output_lines', type=int, default=10,
39                    help='Number of lines of input to display in decoded form.')
40parser.add_argument('-c', action='store_const', const=True, default=False,
41                    help='Use color output for decoded highlights.')
42parser.add_argument('-c256', action='store_const', const=True, default=False,
43                    help='Use 256 color output for decoded highlights.')
44options = parser.parse_args()
45
46input_file = sys.stdin
47if options.input_file is not None:
48    input_file = file(options.input_file, 'rb')
49
50
51blobs = input_file.read().rstrip('\n').replace('\r', '').split('\n')
52#print(repr(blobs))
53
54def terminalHighlightedString(code, s):
55    global options
56    if code == None:
57        return s
58
59    if options.c256:
60        fg = code%216+16
61        bg = (code^0xffffffff)%216+16
62        return "\x1b[0;38;05;%d;48;05;%dm%s\x1b[0m" % (fg,bg,s)
63    elif options.c:
64        fg = code%6+31
65        bg = (code^0xffffffff)%6+41
66        return "\x1b[0;%d;%dm%s\x1b[0m" % (fg,bg,s)
67    else:
68        return "\x1b[7m%s\x1b[0m" % s
69
70
71def printColoredHexDump(blobs, group_size=8):   
[9]72    line_size = 64
[1]73    group_size *= 2 # two hex digits per byte
[9]74    print(group_size)
[1]75    hex_blobs = map(binascii.b2a_hex, blobs)
76    color_map = buffertools.blockWiseColorMap(group_size, hex_blobs)
77
78    for k in range(0,len(hex_blobs)):
79        hex = hex_blobs[k]
80       
[9]81        for i in range(0,len(hex),line_size):
[13]82            line = '%.4X: ' % i
[1]83
[9]84            if len(hex[i:]) < line_size:
85                hex += (line_size-len(hex[i:]))*' '
[1]86
[9]87            for j in range(0,line_size,group_size):
88                group = hex[i+j:i+j+group_size]
89                line += terminalHighlightedString(color_map.get(group, None), group) + ' ' 
90       
[1]91            line += '| '
[9]92            line += repr(blobs[k][i/2:(i+line_size)/2])
[1]93       
[9]94            print(line)
95        print('')
[1]96
97
98
99def analyze(blobs):
100    lengths = blobtools.getLengths(blobs)
101    print('Unique Lengths: ' + ','.join(map(str, lengths)))
102
103    max_block_size = blobtools.maxBlockSize(lengths)
104    print('Maximum Possible Block Size: %d' % max_block_size)
105
106    block_sizes = blobtools.checkCommonBlocksizes(lengths)
107    print('Matching Common Block Sizes: %s' % ','.join(map(str, block_sizes)))
108
109    encodings = blobtools.encodingIntersection(blobs)
110    print('Possible Encodings: ' + ','.join(encodings))
111
112    encoding = blobtools.bestEncoding(encodings)
113    print('Best Encoding: %s' % encoding)
114
115    return encoding,block_sizes
116
[13]117specified_encodings = []
118if options.encoding_chain != None:
119    specified_encodings = options.encoding_chain.split(',')
[1]120
121encoding_chain = []
122encoding = 'dummy'
123while encoding != None:
124    print('='*80)
125    print('Beginning analysis after decoding by chain: %s' % ','.join(encoding_chain))
126    encoding,block_sizes = analyze(blobs)
[13]127    if len(specified_encodings) > 0:
128        encoding = specified_encodings.pop(0)
[1]129
[13]130
[1]131    blobs_to_print = blobs[:options.output_lines]
132    print('First %d Values:' % len(blobs_to_print))
133
[13]134    printColoredHexDump(blobs_to_print, options.block_size)
[1]135
136    if encoding != None:
137        encoding_chain.append(encoding)
138        blobs = blobtools.decodeAll(encoding, blobs)
139
Note: See TracBrowser for help on using the repository browser.