[SHEHZADE//ABDULLAH ANSARI]
Red Team Consultant @ Google | MS in Cybersecurity @ NYU
● Notice //GitHub (@shehzade) is temporarily suspended pending an automated false-positive review. All tools are hosted on this Code Mirror and available on request (contact); GitHub links will return once reinstated.
PUBLIC MIRRORGo v1.0
Multi-protocol network egress assessment and DLP verification framework featuring automated L4 sweeps, corporate proxy traversal, and covert protocol smuggling across 20+ channels.
$
git clone https://shehzade.io/repos/contraband.git
Copy
Source ZIP (1.93 MB)
258 lines · 6.5 KB
| 1 | package evasion |
| 2 | |
| 3 | import ( |
| 4 | "bytes" |
| 5 | "encoding/binary" |
| 6 | "errors" |
| 7 | "fmt" |
| 8 | "hash/crc32" |
| 9 | "image" |
| 10 | "image/color" |
| 11 | "image/draw" |
| 12 | "image/png" |
| 13 | "math/rand" |
| 14 | ) |
| 15 | |
| 16 | var ( |
| 17 | PNGSignature = []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A} |
| 18 | ChunkTypeCtRB = []byte("ctRB") |
| 19 | ) |
| 20 | |
| 21 | // GenerateProceduralPNG creates a dynamic, procedural RGBA PNG image with unique entropy. |
| 22 | func GenerateProceduralPNG(width, height int, seed int64) ([]byte, error) { |
| 23 | img := image.NewRGBA(image.Rect(0, 0, width, height)) |
| 24 | rng := rand.New(rand.NewSource(seed)) |
| 25 | |
| 26 | baseR := uint8(rng.Intn(128) + 64) |
| 27 | baseG := uint8(rng.Intn(128) + 64) |
| 28 | baseB := uint8(rng.Intn(128) + 64) |
| 29 | |
| 30 | for y := 0; y < height; y++ { |
| 31 | for x := 0; x < width; x++ { |
| 32 | c := color.RGBA{ |
| 33 | R: uint8((int(baseR) + x*128/width) % 256), |
| 34 | G: uint8((int(baseG) + y*128/height) % 256), |
| 35 | B: uint8((int(baseB) + (x+y)*64/width) % 256), |
| 36 | A: 255, |
| 37 | } |
| 38 | img.SetRGBA(x, y, c) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | var buf bytes.Buffer |
| 43 | enc := png.Encoder{CompressionLevel: png.DefaultCompression} |
| 44 | if err := enc.Encode(&buf, img); err != nil { |
| 45 | return nil, err |
| 46 | } |
| 47 | return buf.Bytes(), nil |
| 48 | } |
| 49 | |
| 50 | // EmbedPNGAncillary embeds payload into an ancillary ctRB PNG chunk. |
| 51 | func EmbedPNGAncillary(pngData []byte, payload []byte) ([]byte, error) { |
| 52 | if len(pngData) < 8 || !bytes.Equal(pngData[:8], PNGSignature) { |
| 53 | return nil, errors.New("invalid PNG signature") |
| 54 | } |
| 55 | |
| 56 | // Build ctRB chunk: [Length 4B][Type 4B][Data][CRC 4B] |
| 57 | chunkLen := uint32(len(payload)) |
| 58 | crcPayload := append(ChunkTypeCtRB, payload...) |
| 59 | crcVal := crc32.ChecksumIEEE(crcPayload) |
| 60 | |
| 61 | var chunk bytes.Buffer |
| 62 | binary.Write(&chunk, binary.BigEndian, chunkLen) |
| 63 | chunk.Write(ChunkTypeCtRB) |
| 64 | chunk.Write(payload) |
| 65 | binary.Write(&chunk, binary.BigEndian, crcVal) |
| 66 | |
| 67 | // Insert chunk right after IHDR chunk |
| 68 | offset := 8 |
| 69 | ihdrEnd := -1 |
| 70 | for offset < len(pngData) { |
| 71 | length := binary.BigEndian.Uint32(pngData[offset : offset+4]) |
| 72 | chunkType := string(pngData[offset+4 : offset+8]) |
| 73 | nextOffset := offset + 8 + int(length) + 4 |
| 74 | if chunkType == "IHDR" { |
| 75 | ihdrEnd = nextOffset |
| 76 | break |
| 77 | } |
| 78 | offset = nextOffset |
| 79 | } |
| 80 | |
| 81 | if ihdrEnd == -1 || ihdrEnd > len(pngData) { |
| 82 | return nil, errors.New("could not locate IHDR chunk in PNG") |
| 83 | } |
| 84 | |
| 85 | var out bytes.Buffer |
| 86 | out.Write(pngData[:ihdrEnd]) |
| 87 | out.Write(chunk.Bytes()) |
| 88 | out.Write(pngData[ihdrEnd:]) |
| 89 | return out.Bytes(), nil |
| 90 | } |
| 91 | |
| 92 | // ExtractPNGAncillary extracts payload from ctRB ancillary chunk. |
| 93 | func ExtractPNGAncillary(pngData []byte) ([]byte, error) { |
| 94 | if len(pngData) < 8 || !bytes.Equal(pngData[:8], PNGSignature) { |
| 95 | return nil, errors.New("invalid PNG signature") |
| 96 | } |
| 97 | |
| 98 | offset := 8 |
| 99 | for offset+8 <= len(pngData) { |
| 100 | length := binary.BigEndian.Uint32(pngData[offset : offset+4]) |
| 101 | chunkType := pngData[offset+4 : offset+8] |
| 102 | dataStart := offset + 8 |
| 103 | dataEnd := dataStart + int(length) |
| 104 | crcEnd := dataEnd + 4 |
| 105 | |
| 106 | if crcEnd > len(pngData) { |
| 107 | return nil, errors.New("malformed PNG: chunk extends beyond file length") |
| 108 | } |
| 109 | |
| 110 | if bytes.Equal(chunkType, ChunkTypeCtRB) { |
| 111 | payload := pngData[dataStart:dataEnd] |
| 112 | crcVal := binary.BigEndian.Uint32(pngData[dataEnd:crcEnd]) |
| 113 | computedCRC := crc32.ChecksumIEEE(pngData[offset+4 : dataEnd]) |
| 114 | if crcVal != computedCRC { |
| 115 | return nil, errors.New("CRC mismatch in ctRB chunk") |
| 116 | } |
| 117 | return payload, nil |
| 118 | } |
| 119 | offset = crcEnd |
| 120 | } |
| 121 | |
| 122 | return nil, errors.New("no ctRB ancillary chunk found in PNG") |
| 123 | } |
| 124 | |
| 125 | // EmbedPNGLSB embeds payload into RGB pixel LSBs of a PNG. |
| 126 | func EmbedPNGLSB(pngData []byte, payload []byte) ([]byte, error) { |
| 127 | srcImg, err := png.Decode(bytes.NewReader(pngData)) |
| 128 | if err != nil { |
| 129 | return nil, fmt.Errorf("failed to decode PNG: %w", err) |
| 130 | } |
| 131 | |
| 132 | bounds := srcImg.Bounds() |
| 133 | width := bounds.Dx() |
| 134 | height := bounds.Dy() |
| 135 | |
| 136 | rgba := image.NewRGBA(bounds) |
| 137 | draw.Draw(rgba, bounds, srcImg, bounds.Min, draw.Src) |
| 138 | |
| 139 | usableChannels := width * height * 3 // R, G, B |
| 140 | maxCapacity := (usableChannels / 8) - 4 |
| 141 | if len(payload) > maxCapacity { |
| 142 | return nil, fmt.Errorf("payload (%d bytes) exceeds PNG LSB capacity (%d bytes)", len(payload), maxCapacity) |
| 143 | } |
| 144 | |
| 145 | framed := make([]byte, 4+len(payload)) |
| 146 | binary.BigEndian.PutUint32(framed[0:4], uint32(len(payload))) |
| 147 | copy(framed[4:], payload) |
| 148 | |
| 149 | totalBits := len(framed) * 8 |
| 150 | bitIdx := 0 |
| 151 | |
| 152 | outerPixel: |
| 153 | for y := 0; y < height; y++ { |
| 154 | for x := 0; x < width; x++ { |
| 155 | c := rgba.RGBAAt(x, y) |
| 156 | |
| 157 | // Red channel |
| 158 | if bitIdx < totalBits { |
| 159 | bit := (framed[bitIdx/8] >> (7 - (bitIdx % 8))) & 0x01 |
| 160 | c.R = (c.R & 0xFE) | bit |
| 161 | bitIdx++ |
| 162 | } |
| 163 | // Green channel |
| 164 | if bitIdx < totalBits { |
| 165 | bit := (framed[bitIdx/8] >> (7 - (bitIdx % 8))) & 0x01 |
| 166 | c.G = (c.G & 0xFE) | bit |
| 167 | bitIdx++ |
| 168 | } |
| 169 | // Blue channel |
| 170 | if bitIdx < totalBits { |
| 171 | bit := (framed[bitIdx/8] >> (7 - (bitIdx % 8))) & 0x01 |
| 172 | c.B = (c.B & 0xFE) | bit |
| 173 | bitIdx++ |
| 174 | } |
| 175 | |
| 176 | rgba.SetRGBA(x, y, c) |
| 177 | if bitIdx >= totalBits { |
| 178 | break outerPixel |
| 179 | } |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | var buf bytes.Buffer |
| 184 | enc := png.Encoder{CompressionLevel: png.DefaultCompression} |
| 185 | if err := enc.Encode(&buf, rgba); err != nil { |
| 186 | return nil, err |
| 187 | } |
| 188 | return buf.Bytes(), nil |
| 189 | } |
| 190 | |
| 191 | // ExtractPNGLSB extracts payload embedded via EmbedPNGLSB. |
| 192 | func ExtractPNGLSB(pngData []byte) ([]byte, error) { |
| 193 | srcImg, err := png.Decode(bytes.NewReader(pngData)) |
| 194 | if err != nil { |
| 195 | return nil, fmt.Errorf("failed to decode PNG: %w", err) |
| 196 | } |
| 197 | |
| 198 | bounds := srcImg.Bounds() |
| 199 | width := bounds.Dx() |
| 200 | height := bounds.Dy() |
| 201 | |
| 202 | rgba, ok := srcImg.(*image.RGBA) |
| 203 | if !ok { |
| 204 | rgba = image.NewRGBA(bounds) |
| 205 | draw.Draw(rgba, bounds, srcImg, bounds.Min, draw.Src) |
| 206 | } |
| 207 | |
| 208 | // Extract first 32 bits (4 bytes) to read length header |
| 209 | var lengthBuf [4]byte |
| 210 | bitIdx := 0 |
| 211 | |
| 212 | for y := 0; y < height && bitIdx < 32; y++ { |
| 213 | for x := 0; x < width && bitIdx < 32; x++ { |
| 214 | c := rgba.RGBAAt(x, y) |
| 215 | for _, channelVal := range []uint8{c.R, c.G, c.B} { |
| 216 | if bitIdx >= 32 { |
| 217 | break |
| 218 | } |
| 219 | bit := channelVal & 0x01 |
| 220 | lengthBuf[bitIdx/8] |= (bit << (7 - (bitIdx % 8))) |
| 221 | bitIdx++ |
| 222 | } |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | payloadLen := int(binary.BigEndian.Uint32(lengthBuf[:])) |
| 227 | usableChannels := width * height * 3 |
| 228 | maxCapacity := (usableChannels / 8) - 4 |
| 229 | if payloadLen <= 0 || payloadLen > maxCapacity { |
| 230 | return nil, fmt.Errorf("invalid extracted PNG LSB payload length %d (capacity: %d)", payloadLen, maxCapacity) |
| 231 | } |
| 232 | |
| 233 | payload := make([]byte, payloadLen) |
| 234 | totalBits := (4 + payloadLen) * 8 |
| 235 | currBit := 0 |
| 236 | |
| 237 | outerExtract: |
| 238 | for y := 0; y < height; y++ { |
| 239 | for x := 0; x < width; x++ { |
| 240 | c := rgba.RGBAAt(x, y) |
| 241 | for _, channelVal := range []uint8{c.R, c.G, c.B} { |
| 242 | if currBit < 32 { |
| 243 | currBit++ |
| 244 | continue |
| 245 | } |
| 246 | if currBit >= totalBits { |
| 247 | break outerExtract |
| 248 | } |
| 249 | bit := channelVal & 0x01 |
| 250 | targetBit := currBit - 32 |
| 251 | payload[targetBit/8] |= (bit << (7 - (targetBit % 8))) |
| 252 | currBit++ |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | return payload, nil |
| 258 | } |