Skip to content

Commit

Permalink
Merge pull request #124 from s0lst1c3/known-ssids-flag
Browse files Browse the repository at this point in the history
Added --known-ssids flag
  • Loading branch information
s0lst1c3 authored Oct 4, 2019
2 parents 45d1350 + f3bfd09 commit eac33fc
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 8 deletions.
3 changes: 3 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,6 @@ Added ssid and mac address level ACLs.

1.11.0 - Gabriel Ryan <gryan@specterops.io>
Added beacon forger for executing known SSID bursts

1.12.0 - Gabriel Ryan <gryan@specterops.io>
Added --known-ssids flag that can be used instead of --known-ssids-file flag.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ by Gabriel Ryan ([s0lst1c3](https://twitter.com/s0lst1c3))(gryan[at]specterops.i

[![Foo](https://rawcdn.githack.com/toolswatch/badges/8bd9be6dac2a1d445367001f2371176cc50a5707/arsenal/usa/2017.svg)](https://www.blackhat.com/us-17/arsenal.html#eaphammer)

Current release: [v1.11.0](https://github.com/s0lst1c3/eaphammer/releases/tag/v1.11.0)
Current release: [v1.12.0](https://github.com/s0lst1c3/eaphammer/releases/tag/v1.12.0)

Supports _Python 3.5+_.

Expand Down
2 changes: 1 addition & 1 deletion __version__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '1.11.0'
__version__ = '1.12.0'
__codename__ = 'Power Overwhelming'
__author__ = '@s0lst1c3'
__contact__ = 'gryan@specterops.io'
Expand Down
32 changes: 27 additions & 5 deletions core/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
'user_list',
'bootstrap',
'known_ssids_file',
'known_ssids',
'negotiate',
]

Expand Down Expand Up @@ -467,6 +468,13 @@ def set_options():
help='Specify the wordlist to use with '
'the --known-beacons features.')

karma_group.add_argument('--known-ssids',
dest='known_ssids',
nargs='+',
default=None,
type=str,
help='Specify known ssids via the CLI')

ap_advanced_subgroup = parser.add_argument_group('AP Advanced Options')

ap_advanced_subgroup.add_argument('--wmm',
Expand Down Expand Up @@ -908,18 +916,32 @@ def set_options():
print(msg, end='')
sys.exit()

if options['known_ssids_file'] is None:
if options['known_ssids_file'] is None and \
options['known_ssids'] is None:

parser.print_usage()
print()
msg = ('[!] Cannot use --known-beacons without known SSIDS file. '
'Please specify path to known SSIDS file with --known-ssids flag.')
msg = ('[!] Cannot use --known-beacons '
'without list of known SSIDS. '
'Please specify path to known SSIDS '
'file with the --known-ssids-file flag, '
'or provide a list of known SSIDS '
'using the --known-ssids flag.')
print(msg, end='')
sys.exit()


if options['known_ssids_file'] is not None and \
options['known_ssids'] is not None:

parser.print_usage()
print()
msg = ('[!] Cannot use --known-ssids-file '
'and --known-ssids flags simultaneously.')
print(msg, end='')
sys.exit()

if not Path(options['known_ssids_file']).is_file():
if options['known_ssids_file'] is not None and \
not Path(options['known_ssids_file']).is_file():

parser.print_usage()
print()
Expand Down
2 changes: 1 addition & 1 deletion core/hostapd_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def populate_general(self, settings, options):

if options['known_beacons']:
general_configs['known_beacons'] = '1'
general_configs['known_ssids_file'] = options['known_ssids_file']
general_configs['known_ssids_file'] = settings.dict['paths']['hostapd']['known_ssids']
else:
general_configs['known_beacons'] = settings.dict['core']['hostapd']['general']['known_beacons']

Expand Down
73 changes: 73 additions & 0 deletions core/known_ssids_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import os
import shutil
import sys

class KnownSSIDSFile(object):

def __init__(self,
settings,
options):

self.debug = options['debug']
self.known_ssids = []
self.output_path = settings.dict['paths']['hostapd']['known_ssids']

# having to do this makes me wish that python had a
# logic XOR operator... or even a NAND operator for
# that matter...
assert not (options['known_ssids_file'] is None and options['known_ssids'] is None)
assert not (options['known_ssids_file'] is not None and options['known_ssids'] is not None)

if options['known_ssids_file'] is not None:

with open(options['known_ssids_file']) as fd:

for line in fd:

# remove '\n' from end of line
ssid = line.rstrip('\n')
if ssid.strip() != ssid:
print('[eaphammer] WARNING: whitespace detected '
'at beginning or end of known-ssids-file. '
'Assuming this is intentional.')
self.known_ssids.append(ssid)

elif options['known_ssids'] is not None:

self.known_ssids = options['known_ssids']

else:
raise Exception('[KnownSSIDSFile] this should never happen')


if self.debug:
print('[KnownSSIDSFile] self.known_ssids: ', self.known_ssids)
print('[KnownSSIDSFile] self.output_path: ', self.output_path)

def remove(self):

if not self.debug:

try:

os.remove(self.output_path)

except FileNotFoundError:

print('[KnownSSIDSFile] Cannot remove file that does not exist')

def path(self, path=None):

if path is not None:
self.output_path = path

return self.output_path

def generate(self):


with open(self.output_path, 'w') as fd:
for ssid in self.known_ssids:
fd.write('{}\n'.format(ssid))

return self.path()
32 changes: 32 additions & 0 deletions eaphammer
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ from core.hostapd_config import HostapdConfig
from core.eap_user_file import EAPUserFile
from core.hostapd_mac_acl import HostapdMACACL
from core.hostapd_ssid_acl import HostapdSSIDACL
from core.known_ssids_file import KnownSSIDSFile
from core.responder_config import ResponderConfig
from core.lazy_file_reader import LazyFileReader
from core.redirect_server import RedirectServer
Expand Down Expand Up @@ -74,6 +75,10 @@ def hostile_portal():
hostapd_ssid_acl = HostapdSSIDACL(settings, options)
hostapd_ssid_acl.generate()

if options['known_beacons']:
known_ssids_file = KnownSSIDSFile(settings, options)
known_ssids_file.generate()

# write hostapd config file to tmp directory
hostapd_conf = HostapdConfig(settings, options)
hostapd_conf.write()
Expand Down Expand Up @@ -247,6 +252,10 @@ def captive_portal():
hostapd_ssid_acl = HostapdSSIDACL(settings, options)
hostapd_ssid_acl.generate()

if options['known_beacons']:
known_ssids_file = KnownSSIDSFile(settings, options)
known_ssids_file.generate()

# write hostapd config file to tmp directory
hostapd_conf = HostapdConfig(settings, options)
hostapd_conf.write()
Expand Down Expand Up @@ -303,6 +312,9 @@ def captive_portal():

# remove acl file from tmp directory
hostapd_ssid_acl.remove()

if options['known_beacons']:
known_ssids_file.remove()

# restore iptables to a clean state (policy, flush tables)
utils.Iptables.accept_all()
Expand Down Expand Up @@ -341,6 +353,9 @@ def captive_portal():

# remove acl file from tmp directory
hostapd_ssid_acl.remove()

if options['known_beacons']:
known_ssids_file.remove()

# restore iptables to a clean state (policy, flush tables)
utils.Iptables.accept_all()
Expand Down Expand Up @@ -378,6 +393,10 @@ def troll_defender():
hostapd_ssid_acl = HostapdSSIDACL(settings, options)
hostapd_ssid_acl.generate()

if options['known_beacons']:
known_ssids_file = KnownSSIDSFile(settings, options)
known_ssids_file.generate()

# write hostapd config file to tmp directory
hostapd_conf = HostapdConfig(settings, options)
hostapd_conf.write()
Expand Down Expand Up @@ -421,6 +440,9 @@ def troll_defender():
# remove acl file from tmp directory
hostapd_ssid_acl.remove()

if options['known_beacons']:
known_ssids_file.remove()

# cleanly allow network manager to regain control of interface
interface.nm_on()

Expand Down Expand Up @@ -462,6 +484,10 @@ def reap_creds():
hostapd_ssid_acl = HostapdSSIDACL(settings, options)
hostapd_ssid_acl.generate()

if options['known_beacons']:
known_ssids_file = KnownSSIDSFile(settings, options)
known_ssids_file.generate()

# write hostapd config file to tmp directory
hostapd_conf = HostapdConfig(settings, options)
hostapd_conf.write()
Expand Down Expand Up @@ -497,6 +523,9 @@ def reap_creds():
# remove acl file from tmp directory
hostapd_ssid_acl.remove()

if options['known_beacons']:
known_ssids_file.remove()

# cleanly allow network manager to regain control of interface
interface.nm_on()

Expand Down Expand Up @@ -526,6 +555,9 @@ def reap_creds():
# remove acl file from tmp directory
hostapd_ssid_acl.remove()

if options['known_beacons']:
known_ssids_file.remove()

# cleanly allow network manager to regain control of interface
interface.nm_on()

Expand Down
5 changes: 5 additions & 0 deletions settings/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ def __str__(self):
PHASE1_ACCOUNTS = os.path.join(DB_DIR, 'phase1.accounts')
PHASE2_ACCOUNTS = os.path.join(DB_DIR, 'phase2.accounts')

# known ssids file
output_file = OutputFile(ext='known_ssids').string()
KNOWN_SSIDS_FILE = os.path.join(TMP_DIR, output_file)

# ACL Files
output_file = OutputFile(ext='accept').string()
HOSTAPD_MAC_WHITELIST = os.path.join(TMP_DIR, output_file)
Expand Down Expand Up @@ -193,6 +197,7 @@ def __str__(self):
'mac_blacklist' : HOSTAPD_MAC_BLACKLIST,
'ssid_whitelist' : HOSTAPD_SSID_WHITELIST,
'ssid_blacklist' : HOSTAPD_SSID_BLACKLIST,
'known_ssids' : KNOWN_SSIDS_FILE,
},

'certs' : {
Expand Down

0 comments on commit eac33fc

Please sign in to comment.