Skip to content

Commit 42710cc

Browse files
zeroSteinerBrent Cook
authored andcommitted
Error messages for the python meterpreter
1 parent 4a47f0f commit 42710cc

File tree

3 files changed

+179
-41
lines changed

3 files changed

+179
-41
lines changed

data/meterpreter/ext_server_stdapi.py

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -690,10 +690,10 @@ def stdapi_sys_config_getenv(request, response):
690690
def stdapi_sys_config_getsid(request, response):
691691
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
692692
if not token:
693-
return ERROR_FAILURE, response
693+
return error_result_windows(), response
694694
sid_str = ctypes.c_char_p()
695695
if not ctypes.windll.advapi32.ConvertSidToStringSidA(token.User.Sid, ctypes.byref(sid_str)):
696-
return ERROR_FAILURE, response
696+
return error_result_windows(), response
697697
sid_str = str(ctypes.string_at(sid_str))
698698
response += tlv_pack(TLV_TYPE_SID, sid_str)
699699
return ERROR_SUCCESS, response
@@ -705,10 +705,10 @@ def stdapi_sys_config_getuid(request, response):
705705
elif has_windll:
706706
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
707707
if not token:
708-
return ERROR_FAILURE, response
708+
return error_result_windows(), response
709709
username = get_username_from_token(token)
710710
if not username:
711-
return ERROR_FAILURE, response
711+
return error_result_windows(), response
712712
else:
713713
username = getpass.getuser()
714714
response += tlv_pack(TLV_TYPE_USER_NAME, username)
@@ -796,9 +796,9 @@ def stdapi_sys_process_kill(request, response):
796796
k32 = ctypes.windll.kernel32
797797
proc_h = k32.OpenProcess(PROCESS_TERMINATE, False, pid)
798798
if not proc_h:
799-
return ERROR_FAILURE, response
799+
return error_result_windows(), response
800800
if not k32.TerminateProcess(proc_h, 0):
801-
return ERROR_FAILURE, response
801+
return error_result_windows(), response
802802
elif hasattr(os, 'kill'):
803803
os.kill(pid, 9)
804804
else:
@@ -865,7 +865,7 @@ def stdapi_sys_process_get_processes_via_windll(request, response):
865865
proc_snap = k32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
866866
result = k32.Process32First(proc_snap, ctypes.byref(pe32))
867867
if not result:
868-
return ERROR_FAILURE, response
868+
return error_result_windows(), response
869869
while result:
870870
proc_h = k32.OpenProcess((PROCESS_QUERY_INFORMATION | PROCESS_VM_READ), False, pe32.th32ProcessID)
871871
if not proc_h:
@@ -1348,10 +1348,10 @@ def stdapi_registry_create_key(request, response):
13481348
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
13491349
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
13501350
res_key = ctypes.c_void_p()
1351-
if ctypes.windll.advapi32.RegCreateKeyExA(root_key, ctypes.byref(base_key), 0, None, 0, permission, None, ctypes.byref(res_key), None) == ERROR_SUCCESS:
1352-
response += tlv_pack(TLV_TYPE_HKEY, res_key.value)
1353-
return ERROR_SUCCESS, response
1354-
return ERROR_FAILURE, response
1351+
if ctypes.windll.advapi32.RegCreateKeyExA(root_key, ctypes.byref(base_key), 0, None, 0, permission, None, ctypes.byref(res_key), None) != ERROR_SUCCESS:
1352+
return error_result_windows(), response
1353+
response += tlv_pack(TLV_TYPE_HKEY, res_key.value)
1354+
return ERROR_SUCCESS, response
13551355

13561356
@meterpreter.register_function_windll
13571357
def stdapi_registry_delete_key(request, response):
@@ -1442,33 +1442,31 @@ def stdapi_registry_open_key(request, response):
14421442
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
14431443
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
14441444
handle_id = ctypes.c_void_p()
1445-
if ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id)) == ERROR_SUCCESS:
1446-
response += tlv_pack(TLV_TYPE_HKEY, handle_id.value)
1447-
return ERROR_SUCCESS, response
1448-
return ERROR_FAILURE, response
1445+
if ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id)) != ERROR_SUCCESS:
1446+
return error_result_windows(), response
1447+
response += tlv_pack(TLV_TYPE_HKEY, handle_id.value)
1448+
return ERROR_SUCCESS, response
14491449

