~hrbrmstr/attckr

a651df92ea25a0b347a163906e56cd5e2376841f — hrbrmstr 8 months ago 71c2b1b master
0.2.0
M DESCRIPTION => DESCRIPTION +2 -2
@@ 1,8 1,8 @@
Package: attckr
Type: Package
Title: Analyze Adversary Tactics and Techniques Using the MITRE ATT&CK CTI Corpus
Version: 0.1.0
Date: 2019-07-28
Version: 0.2.0
Date: 2019-10-24
Authors@R: c(
    person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), 
           comment = c(ORCID = "0000-0001-5670-2640"))

M NAMESPACE => NAMESPACE +2 -0
@@ 1,8 1,10 @@
# Generated by roxygen2: do not edit by hand

export(attck_cdf_tactic)
export(attck_map)
export(fct_tactic)
export(read_events)
export(theme_enhance_atkmap)
export(validate_tactics)
export(validate_technique_ids)
export(validate_techniques)

A R/atck-cdf.R => R/atck-cdf.R +60 -0
@@ 0,0 1,60 @@
#' Product an ATT&CK Cumulative Distribution Function by Tactic
#'
#' @param xdf a data frame with `tactic`, `technique` and `value` columns.
#'        If no `value` column exists, then the function will assume you
#'        have passed in individual events and will perform a "count"
#'        summarization before generating the heatmap.
#' @param input,output,matrix if both are not `NULL` then they should be
#'        what [fct_tactic()] takes as parameters. Otherwise, the function
#'        will assume that the `tactic` column is already an ordered factor.
#' @param ... passed on to [ggplot2::geom_label()]
#' @export
attck_cdf_tactic <- function(xdf, input = NULL, output = NULL, matrix = NULL,  ...) {

  cn <- colnames(xdf)
  if (!all(c("tactic", "technique") %in% cn)) {
    stop("'xdf' needs both 'tactic' and 'technique' columns.", call.=FALSE)
  }

  if (!("value" %in% cn)) {
    xdf <- dplyr::count(xdf, tactic, technique, name = "value")
  }

  if (is.null(input) && is.null(output)) {
    if (!is.factor(xdf$tactic)) {
      stop(
        "No 'input'/'output' transformation specified but 'tactic' is not a factor.",
        call.=FALSE
      )
    }
  } else {
    if (sum(c(!is.null(input), !is.null(output), !is.null(matrix))) != 3) {
      stop("Must specify 'input', 'output', and 'matrix' if any one of them is not NULL", call.=FALSE)
    }
    xdf$tactic <- fct_tactic(xdf$tactic, input = input, output = output, matrix = matrix)
  }

  xdf <- dplyr::count(xdf, tactic, wt=value)
  xdf <- dplyr::arrange(xdf, tactic)
  xdf <- dplyr::mutate(xdf, pct = n/sum(n))
  xdf <- dplyr::mutate(xdf, cpct = cumsum(pct))

  gg <- ggplot(xdf, aes(tactic, cpct, group=1))
  gg <- gg + geom_path()
  gg <- gg + geom_label(
    aes(
      label = sprintf("%s\n%s\n%s", scales::comma(n), scales::percent(pct), scales::percent(cpct)),
    ), lineheight = 0.875, ...
  )
  gg <- gg + scale_x_discrete(
    expand = c(0, 0.5), position = "top",
    breaks = levels(xdf$tactic), limits = levels(xdf$tactic)
  )
  gg <- gg + scale_y_continuous(
    expand = c(0, 0.05), limits = c(-0.05, 1.05), label = scales::percent
  )
  gg <- gg + labs(x = NULL, y = NULL)

  gg

}

