123 lines
3.5 KiB
Python
Executable File
123 lines
3.5 KiB
Python
Executable File
import socket
|
|
import struct
|
|
import sys
|
|
from target import Target
|
|
import threading
|
|
import time
|
|
|
|
# Load settings from file and assign to vars
|
|
settingsFile = "/pineapple/modules/CursedScreech/includes/forest/settings"
|
|
MCAST_GROUP = IFACE = target_list = activity_log = ""
|
|
MCAST_PORT = hbInterval = 0
|
|
settings = {}
|
|
with open(settingsFile, "r") as sFile:
|
|
for line in sFile:
|
|
params = line.strip("\n").split("=")
|
|
if params[0] == "target_list":
|
|
target_list = params[1]
|
|
elif params[0] == "activity_log":
|
|
activity_log = params[1]
|
|
elif params[0] == "mcast_group":
|
|
MCAST_GROUP = params[1]
|
|
elif params[0] == "mcast_port":
|
|
MCAST_PORT = int(params[1])
|
|
elif params[0] == "hb_interval":
|
|
hbInterval = int(params[1])
|
|
elif params[0] == "iface_ip":
|
|
IFACE = params[1]
|
|
else:
|
|
pass
|
|
|
|
# Default to a heartbeat of 5 seconds
|
|
# if one has not been set in file
|
|
if hbInterval == 0:
|
|
hbInterval = 5
|
|
|
|
# Function to determine if a target exists in the supplied list
|
|
def targetExists(tgt,l):
|
|
for t in l:
|
|
if tgt in t.addr:
|
|
return True
|
|
return False
|
|
|
|
def logActivity(msg):
|
|
with open(activity_log, "a") as log:
|
|
log.write(msg + "\n")
|
|
|
|
def writeTargets(targets):
|
|
with open(target_list, 'w') as tlog:
|
|
for target in targets:
|
|
tlog.write(target.sockName() + "\n")
|
|
|
|
# Set up the receiver socket to listen for multicast messages
|
|
sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
|
sck.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
sck.bind((MCAST_GROUP, MCAST_PORT))
|
|
sck.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MCAST_GROUP)+socket.inet_aton(IFACE))
|
|
|
|
# Import targets from file if any exist
|
|
targets = []
|
|
with open(target_list, 'r') as tList:
|
|
for line in tList:
|
|
targets.append(Target(line.split(":")[0], line.split(":")[1]))
|
|
|
|
def checkMissingTargets():
|
|
while True:
|
|
# Check if any targets are missing. If they are remove them
|
|
# from the target_list and writeTargets().
|
|
# 'Missing' is indicated by not receiving a heartbeat from a target
|
|
# within thrice the set heartbeat interval.
|
|
global targets
|
|
global hbInterval
|
|
updateTargetList = False
|
|
for t in targets:
|
|
if t.isMissing(hbInterval * 3):
|
|
targets.remove(t)
|
|
updateTargetList = True
|
|
|
|
if updateTargetList:
|
|
writeTargets(targets)
|
|
|
|
# Set up a separate thread to constantly check if targets
|
|
# have missed multiple heartbeats.
|
|
threads = []
|
|
newThread = threading.Thread(target=checkMissingTargets)
|
|
threads.append(newThread)
|
|
newThread.start()
|
|
|
|
while True:
|
|
print "Waiting for heartbeat..."
|
|
try:
|
|
msg = sck.recv(10240)
|
|
ip = msg.split(":")[0]
|
|
port = msg.split(":")[1]
|
|
|
|
print "Received: " + msg
|
|
|
|
# The heartbeat is sometimes used to send a message telling us
|
|
# when an invalid cert was sent to the target. This can be a sign
|
|
# of an attacker on the network attempting to access the shell
|
|
# we worked so hard to get on the target's system.
|
|
# We check for messages here and direct them to the proper log.
|
|
# For brevity's sake ip will let us know if it's a message and
|
|
# port will contain the contents of the message.
|
|
if ip == "msg":
|
|
logActivity("Multicast Message: " + port)
|
|
continue
|
|
|
|
# Check if the target currently exists in the target list
|
|
# if not then append it and write the list back out to
|
|
# target_list
|
|
if targetExists(ip, targets):
|
|
for i,t in enumerate(targets):
|
|
if ip == t.addr:
|
|
t.setPort(port)
|
|
t.lastSeen = time.time()
|
|
writeTargets(targets)
|
|
else:
|
|
targets.append(Target(ip, port))
|
|
writeTargets(targets)
|
|
|
|
except KeyboardInterrupt:
|
|
sys.exit()
|