14501450
@meterpreter.register_function_windll
14511451
def stdapi_registry_open_remote_key(request, response):
14521452
target_host = packet_get_tlv(request, TLV_TYPE_TARGET_HOST)['value']
14531453
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
14541454
result_key = ctypes.c_void_p()
1455-
result = ctypes.windll.advapi32.RegConnectRegistry(target_host, root_key, ctypes.byref(result_key))
1456-
if (result == ERROR_SUCCESS):
1457-
response += tlv_pack(TLV_TYPE_HKEY, result_key.value)
1458-
return ERROR_SUCCESS, response
1459-
return ERROR_FAILURE, response
1455+
if ctypes.windll.advapi32.RegConnectRegistry(target_host, root_key, ctypes.byref(result_key)) != ERROR_SUCCESS:
1456+
return error_result_windows(), response
1457+
response += tlv_pack(TLV_TYPE_HKEY, result_key.value)
1458+
return ERROR_SUCCESS, response
14601459

14611460
@meterpreter.register_function_windll
14621461
def stdapi_registry_query_class(request, response):
14631462
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
14641463
value_data = (ctypes.c_char * 4096)()
14651464
value_data_sz = ctypes.c_uint32()
14661465
value_data_sz.value = ctypes.sizeof(value_data)
1467-
result = ctypes.windll.advapi32.RegQueryInfoKeyA(hkey, value_data, ctypes.byref(value_data_sz), None, None, None, None, None, None, None, None, None)
1468-
if result == ERROR_SUCCESS:
1469-
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data))
1470-
return ERROR_SUCCESS, response
1471-
return ERROR_FAILURE, response
1466+
if ctypes.windll.advapi32.RegQueryInfoKeyA(hkey, value_data, ctypes.byref(value_data_sz), None, None, None, None, None, None, None, None, None) != ERROR_SUCCESS:
1467+
return error_result_windows(), response
1468+
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data))
1469+
return ERROR_SUCCESS, response
14721470

14731471
@meterpreter.register_function_windll
14741472
def stdapi_registry_query_value(request, response):
@@ -1496,7 +1494,7 @@ def stdapi_registry_query_value(request, response):
14961494
else:
14971495
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data, value_data_sz.value))
14981496
return ERROR_SUCCESS, response
1499-
return ERROR_FAILURE, response
1497+
return error_result_windows(), response
15001498

15011499
@meterpreter.register_function_windll
15021500
def stdapi_registry_set_value(request, response):

data/meterpreter/meterpreter.py

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
has_urllib = True
3838

3939
if sys.version_info[0] < 3:
40+
is_str = lambda obj: issubclass(obj.__class__, str)
4041
is_bytes = lambda obj: issubclass(obj.__class__, str)
4142
bytes = lambda *args: str(*args[:1])
4243
NULL_BYTE = '\x00'
@@ -71,6 +72,8 @@
7172
ERROR_SUCCESS = 0
7273
# not defined in original C implementation
7374
ERROR_FAILURE = 1
75+
ERROR_FAILURE_PYTHON = 2
76+
ERROR_FAILURE_WINDOWS = 3
7477

7578
CHANNEL_CLASS_BUFFERED = 0
7679
CHANNEL_CLASS_STREAM = 1
@@ -155,6 +158,50 @@ def generate_request_id():
155158
chars = 'abcdefghijklmnopqrstuvwxyz'
156159
return ''.join(random.choice(chars) for x in range(32))
157160

161+
@export
162+
def crc16(data):
163+
poly = 0x1021
164+
reg = 0x0000
165+
if is_str(data):
166+
data = list(map(ord, data))
167+
elif is_bytes(data):
168+
data = list(data)
169+
data.append(0)
170+
data.append(0)
171+
for byte in data:
172+
mask = 0x80
173+
while mask > 0:
174+
reg <<= 1
175+
if byte & mask:
176+
reg += 1
177+
mask >>= 1
178+
if reg > 0xffff:
179+
reg &= 0xffff
180+
reg ^= poly
181+
return reg
182+
183+
@export
184+
def error_result(exception=None):
185+
if not exception:
186+
_, exception, _ = sys.exc_info()
187+
exception_crc = crc16(exception.__class__.__name__)
188+
if exception_crc == 0x4cb2: # WindowsError
189+
return error_result_windows(exception.errno)
190+
else:
191+
result = ((exception_crc << 16) | ERROR_FAILURE_PYTHON)
192+
return result
193+
194+
@export
195+
def error_result_windows(error_number=None):
196+
if not has_windll:
197+
return ERROR_FAILURE
198+
if error_number == None:
199+
error_number = ctypes.windll.kernel32.GetLastError()
200+
if error_number > 0xffff:
201+
return ERROR_FAILURE
202+
result = ((error_number << 16) | ERROR_FAILURE_WINDOWS)
203+
return result
204+
158205
@export
159206
def inet_pton(family, address):
160207
if hasattr(socket, 'inet_pton'):
@@ -337,6 +384,10 @@ def __init__(self, socket=None):
337384
getattr(self, 'driver_init_' + self.driver)()
338385
self.running = True
339386

387+
def debug_print(self, msg):
388+
if DEBUGGING:
389+
print(msg)
390+
340391
def driver_init_http(self):
341392
if HTTP_PROXY:
342393
proxy_handler = urllib.ProxyHandler({'http': HTTP_PROXY})
@@ -533,7 +584,7 @@ def _core_channel_open(self, request, response):
533584
channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE)
534585
handler = 'channel_open_' + channel_type['value']
535586
if handler not in self.extension_functions:
536-
return ERROR_FAILURE, response
587+
return error_result(NotImplementedError), response
537588
handler = self.extension_functions[handler]
538589
return handler(request, response)
539590

@@ -641,18 +692,16 @@ def create_response(self, request):
641692
if handler_name in self.extension_functions:
642693
handler = self.extension_functions[handler_name]
643694
try:
644-
if DEBUGGING:
645-
print('[*] running method ' + handler_name)
695+
self.debug_print('[*] running method ' + handler_name)
646696
result, resp = handler(request, resp)
647697
except Exception:
698+
self.debug_print('[-] method ' + handler_name + ' resulted in an error')
648699
if DEBUGGING:
649-
print('[-] method ' + handler_name + ' resulted in an error')
650700
traceback.print_exc(file=sys.stderr)
651-
result = ERROR_FAILURE
701+
result = error_result()
652702
else:
653-
if DEBUGGING:
654-
print('[-] method ' + handler_name + ' was requested but does not exist')
655-
result = ERROR_FAILURE
703+
self.debug_print('[-] method ' + handler_name + ' was requested but does not exist')
704+
result = error_result(NotImplementedError)
656705
resp += tlv_pack(TLV_TYPE_RESULT, result)
657706
resp = struct.pack('>I', len(resp) + 4) + resp
658707
return resp

lib/msf/base/sessions/meterpreter_python.rb

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: binary -*-
22

33
require 'msf/base/sessions/meterpreter'
4+
require 'msf/windows_error'
45

