detection-hackathon-apt29 icon indicating copy to clipboard operation
detection-hackathon-apt29 copied to clipboard

4.C) File and Directory Discovery, System Owner/User Discovery, System Information Discovery, System Network Configuration Discovery, Process Discovery, Security Software Discovery, Permission Groups Discovery, Execution through API

Open Cyb3rWard0g opened this issue 4 years ago • 16 comments

Description

Finally, the attacker launches a PowerShell script that performs a wide variety of reconnaissance commands (T1083, T1033, T1082, T1016, T1057, T1063, T1069), some of which are done by accessing the Windows API (T1106).

Invoke-Discovery

Cyb3rWard0g avatar May 02 '20 10:05 Cyb3rWard0g

Maybe?: https://github.com/mitre-attack/attack-arsenal/blob/master/adversary_emulation/APT29/Emulation_Plan/Day%201/payloads/SysinternalsSuite/readme.txt#L591

Basic Query to find for handles requested to AD objects over the network

SELECT o.`@timestamp`, o.TargetUserName, o.TargetLogonId,
    a.EventID, a.ObjectName, a.ObjectType, a.ObjectServer, a.Hostname
FROM apt29Table o
INNER JOIN (
    SELECT EventID, SubjectLogonId, ObjectName, ObjectType, ObjectServer, Hostname
    FROM apt29Table
    WHERE lower(Channel) = "security"
        AND EventID = 4661
        AND ObjectType = "SAM_DOMAIN"
        AND ObjectServer = "Security Account Manager"
    ) a
ON o.TargetLogonId = a.SubjectLogonId
WHERE lower(Channel) = "security" 
        AND o.EventID = 4624
        AND o.LogonType = 3
        AND NOT o.TargetUserName LIKE "%$"

Results:

-RECORD 0----------------------------------
 @timestamp     | 2020-05-02T03:04:05.749Z 
 TargetUserName | pbeesly                  
 TargetLogonId  | 0x5dd594                 
 EventID        | 4661                     
 ObjectName     | DC=dmevals,DC=local      
 ObjectType     | SAM_DOMAIN               
 ObjectServer   | Security Account Manager 
 Hostname       | NEWYORK.dmevals.local 

Cyb3rWard0g avatar May 02 '20 17:05 Cyb3rWard0g

4.C.12 Execution through API

Detection Gategory - Telemetry

Procedure: Executed API call by reflectively loading Netapi32.dll Criteria: The NetUserGetLocalGroups API function loaded into powershelle.exe from Netapi32.dll

Query needs some validation and filtering

netapi = spark.sql(
    '''
SELECT Image, count(*) as count
FROM apt29Table
WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
AND EventID = 7 AND LOWER(ImageLoaded) LIKE "%netapi32.dll%"
GROUP BY Image
ORDER BY count DESC
                          ''')
netapi.show(100,truncate = False, vertical = False)

results

+------------------------------------------------------------------------+-----+
|Image                                                                   |count|
+------------------------------------------------------------------------+-----+
|C:\Windows\System32\wbem\WmiPrvSE.exe                                   |6    |
|C:\Windows\System32\sppsvc.exe                                          |5    |
|C:\Windows\System32\svchost.exe                                         |5    |
|C:\Windows\PSEXESVC.exe                                                 |4    |
|C:\Program Files\SysinternalsSuite\PsExec64.exe                         |4    |
|C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe               |3    |
|C:\Windows\System32\WerFault.exe                                        |2    |
|C:\Program Files (x86)\Google\Update\1.3.35.452\GoogleCrashHandler.exe  |2    |
|C:\Program Files (x86)\Google\Update\1.3.35.452\GoogleCrashHandler64.exe|2    |
|C:\ProgramData\victim\‮cod.3aka3.scr                                  |1    |
|C:\Windows\System32\rundll32.exe                                        |1    |
|C:\Windows\System32\wermgr.exe                                          |1    |
|C:\Windows\Temp\python.exe                                              |1    |
+------------------------------------------------------------------------+-----+


Cyb3rWard0g avatar May 11 '20 07:05 Cyb3rWard0g

4.C.1 File and Directory Discovery

Procedure: Enumerated user's temporary directory path using PowerShell Criteria: powershell.exe executing $env:TEMP

Cyb3rWard0g avatar May 13 '20 19:05 Cyb3rWard0g

Sysmon + PowerShell Logs

SELECT Message
FROM apt29Host f
INNER JOIN (
  SELECT d.ProcessId
  FROM apt29Host d
  INNER JOIN (
    SELECT a.ProcessGuid, a.ParentProcessGuid
    FROM apt29Host a
    INNER JOIN (
      SELECT ProcessGuid
      FROM apt29Host
      WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
          AND EventID = 1
          AND LOWER(Image) LIKE "%control.exe"
          AND LOWER(ParentImage) LIKE "%sdclt.exe"
    ) b
    ON a.ParentProcessGuid = b.ProcessGuid
    WHERE a.Channel = "Microsoft-Windows-Sysmon/Operational"
      AND a.EventID = 1
      AND a.IntegrityLevel = "High"
  ) c
  ON d.ParentProcessGuid= c.ProcessGuid
  WHERE d.Channel = "Microsoft-Windows-Sysmon/Operational"
    AND d.EventID = 1
    AND d.Image LIKE '%powershell.exe'
) e
ON f.ExecutionProcessID = e.ProcessId
WHERE f.Channel = "Microsoft-Windows-PowerShell/Operational"
  AND f.EventID = 4104
  AND LOWER(f.ScriptBlockText) LIKE "%$env:temp%"

Results

Creating Scriptblock text (1 of 1):
function Invoke-Discovery {
    $DiscoveryInfo =@()
    $CurrentDir = Get-Location

    $DiscoveryInfo += [PSCustomObject]@{
                CurrentDirectory = $CurrentDir
                TempDirectory = $env:TEMP
                UserName = $env:USERNAME
                ComputerName = $env:COMPUTERNAME
                UserDomain = $env:USERDOMAIN
                CurrentPID = $PID
            }

    $DiscoveryInfo | Format-List
    
    $NameSpace = Get-WmiObject -Namespace "root" -Class "__Namespace" | Select Name | Out-String -Stream | Select-String "SecurityCenter"
    foreach ($SecurityCenter in $NameSpace) { 
        Get-WmiObject -Namespace "root\$SecurityCenter" -Class AntiVirusProduct -ErrorAction SilentlyContinue | Select DisplayName, InstanceGuid, PathToSignedProductExe, PathToSignedReportingExe, ProductState, Timestamp | Format-List
        WmiObject -Namespace "root\$SecurityCenter" -Class FireWallProduct -ErrorAction SilentlyContinue | Select DisplayName, InstanceGuid, PathToSignedProductExe, PathToSignedReportingExe, ProductState, Timestamp | Format-List 
    } 

    Gwmi Win32_OperatingSystem | Select Name, OSArchitecture, CSName, BuildNumber, Version | Format-List
    Invoke-NetUserGetGroups
    Invoke-NetUserGetLocalGroups
}

ScriptBlock ID: 70878299-2ee1-4a5d-869f-124b349aee1d
Path: C:\Program Files\SysinternalsSuite\readme.ps1 

Cyb3rWard0g avatar May 13 '20 19:05 Cyb3rWard0g

Security Logs + PowerShell Logs

