@@ -7,17 +7,18 @@ import (
77 "encoding/json"
88 "errors"
99 "fmt"
10- agentstructs "github.com/MythicMeta/MythicContainer/agent_structs"
11- "github.com/MythicMeta/MythicContainer/logging"
12- "github.com/MythicMeta/MythicContainer/mythicrpc"
13- "github.com/MythicMeta/MythicContainer/rabbitmq"
1410 "io"
1511 "net/http"
1612 "os"
1713 "path/filepath"
1814 "slices"
1915 "strings"
2016 "time"
17+
18+ agentstructs "github.com/MythicMeta/MythicContainer/agent_structs"
19+ "github.com/MythicMeta/MythicContainer/logging"
20+ "github.com/MythicMeta/MythicContainer/mythicrpc"
21+ "github.com/MythicMeta/MythicContainer/rabbitmq"
2122)
2223
2324var assemblyVersions = []string {
@@ -514,6 +515,7 @@ func createAssemblyCommand(commandSource collectionSourceCommandData, collection
514515 }
515516 return newCommand
516517}
518+
517519func downloadBofFile (commandSource collectionSourceCommandData , collectionSourceData collectionSource , taskData * agentstructs.PTTaskMessageAllData ) error {
518520 if len (commandSource .customBofFileIDs ) > 0 {
519521 extractPath := filepath .Join ("." , PayloadTypeName , "collections" , collectionSourceData .Name , commandSource .CommandName ) + string (os .PathSeparator )
@@ -568,95 +570,114 @@ func downloadBofFile(commandSource collectionSourceCommandData, collectionSource
568570 }
569571 return nil
570572 }
571- urlPieces := strings .Split (commandSource .RepoURL , "/" )
572- repo := strings .Join (urlPieces [3 :], "/" )
573- url := fmt .Sprintf ("https://api.github.com/repos/%s/releases/latest" , repo )
574- if commandSource .CustomVersion != "" {
575- url = fmt .Sprintf ("https://api.github.com/repos/%s/releases/tags/%s" , repo , commandSource .CustomVersion )
573+
574+ downloadPath := filepath .Join ("." , PayloadTypeName , "collections" , collectionSourceData .Name , commandSource .CommandName + ".tar.gz" )
575+ extractPath := filepath .Join ("." , PayloadTypeName , "collections" , collectionSourceData .Name , commandSource .CommandName ) + string (os .PathSeparator )
576+
577+ err := os .MkdirAll (extractPath , os .ModePerm )
578+ if err != nil {
579+ return err
576580 }
577- req , err := http . NewRequest ( "GET" , url , nil )
581+ downloadFile , err := os . Create ( downloadPath )
578582 if err != nil {
579- logging .LogError (err , "failed to make get request for bof" )
580583 return err
581584 }
582- // Add required headers
583- req .Header .Add ("Accept" , "application/vnd.github.v3.text-match+json" )
584- req .Header .Add ("Accept" , "application/vnd.github.moondragon+json" )
585+ defer downloadFile .Close ()
586+ if taskData != nil {
587+ mythicrpc .SendMythicRPCResponseCreate (mythicrpc.MythicRPCResponseCreateMessage {
588+ TaskID : taskData .Task .ID ,
589+ Response : []byte (fmt .Sprintf ("[*] Downloading %s...\n " , commandSource .Name + ".tar.gz" )),
590+ })
591+ }
592+
593+ tarGzURL := ""
594+ if commandSource .CustomDownloadURL != "" {
595+ logging .LogInfo ("Custom download URL was supplied" )
596+ tarGzURL = commandSource .CustomDownloadURL
597+ } else {
598+ logging .LogInfo ("Using default download procedure, assuming GitHub" )
599+ // calculate GitHub asset download URL
600+ urlPieces := strings .Split (commandSource .RepoURL , "/" )
601+ repo := strings .Join (urlPieces [3 :], "/" )
602+ url := fmt .Sprintf ("https://api.github.com/repos/%s/releases/latest" , repo )
603+ if commandSource .CustomVersion != "" {
604+ url = fmt .Sprintf ("https://api.github.com/repos/%s/releases/tags/%s" , repo , commandSource .CustomVersion )
605+ }
606+ req , err := http .NewRequest ("GET" , url , nil )
607+ if err != nil {
608+ logging .LogError (err , "failed to make get request for bof" )
609+ return err
610+ }
611+ // Add required headers
612+ req .Header .Add ("Accept" , "application/vnd.github.v3.text-match+json" )
613+ req .Header .Add ("Accept" , "application/vnd.github.moondragon+json" )
614+ if taskData != nil {
615+ if _ , ok := taskData .Secrets ["GITHUB_TOKEN" ]; ok {
616+ req .Header .Add ("Authorization" , "Bearer " + taskData .Secrets ["GITHUB_TOKEN" ].(string ))
617+ }
618+ }
619+ body , err := rateLimitLoopFetchURL (req )
620+ if err != nil {
621+ return err
622+ }
623+ result := make (map [string ]interface {})
624+ err = json .Unmarshal (body , & result )
625+ if err != nil {
626+ logging .LogError (err , "failed to unmarshal response body" )
627+ return err
628+ }
629+ if len (result ["assets" ].([]interface {})) == 0 {
630+ return errors .New ("no assets found in GitHub release" )
631+ }
632+ found := false
633+ for _ , asset := range result ["assets" ].([]interface {}) {
634+ if asset .(map [string ]interface {})["name" ].(string ) == commandSource .CommandName + ".tar.gz" {
635+ tarGzURL = asset .(map [string ]interface {})["url" ].(string )
636+ found = true
637+ }
638+ }
639+ if ! found {
640+ return errors .New ("unable to find command name in assets" )
641+ }
642+ }
643+
644+ if tarGzURL == "" {
645+ return errors .New ("no download URL present" )
646+ }
647+
648+ downloadReq , err := http .NewRequest ("GET" , tarGzURL , nil )
649+ if err != nil {
650+ logging .LogError (err , "failed to make new request for bof in released assets" )
651+ return err
652+ }
653+ downloadReq .Header .Add ("Accept" , "application/octet-stream" )
585654 if taskData != nil {
586655 if _ , ok := taskData .Secrets ["GITHUB_TOKEN" ]; ok {
587- req .Header .Add ("Authorization" , "Bearer " + taskData .Secrets ["GITHUB_TOKEN" ].(string ))
656+ downloadReq .Header .Add ("Authorization" , "Bearer " + taskData .Secrets ["GITHUB_TOKEN" ].(string ))
588657 }
589658 }
590- body , err := rateLimitLoopFetchURL (req )
659+ downloadFileBody , err := rateLimitLoopFetchURL (downloadReq )
591660 if err != nil {
661+ os .Remove (downloadPath )
592662 return err
593663 }
594- result := make (map [string ]interface {})
595- err = json .Unmarshal (body , & result )
664+ _ , err = downloadFile .Write (downloadFileBody )
596665 if err != nil {
597- logging . LogError ( err , "failed to unmarshal response body" )
666+ os . Remove ( downloadPath )
598667 return err
599668 }
600- for _ , asset := range result ["assets" ].([]interface {}) {
601- if asset .(map [string ]interface {})["name" ].(string ) == commandSource .CommandName + ".tar.gz" {
602- downloadURL := asset .(map [string ]interface {})["url" ].(string )
603- downloadPath := filepath .Join ("." , PayloadTypeName , "collections" , collectionSourceData .Name , commandSource .CommandName + ".tar.gz" )
604- extractPath := filepath .Join ("." , PayloadTypeName , "collections" , collectionSourceData .Name , commandSource .CommandName ) + string (os .PathSeparator )
605- err = os .MkdirAll (extractPath , os .ModePerm )
606- if err != nil {
607- return err
608- }
609- downloadFile , err := os .Create (downloadPath )
610- if err != nil {
611- return err
612- }
613- if taskData != nil {
614- mythicrpc .SendMythicRPCResponseCreate (mythicrpc.MythicRPCResponseCreateMessage {
615- TaskID : taskData .Task .ID ,
616- Response : []byte (fmt .Sprintf ("[*] Downloading %s...\n " , commandSource .Name + ".tar.gz" )),
617- })
618- }
619-
620- downloadReq , err := http .NewRequest ("GET" , downloadURL , nil )
621- if err != nil {
622- downloadFile .Close ()
623- logging .LogError (err , "failed to make new request for bof in released assets" )
624- return err
625- }
626- downloadReq .Header .Add ("Accept" , "application/octet-stream" )
627- if taskData != nil {
628- if _ , ok := taskData .Secrets ["GITHUB_TOKEN" ]; ok {
629- downloadReq .Header .Add ("Authorization" , "Bearer " + taskData .Secrets ["GITHUB_TOKEN" ].(string ))
630- }
631- }
632- downloadFileBody , err := rateLimitLoopFetchURL (downloadReq )
633- if err != nil {
634- downloadFile .Close ()
635- os .Remove (downloadPath )
636- return err
637- }
638- _ , err = downloadFile .Write (downloadFileBody )
639- if err != nil {
640- downloadFile .Close ()
641- os .Remove (downloadPath )
642- return err
643- }
644- if taskData != nil {
645- mythicrpc .SendMythicRPCResponseCreate (mythicrpc.MythicRPCResponseCreateMessage {
646- TaskID : taskData .Task .ID ,
647- Response : []byte (fmt .Sprintf ("[+] Finished Downloading %s\n " , commandSource .Name + ".tar.gz" )),
648- })
649- }
650- downloadFile .Seek (0 , 0 )
651- err = ExtractTarGz (downloadFile , extractPath )
652- if err != nil {
653- return err
654- }
655- return nil
656- }
657- //logging.LogInfo("asset data", "asset", asset.(map[string]interface{}))
669+ if taskData != nil {
670+ mythicrpc .SendMythicRPCResponseCreate (mythicrpc.MythicRPCResponseCreateMessage {
671+ TaskID : taskData .Task .ID ,
672+ Response : []byte (fmt .Sprintf ("[+] Finished Downloading %s\n " , commandSource .Name + ".tar.gz" )),
673+ })
658674 }
659- return errors .New ("failed to find file in latest assets" )
675+ downloadFile .Seek (0 , 0 )
676+ err = ExtractTarGz (downloadFile , extractPath )
677+ if err != nil {
678+ return err
679+ }
680+ return nil
660681}
661682
662683type bofCommandDefinitionFiles struct {
0 commit comments