source: trunk/bin/bletchley-analyze @ 35

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

now encoding '/' in percent encoding

fixed bug in POA's stripping of pkcs5 pads

debugging statement changes

  • Property svn:executable set to *
File size: 5.0 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
[28]31parser = argparse.ArgumentParser(
32    description='Analyzes samples of encrypted data in an attempt to decode'
33    ' samples to binary and identify patterns useful in cryptanalysis.'
34    ' For more information, see:  http://code.google.com/p/bletchley/wiki/Overview')
[1]35parser.add_argument('input_file', nargs='?', default=None,
[28]36                    help='File containing encrypted blobs to analyze, one per'
37                    ' line. Omit to read from stdin.')
[13]38parser.add_argument('-e', dest='encoding_chain', type=str, default=None,
[28]39                    help='Comma-separated sequence of formats used to encode'
40                    ' the tokens, beginning with the last one applied. '
41                    '(default: auto-detect. Use "?" for a listing of supported encodings.)')
[13]42parser.add_argument('-b', dest='block_size', type=int, default=8,
43                    help='The block size displayed and used in highlighting (default: 8)')
[1]44parser.add_argument('-p', dest='output_lines', type=int, default=10,
45                    help='Number of lines of input to display in decoded form.')
46parser.add_argument('-c', action='store_const', const=True, default=False,
47                    help='Use color output for decoded highlights.')
48parser.add_argument('-c256', action='store_const', const=True, default=False,
49                    help='Use 256 color output for decoded highlights.')
50options = parser.parse_args()
51
[28]52if options.encoding_chain == '?':
53    print('\n\t'.join(['Supported encodings:']+blobtools.supportedEncodings()))
54    sys.exit(0)
55
[1]56input_file = sys.stdin
57if options.input_file is not None:
58    input_file = file(options.input_file, 'rb')
59
60blobs = input_file.read().rstrip('\n').replace('\r', '').split('\n')
61#print(repr(blobs))
62
63def terminalHighlightedString(code, s):
64    global options
65    if code == None:
66        return s
67
68    if options.c256:
69        fg = code%216+16
70        bg = (code^0xffffffff)%216+16
71        return "\x1b[0;38;05;%d;48;05;%dm%s\x1b[0m" % (fg,bg,s)
72    elif options.c:
73        fg = code%6+31
74        bg = (code^0xffffffff)%6+41
75        return "\x1b[0;%d;%dm%s\x1b[0m" % (fg,bg,s)
76    else:
77        return "\x1b[7m%s\x1b[0m" % s
78
79
80def printColoredHexDump(blobs, group_size=8):   
[9]81    line_size = 64
[1]82    group_size *= 2 # two hex digits per byte
83    hex_blobs = map(binascii.b2a_hex, blobs)
84    color_map = buffertools.blockWiseColorMap(group_size, hex_blobs)
85
86    for k in range(0,len(hex_blobs)):
87        hex = hex_blobs[k]
88       
[9]89        for i in range(0,len(hex),line_size):
[13]90            line = '%.4X: ' % i
[1]91
[9]92            if len(hex[i:]) < line_size:
93                hex += (line_size-len(hex[i:]))*' '
[1]94
[9]95            for j in range(0,line_size,group_size):
96                group = hex[i+j:i+j+group_size]
97                line += terminalHighlightedString(color_map.get(group, None), group) + ' ' 
98       
[1]99            line += '| '
[9]100            line += repr(blobs[k][i/2:(i+line_size)/2])
[1]101       
[9]102            print(line)
103        print('')
[1]104
105
106
107def analyze(blobs):
108    lengths = blobtools.getLengths(blobs)
109    print('Unique Lengths: ' + ','.join(map(str, lengths)))
110
111    max_block_size = blobtools.maxBlockSize(lengths)
112    print('Maximum Possible Block Size: %d' % max_block_size)
113
114    block_sizes = blobtools.checkCommonBlocksizes(lengths)
115    print('Matching Common Block Sizes: %s' % ','.join(map(str, block_sizes)))
116
117    encodings = blobtools.encodingIntersection(blobs)
118    print('Possible Encodings: ' + ','.join(encodings))
119
120    encoding = blobtools.bestEncoding(encodings)
121    print('Best Encoding: %s' % encoding)
122
123    return encoding,block_sizes
124
[13]125specified_encodings = []
126if options.encoding_chain != None:
127    specified_encodings = options.encoding_chain.split(',')
[1]128
129encoding_chain = []
130encoding = 'dummy'
131while encoding != None:
132    print('='*80)
133    print('Beginning analysis after decoding by chain: %s' % ','.join(encoding_chain))
134    encoding,block_sizes = analyze(blobs)
[13]135    if len(specified_encodings) > 0:
136        encoding = specified_encodings.pop(0)
[1]137
[13]138
[1]139    blobs_to_print = blobs[:options.output_lines]
140    print('First %d Values:' % len(blobs_to_print))
141
[13]142    printColoredHexDump(blobs_to_print, options.block_size)
[1]143
144    if encoding != None:
145        encoding_chain.append(encoding)
146        blobs = blobtools.decodeAll(encoding, blobs)
147
Note: See TracBrowser for help on using the repository browser.