EvilLimiter-NG as a Library API for your own scripts

Before version 3.0, the evillimiter-ng code was too monolithic, and using it as a library was very hard and a bad idea, you had to import the MainMenu and pass fake arguments to it, the result?: unclear visual elements spamming the terminal and a lot of code fragmented in various functions, without a centralized API.

Now, in version 3.0, ENG has a clear and simple API, that can be used in your own scripts or big projects, with options to see or hide visual elements, automatically resolve the network data, and more, this documentation shows the basic usage of each function or class.

Getting Started

This is a very simple, but useful, example:

from evillimiter_ng.lib import manager

myeng = manager.CoreLimiter() # Create a CoreLimiter manager

myeng.add("IP_TO_BLOCK") # Replace 'IP_TO_BLOCK' with a real IP from your network
myeng.block(0) # Block the host with id #0, there is only one host in this example
input("Press enter to free the host...")
myeng.free("all") # Free all the spoofed hosts
print("Done!")
myeng.interrupt() # IMPORTANT: Clean all evillimiter-ng firewall rules and stop the scanners.

This small script assumes a "perfect" environment, where all network data will be resolved correctly and no errors will occur. However, the CoreLimiter class includes parameters that the user can pass in case a value cannot be resolved automatically. Keep in mind that if you distribute a program with fixed values, this may cause incompatibilities between devices.

class CoreLimiter (evillimiter_ng.lib.manager.CoreLimiter)

This section shows the parameters you can pass to the CoreLimiter class and how its behavior varies depending on certain possible values.

from evillimiter_ng.lib.errors import EnvnetError
from evillimiter_ng.lib.manager import CoreLimiter

try:
    cl = CoreLimiter(
        interface = None,
        gateway_ip = None,
        gateway_mac = None,
        netmask = None,
        verify_vars = True,
        auto_initialize = True,
        auto_stop = True,
        show_io = False,)
except EnvnetError as e:
    print(e)

As you can see, by default, the values for interface gateway_ip gateway_mac and netmask are None. This might seem like a problem that would cause a fatal error; however, the verify_vars setting, which is set to true by default, ensures that during class initialization, evillimiter-ng attempts to resolve these values.

You can even pass just one value as the netmask and set verify_vars to true so that it only checks for missing values. This is useful for ensuring functionality across different environments and network hardware; however, if the library cannot obtain a value and that value was not specified, an EnvnetError is raised.

If you set verify_vars to False and do not pass any network data, errors such as TypeError or others will occur during execution.

auto_initialize

auto_initialize tells CoreLimiter to start the programs necessary for the library to run—such as tc and nftables—on its own, as well as to verify whether the program is running on Linux and as root. When this variable is set to False, you must initialize it manually before running any other components.

from evillimiter_ng.lib.envnet import get_default_interface, initialize
from evillimiter_ng.lib.errors import UnsupportedSystem
from evillimiter_ng.lib.manager import CoreLimiter

try:
    initialize(get_default_interface())
except (PermissionError, UnsupportedSystem) as e:
    print(e)
cl = CoreLimiter(auto_initialize=False)

If your system isn't running Linux, the error evillimiter_ng.lib.errors.UnsupportedSystem occurs, and if you run it without root privileges, the standard Python PermissionError occurs.

auto_stop

Just like auto_initialize, if you set auto_stop to False, you must manually execute the function needed to stop the library's internal components once your own scripts have finished running.

from evillimiter_ng.lib.envnet import get_default_interface, stop_eng
from evillimiter_ng.lib.manager import CoreLimiter

cl = CoreLimiter(auto_stop=False)

cl.interrupt() # with auto_stop=False, this only stops the scanners and spoofers
stop_eng(get_default_interface())

show_io

By default, this variable is set to False, which hides the terminal messages generated by the program. If you set it to True, you can avoid having to type your own messages, but they will be in English.

Methods of the CoreLimiter class

Only a few of CoreLimiter's methods are intended for use in custom scripts, and those are the ones that will be explained here; the rest are for internal use only or for use in the MainMenu class, which is not part of the library.

These methods are based on the familiar CLI commands. Here, we show the definitions, required values, or those that already have a default value and are optional. Consult the evillimiter-ng CLI help or see the README to learn what each command (or, in this case, function) does. If a function differs significantly from its CLI command, the necessary explanation will be provided in this guide.

Other methods that have already been explained—such as interrupt—will not be mentioned again here.

scan

cl.scan(ip_range = None, intensity = "2", transient = True) -> list[Host] | None

The only notable difference between this method and the CLI command is the transient parameter. In the CLI, the scan is always non-transient (False). In the library, it defaults to True, meaning no progress bar is maintained and the method simply returns the list of discovered hosts. Set it to False if you want the scan to print the progress bar to the terminal

block

cl.block(hid: str | int, upload: str | None = None, download: str | None = None) -> bool

free

cl.free(hid: str | int) -> bool

limit

cl.limit(hid: str, rate: str | BitRate, upload: str | None = None, download: str | None = None) -> bool

This method is very similar to the CLI command, with one key difference: the rate parameter accepts not only a rate string like "100kbit" or "1gbit", but also a BitRate object from evillimiter_ng.networking.utils. This is useful if you are building the rate value programmatically. The upload and download flags work the same as in the CLI. Returns True on success, False otherwise.

add

cl.add(ip: str, mac: str | None = None, name: str | None = None) -> bool

Similar to the CLI add command, with an additional optional name parameter. In the CLI, the hostname is resolved automatically via DNS; here, if name is not provided, it also attempts to resolve the hostname automatically. If mac is omitted, it is resolved via ARP. Returns True on success, False otherwise.

export_json

cl.export_json(json_path: str | Path) -> bool

import_json

cl.import_json(json_path: str | Path) -> bool

Some CLI functions have not yet been implemented in the library; they may be implemented in future versions if the need arises beyond the tables generated by certain commands. Other commands simply will not be implemented in the library, such as sleep, which can be used in Python with the standard time library, or clear, which can be called via subprocess.run, which is also part of the standard library.