pupy/create-workspace.py

197 lines
7.3 KiB
Python
Executable File

#!/usr/bin/env python2
import argparse
import subprocess
import os
import sys
import errno
import urllib2
import time
default_local_bin_location = os.path.expanduser('~/.local/bin/')
ROOT = os.path.abspath(os.path.dirname(__file__))
parser = argparse.ArgumentParser(prog="create-workspace.py")
parser.add_argument('-P', '--pupy-git-folder', default=ROOT, help='Path to pupy git')
parser.add_argument('-NC', '--do-not-compile-templates',
action='store_true', default=False, help='Do not compile payload templates')
parser.add_argument('-DG', '--download-templates-from-github-releases',
action='store_true', default=False, help='Do not compile payload templates and download latest templates from travis-ci automatic build')
parser.add_argument('-R', '--docker-repo',
help='Use non-default toolchains repo (Use "local" to build all the things on your PC')
parser.add_argument('-B', '--bin-path', default=default_local_bin_location,
help='Store pupy launch wrapper to this folder (default={})'.format(
default_local_bin_location))
parser.add_argument('-NI', '--no-pip-install-deps', action='store_true', default=False,
help='Do not install missing python deps (virtualenv, python-docker) using pip')
parser.add_argument('workdir', help='Location of workdir')
def main():
args = parser.parse_args()
try:
with open('/dev/null', 'w') as devnull:
subprocess.check_call(['git', '--help'], stdout=devnull)
except:
sys.exit("Install git (example: sudo apt-get install git)")
if args.download_templates_from_github_releases:
args.do_not_compile_templates=True
elif not args.do_not_compile_templates:
try:
with open('/dev/null', 'w') as devnull:
subprocess.check_call(['docker', '--help'], stdout=devnull)
except:
sys.exit("Install docker: https://docs.docker.com/install/")
vsc = '/proc/sys/abi/vsyscall32'
if os.path.isfile(vsc):
vsyscall = int(open(vsc).read())
if not vsyscall:
sys.exit('You need to have vsyscall enabled:\n~> sudo sysctl -w abi.vsyscall32=1\n~> sudo reboot')
try:
import virtualenv
except:
if args.no_pip_install_deps:
sys.exit('virtualenv missing: pip install --user virtualenv')
else:
subprocess.check_output('pip install --user virtualenv', shell=True)
import virtualenv
workdir = os.path.abspath(args.workdir)
if not os.path.isfile(os.path.join(args.pupy_git_folder, 'create-workspace.py')):
sys.exit('{} is not pupy project folder'.format(args.pupy_git_folder))
if os.path.isdir(workdir) and os.listdir(workdir):
sys.exit('{} is not empty'.format(workdir))
pupy = os.path.abspath(args.pupy_git_folder)
print "[+] Pupy at {}".format(pupy)
if not args.do_not_compile_templates:
print "[+] Compile common templates"
env = os.environ.copy()
if args.docker_repo:
env['REPO'] = args.docker_repo
subprocess.check_call([
os.path.join(args.pupy_git_folder, 'client', 'build-docker.sh')
], env=env, cwd=os.path.join(args.pupy_git_folder, 'client'))
print "[+] Create VirtualEnv environment"
try:
os.makedirs(args.workdir)
except OSError, e:
if e.errno == errno.EEXIST:
pass
virtualenv.create_environment(workdir)
print "[+] Update pip version ..."
subprocess.check_call([
os.path.join(workdir, 'bin', 'pip'),
'install',
'--upgrade', 'pip'
], cwd=os.path.join(pupy, 'pupy'))
print "[+] Install dependencies"
subprocess.check_call([
os.path.join(workdir, 'bin', 'pip'),
'install',
'-r', 'requirements.txt'
], cwd=os.path.join(pupy, 'pupy'))
subprocess.check_call([
os.path.abspath(os.path.join(workdir, 'bin', 'pip')),
'install', '--upgrade', '--force-reinstall',
'pycryptodome'
], cwd=os.path.join(pupy, 'pupy'))
if args.download_templates_from_github_releases:
download_link="https://github.com/n1nj4sec/pupy/releases/download/latest/payload_templates.txz"
print "downloading payload_templates from {}".format(download_link)
subprocess.check_call(["wget", "-O", "payload_templates.txz", download_link], cwd=os.path.join(pupy))
print "extracting payloads ..."
subprocess.check_call(["tar", "xf", "payload_templates.txz", "-C", "pupy/"], cwd=os.path.join(pupy))
wrappers=["pupysh", "pupygen"]
print "[+] Create {} wrappers".format(','.join(wrappers))
pupysh_update_path = os.path.join(workdir, 'bin', 'pupysh-update')
pupysh_paths=[]
for script in wrappers:
pupysh_path = os.path.join(workdir, 'bin', script)
pupysh_paths.append(pupysh_path)
with open(pupysh_path, 'w') as pupysh:
wa = os.path.abspath(workdir)
print >>pupysh, '#!/bin/sh'
print >>pupysh, 'cd {}'.format(wa)
print >>pupysh, 'exec bin/python -B {} "$@"'.format(
os.path.join(pupy, 'pupy', script+'.py'))
os.chmod(pupysh_path, 0755)
with open(pupysh_update_path, 'w') as pupysh_update:
wa = os.path.abspath(workdir)
print >>pupysh_update, '#!/bin/sh'
print >>pupysh_update, 'set -e'
print >>pupysh_update, 'echo "[+] Update pupy repo"'
print >>pupysh_update, 'cd {}; git pull --recurse-submodules'.format(pupy)
print >>pupysh_update, 'echo "[+] Update python dependencies"'
print >>pupysh_update, 'source {}/bin/activate; cd pupy; pip install --upgrade -r requirements.txt'.format(
workdir)
if not args.do_not_compile_templates:
print >>pupysh_update, 'echo "[+] Recompile templates"'
for target in ('windows', 'linux32', 'linux64'):
print >>pupysh_update, 'echo "[+] Build {}"'.format(target)
print >>pupysh_update, 'docker start -a build-pupy-{}'.format(target)
print >>pupysh_update, 'echo "[+] Update completed"'
os.chmod(pupysh_update_path, 0755)
if args.bin_path:
bin_path = os.path.abspath(args.bin_path)
print "[+] Store symlink to pupysh to {}".format(bin_path)
if not os.path.isdir(bin_path):
os.makedirs(bin_path)
for src, sympath in [(x, os.path.splitext(os.path.basename(x))[0]) for x in pupysh_paths]+[(pupysh_update_path, 'pupysh-update')]:
sympath = os.path.join(bin_path, sympath)
if os.path.islink(sympath):
os.unlink(sympath)
elif os.path.exists(sympath):
sys.exit("[-] File at {} already exists and not symlink".format(sympath))
os.symlink(src, sympath)
if bin_path not in os.environ['PATH']:
print "[-] {} is not in your PATH!".format(bin_path)
else:
print "[I] To execute pupysh:"
print "~ > pupysh"
print "[I] To update:"
print "~ > pupysh-update"
else:
print "[I] To execute pupysh:"
print "~ > {}".format(pupysh_paths[0])
print "[I] To update:"
print "~ > {}".format(pupysh_update_path)
if __name__ == '__main__':
main()