GRAPL

 A Graph Platform for

Detection and Response

Twitter: 

@insanitybit

{
  "host_id": "cobrien-mac",
  "parent_pid": 3,
  "pid": 4,
  "image_name": "word.exe",
  "create_time": 600,
}
{
  "host_id": "cobrien-mac",
  "parent_pid": 4,
  "pid": 5,
  "image_name": "payload.exe",
  "create_time": 650,
}

explorer.exe

payload.exe

word.exe

word.exe

payload.exe

word.exe

word.exe

payload.exe

ssh.exe

/secret/file

11.22.34.55

mal.doc

PARSING

SUBGRAPH

GENERATION

IDENTIFICATION

MERGING

ANALYSIS

ENGAGEMENTS

PYRAMID OF PAIN

WE WANT

TO BE HERE!

AT BEST,

WE'RE HERE

MOST ARE HERE

This is not

how we climb

the pyramid of pain:

image_name="procdump"
args = "*-ma*"
args = "*lsass.exe*"

Dropper:

  • Dropper executes
  • Dropper reaches out to network
  • Dropper creates file
  • Dropper executes file

A process that downloads

a payload & executes it.

// Search all processes over 1 hour for dropper-like behavior
search process_executions
| join [
    | search process_executions process_id = $parent_process_id$
]
| join [
    | search network_connections process_id = $parent_process_id$
]
| join [
    | search file_creations creator=$parent_process_id$ 
      AND $file_path$ = image_name 
]
// TODO: Handle pid collisions

"By default, subsearches return a maximum of 10,000 results and have a

maximum runtime of 60 seconds. In large production environments,

it is possible that subsearches [..] will timeout"

"Performing full SQL-style joins in a distributed system like

Elasticsearch is prohibitively expensive." [..]

 

"If you care about query performance, do not use this query."

class DropperAnalyzer(Analyzer):
    def get_queries(self) -> OneOrMany[ProcessQuery]:
        return (
            ProcessQuery().with_bin_file()
            .with_parent(
            	ProcessQuery()
            	.with_external_connections()
                .with_created_files()
            )
         )

    def on_response(self, payload: ProcessView, output: Sender):
    	dropper = payload.get_parent()
        if payload.bin_file.get_file_path() in dropper.get_created_files():
          output.send(
              ExecutionHit(
                  analyzer_name="Dropper",
                  node_view=payload,
                  risk_score=75,
              )
          )

<any process>

<any file>

<external ip>

Process with external network access creates file, executes child from it

<any browser>

Browser Executing Child Process

<any process>

<winrar/7zip/zip>

<any file>

Process Executed From Unpacked Binary

<any process>

created fi​le

executed as

Mitre ATT&CK |  T1204 - User Execution

<any process>

Rare Parent Child Process

<any process>

executed

executed

created file

executed as

connected to

executed

<any process>

Rare Parent LOLBAS Process

<any process>

executed

<binary>

<lolbas path>

<word/reader/etc>

Commonly Target Application with Non-Whitelisted Child Process

<non whitelisted process>

executed

<any process>

Questions?

?

Copy of [GraphThePlanet 5MIN NO NOTES] - Grapl

By Colin

Copy of [GraphThePlanet 5MIN NO NOTES] - Grapl

  • 673