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  }