This file is indexed.

/usr/lib/python2.7/dist-packages/impacket/examples/ntlmrelayx/utils/targetsutils.py is in python-impacket 0.9.15-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/python
# Copyright (c) 2013-2016 CORE Security Technologies
#
# This software is provided under under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Target utilities
#
# Author:
#  Dirk-jan Mollema / Fox-IT (https://www.fox-it.com)
#
# Description:
#     Classes for handling specified targets and keeping 
# state of which targets have been processed
import logging
import os
import random
import re
import time
from threading import Thread


class TargetsProcessor():
    supported_protocols = ['SMB','HTTP','LDAP','MSSQL','LDAPS']
    def __init__(self,targetlistfile=None,singletarget=None):        
        self.targetregex = re.compile(r'([a-zA-Z]+)://([a-zA-Z0-9\.\-_]+)(:[0-9]+)?/?(.*)?')
        self.targetipregex = re.compile(r'[a-zA-Z\.\-_0-9]+')
        self.clients_targets = {}
        if targetlistfile is None:
            self.filename = None
            self.targets = [self.parse_target(singletarget)]
        else:
            self.filename = targetlistfile
            self.targets = []
            self.read_targets()

    def read_targets(self):
        try:
            with open(self.filename,'r') as f:
                self.targets = []
                for line in f:
                    target = self.parse_target(line.strip())
                    if target is not None:
                        self.targets.append(target)
        except IOError, e:
            logging.error("Could not open file: %s" % self.filename)
            logging.error(str(e))
        if len(self.targets) == 0:
            logging.critical("Warning: no valid targets specified!")

    def parse_target(self,targetline):
        #Try a full target match in the form of protocol://target:port/path first
        ftm = self.targetregex.match(targetline)
        if ftm is not None:
            if ftm.group(1).upper() not in self.supported_protocols:
                logging.error("Unsupported protocol: %s" % ftm.group(1))
                return None
            #Check if the port was specified
            if ftm.group(3) is None:
                port = self.get_default_port(ftm.group(1))
            else:
                #Port regex includes the : remove this
                port = int(ftm.group(3)[1:])
            #Check if the path was specified
            if ftm.group(4) is None:
                path = ''
            else:
                path = ftm.group(4)
            #Targets are always a tuple (protocol,host,port)
            #TODO: Change this to an object so we can have proper representation as string?
            return (ftm.group(1).upper(),ftm.group(2),port,path)
        #Maybe the target is just an IP, this assumes its an SMB target
        itm = self.targetipregex.match(targetline)
        if itm is not None:
            return ('SMB',itm.group(0),445,'')
        #If both dont match, it is probably an invalid target
        logging.error("Invalid target specification: " % targetline)
        return None

    def log_target(self,client,target):
        try:
            self.clients_targets[client].add(target)
        except KeyError:
            self.clients_targets[client] = set([target])
        #print self.clients_targets

    def get_target(self,client):
        try:
            targetlist = self.clients_targets[client]
        except KeyError:
            #Client is probably new
            return self.targets[0]
        for target in self.targets:
            #Check if the target is already in the target list
            if target not in targetlist:
                return target
        #We are here, which means all the targets are already exhausted by the client
        logging.info("All targets processed for client %s" % client)
        return random.choice(self.targets)

    def get_default_port(self,protocol):
        if protocol.upper() == 'SMB':
            return 445
        if protocol.upper() == 'HTTP':
            return 80
        if protocol.upper() == 'HTTPS':
            return 443
        if protocol.upper() == 'LDAP':
            return 389
        if protocol.upper() == 'LDAPS':
            return 636
        if protocol.upper() == 'MSSQL':
            return 1433
        return None

class TargetsFileWatcher(Thread):
    def __init__(self,targetprocessor):
        Thread.__init__(self)
        self.targetprocessor = targetprocessor
        self.lastmtime = os.stat(self.targetprocessor.filename).st_mtime
        #print self.lastmtime

    def run(self):
        while True:
            mtime = os.stat(self.targetprocessor.filename).st_mtime
            if mtime > self.lastmtime:
                logging.info('Targets file modified - refreshing')
                self.lastmtime = mtime
                self.targetprocessor.read_targets()
            time.sleep(1.0)

class ProxyIpTranslator(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.regex = re.compile(r'SRC=([0-9\.]+) DST=([0-9\.]+) .*SPT=([0-9]+)')
        self.iptranslations = {}
    #-A POSTROUTING -o eth0 -j LOG --log-prefix="SMBrelay"
    def run(self):
        logging.info("Setting up Proxy translator - reading from kernel log")
        for line in tail("-f", "/var/log/kern.log", _iter=True):
            if "SMBrelay" in line:
                m = self.regex.search(line)
                if m is not None:
                    self.iptranslations[(m.group(1),m.group(3))] = m.group(2)
                    #logging.info('Found translation from ip: %s port: %s to IP: %s' % (m.group(1),m.group(3),m.group(2)))

    #Look up the destination IP based on source IP and port
    def translate(self,source_ip,source_port):
        try:
            return self.iptranslations[(source_ip,str(source_port))]
        except KeyError:
            return None