M R/attck-map.R => R/attck-map.R +5 -2
@@ 61,9 61,12 @@ attck_map <- function(xdf, input = NULL, output = NULL, matrix = NULL,
    aes(
      label = technique,
      color = I(ifelse(value <= dark_value_threshold, dark_lab, light_lab))
    ), ...
    ), lineheight = 0.875, ...
  )
  gg <- gg + scale_x_discrete(
    expand = c(0, 0), position = "top",
    labels = levels(xdf$tactic), limits = levels(xdf$tactic)
  )
  gg <- gg + scale_x_discrete(expand = c(0, 0), position = "top")
  gg <- gg + scale_y_reverse(expand = c(0, 0))

  gg

M R/data-docs.R => R/data-docs.R +8 -8
@@ 3,36 3,36 @@

#' @title Enterprise Attack Taxonomy v2.0
#' @name enterprise_attack
#' @note Id: `bundle--24c77e72-f42e-48e5-9f6c-5ddfc02e8399`
#' @note Last updated: 2019-07-31
#' @note Id: `bundle--83dad14b-ae53-4473-9f95-5ae37c8eaa5d`
#' @note Last updated: 2019-10-24
#' @references <https://github.com/mitre/cti/raw/master/enterprise-attack/enterprise-attack.json>
#' @docType data
NULL

#' @title Mobile Attack Taxonomy v2.0
#' @name mobile_attack
#' @note Id: `bundle--eeb1ff74-2747-4602-96fb-e7b220361101`
#' @note Last updated: 2019-07-31
#' @note Id: `bundle--d22f39d8-4fa0-4557-a925-1d7bbaffaa46`
#' @note Last updated: 2019-10-24
#' @references <https://github.com/mitre/cti/raw/master/mobile-attack/mobile-attack.json>
#' @docType data
NULL

#' @title Pre-Attack Taxonomy v2.0
#' @name pre_attack
#' @note Id: `bundle--0bf62d3b-a5a3-4dae-996d-e990ca6e2f4d`
#' @note Last updated: 2019-07-31
#' @note Id: `bundle--803f51fd-e986-493c-9ab1-0b33b42a4dec`
#' @note Last updated: 2019-10-24
#' @references <https://github.com/mitre/cti/raw/master/pre-attack/pre-attack.json>
#' @docType data
NULL

#' @title Combined ATT&CK Matricies Tactics, Techniques and Technique detail
#' @name tidy_attack
#' @note Last updated: 2019-07-31
#' @note Last updated: 2019-10-24
#' @docType data
NULL

#' @title Tactics factors (generally for sorting & pretty-printing)
#' @name tactics_f
#' @note Last updated: 2019-07-31
#' @note Last updated: 2019-10-24
#' @docType data
NULL
\ No newline at end of file

A R/theme-enhance-atk.R => R/theme-enhance-atk.R +17 -0
@@ 0,0 1,17 @@
#' Remove cruft from ATT&CK heatmaps
#'
#' @export
theme_enhance_atkmap <- function () {
  ret <- theme(panel.grid = element_blank())
  ret <- ret + theme(axis.text.y = element_blank())
  ret <- ret + theme(axis.title = element_blank())
  ret <- ret + theme(axis.title.x = element_blank())
  ret <- ret + theme(axis.title.x.top = element_blank())
  ret <- ret + theme(axis.title.x.bottom = element_blank())
  ret <- ret + theme(axis.title.y = element_blank())
  ret <- ret + theme(axis.title.y.left = element_blank())
  ret <- ret + theme(axis.title.y.right = element_blank())
  ret <- ret + theme(legend.position = "bottom")
  ret <- ret + theme(legend.key.width = unit(3, "lines"))
  ret
}
\ No newline at end of file