SELECT Message
FROM apt29Host f
INNER JOIN (
  SELECT split(d.NewProcessId, '0x')[1] as NewProcessId
  FROM apt29Host d
  INNER JOIN(
    SELECT a.ProcessId, a.NewProcessId
    FROM apt29Host a
    INNER JOIN (
      SELECT NewProcessId
      FROM apt29Host
      WHERE LOWER(Channel) = "security"
          AND EventID = 4688
          AND LOWER(NewProcessName) LIKE "%control.exe"
          AND LOWER(ParentProcessName) LIKE "%sdclt.exe"
    ) b
    ON a.ProcessId = b.NewProcessId
    WHERE LOWER(a.Channel) = "security"
      AND a.EventID = 4688
      AND a.MandatoryLabel = "S-1-16-12288"
      AND a.TokenElevationType = "%%1937"
  ) c
  ON d.ProcessId = c.NewProcessId
  WHERE LOWER(d.Channel) = "security"
    AND d.EventID = 4688
    AND d.NewProcessName LIKE '%powershell.exe'
) e
ON LOWER(hex(f.ExecutionProcessID)) = e.NewProcessId
WHERE f.Channel = "Microsoft-Windows-PowerShell/Operational"
  AND f.EventID = 4104
  AND LOWER(f.ScriptBlockText) LIKE "%$env:temp%"

Results

Creating Scriptblock text (1 of 1):
function Invoke-Discovery {
    $DiscoveryInfo =@()
    $CurrentDir = Get-Location

    $DiscoveryInfo += [PSCustomObject]@{
                CurrentDirectory = $CurrentDir
                TempDirectory = $env:TEMP
                UserName = $env:USERNAME
                ComputerName = $env:COMPUTERNAME
                UserDomain = $env:USERDOMAIN
                CurrentPID = $PID
            }

    $DiscoveryInfo | Format-List
    
    $NameSpace = Get-WmiObject -Namespace "root" -Class "__Namespace" | Select Name | Out-String -Stream | Select-String "SecurityCenter"
    foreach ($SecurityCenter in $NameSpace) { 
        Get-WmiObject -Namespace "root\$SecurityCenter" -Class AntiVirusProduct -ErrorAction SilentlyContinue | Select DisplayName, InstanceGuid, PathToSignedProductExe, PathToSignedReportingExe, ProductState, Timestamp | Format-List
        WmiObject -Namespace "root\$SecurityCenter" -Class FireWallProduct -ErrorAction SilentlyContinue | Select DisplayName, InstanceGuid, PathToSignedProductExe, PathToSignedReportingExe, ProductState, Timestamp | Format-List 
    } 

    Gwmi Win32_OperatingSystem | Select Name, OSArchitecture, CSName, BuildNumber, Version | Format-List
    Invoke-NetUserGetGroups
    Invoke-NetUserGetLocalGroups
}

ScriptBlock ID: 70878299-2ee1-4a5d-869f-124b349aee1d
Path: C:\Program Files\SysinternalsSuite\readme.ps1

Cyb3rWard0g avatar May 13 '20 19:05 Cyb3rWard0g

4.C.2 System Owner/User Discovery

Procedure: Enumerated the current username using PowerShell Criteria: powershell.exe executing $env:USERNAME

Same as before but looking for LIKE "%$env:username%"

Cyb3rWard0g avatar May 13 '20 19:05 Cyb3rWard0g

4.C.3 System Information Discovery

Procedure: Enumerated the computer hostname using PowerShell Criteria: powershell.exe executing $env:COMPUTERNAME Same as before but looking for LIKE "%$env:computername%"

Cyb3rWard0g avatar May 13 '20 19:05 Cyb3rWard0g

4.C.4 System Network Configuration Discovery

Procedure: Enumerated the current domain name using PowerShell Criteria: powershell.exe executing $env:USERDOMAIN

Same as before but looking for LIKE "%$env:userdomain%"

Cyb3rWard0g avatar May 13 '20 19:05 Cyb3rWard0g

4.C.5 Process Discovery

Procedure: Enumerated the current process ID using PowerShell Criteria: powershell.exe executing $PID

Same as before but looking for LIKE "%$pid%"

Cyb3rWard0g avatar May 13 '20 20:05 Cyb3rWard0g

4.C.6 System Information Discovery

Procedure: Enumerated the OS version using PowerShell Criteria: powershell.exe executing​ Gwmi Win32_OperatingSystem

Same as before but looking for "%gwmi win32_operatingsystem%"

Cyb3rWard0g avatar May 13 '20 21:05 Cyb3rWard0g

