├── .gitignore ├── LICENSE ├── README.md ├── go.mod └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 j3ssie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | str-replace 2 | ============================= 3 | Simple tools to handle string and generate subdomain permutations 4 | 5 | ## Install 6 | 7 | ```bash 8 | go install github.com/j3ssie/str-replace@latest 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```bash 14 | # Build the wordlist by splitting subdomains as '.' string 15 | cat list-of-subdomain.txt | str-replace -d '.' -n 16 | 17 | # Build permutation subdomains from the wordlist from the existing subdomains 18 | # This will replace every part of the subdomain except the tld with the wordlist provided 19 | cat list-of-subdomain.txt | str-replace -W wordlists.txt -tld example.com 20 | 21 | ``` 22 | 23 | ## Don't know how to use it? Well, This is already integrated into the Osmedeus workflow. 24 | 25 |
26 |
27 |
28 | This project was part of Osmedeus Engine. Check out how it was integrated at @OsmedeusEngine 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/j3ssie/str-replace 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "strings" 9 | "sync" 10 | ) 11 | 12 | // Simple tools to handle string and subdomain permutations 13 | // cat list-of-subdomain.txt | str-replace -d '.' -j ',' 14 | 15 | // build the wordlist 16 | // cat list-of-subdomain.txt | str-replace -d '.' -n 17 | 18 | // append the wordlist to existing subdomain 19 | // cat list-of-subdomain.txt | str-replace -W wordlists.txt -j '.' -s 20 | // cat list-of-subdomain.txt | str-replace -W wordlists.txt -j '.' -e 21 | // cat list-of-subdomain.txt | str-replace -W wordlists.txt -tld example.com 22 | 23 | var ( 24 | delimiterString string 25 | joinString string 26 | data []string 27 | result []string 28 | wordLists string 29 | stripString string 30 | word string 31 | tld string 32 | //newLine bool 33 | startOfLine bool 34 | endOfLine bool 35 | joinNewline bool 36 | concurrency int 37 | ) 38 | 39 | func main() { 40 | // cli arguments 41 | flag.IntVar(&concurrency, "c", 20, "Set the concurrency level") 42 | flag.StringVar(&delimiterString, "d", ",", "Delimiter char to split") 43 | flag.StringVar(&joinString, "j", " ", "String to join after split") 44 | flag.StringVar(&stripString, "strip", "", "String to strip before split") 45 | 46 | flag.StringVar(&word, "w", "", "word to replace") 47 | flag.StringVar(&wordLists, "W", "", "Wordlist to replace") 48 | flag.StringVar(&tld, "tld", "", "Top level domain (e.g: example.com)") 49 | 50 | flag.BoolVar(&startOfLine, "s", false, "Adding word at start of line") 51 | flag.BoolVar(&endOfLine, "e", false, "Adding word at end of line") 52 | 53 | flag.BoolVar(&joinNewline, "n", false, "Join the result with new line after split") 54 | flag.Parse() 55 | 56 | if wordLists != "" { 57 | data = ReadingLines(wordLists) 58 | } 59 | if word != "" { 60 | data = append(data, word) 61 | } 62 | 63 | if joinNewline { 64 | joinString = "\n" 65 | } 66 | if joinString == "nN" { 67 | joinString = "\n" 68 | } 69 | 70 | var wg sync.WaitGroup 71 | jobs := make(chan string, concurrency) 72 | 73 | for i := 0; i < concurrency; i++ { 74 | wg.Add(1) 75 | go func() { 76 | defer wg.Done() 77 | for line := range jobs { 78 | if stripString != "" { 79 | line = strings.Trim(line, stripString) 80 | } 81 | handleString(line) 82 | } 83 | }() 84 | } 85 | 86 | sc := bufio.NewScanner(os.Stdin) 87 | go func() { 88 | for sc.Scan() { 89 | line := strings.TrimSpace(sc.Text()) 90 | if err := sc.Err(); err == nil && line != "" { 91 | jobs <- line 92 | } 93 | } 94 | close(jobs) 95 | }() 96 | wg.Wait() 97 | 98 | if len(result) > 0 { 99 | fmt.Println(strings.Join(result, joinString)) 100 | } 101 | } 102 | 103 | func handleStringWithWordlist(raw string) { 104 | for _, replaceWord := range data { 105 | replaceWord = strings.TrimSpace(replaceWord) 106 | if replaceWord == "" { 107 | continue 108 | } 109 | 110 | if startOfLine { 111 | line := fmt.Sprintf("%s%s%s", replaceWord, joinString, raw) 112 | fmt.Println(line) 113 | continue 114 | } 115 | 116 | if endOfLine { 117 | line := fmt.Sprintf("%s%s%s", raw, joinString, replaceWord) 118 | fmt.Println(line) 119 | continue 120 | } 121 | 122 | line := strings.Replace(raw, replaceWord, joinString, -1) 123 | fmt.Println(line) 124 | } 125 | } 126 | 127 | func handleStringWithTLD(raw string) { 128 | if strings.Count(raw, tld) < 1 { 129 | return 130 | } 131 | if strings.Count(raw, ".") < 1 { 132 | return 133 | } 134 | sub := strings.Trim(strings.Split(raw, tld)[0], ".") 135 | subWords := strings.Split(sub, ".") 136 | for _, subWord := range subWords { 137 | for _, replaceWord := range data { 138 | replaceWord = strings.TrimSpace(replaceWord) 139 | if replaceWord == "" { 140 | continue 141 | } 142 | subdomain := strings.Replace(raw, subWord, replaceWord, -1) 143 | if strings.Contains(subdomain, tld) { 144 | fmt.Println(subdomain) 145 | } 146 | 147 | } 148 | } 149 | } 150 | 151 | func handleString(raw string) { 152 | if wordLists != "" { 153 | if tld != "" { 154 | handleStringWithTLD(raw) 155 | } else { 156 | handleStringWithWordlist(raw) 157 | } 158 | return 159 | } 160 | 161 | if !strings.Contains(raw, delimiterString) { 162 | result = append(result, raw) 163 | fmt.Println(strings.Join(result, joinString)) 164 | return 165 | } 166 | 167 | result = strings.Split(raw, delimiterString) 168 | fmt.Println(strings.Join(result, joinString)) 169 | } 170 | 171 | // ReadingLines Reading file and return content as []string 172 | func ReadingLines(filename string) []string { 173 | var result []string 174 | file, err := os.Open(filename) 175 | if err != nil { 176 | return result 177 | } 178 | defer file.Close() 179 | 180 | scanner := bufio.NewScanner(file) 181 | for scanner.Scan() { 182 | val := strings.TrimSpace(scanner.Text()) 183 | if val == "" { 184 | continue 185 | } 186 | result = append(result, val) 187 | } 188 | 189 | if err := scanner.Err(); err != nil { 190 | return result 191 | } 192 | return result 193 | } 194 | --------------------------------------------------------------------------------