forked from p15670423/monkey
improved local interface selection when exploiting
This commit is contained in:
parent
d2203b2220
commit
b3322b2541
|
@ -292,7 +292,7 @@ class RdpExploiter(HostExploiter):
|
||||||
LOG.info("Trying RDP logging into victim %r with user %s and password '%s'",
|
LOG.info("Trying RDP logging into victim %r with user %s and password '%s'",
|
||||||
host, self._config.psexec_user, password)
|
host, self._config.psexec_user, password)
|
||||||
|
|
||||||
LOG.info("RDP logged in to %r", host)
|
LOG.info("RDP connected to %r", host)
|
||||||
|
|
||||||
client_factory = CMDClientFactory(self._config.psexec_user, password, "", command)
|
client_factory = CMDClientFactory(self._config.psexec_user, password, "", command)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
import ntpath
|
import ntpath
|
||||||
import pprint
|
import pprint
|
||||||
import logging
|
import logging
|
||||||
|
@ -8,7 +11,7 @@ import monkeyfs
|
||||||
from difflib import get_close_matches
|
from difflib import get_close_matches
|
||||||
from network import local_ips
|
from network import local_ips
|
||||||
from transport import HTTPServer
|
from transport import HTTPServer
|
||||||
from network.info import get_free_tcp_port
|
from network.info import get_free_tcp_port, get_routes
|
||||||
from network.firewall import app as firewall
|
from network.firewall import app as firewall
|
||||||
from impacket.dcerpc.v5 import transport, srvs
|
from impacket.dcerpc.v5 import transport, srvs
|
||||||
from impacket.dcerpc.v5.dcom.wmi import DCERPCSessionError
|
from impacket.dcerpc.v5.dcom.wmi import DCERPCSessionError
|
||||||
|
@ -369,7 +372,7 @@ class HTTPTools(object):
|
||||||
local_port = get_free_tcp_port()
|
local_port = get_free_tcp_port()
|
||||||
|
|
||||||
if not local_ip:
|
if not local_ip:
|
||||||
local_ip = get_close_matches(host.ip_addr, local_ips())[0]
|
local_ip = get_interface_to_target(host.ip_addr)
|
||||||
|
|
||||||
if not firewall.listen_allowed():
|
if not firewall.listen_allowed():
|
||||||
return None, None
|
return None, None
|
||||||
|
@ -381,6 +384,39 @@ class HTTPTools(object):
|
||||||
return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd
|
return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd
|
||||||
|
|
||||||
|
|
||||||
|
def get_interface_to_target(dst):
|
||||||
|
if sys.platform == "win32":
|
||||||
|
try:
|
||||||
|
import dnet
|
||||||
|
intf = dnet.intf()
|
||||||
|
inte = intf.get_dst(dnet.addr(dst))
|
||||||
|
return str(inte['addr']).split("/")[0]
|
||||||
|
except ImportError:
|
||||||
|
# dnet lib is not installed
|
||||||
|
return get_close_matches(dst, local_ips())[0]
|
||||||
|
else:
|
||||||
|
# based on scapy implementation
|
||||||
|
|
||||||
|
def atol(x):
|
||||||
|
ip = socket.inet_aton(x)
|
||||||
|
return struct.unpack("!I", ip)[0]
|
||||||
|
|
||||||
|
routes = get_routes()
|
||||||
|
dst = atol(dst)
|
||||||
|
pathes = []
|
||||||
|
for d, m, gw, i, a in routes:
|
||||||
|
aa = atol(a)
|
||||||
|
if aa == dst:
|
||||||
|
pathes.append((0xffffffffL, ("lo", a, "0.0.0.0")))
|
||||||
|
if (dst & m) == (d & m):
|
||||||
|
pathes.append((m, (i, a, gw)))
|
||||||
|
if not pathes:
|
||||||
|
return None
|
||||||
|
pathes.sort()
|
||||||
|
ret = pathes[-1][1]
|
||||||
|
return ret[1]
|
||||||
|
|
||||||
|
|
||||||
def get_target_monkey(host):
|
def get_target_monkey(host):
|
||||||
from control import ControlClient
|
from control import ControlClient
|
||||||
import platform
|
import platform
|
||||||
|
|
|
@ -30,9 +30,11 @@ if sys.platform == "win32":
|
||||||
network_adapters.append((add["addr"], add["netmask"]))
|
network_adapters.append((add["addr"], add["netmask"]))
|
||||||
return network_adapters
|
return network_adapters
|
||||||
|
|
||||||
else:
|
def get_routes():
|
||||||
import fcntl
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
else:
|
||||||
|
from fcntl import ioctl
|
||||||
|
|
||||||
def get_host_subnets(only_ips=False):
|
def get_host_subnets(only_ips=False):
|
||||||
"""Get the list of Linux network adapters."""
|
"""Get the list of Linux network adapters."""
|
||||||
|
@ -46,7 +48,7 @@ else:
|
||||||
offset2 = 32
|
offset2 = 32
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
names = array.array('B', '\0' * max_bytes)
|
names = array.array('B', '\0' * max_bytes)
|
||||||
outbytes = struct.unpack('iL', fcntl.ioctl(
|
outbytes = struct.unpack('iL', ioctl(
|
||||||
sock.fileno(),
|
sock.fileno(),
|
||||||
0x8912,
|
0x8912,
|
||||||
struct.pack('iL', max_bytes, names.buffer_info()[0])))[0]
|
struct.pack('iL', max_bytes, names.buffer_info()[0])))[0]
|
||||||
|
@ -54,13 +56,13 @@ else:
|
||||||
for n_cnt in xrange(0, outbytes, offset2)]
|
for n_cnt in xrange(0, outbytes, offset2)]
|
||||||
network_adapters = []
|
network_adapters = []
|
||||||
for adapter_name in adapter_names:
|
for adapter_name in adapter_names:
|
||||||
ip_address = socket.inet_ntoa(fcntl.ioctl(
|
ip_address = socket.inet_ntoa(ioctl(
|
||||||
sock.fileno(),
|
sock.fileno(),
|
||||||
0x8915,
|
0x8915,
|
||||||
struct.pack('256s', adapter_name))[20:24])
|
struct.pack('256s', adapter_name))[20:24])
|
||||||
if ip_address.startswith('127'):
|
if ip_address.startswith('127'):
|
||||||
continue
|
continue
|
||||||
subnet_mask = socket.inet_ntoa(fcntl.ioctl(
|
subnet_mask = socket.inet_ntoa(ioctl(
|
||||||
sock.fileno(),
|
sock.fileno(),
|
||||||
0x891b,
|
0x891b,
|
||||||
struct.pack('256s', adapter_name))[20:24])
|
struct.pack('256s', adapter_name))[20:24])
|
||||||
|
@ -72,10 +74,56 @@ else:
|
||||||
|
|
||||||
return network_adapters
|
return network_adapters
|
||||||
|
|
||||||
|
|
||||||
def local_ips():
|
def local_ips():
|
||||||
return get_host_subnets(only_ips=True)
|
return get_host_subnets(only_ips=True)
|
||||||
|
|
||||||
|
def get_routes(): # based on scapy implementation for route parsing
|
||||||
|
LOOPBACK_NAME = "lo"
|
||||||
|
SIOCGIFADDR = 0x8915 # get PA address
|
||||||
|
SIOCGIFNETMASK = 0x891b # get network PA mask
|
||||||
|
RTF_UP = 0x0001 # Route usable
|
||||||
|
RTF_REJECT = 0x0200
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = open("/proc/net/route", "r")
|
||||||
|
except IOError:
|
||||||
|
return []
|
||||||
|
routes = []
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
ifreq = ioctl(s, SIOCGIFADDR, struct.pack("16s16x", LOOPBACK_NAME))
|
||||||
|
addrfamily = struct.unpack("h", ifreq[16:18])[0]
|
||||||
|
if addrfamily == socket.AF_INET:
|
||||||
|
ifreq2 = ioctl(s, SIOCGIFNETMASK, struct.pack("16s16x", LOOPBACK_NAME))
|
||||||
|
msk = socket.ntohl(struct.unpack("I", ifreq2[20:24])[0])
|
||||||
|
dst = socket.ntohl(struct.unpack("I", ifreq[20:24])[0]) & msk
|
||||||
|
ifaddr = socket.inet_ntoa(ifreq[20:24])
|
||||||
|
routes.append((dst, msk, "0.0.0.0", LOOPBACK_NAME, ifaddr))
|
||||||
|
|
||||||
|
for l in f.readlines()[1:]:
|
||||||
|
iff, dst, gw, flags, x, x, x, msk, x, x, x = l.split()
|
||||||
|
flags = int(flags, 16)
|
||||||
|
if flags & RTF_UP == 0:
|
||||||
|
continue
|
||||||
|
if flags & RTF_REJECT:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
ifreq = ioctl(s, SIOCGIFADDR, struct.pack("16s16x", iff))
|
||||||
|
except IOError: # interface is present in routing tables but does not have any assigned IP
|
||||||
|
ifaddr = "0.0.0.0"
|
||||||
|
else:
|
||||||
|
addrfamily = struct.unpack("h", ifreq[16:18])[0]
|
||||||
|
if addrfamily == socket.AF_INET:
|
||||||
|
ifaddr = socket.inet_ntoa(ifreq[20:24])
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
routes.append((socket.htonl(long(dst, 16)) & 0xffffffffL,
|
||||||
|
socket.htonl(long(msk, 16)) & 0xffffffffL,
|
||||||
|
socket.inet_ntoa(struct.pack("I", long(gw, 16))),
|
||||||
|
iff, ifaddr))
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
return routes
|
||||||
|
|
||||||
|
|
||||||
def get_free_tcp_port(min_range=1000, max_range=65535):
|
def get_free_tcp_port(min_range=1000, max_range=65535):
|
||||||
start_range = min(1, min_range)
|
start_range = min(1, min_range)
|
||||||
|
|
|
@ -32,7 +32,11 @@ Windows:
|
||||||
type > C:\Python27\Lib\site-packages\zope\__init__.py
|
type > C:\Python27\Lib\site-packages\zope\__init__.py
|
||||||
7. Download and extract UPX binary to [source-path]\monkey\chaos_monkey\bin\upx.exe:
|
7. Download and extract UPX binary to [source-path]\monkey\chaos_monkey\bin\upx.exe:
|
||||||
http://upx.sourceforge.net/download/upx391w.zip
|
http://upx.sourceforge.net/download/upx391w.zip
|
||||||
8. Run [source-path]\monkey\chaos_monkey\build_windows.bat to build, output is in dist\monkey.exe
|
8. (Optional) For some exploits to work better, install 'dnet' python library. You'll need to compile it for your OS
|
||||||
|
or use a precompiled setup that can be found at:
|
||||||
|
32bit: https://github.com/Kondziowy/scapy_win64/raw/master/win32/dnet-1.12.win32-py2.7.exe
|
||||||
|
64bit: https://github.com/Kondziowy/scapy_win64/raw/master/win64/dnet-1.12.win-amd64-py2.7.exe
|
||||||
|
9. Run [source-path]\monkey\chaos_monkey\build_windows.bat to build, output is in dist\monkey.exe
|
||||||
|
|
||||||
Linux (Tested on Ubuntu 12.04):
|
Linux (Tested on Ubuntu 12.04):
|
||||||
1. Run:
|
1. Run:
|
||||||
|
|
Loading…
Reference in New Issue