├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── six.txt └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .DS_STORE 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.0.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "anstream" 16 | version = "0.3.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" 19 | dependencies = [ 20 | "anstyle", 21 | "anstyle-parse", 22 | "anstyle-query", 23 | "anstyle-wincon", 24 | "colorchoice", 25 | "is-terminal", 26 | "utf8parse", 27 | ] 28 | 29 | [[package]] 30 | name = "anstyle" 31 | version = "1.0.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" 34 | 35 | [[package]] 36 | name = "anstyle-parse" 37 | version = "0.2.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" 40 | dependencies = [ 41 | "utf8parse", 42 | ] 43 | 44 | [[package]] 45 | name = "anstyle-query" 46 | version = "1.0.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 49 | dependencies = [ 50 | "windows-sys", 51 | ] 52 | 53 | [[package]] 54 | name = "anstyle-wincon" 55 | version = "1.0.1" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" 58 | dependencies = [ 59 | "anstyle", 60 | "windows-sys", 61 | ] 62 | 63 | [[package]] 64 | name = "atty" 65 | version = "0.2.14" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 68 | dependencies = [ 69 | "hermit-abi 0.1.19", 70 | "libc", 71 | "winapi", 72 | ] 73 | 74 | [[package]] 75 | name = "bitflags" 76 | version = "1.3.2" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 79 | 80 | [[package]] 81 | name = "cc" 82 | version = "1.0.79" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 85 | 86 | [[package]] 87 | name = "clap" 88 | version = "4.2.7" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" 91 | dependencies = [ 92 | "clap_builder", 93 | "clap_derive", 94 | "once_cell", 95 | ] 96 | 97 | [[package]] 98 | name = "clap_builder" 99 | version = "4.2.7" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" 102 | dependencies = [ 103 | "anstream", 104 | "anstyle", 105 | "bitflags", 106 | "clap_lex", 107 | "strsim", 108 | ] 109 | 110 | [[package]] 111 | name = "clap_derive" 112 | version = "4.2.0" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" 115 | dependencies = [ 116 | "heck", 117 | "proc-macro2", 118 | "quote", 119 | "syn", 120 | ] 121 | 122 | [[package]] 123 | name = "clap_lex" 124 | version = "0.4.1" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" 127 | 128 | [[package]] 129 | name = "colorchoice" 130 | version = "1.0.0" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 133 | 134 | [[package]] 135 | name = "errno" 136 | version = "0.3.1" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" 139 | dependencies = [ 140 | "errno-dragonfly", 141 | "libc", 142 | "windows-sys", 143 | ] 144 | 145 | [[package]] 146 | name = "errno-dragonfly" 147 | version = "0.1.2" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 150 | dependencies = [ 151 | "cc", 152 | "libc", 153 | ] 154 | 155 | [[package]] 156 | name = "heck" 157 | version = "0.4.1" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 160 | 161 | [[package]] 162 | name = "hermit-abi" 163 | version = "0.1.19" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 166 | dependencies = [ 167 | "libc", 168 | ] 169 | 170 | [[package]] 171 | name = "hermit-abi" 172 | version = "0.3.1" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 175 | 176 | [[package]] 177 | name = "io-lifetimes" 178 | version = "1.0.10" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" 181 | dependencies = [ 182 | "hermit-abi 0.3.1", 183 | "libc", 184 | "windows-sys", 185 | ] 186 | 187 | [[package]] 188 | name = "is-terminal" 189 | version = "0.4.7" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" 192 | dependencies = [ 193 | "hermit-abi 0.3.1", 194 | "io-lifetimes", 195 | "rustix", 196 | "windows-sys", 197 | ] 198 | 199 | [[package]] 200 | name = "libc" 201 | version = "0.2.144" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" 204 | 205 | [[package]] 206 | name = "linux-raw-sys" 207 | version = "0.3.7" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" 210 | 211 | [[package]] 212 | name = "memchr" 213 | version = "2.5.0" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 216 | 217 | [[package]] 218 | name = "once_cell" 219 | version = "1.17.1" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" 222 | 223 | [[package]] 224 | name = "proc-macro2" 225 | version = "1.0.57" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" 228 | dependencies = [ 229 | "unicode-ident", 230 | ] 231 | 232 | [[package]] 233 | name = "quote" 234 | version = "1.0.27" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" 237 | dependencies = [ 238 | "proc-macro2", 239 | ] 240 | 241 | [[package]] 242 | name = "regex" 243 | version = "1.8.1" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" 246 | dependencies = [ 247 | "aho-corasick", 248 | "memchr", 249 | "regex-syntax", 250 | ] 251 | 252 | [[package]] 253 | name = "regex-syntax" 254 | version = "0.7.1" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" 257 | 258 | [[package]] 259 | name = "rustix" 260 | version = "0.37.19" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" 263 | dependencies = [ 264 | "bitflags", 265 | "errno", 266 | "io-lifetimes", 267 | "libc", 268 | "linux-raw-sys", 269 | "windows-sys", 270 | ] 271 | 272 | [[package]] 273 | name = "strsim" 274 | version = "0.10.0" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 277 | 278 | [[package]] 279 | name = "syn" 280 | version = "2.0.16" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" 283 | dependencies = [ 284 | "proc-macro2", 285 | "quote", 286 | "unicode-ident", 287 | ] 288 | 289 | [[package]] 290 | name = "typewriter" 291 | version = "0.1.0" 292 | dependencies = [ 293 | "atty", 294 | "clap", 295 | "regex", 296 | ] 297 | 298 | [[package]] 299 | name = "unicode-ident" 300 | version = "1.0.8" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" 303 | 304 | [[package]] 305 | name = "utf8parse" 306 | version = "0.2.1" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 309 | 310 | [[package]] 311 | name = "winapi" 312 | version = "0.3.9" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 315 | dependencies = [ 316 | "winapi-i686-pc-windows-gnu", 317 | "winapi-x86_64-pc-windows-gnu", 318 | ] 319 | 320 | [[package]] 321 | name = "winapi-i686-pc-windows-gnu" 322 | version = "0.4.0" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 325 | 326 | [[package]] 327 | name = "winapi-x86_64-pc-windows-gnu" 328 | version = "0.4.0" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 331 | 332 | [[package]] 333 | name = "windows-sys" 334 | version = "0.48.0" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 337 | dependencies = [ 338 | "windows-targets", 339 | ] 340 | 341 | [[package]] 342 | name = "windows-targets" 343 | version = "0.48.0" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" 346 | dependencies = [ 347 | "windows_aarch64_gnullvm", 348 | "windows_aarch64_msvc", 349 | "windows_i686_gnu", 350 | "windows_i686_msvc", 351 | "windows_x86_64_gnu", 352 | "windows_x86_64_gnullvm", 353 | "windows_x86_64_msvc", 354 | ] 355 | 356 | [[package]] 357 | name = "windows_aarch64_gnullvm" 358 | version = "0.48.0" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 361 | 362 | [[package]] 363 | name = "windows_aarch64_msvc" 364 | version = "0.48.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 367 | 368 | [[package]] 369 | name = "windows_i686_gnu" 370 | version = "0.48.0" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 373 | 374 | [[package]] 375 | name = "windows_i686_msvc" 376 | version = "0.48.0" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 379 | 380 | [[package]] 381 | name = "windows_x86_64_gnu" 382 | version = "0.48.0" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 385 | 386 | [[package]] 387 | name = "windows_x86_64_gnullvm" 388 | version = "0.48.0" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 391 | 392 | [[package]] 393 | name = "windows_x86_64_msvc" 394 | version = "0.48.0" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 397 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "typewriter" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | clap = { version = "4.2.7", features= ["derive"] } 10 | atty = "0.2.*" 11 | regex = "1.8.*" 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Typewriter

