Skip to content

Commit 9a92b39

Browse files
Merge pull request #30 from tpegl/feat/add_onionshare_support
2 parents 7223d1b + 55fc649 commit 9a92b39

File tree

6 files changed

+210
-23
lines changed

6 files changed

+210
-23
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ dependencies = [
99
"cryptography",
1010
"hashcat",
1111
"protonvpn-cli",
12+
"onionshare_cli"
1213
]
1314

1415
[build-system]

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ pyshark==0.6
99
python-nmap==0.7.1
1010
whois==1.20240129.2
1111
dnspython==2.6.1
12+
onionshare_cli==2.6

src/main.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,44 @@
11
# Main
2+
import os # Operating System functions.
3+
import sys # System stuff.
24
from asyncio import subprocess
3-
import sys # System stuff.
4-
import os # Operating System functions.
5-
from colorama import Fore
65

7-
# For text colour.
6+
from colorama import Fore
87

9-
# Modules
10-
# SECURITY.
11-
# ENUMERATION.
12-
import src.modules.recpull as recpull
13-
# OSINT.
14-
import src.modules.shodan as shodan
15-
import src.modules.numlook as numlook
8+
import src.modules.bankindex as bankindex
9+
import src.modules.cryptotrace as cryptotrace
10+
import src.modules.exif as exif
11+
import src.modules.falcon as falcon
12+
import src.modules.flightinfo as flightinfo
1613
import src.modules.geolock as geolock
14+
import src.modules.loki_decrypt as loki_decrypt
15+
import src.modules.loki_discovery as loki_discovery
16+
import src.modules.loki_encrypt as loki_encrypt
1717
# CASE-GEN.
1818
# SDB.
1919
# Loki.
2020
import src.modules.loki_keygen as loki_keygen
21-
import src.modules.loki_discovery as loki_discovery
22-
import src.modules.loki_encrypt as loki_encrypt
23-
import src.modules.loki_decrypt as loki_decrypt
24-
import src.modules.cryptotrace as cryptotrace
25-
import src.modules.vt as vt
2621
import src.modules.mactrace as mactrace
22+
import src.modules.numlook as numlook
23+
import src.modules.onionshare as onionshare
2724
import src.modules.ovpn as ovpn
2825
import src.modules.pvpn as pvpn
29-
import src.modules.flightinfo as flightinfo
26+
# Modules
27+
# SECURITY.
28+
# ENUMERATION.
29+
import src.modules.recpull as recpull
30+
# OSINT.
31+
import src.modules.shodan as shodan
32+
import src.modules.vt as vt
3033
import src.modules.wigle as wigle
31-
import src.modules.bankindex as bankindex
32-
import src.modules.exif as exif
3334
import src.modules.ytd as ytd
34-
import src.modules.falcon as falcon
3535

3636
from . import apicon
37-
from .utils import print_hero, PROMPT
37+
from .utils import PROMPT, print_hero
38+
39+
# For text colour.
40+
41+
3842

3943
# Pre-run.
4044
os.system("clear")
@@ -70,6 +74,10 @@ def main_script():
7074
vt.vt()
7175
sys.exit(0)
7276

77+
if option.lower() == "onionshare":
78+
onionshare.onionshare()
79+
sys.exit(0)
80+
7381
if option.lower() == "ovpn":
7482
ovpn.ovpn()
7583
sys.exit(0)

src/modules/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__package__ = 'modules'