M README.md => README.md +23 -18
@@ 7,7 7,9 @@ by](https://img.shields.io/badge/Keybase-Verified-brightgreen.svg)](https://keyb
![Signed commit
%](https://img.shields.io/badge/Signed_Commits-100%25-lightgrey.svg)
[![Linux build
Status](https://travis-ci.org/hrbrmstr/attckr.svg?branch=master)](https://travis-ci.org/hrbrmstr/attckr)  
Status](https://travis-ci.org/hrbrmstr/attckr.svg?branch=master)](https://travis-ci.org/hrbrmstr/attckr)
[![Coverage
Status](https://codecov.io/gh/hrbrmstr/attckr/branch/master/graph/badge.svg)](https://codecov.io/gh/hrbrmstr/attckr)
![Minimal R
Version](https://img.shields.io/badge/R%3E%3D-3.2.0-blue.svg)
![License](https://img.shields.io/badge/License-Apache-blue.svg)


@@ 32,6 34,8 @@ CTI Corpus.

The following functions are implemented:

  - `attck_cdf_tactic`: Product an ATT\&CK Cumulative Distribution
    Function by Tactic
  - `attck_map`: Generate an ATT\&CK heatmap
  - `enterprise_attack`: Enterprise Attack Taxonomy v2.0
  - `fct_tactic`: Make an ordered Tactics factor with optional better


@@ 41,6 45,7 @@ The following functions are implemented:
  - `read_events`: Read in ATT\&CK events from a file
  - `tactics_f`: Tactics factors (generally for sorting &
    pretty-printing)
  - `theme_enhance_atkmap`: Remove cruft from ATT\&CK heatmaps
  - `tidy_attack`: Combined ATT\&CK Matricies Tactics, Techniques and
    Technique detail
  - `validate_tactics`: Validate Tactics strings against MITRE


@@ 87,25 92,25 @@ library(tidyverse)

# current version
packageVersion("attckr")
## [1] '0.1.0'
## [1] '0.2.0'
```

``` r
tidy_attack
## # A tibble: 708 x 5
##    technique          description                                                        id      tactic        matrix   
##    <chr>              <chr>                                                              <chr>   <chr>         <chr>    
##  1 .bash_profile and… "<code>~/.bash_profile</code> and <code>~/.bashrc</code> are exec… T1156   persistence   mitre-at…
##  2 Access Token Mani… "Windows uses access tokens to determine the ownership of a runni… T1134   defense-evas… mitre-at…
##  3 Access Token Mani… "Windows uses access tokens to determine the ownership of a runni… T1134   privilege-es… mitre-at…
##  4 Accessibility Fea… "Windows contains accessibility features that may be launched wit… T1015   persistence   mitre-at…
##  5 Accessibility Fea… "Windows contains accessibility features that may be launched wit… T1015   privilege-es… mitre-at…
##  6 Accessibility Fea… "Windows contains accessibility features that may be launched wit… CAPEC-… persistence   mitre-at…
##  7 Accessibility Fea… "Windows contains accessibility features that may be launched wit… CAPEC-… privilege-es… mitre-at…
##  8 Account Discovery  "Adversaries may attempt to get a listing of local system or doma… T1087   discovery     mitre-at…
##  9 Account Discovery  "Adversaries may attempt to get a listing of local system or doma… CAPEC-… discovery     mitre-at…
## 10 Account Manipulat… Account manipulation may aid adversaries in maintaining access to… T1098   credential-a… mitre-at…
## # … with 698 more rows
## # A tibble: 795 x 5
##    technique          description                                                        id      matrix    tactic       
##    <chr>              <chr>                                                              <chr>   <chr>     <chr>        
##  1 .bash_profile and… "<code>~/.bash_profile</code> and <code>~/.bashrc</code> are shel… T1156   mitre-at… persistence  
##  2 Access Token Mani… "Windows uses access tokens to determine the ownership of a runni… T1134   mitre-at… defense-evas…
##  3 Access Token Mani… "Windows uses access tokens to determine the ownership of a runni… T1134   mitre-at… privilege-es…
##  4 Access Token Mani… "Windows uses access tokens to determine the ownership of a runni… CAPEC-… mitre-at… defense-evas…
##  5 Access Token Mani… "Windows uses access tokens to determine the ownership of a runni… CAPEC-… mitre-at… privilege-es…
##  6 Accessibility Fea… "Windows contains accessibility features that may be launched wit… T1015   mitre-at… persistence  
##  7 Accessibility Fea… "Windows contains accessibility features that may be launched wit… T1015   mitre-at… privilege-es…
##  8 Accessibility Fea… "Windows contains accessibility features that may be launched wit… CAPEC-… mitre-at… persistence  
##  9 Accessibility Fea… "Windows contains accessibility features that may be launched wit… CAPEC-… mitre-at… privilege-es…
## 10 Account Access Re… "Adversaries may interrupt availability of system and network res… T1531   mitre-at… impact       
## # … with 785 more rows
```

``` r


@@ 144,8 149,8 @@ attck_map(

| Lang | \# Files |  (%) | LoC |  (%) | Blank lines |  (%) | \# Lines |  (%) |
| :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: |
| R    |       11 | 0.92 | 245 | 0.91 |          65 | 0.76 |      166 | 0.83 |
| Rmd  |        1 | 0.08 |  24 | 0.09 |          20 | 0.24 |       34 | 0.17 |
| R    |       13 | 0.93 | 304 | 0.93 |          72 | 0.78 |      180 | 0.84 |
| Rmd  |        1 | 0.07 |  24 | 0.07 |          20 | 0.22 |       34 | 0.16 |

## Code of Conduct


M data-raw/enterprise-attack.json.xz => data-raw/enterprise-attack.json.xz +0 -0

M data-raw/mobile-attack.json.xz => data-raw/mobile-attack.json.xz +0 -0

M data-raw/pre-attack.json.xz => data-raw/pre-attack.json.xz +0 -0

M data/enterprise_attack.rda => data/enterprise_attack.rda +0 -0

M data/mobile_attack.rda => data/mobile_attack.rda +0 -0

M data/pre_attack.rda => data/pre_attack.rda +0 -0

M data/tidy_attack.rda => data/tidy_attack.rda +0 -0

A inst/extdat/more-incidents.rds => inst/extdat/more-incidents.rds +0 -0

M inst/extdat/sample-incidents.csv.gz => inst/extdat/sample-incidents.csv.gz +0 -0

A inst/rmarkdown/templates/attcksummary/skeleton/skeleton.Rmd => inst/rmarkdown/templates/attcksummary/skeleton/skeleton.Rmd +312 -0
@@ 0,0 1,312 @@
---
title: "ATT&CK Metrics Overview"
output:
    html_document:
      toc: true
      toc_float: true
      toc_depth: 2
editor_options: 
  chunk_output_type: console
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  echo = FALSE,
  message = FALSE,
  warning = FALSE,
  fig.retina = 2,
  fig.width=900/72, 
  fig.height = 700/72
)
```

```{r libs}
library(hrbrthemes)
library(attckr)
library(tidyverse)
```

```{r atk-data}
xdf <- readRDS(system.file("extdat/more-incidents.rds", package = "attckr"))
xdf <- mutate(xdf, quarter = sprintf("Q%d", lubridate::quarter(containment_ts)))
xdf <- mutate(xdf, month = lubridate::month(containment_ts, abbr=FALSE, label=TRUE))
```

# Dwell Time

```{r dwell-calc}
xdf %>% 
  mutate(delta = as.numeric(containment_ts - first_event_ts, "days")) %>% 
  ungroup() %>% 
  mutate(
    delta_ord = case_when(
      delta < 1 ~ "< 1 day",
      delta < 2 ~ "1 day",
      delta <= 7 ~ "1 week",
      delta <= 14 ~ "2 weeks",
      delta <= 28 ~ "1 month",
      delta <= 46 ~ "2 months",
      delta <= 84 ~ "3 months",
      delta <= 112 ~ ">1 qtr",
      is.na(delta) ~ "Unknown",
      TRUE ~ "> 1 qtr"
    )
  ) %>% 
  mutate(
    delta_ord = factor(delta_ord, levels = c("< 1 day", "1 day", "1 week", "2 weeks", "1 month", "2 months", "3 months", ">1 qtr", "Unknown"))
  ) -> dwell_df
```

## Overall

```{r dwell-time-overall, fig.height = 400/72}
count(dwell_df, delta_ord) %>% 
  mutate(pct = n/sum(n)) %>% 
  ggplot(aes(delta_ord, pct)) +
  geom_col(width=0.55, fill = ft_cols$blue) +
  scale_y_percent(limits = c(0, 1)) +
  labs(
    x = NULL, y = "% Incidents",
    title = "Dwell Time % (Overall)"
  ) +
  theme_ipsum_es(grid="Y") +
  theme(legend.position = "bottom")
```

## by Quarter

```{r dwell-time-quarter, fig.height = 900/72}
count(dwell_df, quarter, delta_ord) %>% 
  group_by(quarter) %>% 
  mutate(pct = n/sum(n)) %>% 
  ungroup() %>% 
  ggplot(aes(delta_ord, pct)) +
  geom_col(width=0.55, fill = ft_cols$blue) +
  scale_x_discrete(
    breaks = c("< 1 day", "1 day", "1 week", "2 weeks", "1 month", "2 months", "3 months", ">1 qtr", "Unknown"), 
    limits = c("< 1 day", "1 day", "1 week", "2 weeks", "1 month", "2 months", "3 months", ">1 qtr", "Unknown")
  ) +
  scale_y_percent(limits = c(0, 1)) +
  facet_wrap(~quarter, ncol=1, scales = "free") +
  labs(
    x = NULL, y = "% Incidents",
    title = "Dwell Time % (by Quarter)"
  ) +
  theme_ipsum_es(grid="Y") +
  theme(legend.position = "bottom")
```

```{r dwell-time-quarter-line}
count(dwell_df, quarter, delta_ord) %>% 
  group_by(quarter) %>% 
  mutate(pct = n/sum(n)) %>% 
  ungroup() %>% 
  arrange(quarter) %>% 
  mutate(quarter = fct_inorder(as.character(quarter)) %>% fct_rev()) %>% 
  complete(quarter, delta_ord) %>% 
  ggplot(aes(quarter, pct, group = delta_ord, color = delta_ord)) +
  geom_line() +
  geom_label(
    aes(
      label = scales::percent(pct),
    ), lineheight = 0.875, family = font_es, size = 4, show.legend = FALSE
  ) +
  scale_x_discrete(position = "top") +
  scale_y_percent(limits = c(-0.05, 1.05)) +
  labs(
    x = NULL, y = NULL, color = 'Dwell Time',
    title = "Dwell Time % (by Quarter)"
  ) +
  theme_ipsum_es(grid="Y") +
  theme(legend.position = "bottom")
```

## by Month

```{r dwell-time-month}
count(dwell_df, month, delta_ord) %>% 
  group_by(month) %>% 
  mutate(pct = n/sum(n)) %>% 
  ungroup() %>% 
  arrange(month) %>% 
  mutate(month = fct_inorder(as.character(month)) %>% fct_rev()) %>% 
  complete(month, delta_ord) %>% 
  ggplot(aes(delta_ord, month)) +
  geom_tile(aes(fill = pct), color = "white", size = 0.5) +
  geom_text(
    aes(
      label = scales::percent(pct),
      color = I(ifelse(pct > 0.1, "white", "black"))
    ), lineheight = 0.875, family = font_es, size = 4
  ) +
  scale_x_discrete(position = "top") +
  scale_fill_viridis_c(
    option = "magma", direction = -1, trans = "identity", label = scales::percent
  ) +
  labs(
    x = NULL, y = NULL, fill = '%',
    title = "Dwell Time % (by Month)"
  ) +
  theme_ipsum_es(grid="Y") +
  theme(legend.position = "bottom") +
  theme(legend.key.width = unit(3, "lines"))
```

```{r dwell-time-month-line}
count(dwell_df, month, delta_ord) %>% 
  group_by(month) %>% 
  mutate(pct = n/sum(n)) %>% 
  ungroup() %>% 
  arrange(month) %>% 
  mutate(month = fct_inorder(as.character(month)) %>% fct_rev()) %>% 
  complete(month, delta_ord) %>% 
  ggplot(aes(month, pct, group = delta_ord, color = delta_ord)) +
  geom_line() +
  geom_label(
    aes(
      label = scales::percent(pct),
    ), lineheight = 0.875, family = font_es, size = 4, show.legend = FALSE
  ) +
  scale_x_discrete(position = "top") +
  scale_y_percent(limits = c(-0.05, 1.05)) +
  labs(
    x = NULL, y = NULL, color = 'Dwell Time',
    title = "Dwell Time % (by Month)"
  ) +
  theme_ipsum_es(grid="Y") +
  theme(legend.position = "bottom")
```

# ATT&CK Heatmap

## Overall

```{r}
unnest(xdf, mitre_attack) %>% 
  select(tactic, technique) %>% 
  attck_map(
    input = "pretty", output = "nl", matrix = "enterprise",
    family = font_es, size = 3
  ) +
  scale_fill_viridis_c(option = "magma") +
  guides(
    fill = guide_colourbar(title.position = "top")
  ) +
  labs(
    fill = "Tactics Raw Count: ",
    title = "Overall ATT&CK Heatmap"
  ) +
  theme_ipsum_es(grid="") +
  theme_enhance_atkmap()
```

## by Quarter

```{r heatmap-by-quarter, fig.width = 1200/72, fig.height = 1200/72}
unnest(xdf, mitre_attack) %>% 
  mutate(quarter = sprintf("Q%d", lubridate::quarter(containment_ts))) %>% 
  count(quarter, tactic, technique) %>% 
  mutate(
    tactic = fct_tactic(tactic, "pretty", "nl", "enterprise"),
    technique = gsub("[[:space:]]+", "\n", technique),
  ) %>% 
  group_by(quarter, tactic) %>% 
  mutate(ids = (n():1)) -> plot_df

plot_df %>% 
  ggplot(aes(tactic, ids)) +
  geom_tile(aes(fill = n), color = "white") +
  geom_text(
    aes(
      label = technique,
      color = I(ifelse(n > 20, "black", "white"))
    ),
    family = font_es, size = 3, lineheight = 0.875
  ) +
  scale_x_discrete(
    breaks = levels(plot_df$tactic), limits = levels(plot_df$tactic),
    position = "top"
  ) +
  scale_y_reverse() +
  scale_fill_viridis_c(option = "magma", trans = "log10", label = scales::comma) +
  facet_wrap(~quarter, ncol = 1, scales = "free") +
  guides(
    fill = guide_colourbar(title.position = "top")
  ) +
  labs(
    fill = "Tactics Raw Count: ",
    title = "Quarterly ATT&CK Heatmap"
  ) +
  theme_ipsum_es(grid="") +
  theme_enhance_atkmap() +
  theme(strip.placement = "outside")
```

# Cumulative ATT&CK Tactics Distributions

## Overall

```{r attck-cdf-all}
unnest(xdf, mitre_attack) %>% 
  count(tactic) %>% 
  mutate(tactic = fct_tactic(tactic, "pretty", "nl")) %>% 
  arrange(tactic) %>% 
  mutate(pct = n/sum(n)) %>% 
  mutate(cpct = cumsum(pct)) -> cdf

ggplot(cdf, aes(tactic, cpct, group=1)) +
  geom_path() +
  geom_label(
    aes(
      label = sprintf("%s\n%s\n%s", scales::comma(n), scales::percent(pct), scales::percent(cpct)),
    ), lineheight = 0.875, family = font_es, size = 3
  ) +
  scale_x_discrete(
    expand = c(0, 0.5), position = "top",
    breaks = levels(cdf$tactic), limits = levels(cdf$tactic)
  ) +
  scale_y_continuous(
    expand = c(0, 0.05), limits = c(-0.05, 1.05), label = scales::percent
  ) +
  labs(
    x = NULL, y = NULL,
    title = "ATT&CK Tactics Cumulative Distribution (All Time)"
  ) +
  theme_ipsum_es(grid="XY")
```

## by Industry

```{r attck-cdf-industry}
unnest(xdf, mitre_attack) %>% 
  count(tactic, industry) %>% 
  mutate(tactic = fct_tactic(tactic, "pretty", "nl")) %>% 
  arrange(tactic) %>% 
  group_by(industry) %>% 
  mutate(pct = n/sum(n)) %>% 
  mutate(cpct = cumsum(pct)) %>% 
  ungroup() -> cdf

ggplot(cdf, aes(tactic, cpct, group=industry)) +
  geom_path(aes(colour = industry)) +
  geom_label(
    aes(
      label = sprintf("%s\n%s\n%s", scales::comma(n), scales::percent(pct), scales::percent(cpct)),
      color = industry, 
    ), lineheight = 0.875, family = font_es, size = 3, show.legend = FALSE
  ) +
  scale_x_discrete(
    expand = c(0, 0.5), position = "top",
    breaks = levels(cdf$tactic), limits = levels(cdf$tactic)
  ) +
  scale_y_continuous(
    expand = c(0, 0.05), limits = c(-0.05, 1.05), label = scales::percent
  ) +
  ggthemes::scale_colour_tableau("Tableau 20") +
  labs(
    x = NULL, y = NULL, colour = NULL,
    title = "ATT&CK Tactics Cumulative Distribution By Industry"
  ) +
  theme_ipsum_es(grid="XY") +
  theme(legend.position = "bottom")
```

A inst/rmarkdown/templates/attcksummary/template.yaml => inst/rmarkdown/templates/attcksummary/template.yaml +5 -0
@@ 0,0 1,5 @@
name: ATT&CK Summary Report
description: >
  Basic ATT&CK Summary Reporting (Customizable)
create_dir: false


A man/attck_cdf_tactic.Rd => man/attck_cdf_tactic.Rd +24 -0
@@ 0,0 1,24 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/atck-cdf.R
\name{attck_cdf_tactic}
\alias{attck_cdf_tactic}
\title{Product an ATT&CK Cumulative Distribution Function by Tactic}
\usage{
attck_cdf_tactic(xdf, input = NULL, output = NULL, matrix = NULL,
  ...)
}
\arguments{
\item{xdf}{a data frame with \code{tactic}, \code{technique} and \code{value} columns.
If no \code{value} column exists, then the function will assume you
have passed in individual events and will perform a "count"
summarization before generating the heatmap.}

\item{input, output, matrix}{if both are not \code{NULL} then they should be
what \code{\link[=fct_tactic]{fct_tactic()}} takes as parameters. Otherwise, the function
will assume that the \code{tactic} column is already an ordered factor.}

\item{...}{passed on to \code{\link[ggplot2:geom_label]{ggplot2::geom_label()}}}
}
\description{
Product an ATT&CK Cumulative Distribution Function by Tactic
}

M man/enterprise_attack.Rd => man/enterprise_attack.Rd +2 -2
@@ 8,9 8,9 @@
Enterprise Attack Taxonomy v2.0
}
\note{
Id: \code{bundle--24c77e72-f42e-48e5-9f6c-5ddfc02e8399}
Id: \code{bundle--83dad14b-ae53-4473-9f95-5ae37c8eaa5d}

Last updated: 2019-07-31
Last updated: 2019-10-24
}
\references{
\url{https://github.com/mitre/cti/raw/master/enterprise-attack/enterprise-attack.json}

M man/figures/README-events-1.png => man/figures/README-events-1.png +0 -0

M man/mobile_attack.Rd => man/mobile_attack.Rd +2 -2
@@ 8,9 8,9 @@
Mobile Attack Taxonomy v2.0
}
\note{
Id: \code{bundle--eeb1ff74-2747-4602-96fb-e7b220361101}
Id: \code{bundle--d22f39d8-4fa0-4557-a925-1d7bbaffaa46}

Last updated: 2019-07-31
Last updated: 2019-10-24
}
\references{
\url{https://github.com/mitre/cti/raw/master/mobile-attack/mobile-attack.json}

M man/pre_attack.Rd => man/pre_attack.Rd +2 -2
@@ 8,9 8,9 @@
Pre-Attack Taxonomy v2.0
}
\note{
Id: \code{bundle--0bf62d3b-a5a3-4dae-996d-e990ca6e2f4d}
Id: \code{bundle--803f51fd-e986-493c-9ab1-0b33b42a4dec}

Last updated: 2019-07-31
Last updated: 2019-10-24
}
\references{
\url{https://github.com/mitre/cti/raw/master/pre-attack/pre-attack.json}

M man/tactics_f.Rd => man/tactics_f.Rd +1 -1
@@ 8,5 8,5 @@
Tactics factors (generally for sorting & pretty-printing)
}
\note{
Last updated: 2019-07-31
Last updated: 2019-10-24
}

A man/theme_enhance_atkmap.Rd => man/theme_enhance_atkmap.Rd +11 -0
@@ 0,0 1,11 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/theme-enhance-atk.R
\name{theme_enhance_atkmap}
\alias{theme_enhance_atkmap}
\title{Remove cruft from ATT&CK heatmaps}
\usage{
theme_enhance_atkmap()
}
\description{
Remove cruft from ATT&CK heatmaps
}

M man/tidy_attack.Rd => man/tidy_attack.Rd +1 -1
@@ 8,5 8,5 @@
Combined ATT&CK Matricies Tactics, Techniques and Technique detail
}
\note{
Last updated: 2019-07-31
Last updated: 2019-10-24
}

M tools/update-framework.R => tools/update-framework.R +3 -4
@@ 67,7 67,6 @@ mobile_attack[["objects"]] <- tibble::as_tibble(mobile_attack[["objects"]])

# Make Pre matrix ---------------------------------------------------------


jsonlite::fromJSON(
  here::here("data-raw/pre-attack.json.xz")
) -> pre_attack


@@ 86,7 85,7 @@ bind_rows(
      id = discard(enterprise_attack$objects$external_references[[.x]]$external_id, is.na) %||% NA_character_,
      phs = enterprise_attack$objects$kill_chain_phases[.x]
    ) %>%
      unnest()
      unnest(phs)
  }),
  map_df(1:nrow(mobile_attack$objects), ~{
    if (is.na(mobile_attack$objects$name[[.x]])) return(NULL)


@@ 97,7 96,7 @@ bind_rows(
      id = discard(mobile_attack$objects$external_references[[.x]]$external_id, is.na) %||% NA_character_,
      phs = mobile_attack$objects$kill_chain_phases[.x]
    ) %>%
      unnest()
      unnest(phs)
  }),
  map_df(1:nrow(pre_attack$objects), ~{
    if (is.na(pre_attack$objects$name[[.x]])) return(NULL)


@@ 108,7 107,7 @@ bind_rows(
      id = discard(pre_attack$objects$external_references[[.x]]$external_id, is.na) %||% NA_character_,
      phs = pre_attack$objects$kill_chain_phases[.x]
    ) %>%
      unnest()
      unnest(phs)
  })
) %>%
  rename(tactic = phase_name, matrix = kill_chain_name) %>%