Last active
August 17, 2024 18:38
-
-
Save bplaxco/44a97d3817448c2307237517c9c6f314 to your computer and use it in GitHub Desktop.
Locate strings of base64 data in text and decodes them in place. This is a PoC for some secrets scanning work.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "encoding/base64" | |
| "io" | |
| "log" | |
| "os" | |
| "regexp" | |
| "unicode" | |
| ) | |
| var b64Regexp *regexp.Regexp | |
| type EncodedSegment struct { | |
| start int | |
| value string | |
| } | |
| func init() { | |
| b64Regexp = regexp.MustCompile(`[\w\/\-\+]{14,}={0,3}`) | |
| } | |
| func encodedSegments(data []byte) []EncodedSegment { | |
| if len(data) == 0 { | |
| return []EncodedSegment{} | |
| } | |
| matchIndices := b64Regexp.FindAllIndex(data, -1) | |
| if matchIndices == nil { | |
| return []EncodedSegment{} | |
| } | |
| segments := make([]EncodedSegment, len(matchIndices)) | |
| for i, matchIndex := range matchIndices { | |
| segments[i] = EncodedSegment{ | |
| start: matchIndex[0], | |
| value: string(data[matchIndex[0]:matchIndex[1]]), | |
| } | |
| } | |
| return segments | |
| } | |
| func decode(data []byte, segments []EncodedSegment) []byte { | |
| decodedSubstrings := make(map[string][]byte) | |
| for _, segment := range segments { | |
| // No need to decode this one again | |
| if _, skip := decodedSubstrings[segment.value]; skip { | |
| continue | |
| } | |
| dec, err := base64.StdEncoding.DecodeString(segment.value) | |
| if err == nil && len(dec) > 0 && isASCII(dec) { | |
| decodedSubstrings[segment.value] = dec | |
| } | |
| dec, err = base64.RawURLEncoding.DecodeString(segment.value) | |
| if err == nil && len(dec) > 0 && isASCII(dec) { | |
| decodedSubstrings[segment.value] = dec | |
| } | |
| } | |
| if len(decodedSubstrings) > 0 { | |
| result := bytes.NewBuffer(make([]byte, 0, len(data))) | |
| start := 0 | |
| for _, segment := range segments { | |
| if decoded, ok := decodedSubstrings[segment.value]; ok { | |
| result.Write(data[start:segment.start]) | |
| result.Write(decoded) | |
| start = segment.start + len(segment.value) | |
| } | |
| } | |
| result.Write(data[start:]) | |
| return result.Bytes() | |
| } | |
| return nil | |
| } | |
| func isASCII(b []byte) bool { | |
| for i := 0; i < len(b); i++ { | |
| if b[i] > unicode.MaxASCII { | |
| return false | |
| } | |
| } | |
| return true | |
| } | |
| func main() { | |
| data, err := io.ReadAll(os.Stdin) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| data = decode(data, encodedSegments(data)) | |
| _, err = os.Stdout.Write(data) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment