Skip to content

Instantly share code, notes, and snippets.

@zeroSteiner
Last active December 15, 2015 18:19
Show Gist options
  • Save zeroSteiner/5303198 to your computer and use it in GitHub Desktop.
Save zeroSteiner/5303198 to your computer and use it in GitHub Desktop.
EAP brute forcing utility The mschapext module is not available.
# -*- coding: utf-8 -*-
#
# eapbrute.py
#
# 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 SecureState Consulting 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
# OWNER 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.
#
# Homepage: https://gist.github.com/zeroSteiner/5303198
# Author: Spencer McIntyre (zeroSteiner)
__version__ = '0.0.1'
__authors__ = [ 'Spencer McIntyre' ]
import sys
import argparse
from binascii import hexlify, unhexlify
from hashlib import new
def mschap_bruteforce(challenge, response, passwordfile, quite = True):
import mschapext
ntlm = lambda pw:new('md4', pw.encode('utf-16le'))
line = passwordfile.readline()[:-1]
while line:
if not quite:
sys.stdout.write("Trying Password: " + line + ((40 - len(line)) * ' ' ) + "\r")
sys.stdout.flush()
try:
ntlmhash = ntlm(line).digest()
except:
line = passwordfile.readline().strip()
continue
if mschapext.calcResponse(challenge, ntlmhash) == response:
if not quite: print '\nFound Password: ' + line
return line
line = passwordfile.readline().strip()
passwordfile.close()
if not quite: print '\nPassword not found. Sorry.'
return 0
def md5_bruteforce(reqid, challenge, response, passwordfile, quite = True):
def md5(value):
hasher = new('md5')
hasher.update(value)
return hasher.digest()
reqid = chr(reqid)
line = passwordfile.readline()[:-1]
while line:
if not quite:
sys.stdout.write("Trying Password: " + line + ((40 - len(line)) * ' ' ) + "\r")
sys.stdout.flush()
if md5(reqid + line + challenge) == response:
if not quite: print '\nFound Password: ' + line
return line
line = passwordfile.readline()[:-1]
passwordfile.close()
if not quite: print '\nPassword not found. Sorry.'
return 0
def main():
parser = argparse.ArgumentParser(description = 'EAPBrute: Offline password attacks for common EAP hash and authentication types.', conflict_handler='resolve')
parser.add_argument('-v', '--version', action = 'version', version = parser.prog + ' Version: ' + __version__)
parser.add_argument('-d', '--dic', dest = 'dictionary', action = 'store', type = argparse.FileType('r'), required = True, help = 'dictionary of words to try')
subparsers = parser.add_subparsers(help='attack types')
parser_mschap = subparsers.add_parser('mschap', help = 'MS-CHAPv2')
parser_mschap.add_argument('mschap_challenge', action = 'store', default = None, help = 'mschap challenge in hex')
parser_mschap.add_argument('mschap_response', action = 'store', default = None, help = 'mschap response in hex')
parser_md5 = subparsers.add_parser('md5', help = 'EAP-MD5')
parser_md5.add_argument('md5_reqid', action = 'store', type = int, default = None, help = 'eap-md5 request id')
parser_md5.add_argument('md5_challenge', action = 'store', default = None, help = 'eap-md5 challenge in hex')
parser_md5.add_argument('md5_response', action = 'store', default = None, help = 'eap-md5 response in hex')
results = parser.parse_args()
if hasattr(results, 'mschap_challenge') and hasattr(results, 'mschap_response'): # MSCHAP
challenge = unhexlify(results.mschap_challenge.replace(':', ''))
response = unhexlify(results.mschap_response.replace(':', ''))
mschap_bruteforce(challenge, response, results.dictionary, False)
return 0
elif hasattr(results, 'md5_reqid') and hasattr(results, 'md5_challenge') and hasattr(results, 'md5_response'):
challenge = unhexlify(results.md5_challenge.replace(':', ''))
response = unhexlify(results.md5_response.replace(':', ''))
md5_bruteforce(results.md5_reqid, challenge, response, results.dictionary, False)
return 0
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment