-
Notifications
You must be signed in to change notification settings - Fork 38
Description
We've had a few reoccurring issues in the framework structure for C2s:
c2
itself is a bit of a misnomer. People regularly need to serve up HTTP content (or WebDAV in a recent exploit from me) withHTTPServeFile
, but those are technically not a C2. In general, I actually think this makes the instantiation and singleton logic a little hard to understand and use.- We did add clean shutdowns in Unify clean shutdown and update C2 channel with session tracking #358, but the actual internals are a bit sloppy and I don't believe that the logic for shutting down is easy to replicate and should generally not be the job of the implementer to guess. I generally just want to clean up this logic. Additionally, shutdowns should probably be wrapped in a
context
these days - We have no clean way to handle non-C2 servers or long running components, nor do we have a way to trigger them conditionally once a C2 type is matched for payload generation.
- Logic for cleanup after post-exploitation is not a first-class citizen.
- Periodic tasks are not common as of now, but having the ability to support them would be cool.
In order to solve these in a bit more of a systemic way I propose creating a component
package that would supersede c2
and then allow for other non-c2 server types and other non-server jobs. This would be implemented with a interface that is wrapped around some sort of job management pool. I had been playing around with using gowl completely in place of our current C2 model and I believe it provides a really nice concept for how we could utilize a similar pool (but a bit more tailor made to live in-framework and to allow for non-initial startups).
I think the gowl
model of using a centralized propagating context
is also probably what we should have done in the first place with our C2 clean shutdown implementation, as it directly supports OS shutdowns and timeouts. It also would allow for an exploit to directly control standup and shutdown of arbitrary components, which could be useful in some conditions.
This would also fully take the place of #219 as a component
could be an arbitrary WebDAV server or wrapped by a simple interface.
At the moment my little mock uses the following types for a Pool:
type (
WorkerName string
ID string
Process interface {
Name() string
ID() ID
CreateFlags()
Start(ctx context.Context) bool
Shutdown() bool
// TODO options?
}
Pool interface {
Start() bool
Register(p ...Process)
Kill(ID)
Status() pool.Status
Workers() []WorkerName
WorkerStatus(name WorkerName) worker.Status
ProcessStats(pid ID) ProcessStats
}
ProcessStats struct {
WorkerName WorkerName
Process Process
Status process.Status
StartedAt time.Time
FinishedAt time.Time
ok bool
}
workerPool struct {
status pool.Status
size int
queue chan Process
wg *sync.WaitGroup
processes *processStatusMap
workers []WorkerName
workersStats *workerStatsMap
controlPanel *controlPanelMap
mutex *sync.Mutex
isClosed bool
}
)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status