Initial commit.
This commit is contained in:
commit
2ad6c75ef8
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
files/*
|
||||||
|
!files/.gitkeep
|
24
README.md
Normal file
24
README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Pendora Box
|
||||||
|
|
||||||
|
This too has several functions:
|
||||||
|
* Keep your pentesting scripts, binaries hosted on Github up-to-date. (master branch)
|
||||||
|
* Listen on HTTP or SMB to easily share your files to the victims
|
||||||
|
|
||||||
|
## To-Do
|
||||||
|
|
||||||
|
* Keeping up-to-date from Github releases
|
||||||
|
* Adding more services to listen to ?
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
* requests python module
|
||||||
|
* impacket smbserver.py must be in PATH
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
`python pendora-box.py`
|
||||||
|
|
||||||
|
## Adding a file to track
|
||||||
|
|
||||||
|
Simply add the informations to [config.json](./config.json), and run the script.
|
||||||
|
The file is gonna be automatically downloaded.
|
31
config.json
Normal file
31
config.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"githubfilesync": [
|
||||||
|
{
|
||||||
|
"samratashok/nishang": [
|
||||||
|
"Shells/Invoke-PowerShellTcp.ps1",
|
||||||
|
"Shells/Invoke-PowerShellTcpOneLine.ps1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"samratashok/nishang": [
|
||||||
|
"Shells/Invoke-PowerShellTcp.ps1",
|
||||||
|
"Shells/Invoke-PowerShellTcpOneLine.ps1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"antonioCoco/ConPtyShell": [
|
||||||
|
"Invoke-ConPtyShell.ps1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ly4k/PwnKit": [
|
||||||
|
"PwnKit"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Re4son/Churrasco": [
|
||||||
|
"churrasco.exe"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
0
files/.gitkeep
Normal file
0
files/.gitkeep
Normal file
175
pendora-box.py
Normal file
175
pendora-box.py
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import json
|
||||||
|
import pathlib
|
||||||
|
import hashlib
|
||||||
|
import requests
|
||||||
|
import base64
|
||||||
|
import sys
|
||||||
|
from os import geteuid
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def compute_file_hash(filepath):
|
||||||
|
with open(filepath, 'rb') as file_for_hash:
|
||||||
|
data = file_for_hash.read()
|
||||||
|
filesize = len(data)
|
||||||
|
# Github sha value is computed as such:
|
||||||
|
return hashlib.sha1(b"blob " + bytes(str(filesize), 'utf-8') + b"\0" + data).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def get_info(repo, filepath):
|
||||||
|
url = f"https://api.github.com/repos/{repo}/contents/{filepath}"
|
||||||
|
r = requests.get(url)
|
||||||
|
sha = r.json()['sha']
|
||||||
|
content = r.json()['content']
|
||||||
|
return sha, content
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
with open("config.json", "r") as jsonfile:
|
||||||
|
config = json.load(jsonfile)
|
||||||
|
|
||||||
|
print("Updating...")
|
||||||
|
|
||||||
|
for repo in config['githubfilesync']:
|
||||||
|
for reponame, value in repo.items():
|
||||||
|
for filepath in value:
|
||||||
|
localfile = pathlib.Path('files').joinpath(pathlib.Path(filepath).name)
|
||||||
|
print(f" * {localfile} ", end='')
|
||||||
|
lastsha, content = get_info(reponame, filepath)
|
||||||
|
|
||||||
|
if not localfile.exists():
|
||||||
|
content = base64.b64decode(content)
|
||||||
|
with open(localfile, 'wb') as f:
|
||||||
|
f.write(content)
|
||||||
|
print('-> Installed! ;)')
|
||||||
|
|
||||||
|
else:
|
||||||
|
sha = compute_file_hash(localfile)
|
||||||
|
|
||||||
|
if sha == lastsha:
|
||||||
|
print('-> Up-to-date.')
|
||||||
|
else:
|
||||||
|
content = base64.b64decode(content)
|
||||||
|
with open(localfile, 'wb') as f:
|
||||||
|
f.write(content)
|
||||||
|
print('-> Updated!')
|
||||||
|
|
||||||
|
|
||||||
|
def print_menu(menu_options):
|
||||||
|
for key in menu_options.keys():
|
||||||
|
print(key, '->', menu_options[key])
|
||||||
|
|
||||||
|
|
||||||
|
def is_sudo():
|
||||||
|
return True if geteuid() == 0 else False
|
||||||
|
|
||||||
|
|
||||||
|
def ask_port(default_port):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
choice = input(f'What port would you like to listen on ? [{default_port}]: ')
|
||||||
|
if choice == '':
|
||||||
|
port = default_port
|
||||||
|
else:
|
||||||
|
port = int(choice)
|
||||||
|
break
|
||||||
|
except ValueError:
|
||||||
|
print('Wrong input. Please enter a number ...')
|
||||||
|
return port
|
||||||
|
|
||||||
|
|
||||||
|
def listen_http(files_dir):
|
||||||
|
port = ask_port(80)
|
||||||
|
ips = get_ips()
|
||||||
|
|
||||||
|
print('The HTTP server is about to start.\nAvailable endpoints:')
|
||||||
|
for iname in ips:
|
||||||
|
if port == 80:
|
||||||
|
print(f' -> {iname}: http://{ips[iname]}/')
|
||||||
|
else:
|
||||||
|
print(f' -> {iname}: http://{ips[iname]}:{port}/')
|
||||||
|
|
||||||
|
if port < 1024 and not is_sudo():
|
||||||
|
print('Listening on any port under 1024 requires root permissions.')
|
||||||
|
cmd = ['sudo', 'python', '-m', 'http.server', '-d', files_dir, str(port)]
|
||||||
|
else:
|
||||||
|
cmd = ['python', '-m', 'http.server', '-d', files_dir, str(port)]
|
||||||
|
subprocess.call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def listen_smb(files_dir):
|
||||||
|
port = ask_port(445)
|
||||||
|
ips = get_ips()
|
||||||
|
|
||||||
|
print('The HTTP server is about to start.\nAvailable endpoints:')
|
||||||
|
for iname in ips:
|
||||||
|
if port == 445:
|
||||||
|
print(f' -> {iname}: \\\\{ips[iname]}\\share\\')
|
||||||
|
else:
|
||||||
|
print(f' -> {iname}: \\\\{ips[iname]}:{port}\\share\\ # This syntax (:port) is not supported on Windows ?')
|
||||||
|
|
||||||
|
if port < 1024 and not is_sudo():
|
||||||
|
print('Listening on any port under 1024 requires root permissions.')
|
||||||
|
cmd = ['sudo', 'smbserver.py', '-port', str(port), 'share', files_dir]
|
||||||
|
else:
|
||||||
|
cmd = ['smbserver.py', '-port', str(port), 'share', files_dir]
|
||||||
|
subprocess.call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def get_public_ip():
|
||||||
|
return requests.get('https://api.ipify.org').text
|
||||||
|
|
||||||
|
|
||||||
|
def get_ips():
|
||||||
|
ips = dict()
|
||||||
|
try:
|
||||||
|
ips['public'] = get_public_ip()
|
||||||
|
except requests.exceptions.ConnectionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
cmd = ['ip', 'a']
|
||||||
|
out = subprocess.run(cmd, capture_output=True).stdout.decode('utf-8')
|
||||||
|
lines = out.split('\n')
|
||||||
|
|
||||||
|
while("" in lines):
|
||||||
|
lines.remove("")
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if line[0].isdigit():
|
||||||
|
iname = line.split(' ')[1].split(':')[0]
|
||||||
|
if 'inet ' in line:
|
||||||
|
ip = line.split(' ')[5].split('/')[0]
|
||||||
|
if ip != '127.0.0.1':
|
||||||
|
ips[iname] = ip
|
||||||
|
return ips
|
||||||
|
|
||||||
|
|
||||||
|
def menu_choice(menu_options):
|
||||||
|
while(True):
|
||||||
|
print_menu(menu_options)
|
||||||
|
option = ''
|
||||||
|
try:
|
||||||
|
option = int(input('Enter your choice: '))
|
||||||
|
except ValueError:
|
||||||
|
print('Wrong input. Please enter a number ...')
|
||||||
|
|
||||||
|
files_dir = pathlib.Path.cwd().joinpath('files')
|
||||||
|
|
||||||
|
if option == 1:
|
||||||
|
listen_http(files_dir)
|
||||||
|
elif option == 2:
|
||||||
|
listen_smb(files_dir)
|
||||||
|
elif option == 0:
|
||||||
|
sys.exit('Quitting')
|
||||||
|
else:
|
||||||
|
print('Invalid option. Please enter a valid number.')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
menu_options = {
|
||||||
|
1: 'HTTP',
|
||||||
|
2: 'SMB',
|
||||||
|
0: 'Exit',
|
||||||
|
}
|
||||||
|
update()
|
||||||
|
menu_choice(menu_options)
|
Loading…
Reference in New Issue
Block a user