2 |

Typewriter is a subdomain permutation tool written in Rust and heavily based on Gotator.

3 | 4 | ## Features 5 | - Permutations with the `-` character! 6 | - Unlimited depth, limited only by your computer! 7 | - Deduplication by default! 8 | --- 9 | 10 | ## Installation 11 | `git clone https://github.com/projectmonke/typewriter && cd typewriter && cargo build --release && cp target/release/typewriter .` 12 | 13 | ## Usage 14 | ### Required 15 | - `-i` specifies a single domain 16 | - `-w` specifies the wordlist of permutations (Six2dez's `six.txt` is provided) 17 | - `-f` specifies the wordlist containing a list of subdomains to perform permutations on. 18 | - `-s` specifies that you are reading subdomain data from stdin. 19 | 20 | ### Optional 21 | - `-d` specifies the depth of the permutations (dev.test1.example.com is depth 2, and so on). 22 | - `-r` specifies the range that you want to try for subdomains with numbers (such as test1.example.com). 23 | 24 | ## Example 25 | [puredns](https://github.com/d3mondev/puredns) is recommended for resolving subdomains. 26 | - `./typewriter -w six.txt -i example.com -d 2 > results.txt` 27 | - `subfinder -d example.com | ./typewriter -w six.txt -s -r 5 -d 2` 28 | 29 | ## Limitations 30 | - Domain validation is not robust at all. Still fixing this. 31 | 32 | ## To Do 33 | - Flag for writing to an output file. 34 | - Support for infinitely recursive permutation generation. 35 | - More robust domain checks using an array of TLDs to validate the strings. 36 | -------------------------------------------------------------------------------- /six.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 10 3 | 11 4 | 12 5 | 13 6 | 14 7 | 15 8 | 16 9 | 17 10 | 18 11 | 19 12 | 2 13 | 20 14 | 2017 15 | 2018 16 | 2019 17 | 2020 18 | 2021 19 | 2022 20 | 3 21 | 4 22 | 5 23 | 6 24 | 7 25 | 8 26 | 9 27 | a 28 | acc 29 | accept 30 | acceptatie 31 | access 32 | account 33 | accounting 34 | accounts 35 | ad 36 | addon 37 | addons 38 | adm 39 | admin 40 | admin1 41 | administrator 42 | ads 43 | adserver 44 | affiliate 45 | agenda 46 | akali 47 | akamai 48 | alpha 49 | alt 50 | alumni 51 | america 52 | analytics 53 | ann 54 | apache 55 | api 56 | api-docs 57 | api1 58 | apis 59 | apollo 60 | app 61 | apps 62 | april 63 | ar 64 | archive 65 | art 66 | assets 67 | atlas 68 | auth 69 | auto 70 | autoconfig 71 | autodiscover 72 | av 73 | aws 74 | ayuda 75 | b 76 | b2b 77 | backend 78 | backup 79 | backups 80 | banner 81 | barracuda 82 | bb 83 | bbs 84 | beta 85 | biblioteca 86 | billing 87 | blackboard 88 | blog 89 | blogs 90 | board 91 | boards 92 | book 93 | booking 94 | bookings 95 | box 96 | brand 97 | brasil 98 | brazil 99 | broadcast-ip 100 | bsd 101 | bt 102 | bucket 103 | bucky 104 | bug 105 | bugs 106 | business 107 | c 108 | ca 109 | cache 110 | cacti 111 | cal 112 | calendar 113 | cam 114 | careers 115 | cart 116 | cas 117 | catalog 118 | cc 119 | cctv 120 | cdn 121 | cf 122 | cfg 123 | chat 124 | chef 125 | chimera 126 | chronos 127 | ci 128 | cisco 129 | citrix 130 | classroom 131 | client 132 | clients 133 | cloud 134 | cloudflare-resolve-to 135 | cloudfront 136 | club 137 | cms 138 | cms1 139 | cn 140 | co 141 | com 142 | community 143 | conf 144 | conference 145 | config 146 | confluence 147 | connect 148 | contact 149 | contacts 150 | container 151 | content 152 | control 153 | controller 154 | controlp 155 | controlpanel 156 | corp 157 | corporate 158 | correo 159 | correoweb 160 | cp 161 | cpanel 162 | crm 163 | cs 164 | css 165 | customers 166 | cvs 167 | d 168 | da 169 | data 170 | database 171 | db 172 | dbadmin 173 | dbs 174 | dc 175 | dd 176 | de 177 | dec 178 | default 179 | demo 180 | demon 181 | demostration 182 | deploy 183 | des 184 | descargas 185 | design 186 | designs 187 | desktop 188 | dev 189 | dev1 190 | devel 191 | developer 192 | developers 193 | development 194 | devenv 195 | devops 196 | dialin 197 | diana 198 | direct 199 | directory 200 | dl 201 | dmz 202 | dns 203 | doc 204 | docker 205 | docs 206 | domain 207 | domain-controller 208 | domainadmin 209 | domaincontrol 210 | domaincontroller 211 | domaincontrolpanel 212 | domainmanagement 213 | domains 214 | download 215 | downloads 216 | drop 217 | drupal 218 | e 219 | eaccess 220 | echo 221 | ecommerce 222 | edge 223 | edu 224 | ektron 225 | elasticbeanstalk 226 | elb 227 | elearning 228 | email 229 | en 230 | eng 231 | engima 232 | engine 233 | engineering 234 | english 235 | enterpriseenrollment 236 | enterpriseregistration 237 | erp 238 | es 239 | eu 240 | europe 241 | europewest 242 | euw 243 | euwe 244 | evelynn 245 | event 246 | events 247 | ex 248 | example 249 | examples 250 | exchange 251 | external 252 | extranet 253 | f 254 | facebook 255 | faq 256 | fax 257 | fb 258 | feb 259 | feedback 260 | feeds 261 | fet 262 | file 263 | files 264 | fileserver 265 | finance 266 | firewall 267 | folders 268 | forms 269 | foro 270 | foros 271 | forum 272 | forums 273 | foto 274 | fr 275 | free 276 | freebsd 277 | frontpage 278 | fs 279 | ftp 280 | ftp1 281 | ftpadmin 282 | ftpd 283 | fw 284 | g 285 | galeria 286 | gallery 287 | game 288 | games 289 | gate 290 | gateway 291 | germany 292 | gh 293 | ghcpi 294 | gilford 295 | gis 296 | git 297 | github 298 | gitlab 299 | global 300 | gmail 301 | go 302 | google 303 | groups 304 | groupwise 305 | gu 306 | guest 307 | guia 308 | guide 309 | gw 310 | h 311 | health 312 | help 313 | helpdesk 314 | hera 315 | heracles 316 | hercules 317 | hermes 318 | hkg 319 | home 320 | homer 321 | host 322 | hosting 323 | hotspot 324 | hr 325 | hw 326 | hwcdn 327 | hypernova 328 | i 329 | id 330 | idp 331 | ids 332 | im 333 | image 334 | images 335 | imail 336 | imap 337 | imap3d 338 | imapd 339 | imaps 340 | img 341 | imgs 342 | imogen 343 | in 344 | incoming 345 | info 346 | infra 347 | inmuebles 348 | int 349 | inte 350 | integration 351 | inter 352 | internal 353 | interno 354 | intra 355 | intranet 356 | io 357 | ip 358 | ipfixe 359 | iphone 360 | ipmi 361 | ipsec 362 | ipv4 363 | irc 364 | ircd 365 | is 366 | isa 367 | it 368 | j 369 | ja 370 | jabber 371 | jboss 372 | jenkins 373 | jinx 374 | jira 375 | job 376 | jobs 377 | jp 378 | js 379 | july 380 | june 381 | jupiter 382 | k 383 | kb 384 | kerberos 385 | kor 386 | korea 387 | kr 388 | l 389 | la 390 | lab 391 | laboratories 392 | laboratorio 393 | laboratory 394 | labs 395 | lan 396 | las 397 | latin 398 | latinamerica 399 | lax 400 | lax1 401 | lb 402 | ldap 403 | legacy 404 | lib 405 | library 406 | link 407 | links 408 | linux 409 | lisa 410 | list 411 | lists 412 | live 413 | lms 414 | loadbalancer 415 | local 416 | localhost 417 | log 418 | loghost 419 | login 420 | logon 421 | logs 422 | london 423 | loopback 424 | love 425 | lp 426 | lync 427 | lyncdiscover 428 | m 429 | machine 430 | magento 431 | mail 432 | mailadmin 433 | mailbackup 434 | mailbox 435 | mailer 436 | mailgate 437 | mailhost 438 | mailing 439 | mailman 440 | mailserver 441 | main 442 | manage 443 | manager 444 | mantis 445 | map 446 | maps 447 | march 448 | market 449 | marketing 450 | mars 451 | master 452 | math 453 | mb 454 | mc 455 | mdm 456 | media 457 | meet 458 | member 459 | members 460 | merch 461 | mercury 462 | meta 463 | miembros 464 | mijn 465 | minerva 466 | mirror 467 | ml 468 | mm 469 | mob 470 | mobil 471 | mobile 472 | mon 473 | monitor 474 | monitoring 475 | moodle 476 | movil 477 | mrtg 478 | ms 479 | msoid 480 | mssql 481 | munin 482 | music 483 | mx 484 | mx-a 485 | mx-b 486 | my 487 | mysql 488 | n 489 | na 490 | nagios 491 | nas 492 | nat 493 | nautilus 494 | nelson 495 | neon 496 | net 497 | netherlands 498 | netmail 499 | netscaler 500 | network 501 | network-ip 502 | networks 503 | new 504 | newmail 505 | news 506 | newsgroups 507 | newsite 508 | newsletter 509 | nginx 510 | nl 511 | noc 512 | node 513 | northamerica 514 | nov 515 | novell 516 | ns 517 | nt 518 | ntp 519 | o 520 | oa 521 | oceania 522 | oct 523 | office 524 | old 525 | oldmail 526 | oldsite 527 | oldwww 528 | on 529 | one 530 | online 531 | op 532 | openbsd 533 | operation 534 | operations 535 | ops 536 | ora 537 | oracle 538 | org 539 | origin 540 | orion 541 | os 542 | osx 543 | ou 544 | outgoing 545 | outlook 546 | owa 547 | ox 548 | p 549 | page 550 | painel 551 | panel 552 | pantheon 553 | partner 554 | partners 555 | pass 556 | pay 557 | payment 558 | payments 559 | pbx 560 | pc 561 | pcanywhere 562 | pda 563 | pegasus 564 | pendrell 565 | personal 566 | pgsql 567 | phoenix 568 | photo 569 | photos 570 | php 571 | phpmyadmin 572 | pl 573 | plugins 574 | pm 575 | pma 576 | poczta 577 | poland 578 | pop 579 | portal 580 | portfolio 581 | post 582 | postgres 583 | postgresql 584 | postman 585 | postmaster 586 | pp 587 | ppp 588 | pr 589 | prd 590 | pre-prod 591 | pre-production 592 | preferences 593 | prep 594 | preprod 595 | press 596 | preview 597 | priv 598 | private 599 | pro 600 | prod 601 | produ 602 | production 603 | profile 604 | profiles 605 | project 606 | projects 607 | promo 608 | promotion 609 | proxy 610 | prueba 611 | pruebas 612 | pt 613 | pub 614 | public 615 | q 616 | qa 617 | qq 618 | quiz 619 | r 620 | ra 621 | radio 622 | radius 623 | ras 624 | rdp 625 | redir 626 | redirect 627 | redirector 628 | redmine 629 | region 630 | register 631 | relay 632 | remote 633 | repo 634 | report 635 | reports 636 | repos 637 | repository 638 | research 639 | reset 640 | resources 641 | restrict 642 | restricted 643 | review 644 | reviews 645 | robinhood 646 | root 647 | router 648 | rss 649 | rt 650 | rtmp 651 | ru 652 | s 653 | s3 654 | sa 655 | sales 656 | sample 657 | samples 658 | sandbox 659 | sap 660 | sc 661 | search 662 | secure 663 | security 664 | seo 665 | sept 666 | server 667 | service 668 | services 669 | sftp 670 | share 671 | sharepoint 672 | shell 673 | shop 674 | shopping 675 | signup 676 | singed 677 | sip 678 | site 679 | siteadmin 680 | sitebuilder 681 | sites 682 | skins 683 | skype 684 | slave 685 | sms 686 | smtp 687 | snmp 688 | social 689 | software 690 | solaris 691 | soporte 692 | sp 693 | spam 694 | speedtest 695 | sport 696 | sports 697 | spring 698 | sql 699 | sqlserver 700 | squirrel 701 | squirrelmail 702 | ssh 703 | ssl 704 | sslvpn 705 | sso 706 | st 707 | staff 708 | stag 709 | stage 710 | stage1 711 | staging 712 | start 713 | stat 714 | static 715 | stats 716 | status 717 | stg 718 | storage 719 | store 720 | stream 721 | streaming 722 | student 723 | sun 724 | support 725 | survey 726 | sv 727 | svn 728 | swagger 729 | system 730 | t 731 | team 732 | tech 733 | telewerk 734 | telework 735 | temp 736 | test 737 | test1 738 | testbed 739 | testing 740 | testing1 741 | testsite 742 | testweb 743 | tfs 744 | tftp 745 | threestage 746 | thumbs 747 | ticket 748 | tickets 749 | time 750 | tomcat 751 | tool 752 | tools 753 | tpe 754 | tr 755 | trac 756 | track 757 | tracker 758 | tracking 759 | train 760 | training 761 | travel 762 | trial 763 | ts 764 | tst 765 | tunnel 766 | tur 767 | turk 768 | turkey 769 | tutorials 770 | tv 771 | tw 772 | twitch 773 | two 774 | u 775 | uat 776 | uk 777 | unix 778 | up 779 | update 780 | upload 781 | uploads 782 | us 783 | user 784 | users 785 | v 786 | v1 787 | v2 788 | vc 789 | ventas 790 | version 791 | vi 792 | video 793 | videos 794 | vip 795 | virtual 796 | vista 797 | vle 798 | vm 799 | vms 800 | vmware 801 | vnc 802 | vod 803 | voip 804 | vpn 805 | vps 806 | w 807 | w3 808 | wap 809 | wc 810 | web 811 | web1 812 | webadmin 813 | webapp 814 | webcam 815 | webconf 816 | webct 817 | webdb 818 | webdisk 819 | weblog 820 | webmail 821 | webmaster 822 | webmin 823 | webservices 824 | webstats 825 | webstore 826 | westeurope 827 | whm 828 | wifi 829 | wiki 830 | win 831 | win32 832 | windows 833 | wordpress 834 | work 835 | wp 836 | ws 837 | wsus 838 | ww 839 | www 840 | www-test 841 | wwwm 842 | wwwold 843 | wwww 844 | x 845 | xml 846 | y 847 | z 848 | zabbix 849 | zeus 850 | zimbra -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use atty; 2 | use regex::Regex; 3 | use std::fs::File; 4 | use std::str::FromStr; 5 | use std::error::Error; 6 | use clap::{ArgGroup, Parser}; 7 | use std::io::{self, BufRead}; 8 | use std::collections::HashSet; 9 | 10 | #[derive(Parser)] 11 | #[command(author = "Monke (https://hackerone.com/monke)", version = "1.0.0", about, long_about = None)] 12 | #[clap(group = ArgGroup::new("input").required(true).args(&["stdin", "filename", "domain"]))] 13 | struct Typewriter { 14 | /// The depth to generate subdomains at. 15 | #[clap(short = 'd', long = "depth", default_value = "1")] 16 | depth: i32, 17 | 18 | /// The amount of range for generating permutations with numbers in them such as test1.example.com. 19 | #[clap(short = 'r', long = "range", default_value = "1")] 20 | range: i32, 21 | 22 | /// Ingest subdomains from stdin 23 | #[clap(short = 's', long = "stdin")] 24 | stdin: bool, 25 | 26 | /// Generate permutations for one domain or subdomain 27 | #[clap(short = 'i', long = "input")] 28 | domain: Option, 29 | 30 | /// Ingest subdomains from a file 31 | #[clap(short = 'f', long = "file")] 32 | filename: Option, 33 | 34 | /// The wordlist to generate permutations with 35 | #[clap(short = 'w', long = "wordlist")] 36 | wordlist: String, 37 | } 38 | 39 | fn main() { 40 | let typewriter = Typewriter::parse(); 41 | let generated_permutations = generate_permutations(typewriter.wordlist, typewriter.range).expect("Failed to generate permutations"); 42 | 43 | if typewriter.stdin { 44 | if atty::is(atty::Stream::Stdin) { 45 | println!("No stdin found."); 46 | } else { 47 | let generated_domains: HashSet = io::stdin() 48 | .lock() 49 | .lines() 50 | .filter_map(Result::ok) 51 | .map(|line| line.replace(' ', "")) 52 | .filter(|line| line.split('.').count() >= 2) 53 | .collect::>(); 54 | 55 | for domain in generated_domains.iter(){ 56 | permutator(domain, &generated_domains, &generated_permutations, typewriter.depth, true); 57 | } 58 | } 59 | } else if let Some(file) = typewriter.filename { 60 | let generated_domains = generate_domains_from_file(file).expect("Failed to generate domains."); 61 | for domain in generated_domains.iter(){ 62 | permutator(domain, &generated_domains, &generated_permutations, typewriter.depth, true); 63 | } 64 | } else if let Some(domain) = typewriter.domain{ 65 | let mut generated_domains: HashSet = HashSet::new(); 66 | generated_domains.insert(domain.clone()); 67 | permutator(&domain, &generated_domains , &generated_permutations, typewriter.depth, true); 68 | } 69 | } 70 | 71 | fn permutator(domain: &str, domains: &HashSet, permutations: &HashSet, depth: i32, first_time: bool){ 72 | if depth < 1 { 73 | return 74 | } 75 | 76 | for permutation in permutations.iter(){ 77 | let joins = get_joins(domain, permutation, first_time); 78 | for join in joins.iter(){ 79 | let new_subdomain = format!("{}{}{}", permutation, join, domain); 80 | if new_subdomain.split('.').count() > 2{ 81 | if !domains.contains(&new_subdomain){ 82 | println!("{}", new_subdomain); 83 | permutator(&new_subdomain, domains, permutations, depth - 1, false); 84 | } 85 | } 86 | } 87 | if depth == 1 && first_time{ 88 | if domain.len() > 2 { 89 | let domain_split: Vec<&str> = domain.split('.').collect(); 90 | let first_item = domain_split[0]; 91 | let subdomain_first_item = first_item 92 | .chars() 93 | .filter(|c| !c.is_digit(10)) 94 | .collect::(); 95 | let new_permutation = permutation 96 | .chars() 97 | .filter(|c| !c 98 | .is_digit(10)) 99 | .collect::(); 100 | 101 | if subdomain_first_item != new_permutation && !subdomain_first_item.ends_with(&new_permutation) { 102 | let new_subdomain = format!("{}{}{}", first_item, permutation, domain_split[1..].join(".")); 103 | if new_subdomain.split('.').count() > 2{ 104 | if !domains.contains(&new_subdomain) { 105 | println!("{}", new_subdomain); 106 | } 107 | } 108 | 109 | let new_subdomain = format!("{}-{}{}", first_item, permutation, domain_split[1..].join(".")); 110 | if new_subdomain.split('.').count() > 2 { 111 | if !domains.contains(&new_subdomain) { 112 | println!("{}", new_subdomain); 113 | } 114 | } 115 | 116 | } 117 | } 118 | } 119 | } 120 | } 121 | 122 | fn generate_domains_from_file(filename: String) -> io::Result> { 123 | let domains_file = File::open(filename)?; 124 | let mut domains = HashSet::new(); 125 | 126 | for line in io::BufReader::new(domains_file).lines() { 127 | let line = line?; 128 | let cleaned_line = line.replace(' ', ""); 129 | if cleaned_line.split('.').count() < 2 || domains.contains(&cleaned_line) { 130 | continue; 131 | } 132 | domains.insert(cleaned_line); 133 | } 134 | Ok(domains.into_iter().collect()) 135 | } 136 | 137 | fn generate_permutations(filename: String, permutation_number: i32) -> io::Result> { 138 | let file = File::open(filename)?; 139 | let reader = io::BufReader::new(file); 140 | let mut new_permutations: HashSet = HashSet::new(); 141 | let numbers_pattern = Regex::new("\\d+").unwrap(); 142 | 143 | for line in reader.lines() { 144 | let line = line?; 145 | let cleaned_line = line.replace(' ', ""); 146 | if !new_permutations.insert(cleaned_line.clone()) { 147 | continue; 148 | } 149 | go_bananas(&mut new_permutations, &numbers_pattern, &cleaned_line, permutation_number).expect("Advanced permutation error."); 150 | 151 | let data: Vec = numbers_pattern.find_iter(&line) 152 | .map(|mat| mat.as_str().to_string()) 153 | .collect(); 154 | if !data.is_empty() { 155 | permutator_numbers(&mut new_permutations, &line, &data, permutation_number) 156 | .expect("Number permutation failed."); 157 | } 158 | } 159 | 160 | Ok(new_permutations.into_iter().collect()) 161 | } 162 | 163 | fn permutator_numbers( 164 | permutations: &mut HashSet, 165 | permutation: &str, 166 | data_to_replace: &Vec, 167 | permutator_number: i32 168 | ) -> Result<(), Box> { 169 | for num_to_replace in data_to_replace { 170 | let num = i32::from_str(num_to_replace)?; 171 | for i in 1..=permutator_number { 172 | let new_permutation = permutation.replace(num_to_replace, &(num + i).to_string()); 173 | permutations.insert(new_permutation); 174 | if num - i >= 0 { 175 | let new_permutation = permutation.replace(num_to_replace, &(num - i).to_string()); 176 | permutations.insert(new_permutation); 177 | } 178 | } 179 | } 180 | Ok(()) 181 | } 182 | 183 | fn go_bananas(permutations: &mut HashSet, num_pat: &Regex, data: &str, permutator_number: i32) -> Result<(), Box> { 184 | for new_split in data.split('-').filter(|s| !s.is_empty()) { 185 | let new_split = new_split.to_string(); 186 | if !permutations.contains(&new_split) { 187 | permutations.insert(new_split.clone()); 188 | let data: Vec<_> = num_pat 189 | .find_iter(&new_split) 190 | .map(|m| m.as_str().to_string()) 191 | .collect(); 192 | if !data.is_empty() && permutator_number > 0 { 193 | permutator_numbers(permutations, &new_split, &data, permutator_number)?; 194 | } 195 | } 196 | } 197 | Ok(()) 198 | } 199 | 200 | 201 | fn get_joins(domain: &str, permutation: &str, first_time: bool) -> Vec { 202 | let mut joins = vec![".".to_string(), "-".to_string()]; 203 | let number_prefix = domain.chars().next().map(|c| c.is_digit(10)).unwrap_or(false); 204 | 205 | if number_prefix && permutation.chars().last().map(|c| c.is_digit(10)).unwrap_or(false) { 206 | return joins; 207 | } 208 | 209 | if domain.split('.').count() == 2 && first_time{ 210 | joins.clear(); 211 | joins.push(".".to_string()); 212 | } 213 | 214 | let first_element = domain.split('.').next().unwrap_or(""); 215 | match first_element { 216 | _ if first_element == permutation => { 217 | joins.clear(); 218 | }, 219 | _ if permutation.len() >= 4 && first_element.starts_with(permutation) => { 220 | joins.clear(); 221 | joins.extend(vec![".".to_string(), "-".to_string()]); }, 222 | _ => { 223 | let subdomain_first_element = first_element.chars().filter(|c| !c.is_digit(10)).collect::(); 224 | let new_permutation = permutation.chars().filter(|c| !c.is_digit(10)).collect::(); 225 | if subdomain_first_element == new_permutation { 226 | joins.clear(); 227 | } else if subdomain_first_element.ends_with(&new_permutation) { 228 | joins.clear(); 229 | joins.push(".".to_string()); 230 | } 231 | } 232 | } 233 | joins 234 | } 235 | --------------------------------------------------------------------------------