Skip to content

Commit

Permalink
Added WMI AV Support
Browse files Browse the repository at this point in the history
  • Loading branch information
achilles4828 committed Aug 16, 2022
1 parent 1acbce9 commit 19a27b5
Show file tree
Hide file tree
Showing 17 changed files with 362 additions and 24 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dist
EDRHunt.exe
dist
EDRHunt.exe
.vscode
26 changes: 14 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
all: build

build:
go build -ldflags="-w -s" -o EDRHunt.exe github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt
garble-build:
garble -literals build -ldflags="-w -s" -o EDRHunt.exe github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt
local:
go build -ldflags="-w -s" -o EDRHunt.exe github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt
run:
go run -ldflags="-w -s" github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt all
drivers:
go run -ldflags="-w -s" github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt -d
all: build

build:
go build -ldflags="-w -s" -o EDRHunt.exe github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt
garble-build:
garble -literals build -ldflags="-w -s" -o EDRHunt.exe github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt
local:
go build -ldflags="-w -s" -o EDRHunt.exe github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt
run:
go run -ldflags="-w -s" github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt all
drivers:
go run -ldflags="-w -s" github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt -d
avwmi:
go run -ldflags="-w -s" github.com/FourCoreLabs/EDRHunt/cmd/EDRHunt -w
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![goreleaser](https://github.com/FourCoreLabs/EDRHunt/actions/workflows/goreleaser.yml/badge.svg)](https://github.com/FourCoreLabs/EDRHunt/actions/workflows/goreleaser.yml)

EDRHunt scans Windows services, drivers, processes, registry for installed EDRs (Endpoint Detection And Response). Read more about EDRHunt [here](https://www.fourcore.vision/blogs/red-team-adventure-windows-endpoints-edr-edrhunt).
EDRHunt scans Windows services, drivers, processes, registry, wmi for installed EDRs (Endpoint Detection And Response). Read more about EDRHunt [here](https://www.fourcore.vision/blogs/red-team-adventure-windows-endpoints-edr-edrhunt).

[![asciicast](https://asciinema.org/a/P8i99w9mI497qUPTNbdwYWcwQ.svg)](https://asciinema.org/a/P8i99w9mI497qUPTNbdwYWcwQ)

Expand Down Expand Up @@ -30,7 +30,7 @@ Detected EDR: Kaspersky Security
```
$ .\EDRHunt.exe all
Running in user mode, escalate to admin for more details.
Scanning processes, services, drivers, and registry...
Scanning processes, services, drivers, wmi, and registry...
[PROCESSES]
Suspicious Process Name: MsMpEng.exe
Expand Down Expand Up @@ -131,6 +131,13 @@ $ .\EDRHunt.exe -d
$ .\EDRHunt.exe -r
```


- Find WMI Repository keys matching EDR keywords

```
$ .\EDRHunt.exe -w
```

## Detections

EDR Detections Currently Available
Expand All @@ -145,6 +152,9 @@ EDR Detections Currently Available
- SentinelOne
- FireEye
- Elastic EDR
- Qualys EDR
- Trend Micro EDR
- ESET EDR

More to be added soon.

Expand Down
29 changes: 26 additions & 3 deletions cmd/EDRHunt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ var (
processes bool
services bool
registry bool
avwmi bool
all bool
versionStr string = "1.3.1"
versionStr string = "1.4.0"
versionCheck bool
)

Expand Down Expand Up @@ -46,7 +47,8 @@ func edrCommand(cmd *cobra.Command, args []string) {
drivers = true
services = true
registry = true
fmt.Println("Scanning processes, services, drivers, and registry...")
avwmi = true
fmt.Println("Scanning processes, services, drivers, wmi, and registry...")
}

if processes {
Expand All @@ -67,6 +69,12 @@ func edrCommand(cmd *cobra.Command, args []string) {
printServices(summary)
fmt.Println()
}
if avwmi {
fmt.Println("[WMI-REPO]")
summary, _ := edrRecon.CheckAVWmiRepo()
printAVWmi(summary)
fmt.Println()
}
if registry {
fmt.Println("[REGISTRY]")
summary, _ := edrRecon.CheckRegistry(context.Background())
Expand Down Expand Up @@ -100,7 +108,7 @@ func allCommand(cmd *cobra.Command, args []string) {
var rootCmd = &cobra.Command{
Use: "EDRHunt",
Short: "scans EDR/AV",
Long: `EDRHunt scans and finds the installed EDR/AV by scanning services, processes, registry, and drivers.`,
Long: `EDRHunt scans and finds the installed EDR/AV by scanning services, processes, registry, wmi, and drivers.`,
Run: edrCommand,
}

Expand All @@ -125,6 +133,20 @@ var allCmd = &cobra.Command{
Run: allCommand,
}

func printAVWmi(summary []resources.AVWmiMetaData) {
for _, antivirus := range summary {
fmt.Printf("Suspicious Product Name: %s\n", antivirus.ProductName)
fmt.Printf("Suspicious Product GUID: %s\n", antivirus.ProductGUID)
fmt.Printf("Path to Suspicious Product Exe: %s\n", antivirus.PathToProductExe)
fmt.Printf("Suspicious Product Exe Metadata: \t%s\n", edrRecon.FileMetaDataParser(antivirus.ProductExeMetaData))
fmt.Printf("Path to Suspicious Reporting Exe: %s\n", antivirus.PathToReportingExe)
fmt.Printf("Suspicious Reporting Exe Metadata: \t%s\n", edrRecon.FileMetaDataParser(antivirus.ReportingExeMetaData))
fmt.Printf("Suspicious Product State: %d\n", antivirus.ProductState)
fmt.Printf("Matched Keyword: %s\n", antivirus.ScanMatch)
fmt.Println()
}
}

func printProcess(summary []resources.ProcessMetaData) {
for _, process := range summary {
fmt.Printf("Suspicious Process Name: %s\n", process.ProcessName)
Expand Down Expand Up @@ -184,6 +206,7 @@ func init() {
rootCmd.PersistentFlags().BoolVarP(&processes, "processes", "p", processes, "Scan installed processes")
rootCmd.PersistentFlags().BoolVarP(&services, "services", "s", services, "Scan installed services")
rootCmd.PersistentFlags().BoolVarP(&registry, "registry", "r", registry, "Scan installed registry")
rootCmd.PersistentFlags().BoolVarP(&avwmi, "avwmi", "w", avwmi, "Scan installed AntiVirus Providers")
rootCmd.PersistentFlags().BoolVarP(&versionCheck, "version", "v", versionCheck, "Output version information and exit")

rootCmd.AddCommand(versionCmd)
Expand Down
6 changes: 5 additions & 1 deletion pkg/edrRecon/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/FourCoreLabs/EDRHunt/pkg/resources"
)

// GetSystemData collects the parsed list of processes, services, drivers and registry keys to be used for EDR heuristics.
// GetSystemData collects the parsed list of processes, services, drivers, wmi and registry keys to be used for EDR heuristics.
func GetSystemData(ctx context.Context) (resources.SystemData, error) {
var err error
var systemData resources.SystemData
Expand All @@ -32,5 +32,9 @@ func GetSystemData(ctx context.Context) (resources.SystemData, error) {
return systemData, fmt.Errorf("failed to check drivers: %w", err)
}

systemData.AVProviders, err = CheckAVWmiRepo()
if err != nil {
return systemData, fmt.Errorf("failed to check wmi repo: %w", err)
}
return systemData, nil
}
10 changes: 10 additions & 0 deletions pkg/edrRecon/edrRecon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ func TestCheckProcesses(t *testing.T) {
}
}

func TestCheckAVWMI(t *testing.T) {
summary, _ := CheckAVWmiRepo()
for _, av := range summary {
fmt.Println(av)
}
// if err.Error() != "" {
// fmt.Println("error", err)
// }
}

func TestGetFileMetaData(t *testing.T) {
fileMetaData, err := GetFileMetaData(`C:\Users\hardi\AnyDesk.exe`)
if err != nil {
Expand Down
9 changes: 9 additions & 0 deletions pkg/edrRecon/edrdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,15 @@ var EdrList = []string{
"elastic-endpoint.exe",
"elastic-endpoint-driver",
"ElasticEndpoint",
"ecmd.exe",
"ekrn.exe",
"ESET",
"mcupdate.exe",
"ProtectedModuleHost.exe",
"dsa.exe",
"Notifier.exe",
"qualys",
"qualysagent.exe",
}

var ReconList = []string{
Expand Down
113 changes: 113 additions & 0 deletions pkg/edrRecon/wmi_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package edrRecon

import (
"errors"
"fmt"
"strings"
"time"

"github.com/FourCoreLabs/EDRHunt/pkg/resources"
"github.com/hashicorp/go-multierror"
"github.com/yusufpapurcu/wmi"
)

type AntiVirusProduct struct {
DisplayName string
InstanceGuid string
PathToSignedProductExe string
PathToSignedReportingExe string
ProductState uint32
}

type AvResult struct {
AvProduct []AntiVirusProduct
Err error
}

const (
namespace = "root\\SecurityCenter2"
class = "AntiVirusProduct"
wmiErr = "wmi query timed out"
)

func CheckAVWmiRepo() ([]resources.AVWmiMetaData, error) {
var (
avList []AntiVirusProduct
multiErr error
summary []resources.AVWmiMetaData = make([]resources.AVWmiMetaData, 0)
err error
)

avList, err = GetAVwithWMI()
if err != nil {
return summary, err
}
for _, av := range avList {
if av.DisplayName == "" {
continue
}
output, err := AnalyzeAVProduct(av)
if err != nil {
multiErr = multierror.Append(multiErr, err)
continue
}

if len(output.ScanMatch) > 0 {
summary = append(summary, output)
}

}
return summary, multiErr
}

func AnalyzeAVProduct(av AntiVirusProduct) (resources.AVWmiMetaData, error) {
analysis := resources.AVWmiMetaData{
ProductName: av.DisplayName,
ProductGUID: av.InstanceGuid,
PathToProductExe: av.PathToSignedProductExe,
PathToReportingExe: av.PathToSignedReportingExe,
ProductState: av.ProductState,
}

if analysis.PathToProductExe != "" {
analysis.ProductExeMetaData, _ = GetFileMetaData(analysis.PathToProductExe)
}

if analysis.PathToReportingExe != "" {
analysis.ReportingExeMetaData, _ = GetFileMetaData(analysis.PathToReportingExe)
}

for _, edr := range EdrList {
if strings.Contains(
strings.ToLower(fmt.Sprint(analysis)),
strings.ToLower(edr)) {
analysis.ScanMatch = append(analysis.ScanMatch, edr)
}
}

return analysis, nil
}

func GetAVwithWMI() ([]AntiVirusProduct, error) {
result := make(chan AvResult, 1)
go func() {
result <- WMIQuery()
}()
select {
case <-time.After(6 * time.Second):
return nil, errors.New(wmiErr)
case result := <-result:
return result.AvProduct, result.Err
}

}

func WMIQuery() AvResult {
var avResults []AntiVirusProduct
query := wmi.CreateQuery(&avResults, "", class)
err := wmi.QueryNamespace(query, &avResults, namespace)
return AvResult{
AvProduct: avResults,
Err: err,
}
}
12 changes: 12 additions & 0 deletions pkg/resources/edrRecon.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type Recon interface {
CheckServices() ([]ServiceMetaData, error)
CheckDrivers() ([]DriverMetaData, error)
CheckRegistry() (RegistryMetaData, error)
CheckAVWmiRepo() ([]AVWmiMetaData, error)
CheckDirectory() (string, error)
}

Expand Down Expand Up @@ -32,6 +33,17 @@ type ServiceMetaData struct {
ScanMatch []string
}

type AVWmiMetaData struct {
ProductName string
ProductGUID string
PathToProductExe string
ProductExeMetaData FileMetaData
PathToReportingExe string
ReportingExeMetaData FileMetaData
ProductState uint32
ScanMatch []string
}

type ProcessMetaData struct {
ProcessName string
ProcessPath string
Expand Down
3 changes: 3 additions & 0 deletions pkg/resources/scan_edr.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ var (
SentinelOneEDR EDRType = "sentinel_one"
FireEyeEDR EDRType = "fireeye"
ElasticAgentEDR EDRType = "elastic_agent"
QualysEDR EDRType = "qualys"
TrendMicroEDR EDRType = "trend_micro"
ESETEDR EDRType = "eset"
)
13 changes: 9 additions & 4 deletions pkg/resources/systemdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (
)

type SystemData struct {
Processes []ProcessMetaData
Registry RegistryMetaData
Services []ServiceMetaData
Drivers []DriverMetaData
Processes []ProcessMetaData
Registry RegistryMetaData
Services []ServiceMetaData
Drivers []DriverMetaData
AVProviders []AVWmiMetaData
}

// CountMatchesAll collects all the scanned matches of suspicious names and checks for passed keywords in the matches.
Expand All @@ -30,6 +31,10 @@ func (s *SystemData) CountMatchesAll(keywords ...[]string) (int, bool) {
scanMatchList = append(scanMatchList, v.ScanMatch...)
}

for _, v := range s.AVProviders {
scanMatchList = append(scanMatchList, v.ScanMatch...)
}

scanMatchList = append(scanMatchList, s.Registry.ScanMatch...)

var totalLen int
Expand Down
Loading

0 comments on commit 19a27b5

Please sign in to comment.