"""
Main Module of the project.
The configuration from config/config.ini is parsed.
All needed devices (client, server, attacker) are initialized and started as seperate processes.
"""
import multiprocessing
import time
import xml.etree.ElementTree as ET
import random
import configparser
import sys
import logging
logging.getLogger("scapy").setLevel(1)
from scapy.all import *
from src import SomeIPPacket
from src import Client
from src import Server
from src import Configuration
from src import Msg
from src import Attacker
# Expects: own Queue, Number of incomming 'Done's, ServerDeviceConfiguration, ClientDeviceConfiguration
def writerWorker(q, serverCount, attackerList, attackerQueue, ServerDeviceConfig, ClientDeviceConfig, interface, pcap):
"""
Used for a seperate writer process that is getting all packets to be send and append them to the .pcap file configured.
:param q: Own Queue to receive all packets forwarded by the attackers.
:param serverCount: number of servers in the system.
:param attackerList: List of attackers in the system.
:param attackerQueue: Message Queues of the attackers.
:param ServerDeviceConfig: Server Device Configuration with needed meta data for sending packets.
:param ClientDeviceConfig: Client Device Configuration (includes attacker device) with needed meta data for sending packets.
:param interface: Interface to send the data.
:param pcap: .pcap file to write the data.
"""
deviceConfig = {}
for key, value in ServerDeviceConfig.items():
deviceConfig[key] = value
for key, value in ClientDeviceConfig.items():
deviceConfig[key] = value
counter = 0
start_time = time.time()
if interface != None:
sck = conf.L2socket(iface=interface)
# wait fo incomming messages to prepare for sending
while (True):
msg = q.get()
# attacker sending 'Done's in case all requests are processed
if msg == 'Done':
break
else:
# capture received messaged and transform into SomeIP packtes
sender = {}
sender['mac'] = deviceConfig[msg.sender]['mac']
sender['ip'] = deviceConfig[msg.sender]['ip']
sender['port'] = deviceConfig[msg.sender]['sendPort']
receiver = {}
receiver['mac'] = deviceConfig[msg.receiver]['mac']
receiver['ip'] = deviceConfig[msg.receiver]['ip']
receiver['port'] = deviceConfig[msg.receiver]['recPort']
message = msg.message
timestamp = msg.timestamp
packet = SomeIPPacket.createSomeIP(sender, receiver, message)
packet.time = timestamp
counter = counter + 1
if pcap != None:
wrpcap(pcap, packet, append=True)
if interface != None:
sck.send(packet)
print ('Writer Stoped By Attacker')
stop_time = time.time()
print ('Number of Packets generated: ', counter)
print ('Time to generate Packets:', stop_time - start_time)
print ('Writer Exiting')
[docs]def stop(q, clientCounts, servers, serverQueues):
"""
First Level of stopping all processes.
This function is running as a process and waits for all clients to be done (all required messages are sent and no state).
In this case, a DONE message is sent to all servers to indicate that no more clients requests will arrive and they can shut down.
:param q: Own Queue to listen on incomming DONE messages.
:param clientCounts: Number of expected DONE messages.
:param servers: List of server instances.
:param serverQueues: List of server queues.
"""
counter = 0
while (True):
obj = q.get()
counter = counter + 1
print ("Clients Done:", counter)
if (counter == clientCounts):
for server in servers:
serverQueues[server].put('Done')
break;
print ("Stop", 'Exiting')
[docs]def stop2(q, serverCounts, attackers, attackerQueue):
"""
Second Level of stopping all processes.
This function is running as a process and waits for all servers to be done (server got a DONE message previously).
In this case, a DONE message is sent to all attackers to indicate that no more packets will arrive and they can shut down.
:param q: Own Queue to listen on incomming DONE messages.
:param serverCounts: Number of expected DONE messages.
:param attackers: List of attacker instances.
:param attackerQueue: List of attacker queues.
"""
counter = 0
while (True):
obj = q.get()
counter = counter + 1
print ("Servers Done:", counter)
if (counter == serverCounts):
for attacker in attackers:
attackerQueue.put('Done')
break;
print ("Stop", 'Exiting')
def str2bool(s):
if s == 'True' or s == 'true':
return True
else:
return False
[docs]def start():
"""
Starts the Generator.
Reads needed Configurations and initializes Clients, Servers and Attackers.
Starts Client, Server and Attackers as seperate processes.
"""
Config = configparser.ConfigParser()
Config.read("config/config.ini")
deviceFile = Config["Files"]['deviceFile']
serviceFile = Config["Files"]['serviceFile']
interface = Config["Pcap"].get('interface', None)
pcap = Config["Pcap"].get('file', None)
packetCount = int(Config["Pcap"].get('counter', 100))
packetCountAttack = int(Config["Attacks"].get('counter', 1))
attacks = Config._sections["Attacks"]
clientVerbose = str2bool(Config["Verbose"].get('client', False))
serverVerbose = str2bool(Config["Verbose"].get('server', False))
attackerVerbose = str2bool(Config["Verbose"].get('attacker', False))
tree = ET.parse(deviceFile)
root = tree.getroot()
clientList = []
serverList = []
attackerList = []
for dev in root.iter('device'):
if (dev.get('type') == 'client'):
clientList.append(dev.get('name'))
elif (dev.get('type') == 'server'):
serverList.append(dev.get('name'))
elif (dev.get('type') == 'attacker'):
attackerList.append(dev.get('name'))
else:
print ("Error - unkown type")
# List of processes of Entities
servers = []
clients = []
attackers = []
# Dict of Client/ServerObjects
clientObjects = {}
serverObjects = {}
# Dict of configs
clientConfigs = {}
serverConfigs = {}
attackerConfigs = {}
# Dict of deviceConfig
clientDeviceConfigs = {}
serverDeviceConfigs = {}
# dict of queues
serverQueues = {}
clientQueues = {}
# list of all used queues
queues = []
# dedicated attacker queue
attackerQueue = multiprocessing.Queue()
queues.append(attackerQueue)
#prepare all queues and configs
for serverName in serverList:
serverConfig = Configuration.getServerConfig(serverName, serviceFile, serverVerbose)
serverConfigs[serverName] = serverConfig
serverDeviceConfig = Configuration.getDeviceConfig(serverName, deviceFile, serverVerbose)
serverDeviceConfigs[serverName] = serverDeviceConfig
q = multiprocessing.Queue()
queues.append(q)
serverQueues[serverName] = q
for clientName in clientList:
clientConfig = Configuration.getClientConfig(clientName, serviceFile, deviceFile, clientVerbose)
clientConfigs[clientName] = clientConfig
clientDeviceConfig = Configuration.getDeviceConfig(clientName, deviceFile, clientVerbose)
clientDeviceConfigs[clientName] = clientDeviceConfig
q = multiprocessing.Queue()
queues.append(q)
clientQueues[clientName] = q
for attackerName in attackerList:
attackerConfig = Configuration.getClientConfig(attackerName, serviceFile, deviceFile, attackerVerbose)
attackerConfigs[attackerName] = attackerConfig
attackerDeviceConfig = Configuration.getDeviceConfig(attackerName, deviceFile, attackerVerbose)
clientDeviceConfigs[attackerName] = attackerDeviceConfig
# prepare Writer that is generating the SOMEIP Packets
writerQueue = multiprocessing.Queue()
writer = multiprocessing.Process(target=writerWorker, args=(writerQueue, len(serverList), attackerList, attackerQueue, serverDeviceConfigs, clientDeviceConfigs, interface, pcap))
writer.start()
# prepare Stop Worker to shutdown all services
clientStopQueue = multiprocessing.Queue()
clientStop = multiprocessing.Process(target=stop, args=(clientStopQueue, len(clientList), serverList, serverQueues, ))
clientStop.start()
serverStopQueue = multiprocessing.Queue()
serverStop = multiprocessing.Process(target=stop2, args=(serverStopQueue, len(serverList), attackerList, attackerQueue, ))
serverStop.start()
# start server worker
for serverName in serverList:
s = Server.Server(config=serverConfigs[serverName], q=serverQueues[serverName], writer=writerQueue, clientQueues=clientQueues, attackers=attackerQueue, stopQueue=serverStopQueue, verbose=serverVerbose)
serverObjects[serverName] = s
p = multiprocessing.Process(name=serverName, target=Server.server, args=(s, ))
servers.append(p)
p.start()
# start client worker
for clientName in clientList:
c = Client.Client(config=clientConfigs[clientName], q=clientQueues[clientName], writer=writerQueue, serverQueues=serverQueues, stopQueue=clientStopQueue, counter=packetCount, attackers=attackerQueue, verbose=clientVerbose)
clientObjects[clientName] = c
p = multiprocessing.Process(name=clientName, target=Client.client, args=(c, ))
clients.append(p)
p.start()
# start attacker
for attackerName in attackerList:
a = Attacker.Attacker(config=attackerConfigs[attackerName], clientConfigs=clientConfigs, clientQueues=clientQueues, serverConfigs=serverConfigs, serverQueues=serverQueues, writer=writerQueue, counter=packetCountAttack, attacks=attacks, attackerQueue=attackerQueue, attackers=attackerList, verbose=attackerVerbose)
p = multiprocessing.Process(name=attackerName, target=Attacker.attacker, args=(a, ))
attackers.append(p)
p.start()