github.com/iDigitalFlame/xmt@v0.5.4/c2/transform/base64.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 18 19 import ( 20 "encoding/base64" 21 "io" 22 "sync" 23 24 "github.com/iDigitalFlame/xmt/util/bugtrack" 25 ) 26 27 // Base64 is a transform that auto converts the data to and from Base64 28 // encoding. This instance does not include any shifting. 29 const Base64 = B64(0) 30 31 const bufMax = 2 << 14 32 33 var bufs = sync.Pool{ 34 New: func() interface{} { 35 b := make([]byte, 512, bufMax) 36 _ = b[511] // BCE 37 return &b 38 }, 39 } 40 41 // B64 is the underlying type for the Base64 Transform. This Transform encodes 42 // data into a Base64 string before the final write to the output. 43 type B64 byte 44 45 // B64Shift returns a Base64 Transform that also shifts the bytes by the 46 // specified amount before writes and after reads. This is useful for evading 47 // detection by avoiding commonly flagged Base64 values. 48 func B64Shift(n int) B64 { 49 return B64(n) 50 } 51 52 // Read satisfies the Transform interface requirements. 53 func (b B64) Read(p []byte, w io.Writer) error { 54 n := base64.StdEncoding.DecodedLen(len(p)) 55 if n > bufMax { 56 if bugtrack.Enabled { 57 bugtrack.Track("transform.(B64).Read(): Creating non-heap buffer, n=%d, bufMax=%d", n, bufMax) 58 } 59 var ( 60 o = make([]byte, n) 61 err = decodeShift(w, byte(b), p, &o) 62 ) 63 o = nil 64 return err 65 } 66 o := bufs.Get().(*[]byte) 67 if len(*o) < n { 68 if bugtrack.Enabled { 69 bugtrack.Track("transform.(B64).Read(): Increasing heap buffer size len(*o)=%d, n=%d", len(*o), n) 70 } 71 *o = append(*o, make([]byte, n-len(*o))...) 72 } 73 err := decodeShift(w, byte(b), p, o) 74 bufs.Put(o) 75 return err 76 } 77 78 // Write satisfies the Transform interface requirements. 79 func (b B64) Write(p []byte, w io.Writer) error { 80 if b != 0 { 81 for i := range p { 82 p[i] += byte(b) 83 } 84 } 85 var ( 86 e = base64.NewEncoder(base64.StdEncoding, w) 87 c, err = e.Write(p) 88 ) 89 if e.Close(); c != len(p) { 90 return io.ErrShortWrite 91 } 92 e = nil 93 return err 94 } 95 func decodeShift(w io.Writer, b byte, p []byte, o *[]byte) error { 96 n, err := base64.StdEncoding.Decode(*o, p) 97 if err != nil { 98 return err 99 } 100 if b != 0 { 101 for x := 0; x < n; x++ { 102 (*o)[x] -= b 103 } 104 } 105 c, err := w.Write((*o)[:n]) 106 if err != nil { 107 return err 108 } 109 if c != n { 110 return io.ErrShortWrite 111 } 112 return nil 113 }