Guest User

Mudge

a guest
May 12th, 2023
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 7.63 KB | Source Code | 0 0
  1. // Package worker provides all the Mudge functions.
  2. package worker
  3.  
  4. import (
  5.     "bufio"
  6.     "fmt"
  7.     "io"
  8.     "os"
  9.     "runtime"
  10.     "sort"
  11.     "strings"
  12.     "sync"
  13.     "unicode"
  14.  
  15.     "github.com/redactedUsername/munge/models"
  16.     "github.com/spf13/cobra"
  17. )
  18.  
  19. var (
  20.     leetSpeakMap = map[string]string{
  21.         "e": "3",
  22.         "a": "4",
  23.         "i": "!",
  24.         "o": "0",
  25.         "s": "$",
  26.     }
  27.     level2Postfix = []string{
  28.         "1", "123456", "12", "2", "123", "!", ".",
  29.         "?", "_", "0", "01", "69", "21", "22", "23", "1234",
  30.         "8", "9", "10", "11", "13", "3", "4", "5", "6", "7",
  31.     }
  32.     level3Postfix = []string{
  33.         "07", "08", "09", "14", "15", "16", "17", "18", "19", "24", "77",
  34.         "88", "99", "12345", "123456789", "00", "02", "03", "04", "05", "06",
  35.         "19", "20", "25", "26", "27", "28", "007", "1234567", "12345678", "111111",
  36.         "111", "777", "666", "101", "33", "44", "55", "66", "2008", "2009", "2010",
  37.         "2011", "86", "87", "89", "90", "91", "92", "93", "94", "95", "98",
  38.     }
  39. )
  40.  
  41. // mudge mutates the words based on level, sorts and removes duplicates before returning
  42. // a slice of mutated words
  43. func munge(word string, level int) []string {
  44.     var mutatedWord []string
  45.     switch level {
  46.     case 1:
  47.         mutatedWord = basic(word)
  48.     case 2:
  49.         mutatedWord = advanced(word)
  50.     case 3:
  51.         mutatedWord = expert(word)
  52.     }
  53.  
  54.     // sort the mutated words and remove duplicates
  55.     sort.SliceStable(mutatedWord, func(i, j int) bool {
  56.         return mutatedWord[i] < mutatedWord[j]
  57.     })
  58.     mutatedWord = removeDuplicateStr(mutatedWord)
  59.  
  60.     return mutatedWord
  61. }
  62.  
  63. // swapcase function toggles characters from lowercase to uppercase and vise-versa
  64. func swapcase(word string) string {
  65.     swapped := ""
  66.     for _, char := range word {
  67.         if unicode.IsUpper(char) {
  68.             swapped += strings.ToLower(string(char))
  69.         } else if unicode.IsLower(char) {
  70.             swapped += strings.ToUpper(string(char))
  71.         } else {
  72.             swapped += string(char)
  73.         }
  74.     }
  75.     return swapped
  76. }
  77.  
  78. // replace mutates strings to leetspeak and appends commonly used numbers to it before returning a
  79. // slice of mutated words
  80. func replace(word string, chars map[string]string, nums []string) []string {
  81.     var wordlist []string
  82.     for char, val := range chars {
  83.         word = strings.ReplaceAll(word, char, val)
  84.         wordlist = append(wordlist, word)
  85.         for _, val = range nums {
  86.             wordlist = append(wordlist, word+val)
  87.  
  88.         }
  89.     }
  90.     return wordlist
  91. }
  92.  
  93. // removeDuplicateStr removes all duplicate strings
  94. func removeDuplicateStr(strSlice []string) []string {
  95.     allKeys := make(map[string]bool)
  96.     list := []string{}
  97.     for _, item := range strSlice {
  98.         if _, value := allKeys[item]; !value {
  99.             allKeys[item] = true
  100.             list = append(list, item)
  101.         }
  102.     }
  103.     return list
  104. }
  105.  
  106. // basic function does basic level mutiations and returns a wordlist
  107. func basic(word string) []string {
  108.     var wordlist []string
  109.  
  110.     wordlist = append(wordlist, word)
  111.     wordlist = append(wordlist, strings.ToUpper(word))
  112.  
  113.     wordToTitleCase := strings.ToTitle(word)
  114.     wordlist = append(wordlist, wordToTitleCase)
  115.     wordlist = append(wordlist, swapcase(wordToTitleCase))
  116.  
  117.     return wordlist
  118. }
  119.  
  120. // advanced function does level 2 mutations
  121. func advanced(word string) []string {
  122.     var wordlist []string
  123.  
  124.     wordlist = append(wordlist, basic(word)...)
  125.     wordlist = append(wordlist, replace(word, leetSpeakMap, level2Postfix)...)
  126.  
  127.     return wordlist
  128. }
  129.  
  130. // expert function does level 3 mutations
  131. func expert(word string) []string {
  132.     var wordlist []string
  133.  
  134.     wordlist = append(wordlist, advanced(word)...)
  135.     wordlist = append(wordlist, replace(word, leetSpeakMap, level3Postfix)...)
  136.  
  137.     return wordlist
  138. }
  139.  
  140. // Start function does all the mudging
  141. func Start(cmd *cobra.Command, flagvals models.Flags) {
  142.     var wordlist []string
  143.     // Create a task queue channel to hold the mutation tasks
  144.     taskQueue := make(chan string)
  145.  
  146.     // Create a completed queue channel to hold the results of muation tasks
  147.     completedQueue := make(chan string)
  148.  
  149.     // Create a WaitGroup to wait for all Goroutines to finish
  150.     var wg sync.WaitGroup
  151.  
  152.     if flagvals.Level > 3 {
  153.         flagvals.Level = 3
  154.     } else if flagvals.Level < 0 {
  155.         flagvals.Level = 0
  156.     }
  157.  
  158.     if flagvals.Word != "" {
  159.         // We don't need the task queue if we are just working with a word
  160.         close(taskQueue)
  161.  
  162.         // if a word was passed in, just munge that
  163.         wordlist = munge(flagvals.Word, flagvals.Level)
  164.         wg.Add(1)
  165.         go func() {
  166.             defer wg.Done()
  167.  
  168.             for _, finalWord := range wordlist {
  169.                 completedQueue <- finalWord
  170.             }
  171.             println("Completed adding words to completed queue")
  172.         }()
  173.  
  174.     } else if _, err := os.Stat(flagvals.Input); err == nil {
  175.         // Now that we confirmed that the input file exist, we can now
  176.         // open the input file and start reading
  177.         println("Initiating input file read: ", flagvals.Input)
  178.         inputFile, err := os.Open(flagvals.Input)
  179.         if err != nil {
  180.             fmt.Printf("Failed to open input file: %v \n", err)
  181.             return
  182.         }
  183.         defer inputFile.Close()
  184.  
  185.         // Create a reader to read the file line by line
  186.         reader := bufio.NewReader(inputFile)
  187.         wg.Add(1)
  188.         go func() {
  189.             defer close(taskQueue)
  190.             defer wg.Done()
  191.             // Read the file and distribute mutation tasks among Goroutines
  192.             for {
  193.                 // Read a line from the file
  194.                 word, err := reader.ReadString('\n')
  195.                 if err != nil {
  196.                     if err != io.EOF {
  197.                         fmt.Println("Error reading from file:", err)
  198.                     }
  199.                     break // Exit the loop when done reading
  200.                 }
  201.                 println("Pushed: ", word)
  202.                 // Push the word into the task queue for processing by a Goroutine
  203.                 taskQueue <- word
  204.             }
  205.         }()
  206.  
  207.         // Determine the maximum number of Goroutines based on the available CPU cores
  208.         maxGoroutines := runtime.NumCPU()
  209.         println("Identified Max number of Go routines: ", maxGoroutines)
  210.         var agentID int
  211.         // Create the worker pool
  212.         for i := 0; i < maxGoroutines; i++ {
  213.             // Increment the WaitGroup counter for each Goroutine
  214.             wg.Add(1)
  215.             agentID = i
  216.             println("Launchig agent: ", agentID)
  217.             // Launch a Goroutine as a worker
  218.             go func() {
  219.                 defer wg.Done() // Decrement the WaitGroup counter when the Goroutine completes
  220.                 println("Agent launched: ", agentID)
  221.                 // Process tasks from the task queue
  222.                 for word := range taskQueue {
  223.                     mutatedList := munge(word, flagvals.Level) // Call the mutation function on the word
  224.                     for _, mutation := range mutatedList {
  225.                         if mutation != "" {
  226.                             fmt.Printf("Agent %d Pushed %v", agentID, mutation)
  227.                             completedQueue <- mutation
  228.                         }
  229.                     }
  230.                 }
  231.  
  232.             }()
  233.         }
  234.         // Close the task queue to signal that no more tasks will be added
  235.         // defer close(taskQueue)
  236.  
  237.     } else {
  238.         close(completedQueue)
  239.         close(taskQueue)
  240.         cmd.Help()
  241.         return
  242.     }
  243.  
  244.     if flagvals.Output != "" {
  245.         println("Creating output file")
  246.         // create an output outputFile or just print the data using an if else.
  247.         outputFile, err := os.Create(flagvals.Output)
  248.         if err != nil {
  249.             fmt.Printf("Error creating output file: %v \n", err)
  250.             return
  251.         }
  252.         defer outputFile.Close()
  253.         wg.Add(1)
  254.         go func() {
  255.             defer close(completedQueue)
  256.             defer wg.Done()
  257.             // println("Launched file write go routine")
  258.             for finalWord := range completedQueue {
  259.                 println("Wrote: ", finalWord)
  260.                 _, err := outputFile.WriteString(finalWord)
  261.                 if err != nil {
  262.                     fmt.Println("Error writing to file:", err)
  263.                     return
  264.                 }
  265.             }
  266.             println("completed!")
  267.         }()
  268.  
  269.         // fmt.Println("Word list written to file successfully.")
  270.     } else {
  271.         go func() {
  272.             // println("Reading words from completed queue")
  273.             // Read the mutated words from the mutations channel
  274.             for finalWord := range completedQueue {
  275.                 fmt.Println("Mutated word:", finalWord)
  276.             }
  277.  
  278.         }()
  279.  
  280.     }
  281.     defer close(completedQueue)
  282.     // Wait for all Goroutines to finish before exiting the program
  283.     wg.Wait()
  284. }
Tags: golang
Advertisement
Add Comment
Please, Sign In to add comment