package stego import "image" // ExtractLSB проходит пиксели построчно (слева направо, сверху вниз) и // вытаскивает по одному биту (bit) из выбранного канала на пиксель, // упаковывая их в байты (8 пикселей на байт), пока не наберётся maxBytes // байт или не кончится изображение — что раньше. // // Это самая наивная, но и самая частая в CTF-задачах схема: линейная // LSB-стеганография без перемешивания порядка пикселей и без ключа. // Более хитрые схемы (с рассеиванием по PRNG-последовательности, с // несколькими битами разных каналов одновременно, с посимвольным // прыжком через фиксированный интервал пикселей и т.п.) этим не // читаются — придётся разбирать руками, этот пакет вытаскивает только // самый частый частный случай. func ExtractLSB(img *image.RGBA, ch Channel, bit int, maxBytes int) []byte { bounds := img.Bounds() out := make([]byte, 0, maxBytes) var cur byte var count int for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { if len(out) >= maxBytes { return out } v := channelValue(img.RGBAAt(x, y), ch) b := (v >> uint(bit)) & 1 cur = (cur << 1) | b count++ if count == 8 { out = append(out, cur) cur = 0 count = 0 } } } return out }