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
demal-2.1.0.tar.gz
(13.0 kB
view details)
Built Distribution
demal-2.1.0-py3-none-any.whl
(11.0 kB
view details)
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 |