Skip to content

Commit 2752e5f

Browse files
committed
updating file hosting processes
1 parent 8a96739 commit 2752e5f

File tree

7 files changed

+99
-25
lines changed

7 files changed

+99
-25
lines changed

CHANGELOG.MD

+8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [3.3.1-rc25] - 2024-11-18
8+
9+
### Changed
10+
11+
- Updated how file hosting works for C2 profiles
12+
- When syncing to Mythic, C2 profiles get updated file hosting based on existing FileHosted tags in Mythic
13+
- When stopping file hosting, Mythic ensures that the C2 profile successfully processed the request before updating the corresponding Tag
14+
715
## [3.3.1-rc24] - 2024-11-18
816

917
### Changed

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.3.1-rc24
1+
3.3.1-rc25

mythic-docker/src/VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.3.1-rc24
1+
3.3.1-rc25

mythic-docker/src/rabbitmq/check_container_status.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ type rabbitmqAPIQuery struct {
108108

109109
func createGraphQLSpectatorAPITokenAndSendOnStartMessage(containerName string) {
110110
operations := []databaseStructs.Operation{}
111-
err := database.DB.Select(&operations, `SELECT id FROM operation WHERE deleted=false and completed=true`)
111+
err := database.DB.Select(&operations, `SELECT id FROM operation WHERE deleted=false and complete=false`)
112112
if err != nil {
113113
logging.LogError(err, "Failed to fetch operations")
114114
return

mythic-docker/src/rabbitmq/recv_c2_sync.go

+47
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/its-a-feature/Mythic/logging"
1010
"github.com/its-a-feature/Mythic/utils"
1111
amqp "github.com/rabbitmq/amqp091-go"
12+
"strings"
1213
)
1314

1415
// C2_SYNC STRUCTS
@@ -311,4 +312,50 @@ func autoStartC2Profile(c2Profile databaseStructs.C2profile) {
311312
}
312313
}
313314
}
315+
autoReHostFiles(c2Profile)
316+
}
317+
318+
func autoReHostFiles(c2Profile databaseStructs.C2profile) {
319+
fileHostedTagType := databaseStructs.TagType{
320+
Name: "FileHosted",
321+
}
322+
err := database.DB.Get(&fileHostedTagType, `SELECT id FROM tagtype WHERE name=$1`, fileHostedTagType.Name)
323+
if err != nil {
324+
logging.LogError(err, "failed to get existing tag types")
325+
return
326+
}
327+
currentTags := []databaseStructs.Tag{}
328+
err = database.DB.Select(&currentTags, `SELECT * FROM tag WHERE tagtype_id=$1`, fileHostedTagType.ID)
329+
if err != nil {
330+
logging.LogError(err, "failed to get existing tags for FileHosted tagtype")
331+
return
332+
}
333+
for _, tag := range currentTags {
334+
dataStruct := tag.Data.StructValue()
335+
for key, _ := range dataStruct {
336+
if strings.HasPrefix(key, fmt.Sprintf("%s; ", c2Profile.Name)) {
337+
newTagMap := dataStruct[key].(map[string]interface{})
338+
c2HostFileResponse, err := RabbitMQConnection.SendC2RPCHostFile(C2HostFileMessage{
339+
Name: newTagMap["c2_profile"].(string),
340+
FileUUID: newTagMap["agent_file_id"].(string),
341+
HostURL: newTagMap["host_url"].(string),
342+
Remove: false,
343+
})
344+
if err != nil {
345+
logging.LogError(err, "failed to send host file message to c2 profile")
346+
go SendAllOperationsMessage(fmt.Sprintf(
347+
"%s failed to start hosting file:\n%s", newTagMap["c2_profile"].(string),
348+
err.Error()), tag.Operation, "", database.MESSAGE_LEVEL_WARNING)
349+
continue
350+
}
351+
if !c2HostFileResponse.Success {
352+
logging.LogError(err, "c2 profile failed to start hosting file")
353+
go SendAllOperationsMessage(fmt.Sprintf(
354+
"%s failed to start hosting file:\n%s", newTagMap["c2_profile"].(string),
355+
c2HostFileResponse.Error), tag.Operation, "", database.MESSAGE_LEVEL_WARNING)
356+
continue
357+
}
358+
}
359+
}
360+
}
314361
}

mythic-docker/src/webserver/controllers/c2profile_host_file_webhook.go

-22
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"github.com/its-a-feature/Mythic/database"
88
databaseStructs "github.com/its-a-feature/Mythic/database/structs"
99
"github.com/its-a-feature/Mythic/logging"
10-
"github.com/its-a-feature/Mythic/rabbitmq"
1110
)
1211

