Skip to main content

mwdb-iocextract

Python 3 library useful for getting structured IOC data from mwdb configs.

Why?

Warning: this project is only relevant to mwdb and malduck users.

Malduck configs (like the ones in mwdb) are usually unstructured (they're just JSONs with some additional metadata). On the other hand, automated processing often requires structured data.

For example, URL processing and extraction is a common use case for analysts. Sadly, every module stores them a bit differently (and due to backward compatibility we're not ready to change that).

For example, compare how we store URLs from ISFB:

"domains": [
    {
        "cnc": "http://fantaniz.ru"
    },
    {
        "cnc": "http://snezhkaie.ru"
    }
]

Lokibot:

"urls": [
    {
        "url": "http://hockvvee.com/chief4/five/fre.php"
    },
    {
        "url": "kbfvzoboss.bid/alien/fre.php"
    },
    {
        "url": "alphastand.top/alien/fre.php"
    }
]

And mirai:

"cncs": [
    {
        "host": "107.160.244.5",
        "port": 1024
    }
]

With mwdb-iocextract you can handle all these (and dozens more) config types in the same way:

from mwdb_iocextract import parse

config_family = "mirai"
config_data = {
    "cncs": [
        {
            "host": "107.160.244.5",
            "port": 1024
        }
    ],
    "table_key": "0xdedefbaf",
    "variant": "OWARI",
    "type": "mirai"
}

iocs = parse(config_family, config_data)
print(iocs.prettyprint())
> python test.py
NetLoc 107.160.244.5:1024

See below for more usage examples.

Install

$ pip install mwdb-iocextract

You can find the newest version here:

https://pypi.org/project/mwdb-iocextract/

How does it work

Most configs can be parsed without any change to this library. Standard keys, like "urls", are automatically recognised and parsed correctly.

Plurality of the key name does not matter. When value is a list, all elements are added separately. For example both of these are equivalent:

{
    "urls": "127.0.0.1"
}
{
    "url": ["127.0.0.1"]
}

Right now this library supports:

Network Locations

"Network Locations" can be IP, domain, URL, etc. There are many available formats:

    "hosts": [
        "127.0.0.1",  # format 1 - IP
        "http://malware.com",  # format 2 - URL
        { "cnc": "http://malware.com:1337" },  # format 3 - URL in a dict.
        # Allowed keys: "cnc", "url", "ip", "domain", "host" (all handled in the same way)
        { "cnc": "malware.com", "port": 1337 },  # format 4 - domain/port pair

        # NOT allowed: url + port
        # { "cnc": "http://malware.com:1337", "port": 1337 },

Config keys: urls, c2, ips, domains, url, cnc, cncs, hosts, host, cncurl.

Passwords

Passwords hardcoded in malware. Plain text.

Config keys: password.

Mutexes

Config keys: mtx, mutex. Plain text.

Emails

Emails used by malware and hardcoded in the source. Plain text.

Config keys: email, emails.

Ransom messages

HTML or txt ransom messages hardcoded in the source. Plain text.

Config keys: ransommessage.

RSA keys

RSA public or private keys hardcoded in the binary.

There are two supported formats:

  • plaintext ("-----BEGIN PUBLIC KEY-----...")
  • parsed - a dict with "n", "e", and (optionall) "d" keys.

Parsed format is more deterministic and recommended for your modules, but you can use both.

Config keys: publickey, rsapub, rsakey, pubkey, privkey.

AES keys

AES keys hardcoded in the binary. Plaintext.

Config keys: aeskey.

XOR keys

XOR keys hardcoded in the binary. Plaintext.

Config keys: xorkey.

Serpent keys

XOR keys hardcoded in the binary. Plaintext.

Config keys: serpentkey.

Encryption keys

Other key types found in the malware. Extracted as a key of type "unknown". Plaintext.

Config keys: encryptionkey, key, keys.

Dropped files

Paths or filenames of files dropped by the malware. Plaintext.

Config keys: drop_name.

Contributing

If you want to extend this library or add support for more modules, feel free to contribute to this repository. We're only interested in modules at least partially publicly accessible. So mwcfg.info module support is OK to merge, but your in-house internal TLP:RED modules - probably no.

Usage

Scan mwdb

How to download config from mwdb and parse it:

from mwdb_iocextract import parse
from mwdblib import Malwarecage


def main():
    # See also https://mwdblib.readthedocs.io/en/latest/index.html
    mwdb = Malwarecage()
    mwdb.login("msm", "my_secret_password")

    for cfg in mwdb.recent_configs():
        if cfg.type != "static":
            # This library only works with configs of type "static" 
            # (default mwdb config type).
            continue
        iocs = parse(cfg.family, cfg.cfg)
        print(iocs.prettyprint())  # convert all IoCs to string


if __name__ == "__main__":
    main()

Working with IOCs

The result of a parse() is a IocCollection object. You can use it like a normal Python object, for example:

iocs = parse(cfg.family, cfg.cfg)

for rsa_key in iocs.rsa_keys:
    e = rsa_key.e  # get e
    n = rsa_key.n  # get n

for netloc in iocs.network_locations:
    ip = netloc.ip  # get IP if known
    domain = netloc.domain  # get domain if known
    host = netloc.host  # get domain if known, otherwise IP
    port = netloc.port  # get port if known
    loctype = netloc.location_type  # get type (usually CNC)
    url = netloc.url  # get host + port + path

for key_type, key_data in iocs.keys:
    # key_type - for example "rc4"
    # key_data - hexencoded bytes, for example "6123541243"
    pass

iocs.passwords  # passwords or similar data found in the config
iocs.mutexes  # mutex names used by malware
iocs.dropped_filenames  # filenames dropped on the disk
iocs.emails  # emails used by malware

MISP integration

You can convert IocCollection to a MISP object:

def upload_to_misp(family, config):
    iocs = parse(family, config)

    if not iocs:
        # Nothing actionable found - skip the config
        return

    # Be careful not to upload duplicated events.
    # We use uuid5s generated from mwdb dhash as unique deterministic UUIDs.
    event = MISPEvent()
    event.add_tag(f"mwdb:family:{family}")
    event.info = f"Malware configuration ({family})"

    for o in iocs.to_misp():
        event.add_object(o)

    misp = ExpandedPyMISP(MISP_URL, MISP_KEY, MISP_VERIFYCERT)
    misp.add_event(event)

Metadata

Release files for mwdb-iocextract 1.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mwdb-iocextract 1.2.2
File Size Uploaded
mwdb-iocextract-1.2.2.tar.gz 11.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mwdb-iocextract 1.2.2
File Interpreter ABI Platform
mwdb_iocextract-1.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 24.1 kB

Release files / mwdb-iocextract-1.2.2.tar.gz

Download URL mwdb-iocextract-1.2.2.tar.gz
Size 11.2 kB
Tags Source
SHA-256 checksum
How to use checksums
65b84b25c3c485a0b5761ceece16502c8c536bee9d17d68625efc27f3549986f
BLAKE2b-256 checksum
How to use checksums
3a796ea77830b147f0da0048d9cca5c7555dfba8091f80afaf2efb9a772c589d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.10.12

Release files / mwdb_iocextract-1.2.2-py3-none-any.whl

Download URL mwdb_iocextract-1.2.2-py3-none-any.whl
Size 13.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e969a3b6f8ca16634bc5510475ee1fce42f7696125049f3da4b473d5d2290276
BLAKE2b-256 checksum
How to use checksums
ae91e0e56e76129a86a63fe68b44cd94b27d1bf807a31252f440da77e4ec8db1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.10.12

Release history Release notifications | RSS feed

This release

1.2.2 This release

2 release files

1.2.1

1 release file

1.2.0

1 release file

1.1.4

1 release file

1.1.3

2 release files

1.1.2

1 release file

1.1.1

1 release file

1.1.0

1 release file

1.0.4

1 release file

1.0.3

1 release file

1.0.2

1 release file

1.0.1

1 release file

1.0.0

1 release file

0.0.5

1 release file

0.0.4

1 release file

0.0.3

3 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page