etc.git


etc

~ scripts and random things
git clone https://github.com/djnnvx/etc.git
log | files | refs | archive

commit 6772fc538f642ed309fa3133135204e131e8394d
parent 50560fa148b67d593042209afa53beaf1c7c3c88
Author: djnn <[email protected]>
Date: Sun, 22 Jun 2025 16:50:27 +0900

maildigger: adding CLI to check DKM records size

Diffstat:
Amaildigger/.gitignore | 48++++++++++++++++++++++++++++++++++++++++++++++++
Amaildigger/README.md | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amaildigger/dkim/runner.go | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amaildigger/dkim/types.go | 22++++++++++++++++++++++
Amaildigger/go.mod | 18++++++++++++++++++
Amaildigger/go.sum | 22++++++++++++++++++++++
Amaildigger/main.go | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

7 files changed, 320 insertions(+), 0 deletions(-)

diff --git a/maildigger/.gitignore b/maildigger/.gitignore
@@ -0,0 +1,48 @@
+# ---> Go
+# If you prefer the allow list template instead of the deny list, see community template:
+# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
+#
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+
+# Go workspace file
+go.work
+
+# ---> Go.AllowList
+# Allowlisting gitignore template for GO projects prevents us
+# from adding various unwanted local files, such as generated
+# files, developer configurations or IDE-specific files etc.
+#
+# Recommended: Go.AllowList.gitignore
+
+# Ignore everything
+*
+
+# But not these files...
+!/.gitignore
+
+!*.go
+!go.sum
+!go.mod
+
+!README.md
+!LICENSE
+
+# !Makefile
+
+# ...even if they are in subdirectories
+!*/
+
diff --git a/maildigger/README.md b/maildigger/README.md
@@ -0,0 +1,55 @@
+# maildigger
+
+little CLI to check for the size of the key of DKIM records.
+
+```
+
+
+     .-.
+    /'v'\           maildigger
+   (/   \)           ~djnn.sh
+==='="="===<
+    |_|              v0.0.1
+
+                                s/o vsim<3
+                        hack the planet,
+                        travel the world . . .
+------------------------------------------------
+       DNS scrapping tool to recover DKIM
+                   records
+
+    ===> evil.djnn.sh/djnn/maildigger  <===
+------------------------------------------------
+
+
+```
+
+> based on [this research](https://dmarcchecker.app/articles/crack-512-bit-dkim-rsa-key)
+
+## Installing & compiling
+
+Using `go v1.23`.
+
+```bash
+# please clone using https. couldnt be arsed to set up a tcp tunnel on cloudflare
+git clone https://evil.djnn.sh/djnn/maildigger.git
+
+cd maildigger/
+
+make
+```
+
+### Using docker
+
+```bash
+cd maildigger/
+
+make docker
+```
+
+
+## Running
+
+```bash
+./maildigger -d example.txt --dkim-max-len 128
+```
diff --git a/maildigger/dkim/runner.go b/maildigger/dkim/runner.go
@@ -0,0 +1,60 @@
+package dkim
+
+import (
+	"github.com/miekg/dns"
+
+	"fmt"
+	"strings"
+)
+
+func (dk *DkimRunner) Run(maxLen int32) error {
+	dkimPrefix := "k=rsa; p="
+
+	m := new(dns.Client)
+	for _, domain := range dk.Domains {
+		q := dns.Question{
+			Name:   domain + ".",
+			Qtype:  dns.TypeTXT,
+			Qclass: dns.ClassINET,
+		}
+
+		m1 := new(dns.Msg)
+		m1.Id = dns.Id()
+		m1.RecursionDesired = true
+		m1.Question = make([]dns.Question, 1)
+		m1.Question[0] = q
+
+		/* make DNS request */
+		msg, _, err := m.Exchange(m1, dk.DnsServer+":53")
+		if err != nil {
+			println("[+] Could not contact exchange server")
+			return err
+		}
+
+		/* get TXT records from Answer */
+		for _, rr := range msg.Answer {
+			if rr.Header().Rrtype == dns.TypeTXT {
+				txt := rr.(*dns.TXT).Txt
+
+				for _, t := range txt {
+
+					/* we have found something that looks like a DKIM record */
+					if strings.HasPrefix(t, dkimPrefix) {
+
+						key := strings.TrimPrefix(t, dkimPrefix)
+						kLen := len(key)
+
+						/* key is bigger than our max-size, we discard */
+						if int32(kLen) > maxLen {
+							continue
+						}
+
+						fmt.Printf("[+] => %s: %s (len: %d)\n", domain, key, kLen)
+					}
+				}
+			}
+		}
+	}
+
+	return nil
+}
diff --git a/maildigger/dkim/types.go b/maildigger/dkim/types.go
@@ -0,0 +1,22 @@
+package dkim
+
+type DkimRunner struct {
+
+	/* Nameserver target in order to perform the request */
+	DnsServer string
+
+	/* list of domains to hit */
+	Domains []string
+}
+
+type DkimDomain struct {
+
+	/* related base domain */
+	domain string
+
+	/* DKIM key */
+	key string
+
+	/* DKIM key len */
+	keyLen int32
+}
diff --git a/maildigger/go.mod b/maildigger/go.mod
@@ -0,0 +1,18 @@
+module evil.djnn.sh/djnn/maildigger
+
+go 1.23.4
+
+require (
+	github.com/miekg/dns v1.1.62
+	github.com/spf13/cobra v1.8.1
+)
+
+require (
+	github.com/inconshreveable/mousetrap v1.1.0 // indirect
+	github.com/spf13/pflag v1.0.5 // indirect
+	golang.org/x/mod v0.18.0 // indirect
+	golang.org/x/net v0.27.0 // indirect
+	golang.org/x/sync v0.7.0 // indirect
+	golang.org/x/sys v0.22.0 // indirect
+	golang.org/x/tools v0.22.0 // indirect
+)
diff --git a/maildigger/go.sum b/maildigger/go.sum
@@ -0,0 +1,22 @@
+github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
+github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
+github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
+golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
+golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
+golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/maildigger/main.go b/maildigger/main.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+	"github.com/spf13/cobra"
+
+	"evil.djnn.sh/djnn/maildigger/dkim"
+
+	"bufio"
+	"fmt"
+	"os"
+)
+
+const version = "0.0.1"
+const ASCII_ART = `
+
+     .-.
+    /'v'\           maildigger
+   (/   \)           ~djnn.sh
+==='="="===<
+    |_|              v0.0.1
+
+                                s/o vsim<3
+                        hack the planet,
+                        travel the world . . .
+------------------------------------------------
+       DNS scrapping tool to recover DKIM
+                   records
+
+    ===> evil.djnn.sh/djnn/maildigger  <===
+------------------------------------------------
+
+`
+
+var (
+	domainsFilepath string
+	nameserver      string
+
+	maxLenDKIM int32
+	maxLenSPF  int32
+)
+
+var rootCmd = &cobra.Command{
+	Use:     "maildigger",
+	Short:   "simple cli to scrape DKIM or SPF records",
+	Long:    ASCII_ART,
+	Version: version,
+	Run: func(cmd *cobra.Command, args []string) {
+		println(ASCII_ART) /* why make hacking CLIs if you cant print silly ascii art ? */
+
+		if domainsFilepath == "" {
+			println("[!] error: please specify domain.")
+			os.Exit(1)
+		}
+
+		file, err := os.Open(domainsFilepath)
+		if err != nil {
+			panic(err)
+		}
+		defer file.Close()
+
+		domains := make([]string, 1)
+		scanner := bufio.NewScanner(file)
+		for scanner.Scan() {
+			domains = append(domains, scanner.Text())
+		}
+
+		if err := scanner.Err(); err != nil {
+			panic(err)
+		}
+		fmt.Printf("[+] Loaded %d domains...\n", len(domains))
+
+		dkimRunner := dkim.DkimRunner{
+			DnsServer: nameserver,
+			Domains:   domains,
+		}
+
+		err = dkimRunner.Run(maxLenDKIM)
+		if err != nil {
+			println("[!] Error while recovering DKIM records")
+			panic(err)
+		}
+
+		println("[+] DKIM check done.")
+
+	},
+}
+
+func main() {
+
+	rootCmd.Flags().StringVarP(&nameserver, "nameserver", "n", "8.8.8.8", "DNS nameserver")
+	rootCmd.Flags().StringVarP(&domainsFilepath, "domains", "d", "domains.txt", "file containing list of domains (line by line)")
+	rootCmd.Flags().Int32VarP(&maxLenDKIM, "dkim-max-len", "", 128, "DKIM key max size")
+
+	rootCmd.ExecuteC()
+}