4.C.7 Security Software Discovery

Procedure: Enumerated anti-virus software using PowerShell Criteria: powershell.exe executing​ Get-WmiObject ...​ -Class AntiVirusProduct

Same as before but looking for "%-class antivirusproduct%"

Cyb3rWard0g avatar May 13 '20 21:05 Cyb3rWard0g

4.C.8 Security Software Discovery

Procedure: Enumerated firewall software using PowerShell Criteria: powershell.exe executing Get-WmiObject ...​​ -Class FireWallProduct

Same as before but looking for "%-class firewallproduct%"

Cyb3rWard0g avatar May 13 '20 21:05 Cyb3rWard0g

4.C.9 Permission Groups Discovery

Procedure: Enumerated user's domain group membership via the NetUserGetGroups API Criteria: powershell.exe executing the NetUserGetGroups API

One could look for the Invoke-NetUserGetGroups script name in PowerShell Logs but that can be bypassed by simply renaming the function/script :/

Another option (I like the most) is to look for Domain users requesting handles to SAM_DOMAIN objects with access rights 'getlocalgroupmembership'

Security Event Logs

SELECT a.EventTime, o.TargetUserName, o.IpAddress, a.Message
FROM apt29Table o
INNER JOIN (
    SELECT Message, EventTime, SubjectLogonId
    FROM apt29Table
    WHERE lower(Channel) = "security"
        AND EventID = 4661
        AND ObjectType = "SAM_DOMAIN"
        AND SubjectUserName NOT LIKE '%$'
        AND AccessMask = '0x20094'
        AND LOWER(Message) LIKE '%getlocalgroupmembership%'
    ) a
ON o.TargetLogonId = a.SubjectLogonId
WHERE lower(Channel) = "security" 
        AND o.EventID = 4624
        AND o.LogonType = 3

Results

EventTime      | 2020-05-01 23:04:04                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
 TargetUserName | pbeesly                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 IpAddress      | 10.0.1.4                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
 Message        | A handle to an object was requested.

Subject :
	Security ID:		S-1-5-21-1830255721-3727074217-2423397540-1107
	Account Name:		pbeesly
	Account Domain:		DMEVALS
	Logon ID:		0x5DD594

Object:
	Object Server:	Security Account Manager
	Object Type:	SAM_DOMAIN
	Object Name:	DC=dmevals,DC=local
	Handle ID:	0x1fccecf7240

Process Information:
	Process ID:	0x2c0
	Process Name:	C:\Windows\System32\lsass.exe

Access Request Information:
	Transaction ID:	{00000000-0000-0000-0000-000000000000}
	Accesses:	READ_CONTROL
				ReadOtherParameters
				CreateUser
				GetLocalGroupMembership
				
	Access Reasons:		-
	Access Mask:	0x20094
	Privileges Used for Access Check:	-
	Properties:	---
	{19195a5a-6da0-11d0-afd3-00c04fd930c9}
READ_CONTROL
ReadOtherParameters
CreateUser
GetLocalGroupMembership
		{c7407360-20bf-11d0-a768-00aa006e0529}
			{bf9679a4-0de6-11d0-a285-00aa003049e2}
			{bf9679a5-0de6-11d0-a285-00aa003049e2}
			{bf9679a6-0de6-11d0-a285-00aa003049e2}
			{bf9679bb-0de6-11d0-a285-00aa003049e2}
			{bf9679c2-0de6-11d0-a285-00aa003049e2}
			{bf9679c3-0de6-11d0-a285-00aa003049e2}
			{bf967a09-0de6-11d0-a285-00aa003049e2}
			{bf967a0b-0de6-11d0-a285-00aa003049e2}
		{b8119fd0-04f6-4762-ab7a-4986c76b3f9a}
			{bf967a34-0de6-11d0-a285-00aa003049e2}
			{bf967a33-0de6-11d0-a285-00aa003049e2}
			{bf9679c5-0de6-11d0-a285-00aa003049e2}
			{bf967a61-0de6-11d0-a285-00aa003049e2}
			{bf967977-0de6-11d0-a285-00aa003049e2}
			{bf96795e-0de6-11d0-a285-00aa003049e2}
			{bf9679ea-0de6-11d0-a285-00aa003049e2}
		{ab721a52-1e2f-11d0-9819-00aa0040529b}

	Restricted SID Count:	0 