56
module Msf
67
module Sessions
@@ -11,19 +12,109 @@ module Sessions
1112
#
1213
###
1314
class Meterpreter_Python_Python < Msf::Sessions::Meterpreter
15+
ERROR_TYPE_UNKNOWN = 1
16+
ERROR_TYPE_PYTHON = 2
17+
ERROR_TYPE_WINDOWS = 3
18+
# 16-bit CRC-CCITT XMODEM
19+
PYTHON_ERROR_CRCS = {
20+
0x02dd => 'NotImplementedError',
21+
0x049a => 'RuntimeWarning',
22+
0x09ae => 'IndentationError',
23+
0x0bf4 => 'SystemExit',
24+
0x1494 => 'GeneratorExit',
25+
0x1511 => 'ConnectionRefusedError',
26+
0x1765 => 'SyntaxWarning',
27+
0x1f0e => 'SystemError',
28+
0x33b1 => 'StandardError',
29+
0x37b8 => 'IOError',
30+
0x39df => 'PermissionError',
31+
0x39e6 => 'AttributeError',
32+
0x3b70 => 'ChildProcessError',
33+
0x3c93 => 'UserWarning',
34+
0x3ca3 => 'BufferError',
35+
0x3e32 => 'StopIteration',
36+
0x423c => 'NotADirectoryError',
37+
0x42f1 => 'ConnectionError',
38+
0x453b => 'UnboundLocalError',
39+
0x470d => 'LookupError',
40+
0x4cb2 => 'WindowsError',
41+
0x4ecc => 'ResourceWarning',
42+
0x532d => 'UnicodeEncodeError',
43+
0x5dde => 'ConnectionAbortedError',
44+
0x6011 => 'EOFError',
45+
0x637f => 'UnicodeWarning',
46+
0x6482 => 'RuntimeError',
47+
0x6a75 => 'ArithmeticError',
48+
0x6b73 => 'BlockingIOError',
49+
0x70e0 => 'UnicodeDecodeError',
50+
0x72b4 => 'AssertionError',
51+
0x75a1 => 'TabError',
52+
0x77c2 => 'ReferenceError',
53+
0x7a4c => 'FutureWarning',
54+
0x7a78 => 'Warning',
55+
0x7ef9 => 'IsADirectoryError',
56+
0x81dc => 'ConnectionResetError',
57+
0x87fa => 'OSError',
58+
0x8937 => 'KeyError',
59+
0x8a80 => 'SyntaxError',
60+
0x8f3e => 'TypeError',
61+
0x9329 => 'MemoryError',
62+
0x956e => 'ValueError',
63+
0x96a1 => 'OverflowError',
64+
0xa451 => 'InterruptedError',
65+
0xa4d7 => 'FileExistsError',
66+
0xb19a => 'ZeroDivisionError',
67+
0xb27b => 'IndexError',
68+
0xb628 => 'UnicodeError',
69+
0xbb63 => 'TimeoutError',
70+
0xbc91 => 'ImportWarning',
71+
0xc18f => 'BrokenPipeError',
72+
0xc3a0 => 'KeyboardInterrupt',
73+
0xcbab => 'ImportError',
74+
0xcd47 => 'NameError',
75+
0xcd82 => 'ProcessLookupError',
76+
0xdd4a => 'BaseException',
77+
0xe5a3 => 'BytesWarning',
78+
0xe97a => 'FileNotFoundError',
79+
0xe98a => 'PendingDeprecationWarning',
80+
0xf47c => 'DeprecationWarning',
81+
0xf7c6 => 'Exception',
82+
0xfa9d => 'EnvironmentError',
83+
0xfcb4 => 'UnicodeTranslateError',
84+
0xff8d => 'FloatingPointError'
85+
}
86+
87+
def initialize(rstream, opts={})
88+
super
89+
self.platform = 'python/python'
90+
self.binary_suffix = 'py'
91+
end
92+
93+
def lookup_error(error_code)
94+
unknown_error = 'Unknown error'
95+
error_type = error_code & 0x0f
96+
return unknown_error if error_type == ERROR_TYPE_UNKNOWN
97+
98+
error_code &= 0xffff0000
99+
error_code >>= 16
100+
101+
if error_type == ERROR_TYPE_PYTHON
102+
python_error = PYTHON_ERROR_CRCS[error_code]
103+
return "Python exception: #{python_error}" unless python_error.nil?
104+
elsif error_type == ERROR_TYPE_WINDOWS
105+
return "Windows error: #{Msf::WindowsError.description(error_code)}"
106+
end
107+
108+
unknown_error
109+
end
110+
14111
def supports_ssl?
15112
false
16113
end
114+
17115
def supports_zlib?
18116
false
19117
end
20-
def initialize(rstream, opts={})
21-
super
22-
self.platform = 'python/python'
23-
self.binary_suffix = 'py'
24-
end
25118
end
26-
27119
end
28120
end
29-

0 commit comments

Comments
 (0)