diff --git a/README.md b/README.md index d3daa15..7145c81 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,18 @@ # smuggler -A steganography tool that abuses UTF-8 PUAs to encode messages, which can be used as subtle attacks on AI prompts \ No newline at end of file +A steganography tool that abuses UTF-8 PUAs to encode messages, which can be used for subtle attacks on AI prompts + +``` +user@angeltech:$ go build . +``` +``` +user@angeltech:$ ./smuggler encode "test" +Encoded: 󠁴󠁥󠁳󠁴 +``` +``` +user@angeltech:$ ./smuggler decode "<000e0074><000e0065><000e0073><000e0074>" +Decoded: test +``` + +Example of interaction with Grok, for reference: +![Example of interaction with Grok](image.png) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b75d111 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gitea.angeltech.jp/Angel-Technologies/smuggler + +go 1.24.3 diff --git a/image.png b/image.png new file mode 100644 index 0000000..d54ade5 Binary files /dev/null and b/image.png differ diff --git a/main.go b/main.go new file mode 100644 index 0000000..3596504 --- /dev/null +++ b/main.go @@ -0,0 +1,73 @@ +package main + +import ( + "fmt" + "os" + "strings" +) + +const ( + PUA_START = 0xE0000 +) + +func encodeHiddenMessage(message string) string { + var hidden strings.Builder + for _, char := range message { + hidden.WriteRune(PUA_START + char) + } + return hidden.String() +} + +func decodeMixedMessage(input string) string { + var decoded strings.Builder + var hiddenBuffer strings.Builder + inHiddenSequence := false + + for _, char := range input { + if char >= PUA_START && char < PUA_START+0xFFFF { + if !inHiddenSequence && hiddenBuffer.Len() > 0 { + decoded.WriteString(hiddenBuffer.String()) + hiddenBuffer.Reset() + } + inHiddenSequence = true + hiddenBuffer.WriteRune(char - PUA_START) + } else { + if inHiddenSequence { + decoded.WriteString(hiddenBuffer.String()) + hiddenBuffer.Reset() + inHiddenSequence = false + } + decoded.WriteRune(char) + } + } + + if hiddenBuffer.Len() > 0 { + decoded.WriteString(hiddenBuffer.String()) + } + + return decoded.String() +} + +func main() { + if len(os.Args) < 3 { + fmt.Println("Usage:") + fmt.Println(" Encode: go run main.go encode \"secret message\"") + fmt.Println(" Decode: go run main.go decode \"󠁳󠁥󠁣󠁲󠁥󠁴\"") + os.Exit(1) + } + + command := os.Args[1] + text := strings.Join(os.Args[2:], " ") + + switch command { + case "encode": + hidden := encodeHiddenMessage(text) + fmt.Printf("Encoded: %s\n", hidden) + case "decode": + decoded := decodeMixedMessage(text) + fmt.Printf("Decoded: %s\n", decoded) + default: + fmt.Println("Invalid command. Use 'encode' or 'decode'.") + os.Exit(1) + } +}