github.com/iDigitalFlame/xmt@v0.5.4/c2/cfg/setting.go (about)

     1  // Copyright (C) 2020 - 2023 iDigitalFlame
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  //
    16  
    17  package cfg
    18  
    19  import (
    20  	"time"
    21  
    22  	"github.com/iDigitalFlame/xmt/data"
    23  )
    24  
    25  // Separator is an entry that can be used to create Groups in Config instances.
    26  //
    27  // It is recommended to use the 'AddGroup' functions instead, but this can
    28  // be used to create more advanced Groupings.
    29  const Separator = cBit(0xFA)
    30  
    31  const (
    32  	invalid = cBit(0)
    33  
    34  	valHost      = cBit(0xA0)
    35  	valSleep     = cBit(0xA1)
    36  	valJitter    = cBit(0xA2)
    37  	valWeight    = cBit(0xA3)
    38  	valKeyPin    = cBit(0xA6)
    39  	valKillDate  = cBit(0xA4)
    40  	valWorkHours = cBit(0xA5)
    41  )
    42  
    43  type cBit byte
    44  type cBytes []byte
    45  
    46  // Setting is an interface that represents a C2 Profile setting in binary form.
    47  //
    48  // This can be used to generate a C2 Profile from binary data or write a Profile
    49  // to a binary stream or JSON payload (if enabled).
    50  type Setting interface {
    51  	id() cBit
    52  	args() []byte
    53  }
    54  
    55  func (c cBit) id() cBit {
    56  	return c
    57  }
    58  func (cBit) args() []byte {
    59  	return nil
    60  }
    61  func (c cBytes) id() cBit {
    62  	if len(c) == 0 {
    63  		return invalid
    64  	}
    65  	return cBit(c[0])
    66  }
    67  
    68  // Weight returns a Setting that will specify the Weight of the generated
    69  // Profile. Weight is taken into account when multiple Profiles are included to
    70  // make a multi-profile.
    71  //
    72  // This option MUST be included in the Group to take effect. Not including this
    73  // will set the value to zero (0). Multiple values in a Group will take
    74  // the last value.
    75  func Weight(w uint) Setting {
    76  	if w == 0 {
    77  		return nil
    78  	}
    79  	return &cBytes{byte(valWeight), byte(w)}
    80  }
    81  
    82  // Jitter returns a Setting that will specify the Jitter setting of the generated
    83  // Profile. Only Jitter values from zero to one-hundred [0-100] are valid.
    84  //
    85  // Other values are ignored and replaced with the default.
    86  func Jitter(n uint) Setting {
    87  	return &cBytes{byte(valJitter), byte(n)}
    88  }
    89  
    90  // Host will return a Setting that will specify a host setting to the profile.
    91  // If empty, this value is ignored.
    92  //
    93  // This may be included multiple times to add multiple Host entries to be used
    94  // in a single Group entry.
    95  func Host(s string) Setting {
    96  	if len(s) == 0 {
    97  		return nil
    98  	}
    99  	n := len(s)
   100  	if n > 0xFFFF {
   101  		n = 0xFFFF
   102  	}
   103  	c := append(cBytes{byte(valHost), byte(n >> 8), byte(n)}, s[:n]...)
   104  	return &c
   105  }
   106  func (c cBytes) args() []byte {
   107  	return c
   108  }
   109  
   110  // KillDate returns a Setting that will specify the KillDate setting of the
   111  // generated Profile. Zero values will clear the set value.
   112  func KillDate(t time.Time) Setting {
   113  	if t.IsZero() {
   114  		return &cBytes{byte(valKillDate), 0, 0, 0, 0, 0, 0, 0, 0}
   115  	}
   116  	v := t.Unix()
   117  	return &cBytes{
   118  		byte(valKillDate), byte(v >> 56), byte(v >> 48), byte(v >> 40), byte(v >> 32),
   119  		byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v),
   120  	}
   121  }
   122  
   123  // Sleep returns a Setting that will specify the Sleep timeout setting of the
   124  // generated Profile. Values of zero and below are ignored.
   125  func Sleep(t time.Duration) Setting {
   126  	if t <= 0 {
   127  		return nil
   128  	}
   129  	return &cBytes{
   130  		byte(valSleep), byte(t >> 56), byte(t >> 48), byte(t >> 40), byte(t >> 32),
   131  		byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t),
   132  	}
   133  }
   134  
   135  // KeyPin returns a Setting that indicates to the client if the Server's PublicKey
   136  // should be trusted. This Setting can be added multiple times to add multiple
   137  // PublicKeys.
   138  //
   139  // This function takes a trusted PublicKey and hashes it to be matched by the
   140  // client.
   141  func KeyPin(k data.PublicKey) Setting {
   142  	if k.Empty() {
   143  		return nil
   144  	}
   145  	h := k.Hash()
   146  	return &cBytes{byte(valKeyPin), byte(h >> 24), byte(h >> 16), byte(h >> 8), byte(h)}
   147  }