Wiki

Clone wiki

imalse / General structure

Design

To support the variety of modes noted in the introduction, Imalse is designed in a way that separates the bot-net mechanism and the network. The general structure of Imalse is shown in the following figure:

General structure

The two key concepts in the design are the Node and Command Meta Description (CMD) sections. Node is the abstraction of a real computer. A node should support:

  • Basic utility functions: serveral basic utility calls, e.g. getting the system time and making node sleep
  • Socket API, this is required to implement basic network interaction
  • File System
  • Higher Level Application

There is a abstract base class in the core.nodes module named BaseNode. BaseNode defines the APIs a node needs to overload/implement. If you want to extend the framework to support other types of simulators, please subclass BaseNode and implement all the virtual functions.

A command is a basic event. The Command Meta Description defines a set of commands for a node, namely it defines what event a node can generate. There are three types of CMDs:

  1. Server CMD: Command meta description for the server. The server will usually wait until the attack command is received from the bot-master. This will prompt the server to send corresponding commands to clients.
  2. Client CMD: The client will wait until receiving a command from the server. Upon receiving a command from the server the corresponding actions will be executed in the user’s computer. The capabilities of a Client can depend on the Node API.
  3. Botmaster CMD: The bot-master is actually a special client with higher privileges. The bot-master should verify itself by sending verify command to the server, before sending the attack commands.

The basic procedure is that the bot-master will send commands to the server and the server will execute or relay this command to the clients.

Basic botnet mechanism

In the core module, imalse provides a basic framework to create and manage bot-nets and to support the three simulation modes: real network, netns3 and NS-3. The user can create their own flavor of bot-net by sub-classing ServerCMD, ClientCMD and BotmasterCMD in the core.node module. Each flavor is called a new scenario.

The basic bot-net mechanism can be described as a Finite State Machine. The FSM for the ClientCMD is as follows:

ClientCMD FSM

Scenario

As a noted above, user can create their own flavor of bot-net, which is called a scenario. Currently, Imalse provides four sample scenarios:

  1. DDOS Flooding: in this scenario the bot-master can issue an attack command to initiate a ddos flooding attack on a specific server. There are three types of attacks: ping flooding, tcp SYN flooding and HTTP-GET flooding.

  2. File Exfiltration: in this scenario the bot-master can order bots to search in the file system for any file that contains a certain pattern, like a password. Whenever an interesting file is found, the bot will upload this file to a ftp server.

  3. Spamming: in this scenario the bot-master can order bots to crawl the internet in search for email-addresses. This addresses will be used to send spam to. The contents of the spam can be configured by the bot-master. When this scenario is executed in real or in netns3 mode, an interactive console will be available for the user.

  4. Keylogger: in this scenario the bot-master can order bots to log keystrokes entered by the user for a specific duration. When the bots are done logging keystrokes the logs will be send to the bot-master.

The parameters of these scenarios can be configured in their respective configuration files (config.py) or you can use the GUI.

To implement a new scenario, you need to create a new folder in the scenario folder. This folder actually is a new module in python. You should create four files in this folder: config.py, server_cmd.py, client_cmd.py and botmaster_cmd.py. The config file should import the three node description classes from the core.cmd.description module. These classes contain parameters used by the CMD's, these parameters can be configured in this file. The other three files should contain a sub-class of their respective CMD in core.nodes, e.g. ServerCMD. These sub-classes provide a basic bot-net communication scheme and make the transition from real node to netns3 node to ns-3 sim node seamless.

Tips for implementing a new scenario:

  1. Place the temporal pattern of attack into the BotmasterCMD. In other words, in the BotmasterCMD, you can specify which attack should happen at what time. E.g. the botmaster can issue a file_scan attack command every 24 hours.
  2. Place the geographical pattern of attack into the ServerCMD. In other words, which clients should join what attack.
  3. Place the action pattern of attack into ClientCMD. A client command will define a sequence of node actions, which is unique to this attack.
  4. Place attack parameters in the config file. E.g. how many tcp syn request should a bot send to which server.

scenario implementation

Experiment

When performing a simulation it is necessary to select an experiment. Experiments handle the topology and network configuration. Implementing a new experiment is only necessary when you want to run a simulation within a new type of network. The only part you will likely code is implementing a new scenario.

You can find the experiments in the folder ROOT/experiments. Three different experiments are provided:

  • StaticRouteExperiment is a experiment in which a small diamond shape topology in demoed and the routing tables for all nodes are manually specified.
  • TopoExperiment is a experiment in which you can load a topology generated by some topology generators, like Inet. The ip-address of each node will be automatically assigned. The parameters you can customize are: 1. NETWORK_BASE, 2. SERVER_ADDR, 3. IP_MASK, 4. server_id_set, 5. botmaster_id_set, 6. client_id_set, 7. Delay, 8. DataRate. The delay and data rate are the same for every link. All parameters are the static member of the TopoExperiment class and you just need to change them in the code accordingly. You will need this if you only want to specify the topology and don't care about the network configuration.
  • ManualTopoExperiment is similar to TopoExperiment, however, in ManualTopoExperiment, you can specify the delay and data rate of each link and also the ip-address of every interface. Instead of hard coding all parameters in the code, it will load a configuration script with python syntax. You can use the topology editor to create this scripts.

When you want to implement your own experiment, you can place it in ROOT/experiments folder. There is class factory function in the ROOT/experiments/api.py. Depending on the simulation mode, the class factory function will generate a new experiment class with all the methods and members you defined with the corresponding base class.

Some things you need to pay attention are:

  1. There is only one experiment for each file. When you add a new experiment please extend the map in ROOT/experiments/api, which maps the file name to the class name.
  2. The experiment class should declare BaseClass as the base class.

For example, we define the TopoExperiment in ROOT/experiments/TopoExperiment.py, the definition of topology experiment is as follows:

class TopoExperiment(BaseClass):

It declares BaseClass as the base class, though BaseClass is not defined or imported in this file. It probably won’t pass the syntax checker like pyflake and pylint. Actually, BaseClass is a placeholder that will later be replaced by the real implementation. To clarify this ‘strange’ code , I will introduce the implementation details a little bit. If you don’t want to know the reason, just ignore this part.

def experiment_factory(experiment, mode):
    module = load_experiment(experiment)

    try:
        class_name = CLASS_MAP[experiment]
    except KeyError:
        print "Experiment does not exist"
        return None

    ExperimentClass = module.__dict__[class_name]    
    ModeClass = MODE_MAP[mode]

    class Experiment(ExperimentClass, ModeClass):

        def __init__(self):
            ModeClass.__init__(self)            
            ExperimentClass.__init__(self)            

        def setup(self):
            ModeClass.setup(self)
            ExperimentClass.setup(self)                             

    return Experiment()

The code above is the code of the experiment_factory. It will dynamically create an Experiment based on the chosen experiment and simulation mode. The following maps are used to determine which classes the Experiment class should subclass from.

MODE_MAP = {
        'netns3' : ImalseNetnsExperiment,
        'sim' : ImalsePureSimExperiment,
        'basic' : Basic,
        }

CLASS_MAP = {
        "complex_net_exp" : "ComplexNetExperiment",
        "manual_topo_bt_exp" : "ManualTopoBTExperiment",
        "manual_topo_exp" : "ManualTopoExperiment",
        "static_route_exp" : "StaticRouteExperiment",
        "topo_exp" : "TopoExperiment"
        }

Updated