src/modules/onionshare.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import os
2+
import shutil
3+
import subprocess
4+
import sys
5+
6+
from ..utils import *
7+
8+
PLATFORM = sys.platform
9+
10+
11+
# --------------------------------
12+
# Helper functions
13+
# --------------------------------
14+
def has_dependencies_installed() -> bool:
15+
"""
16+
Checks if the required dependencies are installed.
17+
18+
Returns:
19+
bool: True if all dependencies are installed AND EXECUTABLE, False otherwise.
20+
"""
21+
exec_path = shutil.which("tor")
22+
return (exec_path and os.access(exec_path, os.X_OK)) == True
23+
24+
25+
def send(config_file=None, auto_stop_seconds=None, no_autostop_sharing=None):
26+
files = input("Which file(s) would you like to share? ")
27+
args = [
28+
"onionshare-cli",
29+
files,
30+
"--local-only",
31+
f"--config {config_file}" if config_file else None,
32+
f"--auto-stop-timer {auto_stop_seconds}" if auto_stop_seconds else None,
33+
f"--no-autostop-sharing {no_autostop_sharing}" if no_autostop_sharing else None
34+
]
35+
filtered: list[str] = list(filter(lambda x: x is not None, args))
36+
process = subprocess.Popen(filtered, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)
37+
38+
for line in iter(process.stdout.readline, ''):
39+
print(line, end='')
40+
41+
process.stdout.close()
42+
process.wait()
43+
44+
45+
def receive(config_file=None, auto_stop_seconds=None):
46+
args = [
47+
"onionshare-cli",
48+
"--local-only",
49+
"--receive",
50+
f"--config {config_file}" if config_file else None,
51+
f"--auto-stop-timer {auto_stop_seconds}" if auto_stop_seconds else None
52+
]
53+
54+
receiving = input("Would you like to receive files, text or both (f/t/b) ")
55+
56+
while receiving not in ["f", "t", "b"]:
57+
receiving = input(f"Sorry, {receiving} was not one of the allowed values (f, t or b)")
58+
59+
if receiving == "t":
60+
args.append("--disable-files")
61+
elif receiving == "f":
62+
args.append("--disable-text")
63+
64+
if receiving != "t":
65+
data_dir = input("Where would you like the files to be saved to? (blank for default)")
66+
if data_dir != "" and data_dir is not None:
67+
args.append(f"--data-dir {data_dir}")
68+
69+
filtered: list[str] = list(filter(lambda x: x is not None, args))
70+
print("Filtered: ", filtered)
71+
process = subprocess.Popen(filtered, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)
72+
73+
for line in iter(process.stdout.readline, ''):
74+
print(line, end='')
75+
76+
process.stdout.close()
77+
process.wait()
78+
79+
80+
81+
def chat(config_file=None, auto_stop_seconds=None):
82+
args = [
83+
"onionshare-cli",
84+
"--local-only",
85+
"--chat",
86+
f"--config {config_file}" if config_file else None,
87+
f"--auto-stop-timer {auto_stop_seconds}" if auto_stop_seconds else None
88+
]
89+
filtered: list[str] = list(filter(lambda x: x is not None, args))
90+
process = subprocess.Popen(filtered, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)
91+
92+
for line in iter(process.stdout.readline, ''):
93+
print(line, end='')
94+
95+
process.stdout.close()
96+
process.wait()
97+
98+
99+
100+
def onionshare(advanced=False):
101+
if PLATFORM == "win32":
102+
print_alert("Using Onionshare from the commandline is not supported on Windows. Please use the GUI which you can download from:")
103+
print("\t- https://onionshare.org/#download")
104+
print_alert("You'll also need Tor installed, which you can download from:")
105+
print("\t- winget install --id=TorProject.TorBrowser -e")
106+
print("\t- Or visit https://www.torproject.org/download/ to download directly.")
107+
return
108+
109+
if not has_dependencies_installed():
110+
print("You need to have Tor installed to utilise this feature.")
111+
112+
match PLATFORM:
113+
case "linux":
114+
print(
115+
"""
116+
Depending on your distro, the command will something like:
117+
118+
sudo apt install tor
119+
sudo pacman -S tor
120+
sudo dnf install tor
121+
"""
122+
)
123+
return
124+
case "darwin":
125+
print(
126+
"""
127+
brew install tor
128+
"""
129+
)
130+
return
131+
case _:
132+
print("Unknown platform")
133+
return
134+
135+
running = True
136+
config_file = None
137+
no_autostop_sharing = None
138+
auto_stop_seconds = None
139+
140+
if advanced:
141+
config = input("Custom config file location (blank for defaults): ")
142+
if config and config != "":
143+
config_file = config
144+
145+
while running:
146+
method = input("Are you looking to send or receive files? (send/receive/chat/q) ")
147+
148+
if method == "q":
149+
return
150+
151+
if not config_file:
152+
auto_stop = input("Would you like the server to stop automatically? (Y/n) ")
153+
if auto_stop.lower() == "y":
154+
auto_stop_seconds = input("How many seconds should the server run for? ")
155+
156+
157+
try:
158+
if method == "send":
159+
if not config_file:
160+
no_autostop_sharing = True if input("Should the server stop after you have shared the files? (Y/n) ").lower() == 'y' else False
161+
162+
send(config_file=config_file, no_autostop_sharing=no_autostop_sharing, auto_stop_seconds=auto_stop_seconds)
163+
return
164+
elif method == "receive":
165+
receive(config_file=config_file, auto_stop_seconds=auto_stop_seconds)
166+
return
167+
elif method == "chat":
168+
chat(config_file=config_file, auto_stop_seconds=auto_stop_seconds)
169+
return
170+
else:
171+
print(f"Method {method} not available or possible. Try another or exit (q)")
172+
except Exception as e:
173+
print(f"{FAILED}: {str(e)}")
174+
175+
if __name__ == "__main__":
176+
onionshare()

src/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def print_hero():
8989
command(Fore.YELLOW, "Fallenflare | Bypass cloudflare.")
9090
command(Fore.GREEN,"Recpull | Pulls a tracert, whois, dns, mx history & namp, custom-formatted.")
9191
command(Fore.RED,"Anonfile | Up/download from Anonfiles.")
92-
command(Fore.RED,"Onionshare | Up/download from Onionshare.")
92+
command(Fore.YELLOW,"Onionshare | Up/download from Onionshare.")
9393
section("OSINT")
9494
command(Fore.GREEN,"Shodan | Pull Shodan information from API.")
9595
command(Fore.GREEN,"WiGle | Use an API for SSID/BSSIDs stat, locations, & Bluetooth data.")
@@ -119,4 +119,4 @@ def print_hero():
119119
command(Fore.GREEN,"Exif | Check exif data on a file, or wipe it clean.")
120120
command(Fore.GREEN,"Vt | Connect to the virus-total API to scan, or screen files, links, etc.")
121121
command(Fore.GREEN,"Falcon | Packet analysis; sniff for your own in the terminal or use a capture file!")
122-
print(f"\n{NOTICE} Remember; run `apicon` command to configure the API database.")
122+
print(f"\n{NOTICE} Remember; run `apicon` command to configure the API database.")

0 commit comments

Comments
 (0)