1#!/usr/bin/env python
2# Copyright (c) 2003-2016 CORE Security Technologies)
3#
4# This software is provided under under a slightly modified version
5# of the Apache Software License. See the accompanying LICENSE file
6# for more information.
7#
8# Author: Alberto Solino (@agsolino)
9#
10# Description: A Windows Registry Reader Example
11#
12# Reference for:
13#  winregistry.py
14#
15
16import sys
17import argparse
18import ntpath
19from binascii import unhexlify, hexlify
20
21from impacket.examples import logger
22from impacket import version
23from impacket import winregistry
24
25
26def bootKey(reg):
27    baseClass = 'ControlSet001\\Control\\Lsa\\'
28    keys = ['JD','Skew1','GBG','Data']
29    tmpKey = ''
30
31    for key in keys:
32        tmpKey = tmpKey + unhexlify(reg.getClass(baseClass + key).decode('utf-16le')[:8])
33
34    transforms = [ 8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7 ]
35
36    syskey = ''
37    for i in xrange(len(tmpKey)):
38        syskey += tmpKey[transforms[i]]
39
40    print hexlify(syskey)
41
42def getClass(reg, className):
43    regKey = ntpath.dirname(className)
44    regClass = ntpath.basename(className)
45
46    value = reg.getClass(className)
47
48    if value is None:
49        return
50
51    print "[%s]" % regKey
52
53    print "Value for Class %s: \n" % regClass,
54
55    winregistry.hexdump(value,'   ')
56
57def getValue(reg, keyValue):
58    regKey = ntpath.dirname(keyValue)
59    regValue = ntpath.basename(keyValue)
60
61    value = reg.getValue(keyValue)
62
63    print "[%s]\n" % regKey
64
65    if value is None:
66        return
67
68    print "Value for %s:\n    " % regValue,
69    reg.printValue(value[0],value[1])
70
71def enumValues(reg, searchKey):
72    key = reg.findKey(searchKey)
73
74    if key is None:
75        return
76
77    print "[%s]\n" % searchKey
78
79    values = reg.enumValues(key)
80
81    for value in values:
82        print "  %-30s: " % value,
83        data = reg.getValue('%s\\%s'%(searchKey,value))
84        # Special case for binary string.. so it looks better formatted
85        if data[0] == winregistry.REG_BINARY:
86            print ''
87            reg.printValue(data[0],data[1])
88            print ''
89        else:
90            reg.printValue(data[0],data[1])
91
92def enumKey(reg, searchKey, isRecursive, indent='  '):
93    parentKey = reg.findKey(searchKey)
94
95    if parentKey is None:
96        return
97
98    keys = reg.enumKey(parentKey)
99
100    for key in keys:
101        print "%s%s" %(indent, key)
102        if isRecursive is True:
103            if searchKey == '\\':
104                enumKey(reg, '\\%s'%key,isRecursive,indent+'  ')
105            else:
106                enumKey(reg, '%s\\%s'%(searchKey,key),isRecursive,indent+'  ')
107
108def walk(reg, keyName):
109    return reg.walk(keyName)
110
111
112def main():
113    # Init the example's logger theme
114    logger.init()
115    print version.BANNER
116
117    parser = argparse.ArgumentParser(add_help = True, description = "Reads data from registry hives.")
118
119    parser.add_argument('hive', action='store', help='registry hive to open')
120    subparsers = parser.add_subparsers(help='actions', dest='action')
121    # A enum_key command
122    enumkey_parser = subparsers.add_parser('enum_key', help='enumerates the subkeys of the specified open registry key')
123    enumkey_parser.add_argument('-name', action='store', required=True, help='registry key')
124    enumkey_parser.add_argument('-recursive', dest='recursive', action='store_true', required=False, help='recursive search (default False)')
125
126    # A enum_values command
127    enumvalues_parser = subparsers.add_parser('enum_values', help='enumerates the values for the specified open registry key')
128    enumvalues_parser.add_argument('-name', action='store', required=True, help='registry key')
129
130    # A get_value command
131    getvalue_parser = subparsers.add_parser('get_value', help='retrieves the data for the specified registry value')
132    getvalue_parser.add_argument('-name', action='store', required=True, help='registry value')
133
134    # A get_class command
135    getclass_parser = subparsers.add_parser('get_class', help='retrieves the data for the specified registry class')
136    getclass_parser.add_argument('-name', action='store', required=True, help='registry class name')
137
138    # A walk command
139    walk_parser = subparsers.add_parser('walk', help='walks the registry from the name node down')
140    walk_parser.add_argument('-name', action='store', required=True, help='registry class name to start walking down from')
141
142    if len(sys.argv)==1:
143        parser.print_help()
144        sys.exit(1)
145
146    options = parser.parse_args()
147
148    reg = winregistry.Registry(options.hive)
149
150    if options.action.upper() == 'ENUM_KEY':
151        print "[%s]" % options.name
152        enumKey(reg, options.name, options.recursive)
153    elif options.action.upper() == 'ENUM_VALUES':
154        enumValues(reg, options.name)
155    elif options.action.upper() == 'GET_VALUE':
156        getValue(reg, options.name)
157    elif options.action.upper() == 'GET_CLASS':
158        getClass(reg, options.name)
159    elif options.action.upper() == 'WALK':
160        walk(reg, options.name)
161
162    reg.close()
163
164if __name__ == "__main__":
165    main()
166
167