Last active 6 months ago

Revision 8d6f5a3d1c7123dd6846a61103c7a6dbe6f44c7b

dns_xor.go Raw
1// domain data encoding/decoding algo for FrameworkPOS Malware DNS-Tunneling Variant,
2// as described on:
3// https://blog.gdata.de/artikel/neue-variante-von-frameworkpos-schoepft-daten-ueber-dns-anfragen-ab/
4//
5package main
6
7import(
8 "fmt"
9 "os"
10 "encoding/hex"
11 "flag"
12)
13
14// test vectors:
15// data := []byte{0xc3, 0xcb, 0xc0, 0xdc, 0xc3, 0xc4, 0xca, 0xdc, 0xc4, 0xcb, 0xdc, 0xc4, 0xcb}
16// string := "192.168.69.69"
17//
18// data := []byte{0xa2, 0xb3, 0xa7, 0xbe, 0xdf, 0xb3, 0xb0, 0xb1, 0xc3, 0xc0, 0xc1, 0xc6}
19// string := "PAUL-ABC1234"
20const A = 0xAA
21const B = 0x9B
22const C = 0xC3
23
24var op string
25var in string
26
27func init(){
28 flag.StringVar(&op, "op", "decode", "operation to perform: 'encode' or 'decode', default is 'decode'")
29 flag.StringVar(&in, "in", "", "Inputstring to perform choosen operation on")
30}
31
32// decode - decodes single values from dns queries into cleartext
33func decode(data []byte)(result []byte){
34 for _, v := range data {
35 a := v ^ A
36 b := a ^ B
37 result = append(result, b ^ C)
38 }
39 return result
40}
41
42// encode - encodes cleartext values to be used in dns queries
43func encode(data []byte)(result []byte) {
44 for _, v := range data {
45 b := v ^ C
46 a := b ^ B
47 result = append(result, a ^ A)
48 }
49 return result
50}
51
52func main(){
53 flag.Parse()
54 input := []byte(in)
55
56 switch {
57 case op == "encode":
58 encoded := encode(input)
59 fmt.Printf("%s %x\n", input, string(encoded))
60 case op == "decode":
61 data, err := hex.DecodeString(string(input))
62 if err != nil {
63 panic(err)
64 }
65 decoded := decode(data)
66 fmt.Printf("%x %s\n", data, string(decoded))
67 default:
68 prog := os.Args[0]
69 fmt.Printf("For USAGE INFO call: '%s -h'\n", prog)
70 }
71}