1312
type C2HostFileMessageInput struct {
@@ -84,27 +83,6 @@ func C2HostFileMessageWebhook(c *gin.Context) {
8483
})
8584
return
8685
}
87-
c2HostFileResponse, err := rabbitmq.RabbitMQConnection.SendC2RPCHostFile(rabbitmq.C2HostFileMessage{
88-
Name: c2Profile.Name,
89-
FileUUID: input.Input.FileUUID,
90-
HostURL: input.Input.HostURL,
91-
Remove: input.Input.Remove,
92-
})
93-
if err != nil {
94-
logging.LogError(err, "Failed to send RPC call to c2 profile in C2ProfileHostFileWebhook", "c2_profile", c2Profile.Name)
95-
c.JSON(http.StatusOK, C2HostFileMessageResponse{
96-
Status: "error",
97-
Error: "Failed to send RPC message to c2 profile",
98-
})
99-
return
100-
}
101-
if !c2HostFileResponse.Success {
102-
c.JSON(http.StatusOK, C2HostFileMessageResponse{
103-
Status: "error",
104-
Error: c2HostFileResponse.Error,
105-
})
106-
return
107-
}
10886
go tagFileAs(hostFile.ID, operatorOperation.CurrentOperator.Username, hostFile.OperationID, tagTypeHostedByC2, map[string]interface{}{
10987
c2Profile.Name + "; " + input.Input.HostURL: map[string]interface{}{
11088
"c2_profile": c2Profile.Name,

mythic-docker/src/webserver/controllers/utils.go

+41
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,53 @@ Target Host: %s`,
195195
newTagMap["c2_profile"].(string) == oldTagMap["c2_profile"].(string) &&
196196
(newTagMap["host_url"].(string) == "" ||
197197
newTagMap["host_url"].(string) == oldTagMap["host_url"].(string)) {
198+
c2HostFileResponse, err := rabbitmq.RabbitMQConnection.SendC2RPCHostFile(rabbitmq.C2HostFileMessage{
199+
Name: newTagMap["c2_profile"].(string),
200+
FileUUID: newTagMap["agent_file_id"].(string),
201+
HostURL: newTagMap["host_url"].(string),
202+
Remove: remove,
203+
})
204+
if err != nil {
205+
logging.LogError(err, "failed to send message to container to stop hosting it")
206+
go rabbitmq.SendAllOperationsMessage(fmt.Sprintf(
207+
"%s failed to stop hosting file:\n%s", newTagMap["c2_profile"].(string),
208+
err.Error()), operationID, "", database.MESSAGE_LEVEL_WARNING)
209+
continue
210+
}
211+
if !c2HostFileResponse.Success {
212+
logging.LogError(err, "c2 profile failed to stop hosting file")
213+
go rabbitmq.SendAllOperationsMessage(fmt.Sprintf(
214+
"%s failed to stop hosting file:\n%s", newTagMap["c2_profile"].(string),
215+
c2HostFileResponse.Error), operationID, "", database.MESSAGE_LEVEL_WARNING)
216+
continue
217+
}
198218
delete(updateTagData, key)
199219
}
200220
}
201221
}
202222
} else {
203223
for key, val := range tagData {
224+
newTagMap := val.(map[string]interface{})
225+
c2HostFileResponse, err := rabbitmq.RabbitMQConnection.SendC2RPCHostFile(rabbitmq.C2HostFileMessage{
226+
Name: newTagMap["c2_profile"].(string),
227+
FileUUID: newTagMap["agent_file_id"].(string),
228+
HostURL: newTagMap["host_url"].(string),
229+
Remove: remove,
230+
})
231+
if err != nil {
232+
logging.LogError(err, "failed to send host file message to c2 profile")
233+
go rabbitmq.SendAllOperationsMessage(fmt.Sprintf(
234+
"%s failed to start hosting file:\n%s", newTagMap["c2_profile"].(string),
235+
err.Error()), operationID, "", database.MESSAGE_LEVEL_WARNING)
236+
continue
237+
}
238+
if !c2HostFileResponse.Success {
239+
logging.LogError(err, "c2 profile failed to start hosting file")
240+
go rabbitmq.SendAllOperationsMessage(fmt.Sprintf(
241+
"%s failed to start hosting file:\n%s", newTagMap["c2_profile"].(string),
242+
c2HostFileResponse.Error), operationID, "", database.MESSAGE_LEVEL_WARNING)
243+
continue
244+
}
204245
updateTagData[key] = val
205246
}
206247
}

0 commit comments

Comments
 (0)