Skip to content

Commit e426177

Browse files
zeroSteinerTod Beardsley
authored andcommitted
Add process enumeration for windows.
1 parent ee4ba04 commit e426177

File tree

1 file changed

+144
-12
lines changed

1 file changed

+144
-12
lines changed

data/meterpreter/ext_server_stdapi.py

Lines changed: 144 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33
import shlex
4+
import ctypes
45
import socket
56
import struct
67
import shutil
@@ -9,6 +10,43 @@
910
import platform
1011
import subprocess
1112

13+
has_windll = hasattr(ctypes, 'windll')
14+
15+
try:
16+
import pwd
17+
has_pwd = True
18+
except ImportError:
19+
has_pwd = False
20+
21+
class PROCESSENTRY32(ctypes.Structure):
22+
_fields_ = [("dwSize", ctypes.c_uint32),
23+
("cntUsage", ctypes.c_uint32),
24+
("th32ProcessID", ctypes.c_uint32),
25+
("th32DefaultHeapID", ctypes.c_void_p),
26+
("th32ModuleID", ctypes.c_uint32),
27+
("cntThreads", ctypes.c_uint32),
28+
("th32ParentProcessID", ctypes.c_uint32),
29+
("thPriClassBase", ctypes.c_int32),
30+
("dwFlags", ctypes.c_uint32),
31+
("szExeFile", (ctypes.c_char * 260))]
32+
33+
class SYSTEM_INFO(ctypes.Structure):
34+
_fields_ = [("wProcessorArchitecture", ctypes.c_uint16),
35+
("wReserved", ctypes.c_uint16),
36+
("dwPageSize", ctypes.c_uint32),
37+
("lpMinimumApplicationAddress", ctypes.c_void_p),
38+
("lpMaximumApplicationAddress", ctypes.c_void_p),
39+
("dwActiveProcessorMask", ctypes.c_uint32),
40+
("dwNumberOfProcessors", ctypes.c_uint32),
41+
("dwProcessorType", ctypes.c_uint32),
42+
("dwAllocationGranularity", ctypes.c_uint32),
43+
("wProcessorLevel", ctypes.c_uint16),
44+
("wProcessorRevision", ctypes.c_uint16),]
45+
46+
class SID_AND_ATTRIBUTES(ctypes.Structure):
47+
_fields_ = [("Sid", ctypes.c_void_p),
48+
("Attributes", ctypes.c_uint32),]
49+
1250
##
1351
# STDAPI
1452
##
@@ -103,14 +141,6 @@
103141

104142
TLV_TYPE_SHUTDOWN_HOW = TLV_META_TYPE_UINT | 1530
105143

106-
##
107-
# Sys
108-
##
109-
PROCESS_EXECUTE_FLAG_HIDDEN = (1 << 0)
110-
PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1)
111-
PROCESS_EXECUTE_FLAG_SUSPENDED = (1 << 2)
112-
PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN = (1 << 3)
113-
114144
# Registry
115145
TLV_TYPE_HKEY = TLV_META_TYPE_UINT | 1000
116146
TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY
@@ -200,6 +230,19 @@
200230
TLV_TYPE_POWER_FLAGS = TLV_META_TYPE_UINT | 4100
201231
TLV_TYPE_POWER_REASON = TLV_META_TYPE_UINT | 4101
202232

233+
##
234+
# Sys
235+
##
236+
PROCESS_EXECUTE_FLAG_HIDDEN = (1 << 0)
237+
PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1)
238+
PROCESS_EXECUTE_FLAG_SUSPENDED = (1 << 2)
239+
PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN = (1 << 3)
240+
241+
PROCESS_ARCH_UNKNOWN = 0
242+
PROCESS_ARCH_X86 = 1
243+
PROCESS_ARCH_X64 = 2
244+
PROCESS_ARCH_IA64 = 3
245+
203246
##
204247
# Errors
205248
##
@@ -228,6 +271,13 @@ def get_stat_buffer(path):
228271
st_buf += struct.pack('<II', blksize, blocks)
229272
return st_buf
230273

