improved local interface selection when exploiting

This commit is contained in:
itsikkes 2016-09-08 12:30:40 +03:00
parent d2203b2220
commit b3322b2541
4 changed files with 98 additions and 10 deletions

View File

@ -292,7 +292,7 @@ class RdpExploiter(HostExploiter):
LOG.info("Trying RDP logging into victim %r with user %s and password '%s'",
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)

View File

@ -1,4 +1,7 @@
import os
import sys
import socket
import struct
import ntpath
import pprint
import logging
@ -8,7 +11,7 @@ import monkeyfs
from difflib import get_close_matches
from network import local_ips
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 impacket.dcerpc.v5 import transport, srvs
from impacket.dcerpc.v5.dcom.wmi import DCERPCSessionError
@ -369,7 +372,7 @@ class HTTPTools(object):
local_port = get_free_tcp_port()
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():
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
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):
from control import ControlClient
import platform

View File

@ -30,9 +30,11 @@ if sys.platform == "win32":
network_adapters.append((add["addr"], add["netmask"]))
return network_adapters
else:
import fcntl
def get_routes():
raise NotImplementedError()
else:
from fcntl import ioctl
def get_host_subnets(only_ips=False):
"""Get the list of Linux network adapters."""
@ -46,7 +48,7 @@ else:
offset2 = 32
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
names = array.array('B', '\0' * max_bytes)
outbytes = struct.unpack('iL', fcntl.ioctl(
outbytes = struct.unpack('iL', ioctl(
sock.fileno(),
0x8912,
struct.pack('iL', max_bytes, names.buffer_info()[0])))[0]
@ -54,13 +56,13 @@ else:
for n_cnt in xrange(0, outbytes, offset2)]
network_adapters = []
for adapter_name in adapter_names:
ip_address = socket.inet_ntoa(fcntl.ioctl(
ip_address = socket.inet_ntoa(ioctl(
sock.fileno(),
0x8915,
struct.pack('256s', adapter_name))[20:24])
if ip_address.startswith('127'):
continue
subnet_mask = socket.inet_ntoa(fcntl.ioctl(
subnet_mask = socket.inet_ntoa(ioctl(
sock.fileno(),
0x891b,
struct.pack('256s', adapter_name))[20:24])
@ -72,10 +74,56 @@ else:
return network_adapters
def local_ips():
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):
start_range = min(1, min_range)

View File

@ -32,7 +32,11 @@ Windows:
type > C:\Python27\Lib\site-packages\zope\__init__.py
7. Download and extract UPX binary to [source-path]\monkey\chaos_monkey\bin\upx.exe:
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):
1. Run: