5.1. Case Study Mini Botnet
5.1.1. Assignments
5.1.1.1. Mini Botnet
- About:
Name: Mini Botnet
Difficulty: medium
Lines: 45
Minutes: 21
- License:
Copyright 2025, Matt Harasymczuk <matt@python3.info>
This code can be used only for learning by humans (self-education)
This code cannot be used for teaching others (trainings, bootcamps, etc.)
This code cannot be used for teaching LLMs and AI algorithms
This code cannot be used in commercial or proprietary products
This code cannot be distributed in any form
This code cannot be changed in any form outside of training course
This code cannot have its license changed
If you use this code in your product, you must open-source it under GPLv2
Exception can be granted only by the author (Matt Harasymczuk)
Stwórz mini botnet o architekturze podanej na obrazku. Mini botnet składa się z trzech części:
Heartbeat Receiver - server przyjmujący informacje o ofiarach (czy wciąż żyją i jakie mają backdoory),
Victim - ofiara,
Attacker - atakujący.
Run doctests - all must succeed
- Hints:
Do weryfikacji czy port jest otwarty możesz użyć
telnet
albonetcat
5.1.1.2. Heartbeat Receiver
- About:
Name: Heartbeat Receiver
Difficulty: medium
Lines: 45
Minutes: 21
- License:
Copyright 2025, Matt Harasymczuk <matt@python3.info>
This code can be used only for learning by humans (self-education)
This code cannot be used for teaching others (trainings, bootcamps, etc.)
This code cannot be used for teaching LLMs and AI algorithms
This code cannot be used in commercial or proprietary products
This code cannot be distributed in any form
This code cannot be changed in any form outside of training course
This code cannot have its license changed
If you use this code in your product, you must open-source it under GPLv2
Exception can be granted only by the author (Matt Harasymczuk)
- English:
Server should accept UDP messages on port 1337
UTC date of packet arrival, IP and backdoor port should be saved to
sqlite3
database as fields:datetime DATETIME
,host TEXT
,port INTEGER
.
Run doctests - all must succeed
- Polish:
Server ma przyjmować komunikaty UDP na porcie 1337
Datę UTC przyjścia pakietu, IP i port backdoora zapisuje do bazy danych
sqlite3
jako pola:datetime DATETIME
,host TEXT
,port INTEGER
.
Uruchom doctesty - wszystkie muszą się powieść
- Hints:
socketserver.UDPServer
5.1.1.3. Victim
- About:
Name: Victim
Difficulty: medium
Lines: 150
Minutes: 34
- License:
Copyright 2025, Matt Harasymczuk <matt@python3.info>
This code can be used only for learning by humans (self-education)
This code cannot be used for teaching others (trainings, bootcamps, etc.)
This code cannot be used for teaching LLMs and AI algorithms
This code cannot be used in commercial or proprietary products
This code cannot be distributed in any form
This code cannot be changed in any form outside of training course
This code cannot have its license changed
If you use this code in your product, you must open-source it under GPLv2
Exception can be granted only by the author (Matt Harasymczuk)
- English:
After infection it opens random TCP port (backdoor) from range 1025-65535 and listens for commands
Why such port range?
Every 5 seconds it sends information with its backdoor port and IP to Heartbeat Receiver
After receiving XML message on backdoor port it executes command from XML
Victim should send JSON to attacker in format:
date: datetime
(UTC),host: str
,port: int
,stdout: str
,stderr: str
.
Create decorator
is_valid_xml
, which will check if XML is valid (has correct structure) and only then execute commandsCreate decorator
log_incoming_requests
, which will save to filebotnet.log
logs in formatRequest from IP:PORT to execute COMMAND ARGUMENTS
for every command executed on victimRun doctests - all must succeed
- Polish:
Po zainfekowaniu otwiera randomowy port TCP (backdoor) z przedziału 1025-65535 na którym nasłuchuje komunikatów
Dlaczego taki zakres portów?
Co 5 sekund wysyła informację ze swoim numerem portu backdoor oraz swoim adresem IP do Heartbeat Receiver
Po otrzymaniu komunikatu XML na port backdoora wykonuje operację w nim zawarte
Ofiara ma przesyłać JSON atakującemu w formacie:
date: datetime
(UTC),host: str
,port: int
,stdout: str
,stderr: str
.
Stwórz dekorator
is_valid_xml
, który sprawdzi czy XML się waliduje (czy ma poprawną strukturę) i tylko wtedy wykona poleceniaStwórz dekorator
log_incoming_requests
, który zapisze do plikubotnet.log
logi w formacieRequest from IP:PORT to execute COMMAND ARGUMENTS
dla każdego polecenia wykonywanego na systemie ofiaryUruchom doctesty - wszystkie muszą się powieść
- Hints:
random
logging
socket
socketserver.TCPServer
subprocess.run()
json.dumps()
,json.loads()
xml.etree.ElementTree
5.1.1.4. Attacker
- About:
Name: Attacker
Difficulty: medium
Lines: 150
Minutes: 34
- License:
Copyright 2025, Matt Harasymczuk <matt@python3.info>
This code can be used only for learning by humans (self-education)
This code cannot be used for teaching others (trainings, bootcamps, etc.)
This code cannot be used for teaching LLMs and AI algorithms
This code cannot be used in commercial or proprietary products
This code cannot be distributed in any form
This code cannot be changed in any form outside of training course
This code cannot have its license changed
If you use this code in your product, you must open-source it under GPLv2
Exception can be granted only by the author (Matt Harasymczuk)
- English:
Copy contents of listing from section "Given" to file
botnet-commands.xml
Script should be called with command line parameters:
--xml FILENAME
, defaultbotnet-commands.xml
, optional (if other parameters are given),--exec COMMAND
- optional,--cat FILENAME
- optional,--ls PATH
- optional,--eval CODE
- optional.
Script should send to all bots (victims), which pinged heartbeat server in last hour (IP of victim, backdoor port) commands to execute
Commands are:
from XML file given as parameter (if
--xml
flag is given),given as parameter to
--exec
,displaying contents of file given as parameter to
--cat
,listing contents of directory given as parameter to
--ls
,executing Python code and returning results, if
--eval
is given.
Commands to execute regardless of flag must be sent as XML messages
Date, XML message, and list of hosts to which request was sent should be saved to
sqlite3
database as logsResults, which will come from victims should be saved to
sqlite3
database with date of receiving, victim IP, port (backdoor), stdout and stderrFor command line parameters use
argparse
Processing requests should be non-blocking, i.e. open thread for every request
Use
os.path.join
(joining path) andos.walk
(listing contents).Run doctests - all must succeed
- Polish:
Skopiuj zawartość listingu z sekcji "Given" do pliku
botnet-commands.xml
Skrypt można wywoływać z parametrami linii poleceń:
--xml FILENAME
, domyślniebotnet-commands.xml
, opcjonalny (jeżeli podano inne parametry),--exec COMMAND
- opcjonalny,--cat FILENAME
- opcjonalny,--ls PATH
- opcjonalny,--eval CODE
- opcjonalny.
Skrypt ma do wszystkich botów (ofiar), które pingnęły serwer heartbeat w ciągu godziny wysyłać (IP ofiary, port backdoor) polecenia do wykonania
Polecenia są:
w pliku XML podanym jako parametr (jeżeli podano flagę
--xml
),podane jako parametr do
--exec
,wyświetlanie zawartości pliku podanego jako parametr
--cat
,listowanie zawartości katalogu podanego jako parametr
--ls
,wykonywanie kodu Python i zwracanie wyników, jeżeli podano
--eval
.
Polecenia do wykonania bez względu na flagę muszą być przesłane za pomocą komunikatów XML
Datę, komunikat XML, oraz listę hostów do których poszło zapytanie zapisuj w bazie
sqlite3
w charakterze logówWyniki, które przyjdą od ofiar zapisuj w bazie danych
sqlite3
wraz z datą otrzymania, adresem IP ofiary, portem (backdoor), stdout i stderrDo obsługi parametrów z linii poleceń wykorzystaj
argparse
Przetwarzanie requestów jest nieblokujące, tzn. otwieraj wątek dla każdego zapytania
Wykorzystaj
os.path.join
(łączenie ścieżki) orazos.walk
(wyświetlanie zawartości).Uruchom doctesty - wszystkie muszą się powieść
- Given:
<execute> <command timeout="2">/bin/ls -la /home</command> <command>/bin/ls -l /home/ /tmp/</command> <command timeout="1">/bin/sleep 2</command> <command timeout="2">/bin/echo 'hello'</command> </execute>
- Hints:
argparse
socket
json.dumps()
,json.loads()
- Extra task:
Za pomocą
Django
stwórz panel administracyjny dla botnet:Wyszukiwanie aktywnych hostów
command