274+
def windll_GetNativeSystemInfo():
275+
if not has_windll:
276+
return None
277+
sysinfo = SYSTEM_INFO()
278+
ctypes.windll.kernel32.GetNativeSystemInfo(ctypes.byref(sysinfo))
279+
return {0:PROCESS_ARCH_X86, 6:PROCESS_ARCH_IA64, 9:PROCESS_ARCH_X64}.get(sysinfo.wProcessorArchitecture, PROCESS_ARCH_UNKNOWN)
280+
231281
@meterpreter.register_function
232282
def channel_create_stdapi_fs_file(request, response):
233283
fpath = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
@@ -278,11 +328,16 @@ def stdapi_sys_config_sysinfo(request, response):
278328
response += tlv_pack(TLV_TYPE_COMPUTER_NAME, uname_info[1])
279329
response += tlv_pack(TLV_TYPE_OS_NAME, uname_info[0] + ' ' + uname_info[2] + ' ' + uname_info[3])
280330
arch = uname_info[4]
281-
if not arch and uname_info[1] == 'Windows':
282-
if platform.architecture()[0] == '32bit':
283-
arch = 'x86'
284-
elif platform.architecture()[0] == '64bit':
331+
if has_windll:
332+
arch = windll_GetNativeSystemInfo()
333+
if arch == PROCESS_ARCH_IA64:
334+
arch = 'IA64'
335+
elif arch == PROCESS_ARCH_X64:
285336
arch = 'x86_64'
337+
elif arch == PROCESS_ARCH_X86:
338+
arch = 'x86'
339+
else:
340+
arch = uname_info[4]
286341
response += tlv_pack(TLV_TYPE_ARCHITECTURE, arch)
287342
return ERROR_SUCCESS, response
288343

@@ -344,6 +399,8 @@ def stdapi_sys_process_get_processes_via_proc(request, response):
344399
status[k[:-1]] = v.strip()
345400
ppid = status.get('PPid')
346401
uid = status.get('Uid').split('\t', 1)[0]
402+
if has_pwd:
403+
uid = pwd.getpwuid(int(uid)).pw_name
347404
if cmd:
348405
pname = os.path.basename(cmd.split(' ', 1)[0])
349406
ppath = cmd
@@ -359,11 +416,86 @@ def stdapi_sys_process_get_processes_via_proc(request, response):
359416
response += tlv_pack(TLV_TYPE_PROCESS_GROUP, pgroup)
360417
return ERROR_SUCCESS, response
361418

