MAL (Meta Attack Language) to JSON decoding library and command-line tool.
Project description
demal
MAL (Meta Attack Language) to JSON encoding/decoding library and command-line tool.
Convert from MAL to JSON and, as of version 2, from JSON to MAL. Incompatible with the official tool.
Info
Author: Victor Azzam
License: MIT
Latest version: 2.1.0
Requires: Python 3.8 or later
Batteries included: Tests and examples are provided in this repository.
Usage
Install
~ pip install demal
Or install from source
~ git clone https://github.com/victorazzam/demal
~ cd demal && pip install .
Uninstall
~ pip uninstall demal
General usage
Convert file.mal to file.mal.json
~ demal file.mal
Convert file.mal to file.json
~ demal file.mal file.json
Convert file.json to file.mal (if JSON abides by demal's output)
~ demal file.json file.mal -r
Convert file.mal and print it out
~ demal file.mal -
Read from standard input, convert, and print it out
~ cat file.mal | demal - -
Read from standard input, convert, and write to out.json
~ cat file.mal | demal - out.json
Convert several files and view them interactively
~ cat file1.mal file2.mal | demal - - | less
Display debugging information while converting
~ demal test2.mal debug
parse got: '#id: "tmp"'
parse got: '#version: "0.0.0"'
parse got: 'category C1 {'
parse_category got: '}'
parse got: 'category C2'
parse_header got: 'user info: "info"'
parse_header got: '{'
parse_category got: 'asset A1 {'
parse_asset got: '& At1'
parse_asset got: '| At2'
# output truncated
Use it as a Python module
from demal import MalParser
mal = MalParser('threat-model.mal')
mal.debug = True
mal.parse() # displays debugging messages due to the previous line
# output suppressed
mal.dump(out='parsed.json', pretty=True) # beautify and save to parsed.json
print(mal) # pretty-prints the json object
{
"associations": [
{
"asset_l": "Server",
"asset_l": "Client",
# output truncated
Merge multiple instances by addition (or multiplication or bitwise-or) akin to using include
Check tests/test-lib.py:
from demal import MalParser
print('Parse and combine two test files.')
m1, m2 = MalParser('test1.mal'), MalParser('test2.mal')
m1.parse()
m2.parse()
print('First:', m1['version'])
# First: 1.0.0
print('Second:', m2['version'])
# Second: 0.0.0
m = m1 + m2 # combine category/association items, same as "include"
print('Combined:', m['version'])
# Combined: 0.0.0
print('\nModify variable.')
v = {'version': '1.3.3.7'}
m += v
print('New version:', m['version'])
# New version: 1.3.3.7
print('\nChange inner dictionary data.')
print('Before:', m['categories']['System']['assets']['Host']['attributes']['guessedPassword']['probability'])
# Before: Exponential(0.02)
m['categories']['System']['assets']['Host']['attributes']['guessedPassword']['probability'] = 'abc'
print('After:', m['categories']['System']['assets']['Host']['attributes']['guessedPassword']['probability'])
# After: abc
print('\nList assets with dot notation: category.asset')
print('m1:', list(m1))
print('m2:', list(m2))
print('m (m1+m2):', list(m))
# m1: ['System.Host', 'System.Network', 'System.Password', 'System.User']
# m2: ['C2.A1', 'C2.A2', 'C2.A3', 'C2.A4', 'C2.A5', 'C2.A6', 'C3.A1', 'C4.A1', 'C5.distribution']
# m (m1+m2): ['System.Host', 'System.Network', 'System.Password', 'System.User', 'C2.A1', 'C2.A2', 'C2.A3', 'C2.A4', 'C2.A5', 'C2.A6', 'C3.A1', 'C4.A1', 'C5.distribution']
print('\nConvert JSON back to MAL syntax.')
m.dump_mal(out = sys.stdout)
# Output redacted
Output
Expect the following approximate output structure when converting to JSON:
{
"associations": [
{
"asset_l": "left_asset",
"asset_r": "right_asset",
"field_l": "left_field",
"field_r": "right_field",
"meta": {
"key": "value"
# ...
},
"mult_l": "left_multiplier",
"mult_r": "right_multiplier",
"name": "Association"
} # ...
],
"categories": {
"Category1": {
"assets": {
"Asset1": {
"abstract": false,
"attributes": {
"access": {
"cia": ["C", "A"],
"meta": {},
"probability": "Exponential(0.02)", # etc, or simply null
"tags": [],
"type": "and"
},
"authenticate": {
"cia": null,
"leads_to": {
"0": "access",
"a": "b \\/ c " # result of: let a = ...
},
"meta": {},
"probability": null,
"tags": [
"hidden",
"debug",
"trace"
],
"type": "or"
} # ...
},
"extends": null,
"meta": {}
} # ...
},
"meta": {}
}
},
"id": "org.name.project",
"version": "1.0.0"
}
When converting to MAL the output should closely resemble the original, albeit more concise.
Limitations
-
Multi-line comments should be avoided. - Quotation marks must not be escaped.
- Expects clean spec-compliant code.
Resources
- Example: exampleLang/src/main/mal/exampleLang.mal
- Spec: malcompiler/wiki/MAL-language-specification
- Syntax: mal-documentation/wiki/MAL-Syntax
- Reference: malcompiler-lib/src/main/java/org/mal_lang/compiler/lib/Lexer.java
- Guide: https://nse.digital/...
- MAL author video: https://play.kth.se/...
- Project page: https://www.kth.se/...
- Research paper: https://dl.acm.org/doi/10.1145/3230833.3232799
- Official MAL to JSON converter: mal2json
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file demal-2.1.0.tar.gz.
File metadata
- Download URL: demal-2.1.0.tar.gz
- Upload date:
- Size: 13.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.9.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d064fd8dbec78ee11279dfb0c0eecac8dfca232bf73e8c097130a9b7d021c024
|
|
| MD5 |
e613c6bfc70f563bd8f76a378b0f859b
|
|
| BLAKE2b-256 |
2a1d35884aef732361e9d521dfce95743bd2f971ae252e75dbf4f978e8d4ec6d
|
File details
Details for the file demal-2.1.0-py3-none-any.whl.
File metadata
- Download URL: demal-2.1.0-py3-none-any.whl
- Upload date:
- Size: 11.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.9.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afb8b40b5034cfe6270b1f9985fd8b95a72429ee1f62189d59d4a408bc3c2764
|
|
| MD5 |
7d1af9fa0ea494ae167a695f8e3a3e0c
|
|
| BLAKE2b-256 |
225363ae4f7607f4a3eed65743e42672d594939ced84da04280e2a4c0db86f1d
|