3 minute read

After falling in love with the C&C framework “sliver” , I decided to write something for the first time with Golang, as I was curious to play with his data-structures and start learning the lingo.

As a big fan of gamification, I put togheter a super-shitty, spaghetti code that basically simulates a random APT.

The tool, called ali0ssi in honour on a game of the ancitent Rome, just download the latest version of MITRE framework database and randomize some steps. It can be used to perform war games with the blue team, or just get some random idea when stuck during an assesment.

usage

Usage it’s pretty simple, just run:

./ali0ssi

and follow the instruction on screen.

code

note - TBD: soon on github

package main

import (
	//	"errors"
	"fmt"
        "math/rand"
	"encoding/json"
	"log"
	"strings"
	//"strconv"
	"net/http"
	"io/ioutil"
	"github.com/manifoldco/promptui"
	"github.com/fatih/color"
	"os"
    "strconv"
	"reflect"
)

const baseurl = "https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/index.json"
const banner =  `


 _______  _       _________ _______  _______  _______ _________
(  ___  )( \      \__   __/(  __   )(  ____ \(  ____ \\__   __/
| (   ) || (         ) (   | (  )  || (    \/| (    \/   ) (   
| (___) || |         | |   | | /   || (_____ | (_____    | |   
|  ___  || |         | |   | (/ /) |(_____  )(_____  )   | |   
| (   ) || |         | |   |   / | |      ) |      ) |   | |   
| )   ( || (____/\___) (___|  (__) |/\____) |/\____) |___) (___
|/     \|(_______/\_______/(_______)\_______)\_______)\_______/
                                                               

                "A purple team gamification (shitty) script"

                                                        v.0.1
`

func fetchAttackCollections() map[string]string {
	entries := make(map[string]string)
	var data map[string]interface{}
	resp, err := http.Get(baseurl)
	if err != nil {
		fmt.Println("No response from MITRE's github")
		os.Exit(1)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	//var result AttackCollections
	if err := json.Unmarshal(body, &data); err != nil {
		fmt.Println("Cannot unmarshal JSON from MITRE's github!")
		os.Exit(1)
	}
	parsed := data["collections"].([]interface{})

	for _, value := range parsed {
		data := value.(map[string]interface{})
		latestVersion := data["versions"].([]interface{})[0].(map[string]interface{})["url"]
		entries[data["name"].(string)] = latestVersion.(string)

	}
	return entries
}

func fetchAttackPatterns(url string) map[string][]string {
	entries := make(map[string][]string)
	var data map[string]interface{}
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("No response from MITRE's github")
		os.Exit(1)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	//var result AttackCollections
	if err := json.Unmarshal(body, &data); err != nil {
		fmt.Println("Cannot unmarshal JSON from MITRE's github!")
		os.Exit(1)
	}
    mitre_url := ""
	objects := data["objects"].([]interface{})
	fmt.Println(reflect.TypeOf(objects))
	for _, value := range objects {
		data := value.(map[string]interface{})
		if data["type"] == "attack-pattern" {
			reference, ok := data["external_references"].([]interface{})
			if !ok {
				continue
			}
			for _, v := range reference {
				d := v.(map[string]interface{})
				url, ok := d["url"].(string)
                if (ok) {
				if strings.Contains(url, "attack.mitre.org") {
					mitre_url = d["url"].(string)
				}
            }
			}


				phase, ok := data["kill_chain_phases"].([]interface{})
				if !ok {
					continue
				}
				for _, v := range phase {
					d := v.(map[string]interface{})
					entryName := d["phase_name"].(string)
					entry, ok := entries[entryName]
					name := data["name"].(string)

					if !ok {
						slice := []string{}
						slice = append(slice, name + " - " +  mitre_url)
						entries[entryName] = slice
					} else {
						slice := entry
						slice = append(slice, name + " - " + mitre_url)
						entries[entryName] = slice
					}
				}

				//name := data["name")

			}

		}

		return entries
	}

    func RemoveIndex(s []string, index int) []string {
    return append(s[:index], s[index+1:]...)
    }

	   func getRandomsAttacks(value int, dataset map[string][]string) map[string][]string {

	       data := make(map[string][]string)

           for key := range dataset {
            data[key] = []string{}
            for i := 0; i < value; i++ {
                 randomIndex := rand.Intn(len(dataset[key]))
                 //get element 
                 data[key] = append(data[key], dataset[key][randomIndex])
                 dataset[key] = RemoveIndex(dataset[key], randomIndex)    
            }
            }
	       return data


       }
	func main() {

		//spaghetti code
        color.Magenta(banner)

		log.Printf("Feching fresh datasets from MITRE github..")
		collections := fetchAttackCollections()
		log.Printf("Done, have fun")
    	names := []string{}
		for key := range collections {

			names = append(names, key)
		}
		prompt := promptui.Select{
			Label: "Select ATT&CK",
			Items: names,
		}

		prompt2 := promptui.Select{
			Label: "How many elements for attack phase",
			Items: []string{"1", "2", "3", "4", "5"},
		}

		_, result, err := prompt.Run()

		if err != nil {
			fmt.Printf("Prompt failed %v\n", err)
			return
		}
		fmt.Printf("You choose %q\n", result)
		url := collections[result]
		dataset := fetchAttackPatterns(url)
		_, result, err = prompt2.Run()

		if err != nil {
			fmt.Printf("Prompt failed %v\n", err)
			return
		}

		//fmt.Println(dataset)
        intVar, err := strconv.Atoi(result)
        finalData := getRandomsAttacks(intVar, dataset)
		color.Cyan("== PlayBook ==")
        for key,value := range finalData {
        color.Red(key)
        for i:=0;i<len(value);i++ {
            fmt.Println(value[i])
        }
        }

	}


Categories:

Updated: