[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)
164 lines · 4.9 KB
| 1 | package evasion |
| 2 | |
| 3 | import ( |
| 4 | "encoding/binary" |
| 5 | "errors" |
| 6 | "fmt" |
| 7 | "math/rand" |
| 8 | ) |
| 9 | |
| 10 | // GenerateProceduralBMP synthesizes a valid 24-bit uncompressed BMP image. |
| 11 | func GenerateProceduralBMP(width, height int, seed int64) []byte { |
| 12 | rowSize := ((width*3 + 3) / 4) * 4 |
| 13 | imageSize := rowSize * height |
| 14 | fileSize := 14 + 40 + imageSize |
| 15 | |
| 16 | buf := make([]byte, fileSize) |
| 17 | |
| 18 | // BITMAPFILEHEADER (14 bytes) |
| 19 | buf[0] = 'B' |
| 20 | buf[1] = 'M' |
| 21 | binary.LittleEndian.PutUint32(buf[2:6], uint32(fileSize)) |
| 22 | binary.LittleEndian.PutUint32(buf[10:14], 54) // offset to pixel data |
| 23 | |
| 24 | // BITMAPINFOHEADER (40 bytes) |
| 25 | binary.LittleEndian.PutUint32(buf[14:18], 40) |
| 26 | binary.LittleEndian.PutUint32(buf[18:22], uint32(width)) |
| 27 | binary.LittleEndian.PutUint32(buf[22:26], uint32(height)) |
| 28 | binary.LittleEndian.PutUint16(buf[26:28], 1) // planes |
| 29 | binary.LittleEndian.PutUint16(buf[28:30], 24) // 24-bit BGR |
| 30 | binary.LittleEndian.PutUint32(buf[30:34], 0) // BI_RGB uncompressed |
| 31 | binary.LittleEndian.PutUint32(buf[34:38], uint32(imageSize)) |
| 32 | binary.LittleEndian.PutUint32(buf[38:42], 2835) |
| 33 | binary.LittleEndian.PutUint32(buf[42:46], 2835) |
| 34 | |
| 35 | // Fill pixel array with smooth deterministic procedural color gradient |
| 36 | rng := rand.New(rand.NewSource(seed)) |
| 37 | baseR := uint8(rng.Intn(100) + 50) |
| 38 | baseG := uint8(rng.Intn(100) + 50) |
| 39 | baseB := uint8(rng.Intn(100) + 50) |
| 40 | |
| 41 | pixelStart := 54 |
| 42 | for y := 0; y < height; y++ { |
| 43 | rowOffset := pixelStart + y*rowSize |
| 44 | for x := 0; x < width; x++ { |
| 45 | idx := rowOffset + x*3 |
| 46 | buf[idx] = uint8((int(baseB) + x*255/width) % 256) // Blue |
| 47 | buf[idx+1] = uint8((int(baseG) + y*255/height) % 256) // Green |
| 48 | buf[idx+2] = uint8((int(baseR) + (x+y)*128/width) % 256) // Red |
| 49 | } |
| 50 | // Row padding is already 0x00 |
| 51 | } |
| 52 | |
| 53 | return buf |
| 54 | } |
| 55 | |
| 56 | // EmbedBMP embeds payload into 24-bit BMP pixels using 1-bit LSB steganography. |
| 57 | func EmbedBMP(bmpData []byte, payload []byte) ([]byte, error) { |
| 58 | if len(bmpData) < 54 || bmpData[0] != 'B' || bmpData[1] != 'M' { |
| 59 | return nil, errors.New("invalid BMP header") |
| 60 | } |
| 61 | |
| 62 | width := int(binary.LittleEndian.Uint32(bmpData[18:22])) |
| 63 | height := int(binary.LittleEndian.Uint32(bmpData[22:26])) |
| 64 | bitCount := binary.LittleEndian.Uint16(bmpData[28:30]) |
| 65 | compression := binary.LittleEndian.Uint32(bmpData[30:34]) |
| 66 | |
| 67 | if bitCount != 24 || compression != 0 { |
| 68 | return nil, fmt.Errorf("unsupported BMP format: bitCount=%d, compression=%d (requires 24-bit uncompressed)", bitCount, compression) |
| 69 | } |
| 70 | |
| 71 | usablePixels := width * height * 3 |
| 72 | maxCapacity := (usablePixels / 8) - 4 // minus 4 bytes for length header |
| 73 | if len(payload) > maxCapacity { |
| 74 | return nil, fmt.Errorf("payload size (%d bytes) exceeds BMP capacity (%d bytes)", len(payload), maxCapacity) |
| 75 | } |
| 76 | |
| 77 | // Prepare framed payload: [Length uint32 (4B)][Payload] |
| 78 | framed := make([]byte, 4+len(payload)) |
| 79 | binary.BigEndian.PutUint32(framed[0:4], uint32(len(payload))) |
| 80 | copy(framed[4:], payload) |
| 81 | |
| 82 | out := make([]byte, len(bmpData)) |
| 83 | copy(out, bmpData) |
| 84 | |
| 85 | rowSize := ((width*3 + 3) / 4) * 4 |
| 86 | pixelStart := int(binary.LittleEndian.Uint32(bmpData[10:14])) |
| 87 | |
| 88 | bitTotal := len(framed) * 8 |
| 89 | bitIdx := 0 |
| 90 | |
| 91 | outer: |
| 92 | for y := 0; y < height; y++ { |
| 93 | rowOffset := pixelStart + y*rowSize |
| 94 | for x := 0; x < width*3; x++ { |
| 95 | if bitIdx >= bitTotal { |
| 96 | break outer |
| 97 | } |
| 98 | byteVal := framed[bitIdx/8] |
| 99 | bit := (byteVal >> (7 - (bitIdx % 8))) & 0x01 |
| 100 | |
| 101 | targetByte := out[rowOffset+x] |
| 102 | out[rowOffset+x] = (targetByte & 0xFE) | bit |
| 103 | bitIdx++ |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | return out, nil |
| 108 | } |
| 109 | |
| 110 | // ExtractBMP extracts payload embedded via EmbedBMP. |
| 111 | func ExtractBMP(bmpData []byte) ([]byte, error) { |
| 112 | if len(bmpData) < 54 || bmpData[0] != 'B' || bmpData[1] != 'M' { |
| 113 | return nil, errors.New("invalid BMP header") |
| 114 | } |
| 115 | |
| 116 | width := int(binary.LittleEndian.Uint32(bmpData[18:22])) |
| 117 | height := int(binary.LittleEndian.Uint32(bmpData[22:26])) |
| 118 | rowSize := ((width*3 + 3) / 4) * 4 |
| 119 | pixelStart := int(binary.LittleEndian.Uint32(bmpData[10:14])) |
| 120 | |
| 121 | // First extract 32 bits (4 bytes) to read length header |
| 122 | lengthBits := 32 |
| 123 | var lengthBuf [4]byte |
| 124 | bitIdx := 0 |
| 125 | |
| 126 | for y := 0; y < height && bitIdx < lengthBits; y++ { |
| 127 | rowOffset := pixelStart + y*rowSize |
| 128 | for x := 0; x < width*3 && bitIdx < lengthBits; x++ { |
| 129 | bit := bmpData[rowOffset+x] & 0x01 |
| 130 | lengthBuf[bitIdx/8] |= (bit << (7 - (bitIdx % 8))) |
| 131 | bitIdx++ |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | payloadLen := int(binary.BigEndian.Uint32(lengthBuf[:])) |
| 136 | usablePixels := width * height * 3 |
| 137 | maxCapacity := (usablePixels / 8) - 4 |
| 138 | if payloadLen <= 0 || payloadLen > maxCapacity { |
| 139 | return nil, fmt.Errorf("invalid extracted payload length %d (capacity: %d)", payloadLen, maxCapacity) |
| 140 | } |
| 141 | |
| 142 | // Extract payload bits |
| 143 | totalBits := (4 + payloadLen) * 8 |
| 144 | payload := make([]byte, payloadLen) |
| 145 | |
| 146 | outerExtract: |
| 147 | for y := 0; y < height; y++ { |
| 148 | rowOffset := pixelStart + y*rowSize |
| 149 | for x := 0; x < width*3; x++ { |
| 150 | currBit := y*(width*3) + x |
| 151 | if currBit < 32 { |
| 152 | continue |
| 153 | } |
| 154 | if currBit >= totalBits { |
| 155 | break outerExtract |
| 156 | } |
| 157 | bit := bmpData[rowOffset+x] & 0x01 |
| 158 | targetBit := currBit - 32 |
| 159 | payload[targetBit/8] |= (bit << (7 - (targetBit % 8))) |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | return payload, nil |
| 164 | } |