github.com/iDigitalFlame/xmt@v0.5.4/c2/transform/dns.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 transform contains built-in implementations of the 'c2.Transform' 18 // interface, which can be used to manupilate data that is passed between 19 // Sessions and C2 Servers. 20 package transform 21 22 import ( 23 "io" 24 "strings" 25 "sync" 26 27 "github.com/iDigitalFlame/xmt/util" 28 ) 29 30 const ( 31 dnsMax = 2048 32 dnsSeg = 256 33 ) 34 35 // DNS is the standard DNS Transform alias. This alias uses the default 36 // DNS addresses contained in 'DefaultDomains()' to spoof C2 communications 37 // as valid DNS packets. 38 // 39 // Custom options may be used by creating a new DNS alias or updating the 40 // current alias (string array) with new domains. 41 var DNS = DNSTransform{} 42 43 var packets = sync.Pool{ 44 New: func() interface{} { 45 return new(dnsPacket) 46 }, 47 } 48 var dnsBuiltins struct { 49 e []string 50 sync.Once 51 } 52 53 type dnsPacket struct { 54 _ [0]func() 55 b [4096]byte 56 n int 57 } 58 59 // DNSTransform is a Transform alias that attempts to mask C2 traffic in the 60 // form of DNS request packets. 61 type DNSTransform []string 62 63 func createDefaults() { 64 dnsBuiltins.e = getDefaultDomains() 65 } 66 func (p *dnsPacket) Reset() { 67 p.n = 0 68 } 69 70 // DefaultDomains returns an array of DNS names to be used if the DNS Transform 71 // is empty. 72 func DefaultDomains() []string { 73 dnsBuiltins.Do(createDefaults) 74 return dnsBuiltins.e 75 } 76 func (d *DNSTransform) pick() string { 77 // NOTE(dij): This function has to be on a pointer receiver as it can 78 // be used to set the value to the defaults if needed. 79 if len(*d) == 1 { 80 return (*d)[0] 81 } 82 if len(*d) == 0 { 83 if *d = DefaultDomains(); len(*d) == 1 { 84 return (*d)[0] 85 } 86 } 87 return (*d)[util.FastRandN(len(*d))] 88 } 89 func (p *dnsPacket) Flush(w io.Writer) error { 90 if p.n == 0 { 91 return nil 92 } 93 n, err := w.Write(p.b[:p.n]) 94 if p.n -= n; err != nil { 95 return err 96 } 97 if p.n > 0 { 98 return io.ErrShortWrite 99 } 100 p.n = 0 101 return nil 102 } 103 func (p *dnsPacket) Write(b []byte) (int, error) { 104 n := copy(p.b[p.n:], b) 105 if n == 0 { 106 return 0, io.ErrShortWrite 107 } 108 p.n += n 109 return n, nil 110 } 111 func decodePacket(w io.Writer, b []byte) (int, error) { 112 var ( 113 _ = b[12] 114 q = int(b[4])<<8 | int(b[5]) 115 c = int(b[6])<<8 | int(b[7]) 116 t = int(b[10])<<8 | int(b[11]) 117 s = 12 118 ) 119 for ; q > 0; q-- { 120 for i := 0; i < 64; { 121 if i >= len(b) { 122 return 0, io.ErrUnexpectedEOF 123 } 124 if i = int(b[s]); i == 0 { 125 s++ 126 break 127 } 128 s += i + 1 129 } 130 if s += 4; s >= len(b) { 131 return 0, io.ErrUnexpectedEOF 132 } 133 } 134 for ; c > 0; c-- { 135 if s += 10; s > len(b) { 136 return 0, io.ErrUnexpectedEOF 137 } 138 s += int(b[s])<<8 | int(b[s+1]) + 2 139 } 140 for i := 0; t > 0; t-- { 141 if s+6 >= len(b) { 142 return 0, io.ErrUnexpectedEOF 143 } 144 if b[s] != 0xC0 || b[s+1] != 0x0C || b[s+2] != 00 || b[s+3] != 0xA || b[s+4] != 0 || b[s+5] != 1 { 145 return 0, io.ErrNoProgress 146 } 147 s += 10 148 i = int(b[s])<<8 | int(b[s+1]) 149 s += 2 150 if _, err := w.Write(b[s : s+i]); err != nil { 151 return 0, err 152 } 153 s += i 154 } 155 return s, nil 156 } 157 func decodePackets(w io.Writer, b []byte) (int, error) { 158 if len(b) == 0 { 159 return 0, nil 160 } 161 var i int 162 for i < len(b) { 163 n, err := decodePacket(w, b[i:]) 164 if err != nil { 165 return i, err 166 } 167 i += n 168 } 169 return i, nil 170 } 171 172 // Read satisfies the Transform interface requirements. 173 func (d DNSTransform) Read(b []byte, w io.Writer) error { 174 n, err := decodePackets(w, b) 175 if err != nil { 176 return err 177 } 178 if len(b) != n { 179 return io.ErrUnexpectedEOF 180 } 181 return nil 182 } 183 184 // Write satisfies the Transform interface requirements. 185 func (d DNSTransform) Write(b []byte, w io.Writer) error { 186 n, err := encodePackets(w, b, d.pick()) 187 if err != nil { 188 return err 189 } 190 if len(b) != n { 191 return io.ErrShortWrite 192 } 193 return nil 194 } 195 func encodePackets(w io.Writer, b []byte, s string) (int, error) { 196 if len(b) == 0 { 197 return 0, nil 198 } 199 var ( 200 t = bufs.Get().(*[]byte) 201 p = packets.Get().(*dnsPacket) 202 i, n int 203 err error 204 ) 205 for i < len(b) { 206 if n, err = encodePacket(p, t, b[i:], s); err != nil { 207 break 208 } 209 if err = p.Flush(w); err != nil { 210 break 211 } 212 i += n 213 } 214 p.Reset() 215 bufs.Put(t) 216 packets.Put(p) 217 return i, nil 218 } 219 func encodePacket(w io.Writer, u *[]byte, b []byte, s string) (int, error) { 220 _ = (*u)[511] 221 (*u)[0], (*u)[1] = byte(util.FastRand()), byte(util.FastRand()) 222 c := len(b) 223 if c > dnsMax { 224 c = dnsMax 225 } 226 t := c / dnsSeg 227 if t*dnsSeg < c || t == 0 { 228 t++ 229 } 230 var ( 231 e = strings.Split(s, ".") 232 r = len(e) 233 ) 234 if dnsServer { 235 (*u)[2], (*u)[3], (*u)[4], (*u)[5] = 132, 128, 0, 1 236 (*u)[6], (*u)[7], (*u)[8], (*u)[9] = 0, 1, 0, 0 237 } else { 238 (*u)[2], (*u)[3], (*u)[4], (*u)[5] = 1, 0, 0, 1 239 (*u)[6], (*u)[7], (*u)[8], (*u)[9] = 0, 0, 0, 0 240 } 241 (*u)[10], (*u)[11] = byte(t>>8), byte(t) 242 if y, err := w.Write((*u)[0:12]); err != nil { 243 return 0, err 244 } else if y != 12 { 245 return 0, io.ErrShortWrite 246 } 247 for i := 0; i < r; i++ { 248 if len(e[i]) > 256 { 249 e[i] = e[i][:250] 250 } 251 (*u)[0] = byte(len(e[i])) 252 var ( 253 k = copy((*u)[1:256], e[i]) 254 y, err = w.Write((*u)[0 : k+1]) 255 ) 256 if err != nil { 257 return 0, err 258 } else if y != k+1 { 259 return 0, io.ErrShortWrite 260 } 261 } 262 (*u)[0], (*u)[1], (*u)[2], (*u)[3], (*u)[4] = 0, 0, 1, 0, 1 263 if y, err := w.Write((*u)[0:5]); err != nil { 264 return 0, err 265 } else if y != 5 { 266 return 0, io.ErrShortWrite 267 } 268 if dnsServer { 269 (*u)[0], (*u)[1] = 192, 12 270 (*u)[2], (*u)[3], (*u)[4], (*u)[5], (*u)[6], (*u)[7] = 0, 1, 0, 1, 0, 0 271 (*u)[8], (*u)[9], (*u)[10], (*u)[11] = 3, byte(util.FastRand()), 0, 4 272 (*u)[12], (*u)[13] = byte(util.FastRand()), byte(util.FastRand()) 273 (*u)[14], (*u)[15] = byte(util.FastRand()), byte(util.FastRand()) 274 if y, err := w.Write((*u)[0:16]); err != nil { 275 return 0, err 276 } else if y != 16 { 277 return 0, io.ErrShortWrite 278 } 279 } 280 var i int 281 for x, j := 0, 256; x < t && i < len(b) && i < c; x++ { 282 (*u)[0], (*u)[1] = 192, 12 283 (*u)[2], (*u)[3], (*u)[4], (*u)[5], (*u)[6], (*u)[7] = 0, 10, 0, 1, 0, 0 284 if k := len(b) - i; k < 256 { 285 j = k 286 } 287 (*u)[8], (*u)[9], (*u)[10], (*u)[11] = 0, 0, byte(j>>8), byte(j) 288 if y, err := w.Write((*u)[0:12]); err != nil { 289 return 0, err 290 } else if y != 12 { 291 return 0, io.ErrShortWrite 292 } 293 v, err := w.Write(b[i : i+j]) 294 if err != nil { 295 return 0, err 296 } 297 i += v 298 } 299 return i, nil 300 }