From c1393b0051f7ff1b21a0cc53ed74a6dfdadba47f Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Tue, 17 Sep 2024 08:59:11 -0400 Subject: [PATCH 1/9] stub the sigma branch --- SigmaOutput/SigmaOutput.py | 7 +++++++ SigmaOutput/_sample | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 SigmaOutput/SigmaOutput.py create mode 100644 SigmaOutput/_sample diff --git a/SigmaOutput/SigmaOutput.py b/SigmaOutput/SigmaOutput.py new file mode 100644 index 0000000..5a90896 --- /dev/null +++ b/SigmaOutput/SigmaOutput.py @@ -0,0 +1,7 @@ +import yaml +import json +import os + +RMMDIR = './RMMs' +OUTDIR = './ci-output/sigma' + diff --git a/SigmaOutput/_sample b/SigmaOutput/_sample new file mode 100644 index 0000000..7337019 --- /dev/null +++ b/SigmaOutput/_sample @@ -0,0 +1,33 @@ +# https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_remote_access_tools_anydesk.yml + +title: Remote Access Tool - AnyDesk Execution +id: b52e84a3-029e-4529-b09b-71d19dd27e94 +status: test +related: + - id: 065b00ca-5d5c-4557-ac95-64a6d0b64d86 + type: similar +description: | + An adversary may use legitimate desktop support and remote access software, such as Team Viewer, Go2Assist, LogMein, AmmyyAdmin, etc, to establish an interactive command and control channel to target systems within networks. + These services are commonly used as legitimate technical support software, and may be allowed by application control within a target environment. + Remote access tools like VNC, Ammyy, and Teamviewer are used frequently when compared with other legitimate software commonly used by adversaries. (Citation: Symantec Living off the Land) +references: + - https://github.com/redcanaryco/atomic-red-team/blob/f339e7da7d05f6057fdfcdd3742bfcf365fee2a9/atomics/T1219/T1219.md#atomic-test-2---anydesk-files-detected-test-on-windows +author: frack113 +date: 2022-02-11 +modified: 2023-03-05 +tags: + - attack.command-and-control + - attack.t1219 +logsource: + category: process_creation + product: windows +detection: + selection: + - Image|endswith: '\AnyDesk.exe' + - Description: AnyDesk + - Product: AnyDesk + - Company: AnyDesk Software GmbH + condition: selection +falsepositives: + - Legitimate use +level: medium From 6628363082eca711195626a1902f46cf94ed986a Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Tue, 17 Sep 2024 22:06:54 -0400 Subject: [PATCH 2/9] add metadata section to support sigma --- RMMs/AnyDesk.yml | 2 ++ RMMs/Atera.yml | 3 +++ RMMs/FleetDeck.yml | 2 ++ RMMs/GoToMyPC.yml | 2 ++ RMMs/GoToResolve.yml | 2 ++ RMMs/Level.io.yml | 2 ++ RMMs/MeshCentral.yml | 2 ++ RMMs/N-Able.yml | 3 +++ RMMs/NetSupport.yml | 3 +++ RMMs/NinjaRMM.yml | 2 ++ RMMs/NoMachine.yml | 2 ++ RMMs/Pulseway.yml | 2 ++ RMMs/QuickAssist.yml | 2 ++ RMMs/RustDesk.yml | 2 ++ RMMs/ScreenConnect.yml | 3 +++ RMMs/SimpleHelp.yml | 2 ++ RMMs/Splashtop.yml | 2 ++ RMMs/Supremo.yml | 2 ++ RMMs/TacticalRMM.yml | 2 ++ RMMs/Tailscale.yml | 2 ++ RMMs/TeamViewer.yml | 2 ++ RMMs/VSCodeTunnel.yml | 2 ++ RMMs/ZohoAssist.yml | 2 ++ RMMs/ngrok.yml | 3 +++ SigmaOutput/SigmaOutput.py | 51 ++++++++++++++++++++++++++++++++++++++ Validator/_validate_yml.py | 13 ++++++++++ 26 files changed, 117 insertions(+) diff --git a/RMMs/AnyDesk.yml b/RMMs/AnyDesk.yml index 0bbd66c..6b58e6a 100644 --- a/RMMs/AnyDesk.yml +++ b/RMMs/AnyDesk.yml @@ -18,3 +18,5 @@ NetConn: - 50001 - 50002 - 50003 +Meta: + ID: de7dd0b8-b924-4a6a-b433-3428b529119a diff --git a/RMMs/Atera.yml b/RMMs/Atera.yml index 668dd38..9a80843 100644 --- a/RMMs/Atera.yml +++ b/RMMs/Atera.yml @@ -33,3 +33,6 @@ NetConn: - a32dl55qcodech-ats.iot.eu-west-1.amazonaws.com Ports: - 443 +Meta: + ID: 8A1D7AE2-4613-49DB-B7DC-B6BCD88F48C7 + diff --git a/RMMs/FleetDeck.yml b/RMMs/FleetDeck.yml index 8135ab1..df3bb74 100644 --- a/RMMs/FleetDeck.yml +++ b/RMMs/FleetDeck.yml @@ -17,3 +17,5 @@ NetConn: - fleetdm.com Ports: - 443 +Meta: + ID: 64B024F1-C219-497D-98E0-F2DD198B32F3 diff --git a/RMMs/GoToMyPC.yml b/RMMs/GoToMyPC.yml index ddb00a0..cba2ad4 100644 --- a/RMMs/GoToMyPC.yml +++ b/RMMs/GoToMyPC.yml @@ -22,3 +22,5 @@ NetConn: Ports: - 80 - 443 +Meta: + ID: 48D7D443-787B-431C-A528-5BA5C2C75301 diff --git a/RMMs/GoToResolve.yml b/RMMs/GoToResolve.yml index fee264d..e8e8402 100644 --- a/RMMs/GoToResolve.yml +++ b/RMMs/GoToResolve.yml @@ -32,3 +32,5 @@ NetConn: Ports: - 3489 - 443 +Meta: + ID: CCE2B119-8CBB-45CE-AFE8-5BA4D7057E3D diff --git a/RMMs/Level.io.yml b/RMMs/Level.io.yml index 48001c0..f0fe043 100644 --- a/RMMs/Level.io.yml +++ b/RMMs/Level.io.yml @@ -18,3 +18,5 @@ NetConn: - 80 - 3478 - 5349 +Meta: + ID: D3ABD31D-D490-474B-B62A-625906037A6C diff --git a/RMMs/MeshCentral.yml b/RMMs/MeshCentral.yml index 061b691..4ffcd22 100644 --- a/RMMs/MeshCentral.yml +++ b/RMMs/MeshCentral.yml @@ -10,3 +10,5 @@ Executables: NetConn: Domains: Ports: +Meta: + ID: 55EC5C27-A1C8-473F-BE51-4979EC10A7DA diff --git a/RMMs/N-Able.yml b/RMMs/N-Able.yml index 37687a6..93e0587 100644 --- a/RMMs/N-Able.yml +++ b/RMMs/N-Able.yml @@ -36,3 +36,6 @@ NetConn: - 443 - 20 - 21 +Meta: + ID: E37B1F63-542E-46EF-965C-92189AFFEA71 + diff --git a/RMMs/NetSupport.yml b/RMMs/NetSupport.yml index 2a1903e..d487b13 100644 --- a/RMMs/NetSupport.yml +++ b/RMMs/NetSupport.yml @@ -14,3 +14,6 @@ NetConn: Domains: null Ports: - 443 +Meta: + ID: 9B9E5782-E7CC-4525-A933-427030E1725E + diff --git a/RMMs/NinjaRMM.yml b/RMMs/NinjaRMM.yml index faec0aa..9588d5a 100644 --- a/RMMs/NinjaRMM.yml +++ b/RMMs/NinjaRMM.yml @@ -18,3 +18,5 @@ NetConn: Ports: - 80 - 443 +Meta: + ID: 3507D8B2-6C1B-4468-9057-6F17703EE0D4 diff --git a/RMMs/NoMachine.yml b/RMMs/NoMachine.yml index 1eadff5..a8bbb94 100644 --- a/RMMs/NoMachine.yml +++ b/RMMs/NoMachine.yml @@ -77,3 +77,5 @@ NetConn: - 4022 - 4080 - 4443 +Meta: + ID: 68305084-9944-462C-B3BF-ACD17D235EEB diff --git a/RMMs/Pulseway.yml b/RMMs/Pulseway.yml index 1414868..4a1792a 100644 --- a/RMMs/Pulseway.yml +++ b/RMMs/Pulseway.yml @@ -13,3 +13,5 @@ NetConn: - pulseway.com Ports: - 443 +Meta: + ID: 436E7F78-12D3-4379-A6E6-870671F95590 diff --git a/RMMs/QuickAssist.yml b/RMMs/QuickAssist.yml index 8ea5f15..bc3b46a 100644 --- a/RMMs/QuickAssist.yml +++ b/RMMs/QuickAssist.yml @@ -13,3 +13,5 @@ NetConn: - remoteassistanceprodacs* Ports: - 443 +Meta: + ID: 1E21B1CA-DD6D-4505-9018-C9F8C3F40ACC diff --git a/RMMs/RustDesk.yml b/RMMs/RustDesk.yml index 627fe1a..02fec20 100644 --- a/RMMs/RustDesk.yml +++ b/RMMs/RustDesk.yml @@ -18,3 +18,5 @@ NetConn: - 21117 - 21118 - 21119 +Meta: + ID: 074EC611-F61F-4C12-8404-DEADE627F490 diff --git a/RMMs/ScreenConnect.yml b/RMMs/ScreenConnect.yml index 3577360..0162cbf 100644 --- a/RMMs/ScreenConnect.yml +++ b/RMMs/ScreenConnect.yml @@ -22,3 +22,6 @@ NetConn: - 80 - 443 - 8041 +Meta: + ID: 0B1D916C-A462-4BC9-A0D7-B416DF45E8A6 + diff --git a/RMMs/SimpleHelp.yml b/RMMs/SimpleHelp.yml index 1d76923..d9fe3db 100644 --- a/RMMs/SimpleHelp.yml +++ b/RMMs/SimpleHelp.yml @@ -14,3 +14,5 @@ Executables: NetConn: Domains: Ports: +Meta: + ID: E3CF0B3A-E263-41FA-8D14-BF10CA721A06 diff --git a/RMMs/Splashtop.yml b/RMMs/Splashtop.yml index 4eae186..87b0a01 100644 --- a/RMMs/Splashtop.yml +++ b/RMMs/Splashtop.yml @@ -21,3 +21,5 @@ NetConn: - '*.splashtop.eu' Ports: - 443 +Meta: + ID: 532F8698-8390-4A8E-B9E6-DA244BEF341C diff --git a/RMMs/Supremo.yml b/RMMs/Supremo.yml index b2849ea..811323a 100644 --- a/RMMs/Supremo.yml +++ b/RMMs/Supremo.yml @@ -19,3 +19,5 @@ NetConn: - 80 - 443 - 5938 +Meta: + ID: 506CBD0D-4A9C-43D6-AE13-301CA4E0EF49 diff --git a/RMMs/TacticalRMM.yml b/RMMs/TacticalRMM.yml index 5abcbdd..a8739c3 100644 --- a/RMMs/TacticalRMM.yml +++ b/RMMs/TacticalRMM.yml @@ -11,3 +11,5 @@ NetConn: Domains: null Ports: - 443 +Meta: + ID: 47B135F7-39E8-4916-8793-ACC1160EC6E4 diff --git a/RMMs/Tailscale.yml b/RMMs/Tailscale.yml index 44e0776..ef0f537 100644 --- a/RMMs/Tailscale.yml +++ b/RMMs/Tailscale.yml @@ -21,3 +21,5 @@ NetConn: UDPPorts: - 41641 - 3478 +Meta: + ID: F5B51A06-5803-4AAF-AE63-CEAB89238BD7 diff --git a/RMMs/TeamViewer.yml b/RMMs/TeamViewer.yml index adec29b..d0f1234 100644 --- a/RMMs/TeamViewer.yml +++ b/RMMs/TeamViewer.yml @@ -13,3 +13,5 @@ NetConn: - '*.teamviewer.com' Ports: - 5938 +Meta: + ID: 85F6550F-8693-4B68-A081-5DBDA0913014 diff --git a/RMMs/VSCodeTunnel.yml b/RMMs/VSCodeTunnel.yml index e31a359..da1bad3 100644 --- a/RMMs/VSCodeTunnel.yml +++ b/RMMs/VSCodeTunnel.yml @@ -14,3 +14,5 @@ NetConn: - '*.devtunnels.ms' Ports: - 443 +Meta: + ID: 088B75D2-9CC5-4288-A695-2B05B46DCC72 diff --git a/RMMs/ZohoAssist.yml b/RMMs/ZohoAssist.yml index 8385445..191ccf2 100644 --- a/RMMs/ZohoAssist.yml +++ b/RMMs/ZohoAssist.yml @@ -28,3 +28,5 @@ NetConn: Ports: - 80 - 443 +Meta: + ID: 4D4BB5A6-CA27-499A-A6B4-3C7BE4971525 diff --git a/RMMs/ngrok.yml b/RMMs/ngrok.yml index ad94917..5c29752 100644 --- a/RMMs/ngrok.yml +++ b/RMMs/ngrok.yml @@ -16,3 +16,6 @@ NetConn: - 'tunnel.*.ngrok.com' Ports: - 443 +Meta: + ID: 71D2CA02-3905-4DD7-AD0E-C5443F5AC81B + diff --git a/SigmaOutput/SigmaOutput.py b/SigmaOutput/SigmaOutput.py index 5a90896..3c68c80 100644 --- a/SigmaOutput/SigmaOutput.py +++ b/SigmaOutput/SigmaOutput.py @@ -5,3 +5,54 @@ RMMDIR = './RMMs' OUTDIR = './ci-output/sigma' +sigma_template = { + "title": "", + "id": "", # guid + "status": "experimental", + "related": [ + # { + # "id": "065b00ca-5d5c-4557-ac95-64a6d0b64d86", + # "type": "similar" + # } + ], + "description": "", + "references": [ + "" + ], + "author": "RMML Authors", + "date": '', # YYYY-MM-DD + "modified": '', # YYYY-MM-DD + "tags": [ + # "attack.command-and-control", + # "attack.t1219" + ], + "logsource": { + "category": "process_creation", + "product": "windows" + }, + "detection": None, + # { + # "selection": [ + # {"Image|endswith": "\\AnyDesk.exe"}, + # {"Description": "AnyDesk"}, + # {"Product": "AnyDesk"}, + # {"Company": "AnyDesk Software GmbH"}, + # ], + # "condition": "selection", + # }, + "falsepositives": ["Legitimate use"], + "level": "medium", +} + + + +sigmas = [] +for filename in os.listdir(RMMDIR): + file = os.path.join(RMMDIR, filename) + if os.path.isfile(file): + with open(file, 'r') as f: + rmm = yaml.safe_load(f) + rmm_sigma = sigma_template.copy() + rmm_name = file.removeprefix(RMMDIR).removesuffix('.yml').removesuffix('.yaml')[1:] + rmm_sigma['title'] = f'RMML-{rmm_name}' + diff --git a/Validator/_validate_yml.py b/Validator/_validate_yml.py index 5958441..f93dedc 100644 --- a/Validator/_validate_yml.py +++ b/Validator/_validate_yml.py @@ -57,6 +57,7 @@ def check_netconn(r, nc): if not isinstance(p, (int)): ERRORS.append(f'Found a non-int in {r} Ports. Value: {p}') +IDs = set() for filename in os.listdir(RMMDIR): file = os.path.join(RMMDIR, filename) # checking if it is a file @@ -73,6 +74,18 @@ def check_netconn(r, nc): if 'NetConn' not in rmm: print(f'NetConn not defined in {rmm_name}') sys.exit(1) + if 'Meta' not in rmm: + print(f'Meta not defined in {rmm_name}') + sys.exit(1) + # check the IDs + if 'ID' not in rmm['Meta']: + print(f'ID not defined in {rmm_name}, meta section') + sys.exit(1) + if rmm['Meta']['ID'] not in IDs: + IDs.add(rmm['Meta']['ID']) + else: + print(f'DUPLICATE ID defined in {rmm_name}, meta section') + sys.exit(1) check_executables(rmm_name, rmm['Executables']) check_netconn(rmm_name, rmm['NetConn']) if len(ERRORS) == 0: From b3028c064e5f1555f528b3c923fe494414f479c1 Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Tue, 17 Sep 2024 22:07:55 -0400 Subject: [PATCH 3/9] update readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 76ffebe..98758ab 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ NetConn: Ports: - 443 - 8080 +Meta: + ID: ``` Example (from `./RMMs/TeamViewer.yml`): @@ -73,6 +75,8 @@ NetConn: - '*.teamviewer.com' Ports: - 5938 +Meta: + ID: 85F6550F-8693-4B68-A081-5DBDA0913014 ``` A blank to make life easy for creating PRs: @@ -92,4 +96,6 @@ NetConn: - Ports: - 443 +Meta: + ID: ``` From 90ad545468cdff8cce7e89cc49566aee71739f2c Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Thu, 19 Sep 2024 11:02:06 -0400 Subject: [PATCH 4/9] add new fields to RMM and validate them --- RMMs/AnyDesk.yml | 5 +++++ RMMs/Atera.yml | 6 +++++- RMMs/FleetDeck.yml | 5 +++++ RMMs/GoToMyPC.yml | 5 +++++ RMMs/GoToResolve.yml | 5 +++++ RMMs/Level.io.yml | 5 +++++ RMMs/MeshCentral.yml | 5 +++++ RMMs/N-Able.yml | 6 +++++- RMMs/NetSupport.yml | 6 +++++- RMMs/NinjaRMM.yml | 5 +++++ RMMs/NoMachine.yml | 5 +++++ RMMs/Pulseway.yml | 6 ++++++ RMMs/QuickAssist.yml | 5 +++++ RMMs/RustDesk.yml | 5 +++++ RMMs/ScreenConnect.yml | 6 +++++- RMMs/SimpleHelp.yml | 5 +++++ RMMs/Splashtop.yml | 5 +++++ RMMs/Supremo.yml | 5 +++++ RMMs/TacticalRMM.yml | 5 +++++ RMMs/Tailscale.yml | 6 ++++++ RMMs/TeamViewer.yml | 5 +++++ RMMs/VSCodeTunnel.yml | 5 +++++ RMMs/ZohoAssist.yml | 5 +++++ RMMs/ngrok.yml | 6 +++++- Validator/_validate_yml.py | 19 +++++++++++++++++++ 25 files changed, 141 insertions(+), 5 deletions(-) diff --git a/RMMs/AnyDesk.yml b/RMMs/AnyDesk.yml index 6b58e6a..b3bf25a 100644 --- a/RMMs/AnyDesk.yml +++ b/RMMs/AnyDesk.yml @@ -20,3 +20,8 @@ NetConn: - 50003 Meta: ID: de7dd0b8-b924-4a6a-b433-3428b529119a + Description: AnyDesk is a remote desktop tool + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://anydesk.com' diff --git a/RMMs/Atera.yml b/RMMs/Atera.yml index 9a80843..b182d0b 100644 --- a/RMMs/Atera.yml +++ b/RMMs/Atera.yml @@ -35,4 +35,8 @@ NetConn: - 443 Meta: ID: 8A1D7AE2-4613-49DB-B7DC-B6BCD88F48C7 - + Description: Atera is a RMM solution + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://www.atera.com' diff --git a/RMMs/FleetDeck.yml b/RMMs/FleetDeck.yml index df3bb74..0b9418a 100644 --- a/RMMs/FleetDeck.yml +++ b/RMMs/FleetDeck.yml @@ -19,3 +19,8 @@ NetConn: - 443 Meta: ID: 64B024F1-C219-497D-98E0-F2DD198B32F3 + Description: FleetDeck is a remote desktop and remote terminal solution + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://fleetdeck.io' diff --git a/RMMs/GoToMyPC.yml b/RMMs/GoToMyPC.yml index cba2ad4..d92f821 100644 --- a/RMMs/GoToMyPC.yml +++ b/RMMs/GoToMyPC.yml @@ -24,3 +24,8 @@ NetConn: - 443 Meta: ID: 48D7D443-787B-431C-A528-5BA5C2C75301 + Description: GoToMyPC is a remote desktop solution + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://get.gotomypc.com/' diff --git a/RMMs/GoToResolve.yml b/RMMs/GoToResolve.yml index e8e8402..3a886f0 100644 --- a/RMMs/GoToResolve.yml +++ b/RMMs/GoToResolve.yml @@ -34,3 +34,8 @@ NetConn: - 443 Meta: ID: CCE2B119-8CBB-45CE-AFE8-5BA4D7057E3D + Description: GoToResolve is an RMM from goto + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://www.goto.com/it-management/resolve' diff --git a/RMMs/Level.io.yml b/RMMs/Level.io.yml index f0fe043..bc1a3d9 100644 --- a/RMMs/Level.io.yml +++ b/RMMs/Level.io.yml @@ -20,3 +20,8 @@ NetConn: - 5349 Meta: ID: D3ABD31D-D490-474B-B62A-625906037A6C + Description: Level.io is an RMM + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'level.io' diff --git a/RMMs/MeshCentral.yml b/RMMs/MeshCentral.yml index 4ffcd22..5efc9c1 100644 --- a/RMMs/MeshCentral.yml +++ b/RMMs/MeshCentral.yml @@ -12,3 +12,8 @@ NetConn: Ports: Meta: ID: 55EC5C27-A1C8-473F-BE51-4979EC10A7DA + Description: MeshCentral allows for 'full computer management' + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://github.com/Ylianst/MeshCentral' diff --git a/RMMs/N-Able.yml b/RMMs/N-Able.yml index 93e0587..bd2f64e 100644 --- a/RMMs/N-Able.yml +++ b/RMMs/N-Able.yml @@ -38,4 +38,8 @@ NetConn: - 21 Meta: ID: E37B1F63-542E-46EF-965C-92189AFFEA71 - + Description: N-Able is an RMM + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://www.n-able.com/' diff --git a/RMMs/NetSupport.yml b/RMMs/NetSupport.yml index d487b13..86cd7df 100644 --- a/RMMs/NetSupport.yml +++ b/RMMs/NetSupport.yml @@ -16,4 +16,8 @@ NetConn: - 443 Meta: ID: 9B9E5782-E7CC-4525-A933-427030E1725E - + Description: NetSupport is an RMM + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://www.netsupportsoftware.com/' diff --git a/RMMs/NinjaRMM.yml b/RMMs/NinjaRMM.yml index 9588d5a..8acbea8 100644 --- a/RMMs/NinjaRMM.yml +++ b/RMMs/NinjaRMM.yml @@ -20,3 +20,8 @@ NetConn: - 443 Meta: ID: 3507D8B2-6C1B-4468-9057-6F17703EE0D4 + Description: NinjaRMM is a RMM + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://www.ninjaone.com/' diff --git a/RMMs/NoMachine.yml b/RMMs/NoMachine.yml index a8bbb94..dcbf5de 100644 --- a/RMMs/NoMachine.yml +++ b/RMMs/NoMachine.yml @@ -79,3 +79,8 @@ NetConn: - 4443 Meta: ID: 68305084-9944-462C-B3BF-ACD17D235EEB + Description: NoMachine is a remote desktop tool + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'www.nomachine.com' diff --git a/RMMs/Pulseway.yml b/RMMs/Pulseway.yml index 4a1792a..8987f44 100644 --- a/RMMs/Pulseway.yml +++ b/RMMs/Pulseway.yml @@ -15,3 +15,9 @@ NetConn: - 443 Meta: ID: 436E7F78-12D3-4379-A6E6-870671F95590 + Description: Pulseway is a RMM + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://www.pulseway.com/' + \ No newline at end of file diff --git a/RMMs/QuickAssist.yml b/RMMs/QuickAssist.yml index bc3b46a..995a433 100644 --- a/RMMs/QuickAssist.yml +++ b/RMMs/QuickAssist.yml @@ -15,3 +15,8 @@ NetConn: - 443 Meta: ID: 1E21B1CA-DD6D-4505-9018-C9F8C3F40ACC + Description: quickassist is a tool from microsoft that can be used for remote control + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://support.microsoft.com/en-us/windows/install-quick-assist-c17479b7-a49d-4d12-938c-dbfb97c88bca' diff --git a/RMMs/RustDesk.yml b/RMMs/RustDesk.yml index 02fec20..ccf4e73 100644 --- a/RMMs/RustDesk.yml +++ b/RMMs/RustDesk.yml @@ -20,3 +20,8 @@ NetConn: - 21119 Meta: ID: 074EC611-F61F-4C12-8404-DEADE627F490 + Description: RustDesk is an open source remote access tool + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://rustdesk.com/' diff --git a/RMMs/ScreenConnect.yml b/RMMs/ScreenConnect.yml index 0162cbf..6b00c15 100644 --- a/RMMs/ScreenConnect.yml +++ b/RMMs/ScreenConnect.yml @@ -24,4 +24,8 @@ NetConn: - 8041 Meta: ID: 0B1D916C-A462-4BC9-A0D7-B416DF45E8A6 - + Description: Screenconnect is a remote access tool from connectwise + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://screenconnect.connectwise.com/' diff --git a/RMMs/SimpleHelp.yml b/RMMs/SimpleHelp.yml index d9fe3db..2f62e95 100644 --- a/RMMs/SimpleHelp.yml +++ b/RMMs/SimpleHelp.yml @@ -16,3 +16,8 @@ NetConn: Ports: Meta: ID: E3CF0B3A-E263-41FA-8D14-BF10CA721A06 + Description: Simplehelp is a remote access tool + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'simple-help.com' diff --git a/RMMs/Splashtop.yml b/RMMs/Splashtop.yml index 87b0a01..81cc5ab 100644 --- a/RMMs/Splashtop.yml +++ b/RMMs/Splashtop.yml @@ -23,3 +23,8 @@ NetConn: - 443 Meta: ID: 532F8698-8390-4A8E-B9E6-DA244BEF341C + Description: Splashtop is a remote access tool + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'splashtop.com' diff --git a/RMMs/Supremo.yml b/RMMs/Supremo.yml index 811323a..8ade944 100644 --- a/RMMs/Supremo.yml +++ b/RMMs/Supremo.yml @@ -21,3 +21,8 @@ NetConn: - 5938 Meta: ID: 506CBD0D-4A9C-43D6-AE13-301CA4E0EF49 + Description: Supremo is a remote access tool + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'https://www.supremocontrol.com/' diff --git a/RMMs/TacticalRMM.yml b/RMMs/TacticalRMM.yml index a8739c3..a599300 100644 --- a/RMMs/TacticalRMM.yml +++ b/RMMs/TacticalRMM.yml @@ -13,3 +13,8 @@ NetConn: - 443 Meta: ID: 47B135F7-39E8-4916-8793-ACC1160EC6E4 + Description: Tactical RMM is a free RMM utility + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'tacticalrmm.com' diff --git a/RMMs/Tailscale.yml b/RMMs/Tailscale.yml index ef0f537..66228e8 100644 --- a/RMMs/Tailscale.yml +++ b/RMMs/Tailscale.yml @@ -23,3 +23,9 @@ NetConn: - 3478 Meta: ID: F5B51A06-5803-4AAF-AE63-CEAB89238BD7 + Description: Tailscale is a VPN provider + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'tailscale.com' + diff --git a/RMMs/TeamViewer.yml b/RMMs/TeamViewer.yml index d0f1234..64a9904 100644 --- a/RMMs/TeamViewer.yml +++ b/RMMs/TeamViewer.yml @@ -15,3 +15,8 @@ NetConn: - 5938 Meta: ID: 85F6550F-8693-4B68-A081-5DBDA0913014 + Description: Teamviewer allows for remote connections to a machine + Date: 2023-11-18 + Modified: 2023-11-18 + References: + - 'https://www.teamviewer.com/en-us/' diff --git a/RMMs/VSCodeTunnel.yml b/RMMs/VSCodeTunnel.yml index da1bad3..26653c3 100644 --- a/RMMs/VSCodeTunnel.yml +++ b/RMMs/VSCodeTunnel.yml @@ -16,3 +16,8 @@ NetConn: - 443 Meta: ID: 088B75D2-9CC5-4288-A695-2B05B46DCC72 + Description: VSCode tunnels allow connection from remote hosts + Date: 2024-09-10 + Modified: 2024-09-10 + References: + - 'https://code.visualstudio.com/docs/remote/tunnels' diff --git a/RMMs/ZohoAssist.yml b/RMMs/ZohoAssist.yml index 191ccf2..b84a458 100644 --- a/RMMs/ZohoAssist.yml +++ b/RMMs/ZohoAssist.yml @@ -30,3 +30,8 @@ NetConn: - 443 Meta: ID: 4D4BB5A6-CA27-499A-A6B4-3C7BE4971525 + Description: Zoho assist is free remote assistance tool + Date: 2023-11-18 + Modified: 2023-11-18 + References: + - 'https://www.zoho.com/assist/' diff --git a/RMMs/ngrok.yml b/RMMs/ngrok.yml index 5c29752..e154f0d 100644 --- a/RMMs/ngrok.yml +++ b/RMMs/ngrok.yml @@ -18,4 +18,8 @@ NetConn: - 443 Meta: ID: 71D2CA02-3905-4DD7-AD0E-C5443F5AC81B - + Description: ngrok is a tunneling tool + Date: 2024-09-19 + Modified: 2024-09-19 + References: + - 'ngrok.com' diff --git a/Validator/_validate_yml.py b/Validator/_validate_yml.py index f93dedc..64b3b76 100644 --- a/Validator/_validate_yml.py +++ b/Validator/_validate_yml.py @@ -1,6 +1,7 @@ import yaml import sys import os +import datetime RMMDIR = './RMMs' OSES = ['Windows','MacOS','Linux'] @@ -57,6 +58,23 @@ def check_netconn(r, nc): if not isinstance(p, (int)): ERRORS.append(f'Found a non-int in {r} Ports. Value: {p}') +def check_meta(r, meta): + keys = ['ID', 'Description', 'Date', 'Modified', 'References'] + for k in keys: + if k not in meta: + ERRORS.append(f'Missing key {k} in Meta on {r}') + if len(ERRORS) > 0: + return + if not isinstance(meta['Description'], str): + ERRORS.append(f"Description on {r} isn't a string") + if not isinstance(meta['Date'], datetime.date): + ERRORS.append(f"Date on {r} isn't a date") + if not isinstance(meta['Modified'], datetime.date): + ERRORS.append(f"Modified on {r} isn't a date") + if not isinstance(meta['References'], list): + ERRORS.append(f"References on {r} isn't a list") + + IDs = set() for filename in os.listdir(RMMDIR): file = os.path.join(RMMDIR, filename) @@ -88,6 +106,7 @@ def check_netconn(r, nc): sys.exit(1) check_executables(rmm_name, rmm['Executables']) check_netconn(rmm_name, rmm['NetConn']) + check_meta(rmm_name, rmm['Meta']) if len(ERRORS) == 0: sys.exit(0) else: From cf26c584dfd4a6d5c7bab2496676a755ee316a65 Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Thu, 19 Sep 2024 14:56:01 -0400 Subject: [PATCH 5/9] add sigma output for windows exes --- .github/workflows/build_release.yml | 4 ++- SigmaOutput/SigmaOutput.py | 46 +++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml index 5999c8b..5a85016 100644 --- a/.github/workflows/build_release.yml +++ b/.github/workflows/build_release.yml @@ -20,9 +20,11 @@ jobs: - name: execute py script # run file run: | python JsonOutput/JsonOutput.py + python SigmaOutput/SigmaOutput.py + zip -r ./ci-output/sigma_rules.zip ./ci-output/sigma - name: create release run: | - gh release create $TITLE ./ci-output/rmms.json -F CHANGELOG.md + gh release create $TITLE ./ci-output/rmms.json ./ci-output/sigma_rules.zip -F CHANGELOG.md env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TITLE: ${{ github.ref_name }} diff --git a/SigmaOutput/SigmaOutput.py b/SigmaOutput/SigmaOutput.py index 3c68c80..60eed7e 100644 --- a/SigmaOutput/SigmaOutput.py +++ b/SigmaOutput/SigmaOutput.py @@ -4,6 +4,9 @@ RMMDIR = './RMMs' OUTDIR = './ci-output/sigma' +# ensure we don't get references in output yaml +yaml.Dumper.ignore_aliases = lambda *args : True + sigma_template = { "title": "", @@ -23,8 +26,8 @@ "date": '', # YYYY-MM-DD "modified": '', # YYYY-MM-DD "tags": [ - # "attack.command-and-control", - # "attack.t1219" + "attack.command-and-control", + "attack.t1219" ], "logsource": { "category": "process_creation", @@ -47,6 +50,7 @@ sigmas = [] +ids = [] for filename in os.listdir(RMMDIR): file = os.path.join(RMMDIR, filename) if os.path.isfile(file): @@ -55,4 +59,42 @@ rmm_sigma = sigma_template.copy() rmm_name = file.removeprefix(RMMDIR).removesuffix('.yml').removesuffix('.yaml')[1:] rmm_sigma['title'] = f'RMML-{rmm_name}' + rmm_sigma['id'] = rmm['Meta']['ID'] + # add to a list of IDs so that we can add it to all of them when + # we're done building the base ('related') + ids.append(rmm_sigma['id']) + rmm_sigma['description'] = rmm['Meta']['Description'] + rmm_sigma['references'] = rmm['Meta']['References'] + rmm_sigma['date'] = rmm['Meta']['Date'] + rmm_sigma['Modified'] = rmm['Meta']['Modified'] + # no change to tags, maybe later + # right now we're only doing windows, so leave logsource alone + + # detection is next + no_wildcards = [] + has_wildcards = [] + for exe in rmm['Executables']['Windows']: + if '*' not in exe: + no_wildcards.append(exe) + else: + has_wildcards.append(exe) + rmm_sigma['detection'] = {} + rmm_sigma['detection']['selection1'] = {"Image|endswith": no_wildcards} + if len(has_wildcards) == 0: + rmm_sigma['detection']['condition'] = 'selection1' + else: + rmm_sigma['detection']['selection2'] = {"Image": has_wildcards} + rmm_sigma['detection']['condition'] = 'selection1 or selection2' + # no change to falsepositives + # no change to level + # add to the output + sigmas.append(rmm_sigma) + +if not os.path.exists(OUTDIR): + os.mkdir(OUTDIR) +for s in sigmas: + outfile = os.path.join(OUTDIR, s['title']) + outfile = outfile + '.yml' + with open(outfile, 'w') as f: + f.write(yaml.dump(s)) \ No newline at end of file From 763ce734915f8d7bb94b922809212b50701fda05 Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Thu, 19 Sep 2024 14:58:42 -0400 Subject: [PATCH 6/9] updated readme --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 98758ab..4d72f9a 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,11 @@ NetConn: - 8080 Meta: ID: + Description: A description of the RMM/access tool + Date: YYYY-MM-DD + Modified: YYYY-MM-DD + References: + - https://Some_Link.com ``` Example (from `./RMMs/TeamViewer.yml`): @@ -77,6 +82,11 @@ NetConn: - 5938 Meta: ID: 85F6550F-8693-4B68-A081-5DBDA0913014 + Description: Teamviewer allows for remote connections to a machine + Date: 2023-11-18 + Modified: 2023-11-18 + References: + - 'https://www.teamviewer.com/en-us/' ``` A blank to make life easy for creating PRs: @@ -97,5 +107,10 @@ NetConn: Ports: - 443 Meta: - ID: + ID: + Description: + Date: + Modified: + References: + - '' ``` From 430e36e3aa07eb3b0a7c850fc99c4290acea213f Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Fri, 11 Apr 2025 10:27:42 -0400 Subject: [PATCH 7/9] minor updates to chrome and sigma output --- RMMs/ChromeRemoteDesktop.yml | 9 ++++- SigmaOutput/SigmaOutput.py | 78 +++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/RMMs/ChromeRemoteDesktop.yml b/RMMs/ChromeRemoteDesktop.yml index 3d3af92..08902c3 100644 --- a/RMMs/ChromeRemoteDesktop.yml +++ b/RMMs/ChromeRemoteDesktop.yml @@ -35,4 +35,11 @@ NetConn: - remotedesktop.google.com Ports: - 443 - - 3478 \ No newline at end of file + - 3478 +Meta: + ID: 69c85e30-48c9-4072-937a-c467e2511eeb + Description: Chrome Remote Desktop is a chrome plugin that provides remote access + Date: 2024-10-21 + Modified: 2024-10-21 + References: + - 'https://chromewebstore.google.com/detail/chrome-remote-desktop/inomeogfingihgjfjlpeplalcfajhgai?hl=en' \ No newline at end of file diff --git a/SigmaOutput/SigmaOutput.py b/SigmaOutput/SigmaOutput.py index 60eed7e..b91acf3 100644 --- a/SigmaOutput/SigmaOutput.py +++ b/SigmaOutput/SigmaOutput.py @@ -1,6 +1,7 @@ import yaml import json import os +import logging RMMDIR = './RMMs' OUTDIR = './ci-output/sigma' @@ -52,44 +53,47 @@ sigmas = [] ids = [] for filename in os.listdir(RMMDIR): - file = os.path.join(RMMDIR, filename) - if os.path.isfile(file): - with open(file, 'r') as f: - rmm = yaml.safe_load(f) - rmm_sigma = sigma_template.copy() - rmm_name = file.removeprefix(RMMDIR).removesuffix('.yml').removesuffix('.yaml')[1:] - rmm_sigma['title'] = f'RMML-{rmm_name}' - rmm_sigma['id'] = rmm['Meta']['ID'] - # add to a list of IDs so that we can add it to all of them when - # we're done building the base ('related') - ids.append(rmm_sigma['id']) - rmm_sigma['description'] = rmm['Meta']['Description'] - rmm_sigma['references'] = rmm['Meta']['References'] - rmm_sigma['date'] = rmm['Meta']['Date'] - rmm_sigma['Modified'] = rmm['Meta']['Modified'] - # no change to tags, maybe later - # right now we're only doing windows, so leave logsource alone - - # detection is next - no_wildcards = [] - has_wildcards = [] - for exe in rmm['Executables']['Windows']: - if '*' not in exe: - no_wildcards.append(exe) + try: + file = os.path.join(RMMDIR, filename) + if os.path.isfile(file): + with open(file, 'r') as f: + rmm = yaml.safe_load(f) + rmm_sigma = sigma_template.copy() + rmm_name = file.removeprefix(RMMDIR).removesuffix('.yml').removesuffix('.yaml')[1:] + rmm_sigma['title'] = f'RMML-{rmm_name}' + rmm_sigma['id'] = rmm['Meta']['ID'] + # add to a list of IDs so that we can add it to all of them when + # we're done building the base ('related') + ids.append(rmm_sigma['id']) + rmm_sigma['description'] = rmm['Meta']['Description'] + rmm_sigma['references'] = rmm['Meta']['References'] + rmm_sigma['date'] = rmm['Meta']['Date'] + rmm_sigma['modified'] = rmm['Meta']['Modified'] + # no change to tags, maybe later + # right now we're only doing windows, so leave logsource alone + + # detection is next + no_wildcards = [] + has_wildcards = [] + for exe in rmm['Executables']['Windows']: + if '*' not in exe: + no_wildcards.append(exe) + else: + has_wildcards.append(exe) + rmm_sigma['detection'] = {} + rmm_sigma['detection']['selection1'] = {"Image|endswith": no_wildcards} + if len(has_wildcards) == 0: + rmm_sigma['detection']['condition'] = 'selection1' else: - has_wildcards.append(exe) - rmm_sigma['detection'] = {} - rmm_sigma['detection']['selection1'] = {"Image|endswith": no_wildcards} - if len(has_wildcards) == 0: - rmm_sigma['detection']['condition'] = 'selection1' - else: - rmm_sigma['detection']['selection2'] = {"Image": has_wildcards} - rmm_sigma['detection']['condition'] = 'selection1 or selection2' - # no change to falsepositives - # no change to level - - # add to the output - sigmas.append(rmm_sigma) + rmm_sigma['detection']['selection2'] = {"Image": has_wildcards} + rmm_sigma['detection']['condition'] = 'selection1 or selection2' + # no change to falsepositives + # no change to level + + # add to the output + sigmas.append(rmm_sigma) + except Exception as e: + logging.warning(f"Error transforming {filename}. Error: {e}") if not os.path.exists(OUTDIR): os.mkdir(OUTDIR) From 36d3e531285ad2e78fab550d2fdf871697f7963a Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Fri, 11 Apr 2025 10:48:36 -0400 Subject: [PATCH 8/9] add all OS'es to sigma output --- SigmaOutput/SigmaOutput.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/SigmaOutput/SigmaOutput.py b/SigmaOutput/SigmaOutput.py index b91acf3..77f48dd 100644 --- a/SigmaOutput/SigmaOutput.py +++ b/SigmaOutput/SigmaOutput.py @@ -75,11 +75,17 @@ # detection is next no_wildcards = [] has_wildcards = [] - for exe in rmm['Executables']['Windows']: - if '*' not in exe: - no_wildcards.append(exe) - else: - has_wildcards.append(exe) + if filename == 'GoToMyPC.yml': + a = 'foo' + for eos in ['Windows', 'MacOS', 'Linux']: + if eos not in rmm['Executables'] or not rmm['Executables'][eos]: + logging.info('RMM %s doesn\'t have OS: %s', filename, eos) + continue + for exe in rmm['Executables'][eos]: + if '*' not in exe: + no_wildcards.append(exe) + else: + has_wildcards.append(exe) rmm_sigma['detection'] = {} rmm_sigma['detection']['selection1'] = {"Image|endswith": no_wildcards} if len(has_wildcards) == 0: @@ -93,7 +99,7 @@ # add to the output sigmas.append(rmm_sigma) except Exception as e: - logging.warning(f"Error transforming {filename}. Error: {e}") + logging.warning("Error transforming %s. Error: %s", filename, e) if not os.path.exists(OUTDIR): os.mkdir(OUTDIR) From f4ffafe9663d421abf8b076b7dd4ef862ee2a7dd Mon Sep 17 00:00:00 2001 From: Jeremy Mill Date: Fri, 11 Apr 2025 11:14:22 -0400 Subject: [PATCH 9/9] fix supporting all os'es in sigma --- SigmaOutput/SigmaOutput.py | 48 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/SigmaOutput/SigmaOutput.py b/SigmaOutput/SigmaOutput.py index 77f48dd..af9d166 100644 --- a/SigmaOutput/SigmaOutput.py +++ b/SigmaOutput/SigmaOutput.py @@ -2,6 +2,7 @@ import json import os import logging +import copy RMMDIR = './RMMs' OUTDIR = './ci-output/sigma' @@ -48,20 +49,19 @@ "level": "medium", } - - -sigmas = [] -ids = [] -for filename in os.listdir(RMMDIR): +def generate_sigma(eos, filename): try: file = os.path.join(RMMDIR, filename) if os.path.isfile(file): with open(file, 'r') as f: rmm = yaml.safe_load(f) - rmm_sigma = sigma_template.copy() + if eos not in rmm['Executables'] or not rmm['Executables'][eos]: + logging.info('RMM %s doesn\'t have OS: %s', filename, eos) + return + rmm_sigma = copy.deepcopy(sigma_template) rmm_name = file.removeprefix(RMMDIR).removesuffix('.yml').removesuffix('.yaml')[1:] - rmm_sigma['title'] = f'RMML-{rmm_name}' - rmm_sigma['id'] = rmm['Meta']['ID'] + rmm_sigma['title'] = f'RMML-{rmm_name}-{eos}' + rmm_sigma['id'] = f"{rmm['Meta']['ID']}-{eos.lower()}" # add to a list of IDs so that we can add it to all of them when # we're done building the base ('related') ids.append(rmm_sigma['id']) @@ -70,22 +70,15 @@ rmm_sigma['date'] = rmm['Meta']['Date'] rmm_sigma['modified'] = rmm['Meta']['Modified'] # no change to tags, maybe later - # right now we're only doing windows, so leave logsource alone - + rmm_sigma['logsource']['product'] = eos.lower() # detection is next no_wildcards = [] has_wildcards = [] - if filename == 'GoToMyPC.yml': - a = 'foo' - for eos in ['Windows', 'MacOS', 'Linux']: - if eos not in rmm['Executables'] or not rmm['Executables'][eos]: - logging.info('RMM %s doesn\'t have OS: %s', filename, eos) - continue - for exe in rmm['Executables'][eos]: - if '*' not in exe: - no_wildcards.append(exe) - else: - has_wildcards.append(exe) + for exe in rmm['Executables'][eos]: + if '*' not in exe: + no_wildcards.append(exe) + else: + has_wildcards.append(exe) rmm_sigma['detection'] = {} rmm_sigma['detection']['selection1'] = {"Image|endswith": no_wildcards} if len(has_wildcards) == 0: @@ -97,9 +90,20 @@ # no change to level # add to the output - sigmas.append(rmm_sigma) + return rmm_sigma + except Exception as e: logging.warning("Error transforming %s. Error: %s", filename, e) + return None + + +sigmas = [] +ids = [] +for filename in os.listdir(RMMDIR): + for eos in ['Windows', 'MacOS', 'Linux']: + rmm_sigma = generate_sigma(eos, filename) + if rmm_sigma: + sigmas.append(rmm_sigma) if not os.path.exists(OUTDIR): os.mkdir(OUTDIR)