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 }