Cyb3rWard0g avatar May 13 '20 21:05 Cyb3rWard0g

4.C.10 Execution through API

Procedure: Executed API call by reflectively loading Netapi32.dll Criteria: The NetUserGetGroups API function loaded into powershell.exe from Netapi32.dll

Correlating the netapi32.dll load with the previous Bypassuac deff helps to add contexts since that DLL is loaded by several other process.

Sysmon

SELECT Message
FROM apt29Host f
INNER JOIN (
    SELECT d.ProcessGuid
    FROM apt29Host d
    INNER JOIN (
      SELECT a.ProcessGuid, a.ParentProcessGuid
      FROM apt29Host a
      INNER JOIN (
        SELECT ProcessGuid
        FROM apt29Host
        WHERE Channel = "Microsoft-Windows-Sysmon/Operational"
            AND EventID = 1
            AND LOWER(Image) LIKE "%control.exe"
            AND LOWER(ParentImage) LIKE "%sdclt.exe"
      ) b
      ON a.ParentProcessGuid = b.ProcessGuid
      WHERE a.Channel = "Microsoft-Windows-Sysmon/Operational"
        AND a.EventID = 1
        AND a.IntegrityLevel = "High"
    ) c
    ON d.ParentProcessGuid= c.ProcessGuid
    WHERE d.Channel = "Microsoft-Windows-Sysmon/Operational"
      AND d.EventID = 1
      AND d.Image LIKE '%powershell.exe'
) e
ON f.ProcessGuid = e.ProcessGuid
WHERE f.Channel = "Microsoft-Windows-Sysmon/Operational"
AND f.EventID = 7
AND LOWER(f.ImageLoaded) LIKE "%netapi32.dll"

Results

Image loaded:
RuleName: -
UtcTime: 2020-05-02 03:04:04.361
ProcessGuid: {47ab858c-e23d-5eac-c603-000000000400}
ProcessId: 3876
Image: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
ImageLoaded: C:\Windows\System32\netapi32.dll
FileVersion: 10.0.18362.1 (WinBuild.160101.0800)
Description: Net Win32 API DLL
Product: Microsoft® Windows® Operating System
Company: Microsoft Corporation
OriginalFileName: NetApi32.DLL
Hashes: SHA1=7DFDD188B30162DAA87FDD3E5B7A55C80CD839F1,MD5=86A9DF3FA9D5FCAC8EF57601FCCD78F9,SHA256=F8CDA38FD3FF371E772875EA657A37662321EBB7AD8D6978DBCCCA7FC6DB64F1,IMPHASH=7D4E1695394CF47BD397AFD45A40E55D
Signed: true
Signature: Microsoft Windows
SignatureStatus: Valid

Cyb3rWard0g avatar May 13 '20 21:05 Cyb3rWard0g

4.C.11 Permission Groups Discovery

Procedure: Enumerated user's local group membership via the NetUserGetLocalGroups API Criteria: powershell.exe executing the NetUserGetLocalGroups API

One could look for the Invoke-NetUserGetLocalGroups script name in PowerShell Logs but that can be bypassed by simply renaming the function/script :/

Cyb3rWard0g avatar May 13 '20 22:05 Cyb3rWard0g

4.C.12 Execution through API

Procedure: Executed API call by reflectively loading Netapi32.dll Criteria: The NetUserGetLocalGroups API function loaded into powershelle.exe from Netapi32.dll

Correlating the netapi32.dll load with the previous Bypassuac deff helps to add contexts since that DLL is loaded by several other process. Same as query above 4.C.10

Cyb3rWard0g avatar May 13 '20 22:05 Cyb3rWard0g