419+
def stdapi_sys_process_get_processes_via_windll(request, response):
420+
TH32CS_SNAPPROCESS = 2
421+
PROCESS_QUERY_INFORMATION = 0x0400
422+
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
423+
PROCESS_VM_READ = 0x10
424+
TOKEN_QUERY = 0x0008
425+
TokenUser = 1
426+
k32 = ctypes.windll.kernel32
427+
pe32 = PROCESSENTRY32()
428+
pe32.dwSize = ctypes.sizeof(PROCESSENTRY32)
429+
proc_snap = k32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
430+
result = k32.Process32First(proc_snap, ctypes.byref(pe32))
431+
if not result:
432+
return ERROR_FAILURE, response
433+
while result:
434+
proc_h = k32.OpenProcess((PROCESS_QUERY_INFORMATION | PROCESS_VM_READ), False, pe32.th32ProcessID)
435+
if not proc_h:
436+
proc_h = k32.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pe32.th32ProcessID)
437+
exe_path = (ctypes.c_char * 1024)()
438+
success = False
439+
if hasattr(ctypes.windll.psapi, 'GetModuleFileNameExA'):
440+
success = ctypes.windll.psapi.GetModuleFileNameExA(proc_h, 0, exe_path, ctypes.sizeof(exe_path))
441+
elif hasattr(k32, 'GetModuleFileNameExA'):
442+
success = k32.GetModuleFileNameExA(proc_h, 0, exe_path, ctypes.sizeof(exe_path))
443+
if not success and hasattr(k32, 'QueryFullProcessImageNameA'):
444+
dw_sz = ctypes.c_uint32()
445+
dw_sz.value = ctypes.sizeof(exe_path)
446+
success = k32.QueryFullProcessImageNameA(proc_h, 0, exe_path, ctypes.byref(dw_sz))
447+
if not success and hasattr(ctypes.windll.psapi, 'GetProcessImageFileNameA'):
448+
success = ctypes.windll.psapi.GetProcessImageFileNameA(proc_h, exe_path, ctypes.sizeof(exe_path))
449+
if success:
450+
exe_path = ctypes.string_at(exe_path)
451+
else:
452+
exe_path = ''
453+
complete_username = ''
454+
tkn_h = ctypes.c_long()
455+
tkn_len = ctypes.c_uint32()
456+
if ctypes.windll.advapi32.OpenProcessToken(proc_h, TOKEN_QUERY, ctypes.byref(tkn_h)):
457+
ctypes.windll.advapi32.GetTokenInformation(tkn_h, TokenUser, None, 0, ctypes.byref(tkn_len))
458+
buf = (ctypes.c_ubyte * tkn_len.value)()
459+
if ctypes.windll.advapi32.GetTokenInformation(tkn_h, TokenUser, ctypes.byref(buf), ctypes.sizeof(buf), ctypes.byref(tkn_len)):
460+
user_tkn = SID_AND_ATTRIBUTES()
461+
ctypes.memmove(ctypes.byref(user_tkn), buf, ctypes.sizeof(user_tkn))
462+
username = (ctypes.c_char * 512)()
463+
domain = (ctypes.c_char * 512)()
464+
u_len = ctypes.c_uint32()
465+
u_len.value = ctypes.sizeof(username)
466+
d_len = ctypes.c_uint32()
467+
d_len.value = ctypes.sizeof(domain)
468+
use = ctypes.c_ulong()
469+
use.value = 0
470+
ctypes.windll.advapi32.LookupAccountSidA(None, user_tkn.Sid, username, ctypes.byref(u_len), domain, ctypes.byref(d_len), ctypes.byref(use))
471+
complete_username = ctypes.string_at(domain) + '\\' + ctypes.string_at(username)
472+
k32.CloseHandle(tkn_h)
473+
parch = windll_GetNativeSystemInfo()
474+
is_wow64 = ctypes.c_ubyte()
475+
is_wow64.value = 0
476+
if hasattr(k32, 'IsWow64Process'):
477+
if k32.IsWow64Process(proc_h, ctypes.byref(is_wow64)):
478+
if is_wow64.value:
479+
parch = PROCESS_ARCH_X86
480+
pgroup = ''
481+
pgroup += tlv_pack(TLV_TYPE_PID, pe32.th32ProcessID)
482+
pgroup += tlv_pack(TLV_TYPE_PARENT_PID, pe32.th32ParentProcessID)
483+
pgroup += tlv_pack(TLV_TYPE_USER_NAME, complete_username)
484+
pgroup += tlv_pack(TLV_TYPE_PROCESS_NAME, pe32.szExeFile)
485+
pgroup += tlv_pack(TLV_TYPE_PROCESS_PATH, exe_path)
486+
pgroup += tlv_pack(TLV_TYPE_PROCESS_ARCH, parch)
487+
response += tlv_pack(TLV_TYPE_PROCESS_GROUP, pgroup)
488+
result = k32.Process32Next(proc_snap, ctypes.byref(pe32))
489+
k32.CloseHandle(proc_h)
490+
k32.CloseHandle(proc_snap)
491+
return ERROR_SUCCESS, response
362492

363493
@meterpreter.register_function
364494
def stdapi_sys_process_get_processes(request, response):
365495
if os.path.isdir('/proc'):
366496
return stdapi_sys_process_get_processes_via_proc(request, response)
497+
elif has_windll:
498+
return stdapi_sys_process_get_processes_via_windll(request, response)
367499
return ERROR_FAILURE, response
368500

369501
@meterpreter.register_function

0 commit comments

Comments
 (0)