From 5bf003247522759ef1c4e02a5d681e30c9431ded Mon Sep 17 00:00:00 2001 From: Alessandro Riva Date: Sat, 19 Oct 2024 15:28:08 +0200 Subject: [PATCH] Moved regex --- cmd/email.go | 244 ++++++++++----------- cmd/{extractIoc.go => extract_ioc.go} | 9 +- cmd/ip.go | 5 +- cmd/whois.go | 4 +- cmd/constants.go => internal/util/regex.go | 2 +- 5 files changed, 133 insertions(+), 131 deletions(-) rename cmd/{extractIoc.go => extract_ioc.go} (88%) rename cmd/constants.go => internal/util/regex.go (97%) diff --git a/cmd/email.go b/cmd/email.go index 8a85d74..cad278f 100644 --- a/cmd/email.go +++ b/cmd/email.go @@ -7,49 +7,50 @@ See the LICENSE file for details. package cmd import ( - "fmt" - "io" - "mime" - "mime/multipart" - "net/mail" - "os" - "strings" - "github.com/spf13/cobra" + "fmt" + "github.com/spf13/cobra" + "io" + "mime" + "mime/multipart" + "net/mail" + "os" + "soc-cli/internal/util" + "strings" ) var analyzeEmailCmd = &cobra.Command{ - Use: "email [file]", - Short: "Analyze an email in .eml format for attachments and links", - Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { - filePath := args[0] - analyzeEmail(filePath) - }, + Use: "email [file]", + Short: "Analyze an email in .eml format for attachments and links", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + filePath := args[0] + analyzeEmail(filePath) + }, } func init() { - rootCmd.AddCommand(analyzeEmailCmd) + rootCmd.AddCommand(analyzeEmailCmd) } // analyzeEmail processes the .eml file and extracts attachments and links func analyzeEmail(filePath string) { - file, err := os.Open(filePath) - if err != nil { - fmt.Println("Error opening file:", err) - return - } - defer file.Close() - - // Parse the email message - msg, err := mail.ReadMessage(file) - if err != nil { - fmt.Println("Error parsing .eml file:", err) - return - } - - fmt.Println("Subject:", msg.Header.Get("Subject")) - fmt.Println("From:", msg.Header.Get("From")) - fmt.Println("To:", msg.Header.Get("To")) + file, err := os.Open(filePath) + if err != nil { + fmt.Println("Error opening file:", err) + return + } + defer file.Close() + + // Parse the email message + msg, err := mail.ReadMessage(file) + if err != nil { + fmt.Println("Error parsing .eml file:", err) + return + } + + fmt.Println("Subject:", msg.Header.Get("Subject")) + fmt.Println("From:", msg.Header.Get("From")) + fmt.Println("To:", msg.Header.Get("To")) // Check for SPF information spfHeader := msg.Header.Get("Received-SPF") @@ -59,105 +60,104 @@ func analyzeEmail(filePath string) { fmt.Println("\nSPF Information: No Received-SPF header found.") } - // Extract DKIM Information - dkimHeader := msg.Header.Get("DKIM-Signature") - if dkimHeader != "" { - fmt.Println("\nDKIM Information:") - fmt.Println(dkimHeader) - } else { - fmt.Println("\nDKIM Information: No DKIM-Signature header found.") - } - - // Extract DMARC Information from Authentication-Results header - authResults := msg.Header.Get("Authentication-Results") - if authResults != "" { - extractDMARCDKIM(authResults) - } else { - fmt.Println("\nDMARC Information: No Authentication-Results header found.") - } - - mediaType, params, err := mime.ParseMediaType(msg.Header.Get("Content-Type")) - if err != nil { - fmt.Println("Error parsing content type:", err) - return - } - - if strings.HasPrefix(mediaType, "multipart/") { - // Handle multipart emails (usually contains attachments and text) - mr := multipart.NewReader(msg.Body, params["boundary"]) - processMultipart(mr) - } else { - // Handle single-part emails (just extract links) - body, _ := io.ReadAll(msg.Body) - extractLinks(string(body)) - } + // Extract DKIM Information + dkimHeader := msg.Header.Get("DKIM-Signature") + if dkimHeader != "" { + fmt.Println("\nDKIM Information:") + fmt.Println(dkimHeader) + } else { + fmt.Println("\nDKIM Information: No DKIM-Signature header found.") + } + + // Extract DMARC Information from Authentication-Results header + authResults := msg.Header.Get("Authentication-Results") + if authResults != "" { + extractDMARCDKIM(authResults) + } else { + fmt.Println("\nDMARC Information: No Authentication-Results header found.") + } + + mediaType, params, err := mime.ParseMediaType(msg.Header.Get("Content-Type")) + if err != nil { + fmt.Println("Error parsing content type:", err) + return + } + + if strings.HasPrefix(mediaType, "multipart/") { + // Handle multipart emails (usually contains attachments and text) + mr := multipart.NewReader(msg.Body, params["boundary"]) + processMultipart(mr) + } else { + // Handle single-part emails (just extract links) + body, _ := io.ReadAll(msg.Body) + extractLinks(string(body)) + } } // processMultipart processes multipart emails for attachments and links func processMultipart(mr *multipart.Reader) { - for { - part, err := mr.NextPart() - if err == io.EOF { - break - } - if err != nil { - fmt.Println("Error reading part:", err) - return - } - - contentType := part.Header.Get("Content-Type") - disposition := part.Header.Get("Content-Disposition") - - // If it's an attachment, list it - if strings.Contains(disposition, "attachment") { - fileName := part.FileName() - if fileName == "" { - fileName = "unnamed attachment" - } - fmt.Printf("Attachment: %s (MIME type: %s)\n", fileName, contentType) - } else { - // Otherwise, it's likely part of the email body (text or HTML) - body, _ := io.ReadAll(part) - extractLinks(string(body)) - } - } + for { + part, err := mr.NextPart() + if err == io.EOF { + break + } + if err != nil { + fmt.Println("Error reading part:", err) + return + } + + contentType := part.Header.Get("Content-Type") + disposition := part.Header.Get("Content-Disposition") + + // If it's an attachment, list it + if strings.Contains(disposition, "attachment") { + fileName := part.FileName() + if fileName == "" { + fileName = "unnamed attachment" + } + fmt.Printf("Attachment: %s (MIME type: %s)\n", fileName, contentType) + } else { + // Otherwise, it's likely part of the email body (text or HTML) + body, _ := io.ReadAll(part) + extractLinks(string(body)) + } + } } // extractDMARCDKIM extracts DMARC and DKIM results from the Authentication-Results header func extractDMARCDKIM(authResults string) { - fmt.Println("\nAuthentication Results:") - fmt.Println(authResults) - - // Check for DKIM result - if strings.Contains(authResults, "dkim=pass") { - fmt.Println("DKIM: pass") - } else if strings.Contains(authResults, "dkim=fail") { - fmt.Println("DKIM: fail") - } else { - fmt.Println("DKIM: No DKIM result found.") - } - - // Check for DMARC result - if strings.Contains(authResults, "dmarc=pass") { - fmt.Println("DMARC: pass") - } else if strings.Contains(authResults, "dmarc=fail") { - fmt.Println("DMARC: fail") - } else { - fmt.Println("DMARC: No DMARC result found.") - } -} + fmt.Println("\nAuthentication Results:") + fmt.Println(authResults) + + // Check for DKIM result + if strings.Contains(authResults, "dkim=pass") { + fmt.Println("DKIM: pass") + } else if strings.Contains(authResults, "dkim=fail") { + fmt.Println("DKIM: fail") + } else { + fmt.Println("DKIM: No DKIM result found.") + } + // Check for DMARC result + if strings.Contains(authResults, "dmarc=pass") { + fmt.Println("DMARC: pass") + } else if strings.Contains(authResults, "dmarc=fail") { + fmt.Println("DMARC: fail") + } else { + fmt.Println("DMARC: No DMARC result found.") + } +} // extractLinks extracts URLs from email body text or HTML func extractLinks(body string) { - links := URLRegex.FindAllString(body, -1) - - if len(links) > 0 { - fmt.Println("\nLinks found in the email:") - for _, link := range links { - fmt.Println("-", link) - } - } else { - fmt.Println("\nNo links found in the email.") - } + links := util.URLRegex.FindAllString(body, -1) + + if len(links) > 0 { + fmt.Println("\nLinks found in the email:") + for _, link := range links { + fmt.Println("-", link) + } + } else { + fmt.Println("\nNo links found in the email.") + } } diff --git a/cmd/extractIoc.go b/cmd/extract_ioc.go similarity index 88% rename from cmd/extractIoc.go rename to cmd/extract_ioc.go index ff34e30..bd97e9d 100644 --- a/cmd/extractIoc.go +++ b/cmd/extract_ioc.go @@ -13,6 +13,7 @@ import ( "github.com/spf13/cobra" "log" "os" + "soc-cli/internal/util" ) type iocOutput struct { @@ -47,10 +48,10 @@ func extractIOCs(filePath string, asJSON bool) { } // Find all IOCs - uniqueURLs := removeDuplicates(URLRegex.FindAllString(string(data), -1)) - uniqueIPs := removeDuplicates(IPRegex.FindAllString(string(data), -1)) - uniqueEmails := removeDuplicates(EmailRegex.FindAllString(string(data), -1)) - uniqueHashes := removeDuplicates(SHA256Regex.FindAllString(string(data), -1)) + uniqueURLs := removeDuplicates(util.URLRegex.FindAllString(string(data), -1)) + uniqueIPs := removeDuplicates(util.IPRegex.FindAllString(string(data), -1)) + uniqueEmails := removeDuplicates(util.EmailRegex.FindAllString(string(data), -1)) + uniqueHashes := removeDuplicates(util.SHA256Regex.FindAllString(string(data), -1)) if asJSON { // Prepare data for JSON output diff --git a/cmd/ip.go b/cmd/ip.go index f2d1bb2..4cea450 100644 --- a/cmd/ip.go +++ b/cmd/ip.go @@ -14,13 +14,14 @@ import ( "log" "os" "soc-cli/internal/apis" + "soc-cli/internal/util" ) func analyzeIP(ip string) { // Validate provided IP address - if IPRegex.MatchString(ip) { - if RFC1918Regex.MatchString(ip) { + if util.IPRegex.MatchString(ip) { + if util.RFC1918Regex.MatchString(ip) { fmt.Printf("The IP provided %s is a RFC1918 bogus IP address.\n", ip) os.Exit(0) } else if ip == "127.0.0.1" { diff --git a/cmd/whois.go b/cmd/whois.go index 21a0e26..089ffc6 100644 --- a/cmd/whois.go +++ b/cmd/whois.go @@ -25,12 +25,12 @@ func displayData(domainInfo apis.DomainInfo) { fmt.Printf("Updated Date: %s\n", domainInfo.Domain.UpdatedDate) fmt.Printf("Expiration Date: %s\n", domainInfo.Domain.ExpirationDate) - color.Blue("\nRegistrar Information:") + color.Blue("\nRegistrar Information") fmt.Printf("Registrar Name: %s\n", domainInfo.Registrar.Name) fmt.Printf("Registrar Phone: %s\n", domainInfo.Registrar.Phone) fmt.Printf("Registrar Email: %s\n", domainInfo.Registrar.Email) - color.Blue("\nRegistrant Information:") + color.Blue("\nRegistrant Information") fmt.Printf("Registrant Name: %s\n", domainInfo.Registrant.Name) fmt.Printf("Registrant Organization: %s\n", domainInfo.Registrant.Organization) fmt.Printf("Registrant Country: %s\n", domainInfo.Registrant.Country) diff --git a/cmd/constants.go b/internal/util/regex.go similarity index 97% rename from cmd/constants.go rename to internal/util/regex.go index f2039e0..75f01aa 100644 --- a/cmd/constants.go +++ b/internal/util/regex.go @@ -4,7 +4,7 @@ Copyright © 2024 Alessandro Riva Licensed under the MIT License. See the LICENSE file for details. */ -package cmd +package util import "regexp"