Skip to content

Commit 2e31c5b

Browse files
author
Ron
committed
add --seed, --walks, --smart-affix, --toggle-variations
1 parent aaeb5ac commit 2e31c5b

File tree

1 file changed

+165
-11
lines changed

1 file changed

+165
-11
lines changed

main.go

Lines changed: 165 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ type Config struct {
6767
upgrade bool
6868
showVersion bool
6969
Rules []string // Ordered list of rules to apply
70+
seedWords string
71+
keyboardWalks bool
72+
smartAffix bool
73+
toggleVariations bool
7074
}
7175

7276
// ruleFlag is a custom flag type that appends the rule name to the config's Rules list
@@ -92,15 +96,32 @@ func (f *ruleFlag) IsBoolFlag() bool {
9296

9397
// LeetMap defines character substitutions for leet speak
9498
var leetMap = map[rune][]rune{
95-
's': {'$', 'z'},
96-
'e': {'3'},
97-
'a': {'4', '@'},
98-
'o': {'0'},
99-
'i': {'1', '!'},
100-
'l': {'1', '!'},
101-
't': {'7'},
102-
'b': {'8'},
103-
'z': {'2'},
99+
'a': {'4', '@', '^'},
100+
'b': {'8', '6'},
101+
'c': {'(', '<', '[', '{'},
102+
'd': {'|', ')', '?'},
103+
'e': {'3', '&'},
104+
'f': {'|'},
105+
'g': {'9', '6', '&'},
106+
'h': {'#', '4'},
107+
'i': {'1', '!', '|'},
108+
'j': {'|', ';'},
109+
'k': {'<', '|', '{'},
110+
'l': {'1', '!', '|'},
111+
'm': {'|', 'v', 'M'},
112+
'n': {'^', '~'},
113+
'o': {'0', '*'},
114+
'p': {'|', '*'},
115+
'q': {'9', '0'},
116+
'r': {'2'},
117+
's': {'5', '$', 'z'},
118+
't': {'7', '+'},
119+
'u': {'v'},
120+
'v': {'\\', '/', '^'},
121+
'w': {'v'},
122+
'x': {'%', '×'},
123+
'y': {'j'},
124+
'z': {'2', '%', '7'},
104125
}
105126

106127
// CommonWords to append/prepend
@@ -505,6 +526,11 @@ func parseFlags(args []string) *Config {
505526
fs.BoolVar(&config.checkUpdates, "check-updates", false, "check for updates")
506527
fs.BoolVar(&config.upgrade, "upgrade", false, "perform self-upgrade")
507528

529+
fs.StringVar(&config.seedWords, "seed", "", "comma-separated seed words")
530+
fs.BoolVar(&config.keyboardWalks, "walks", false, "add common keyboard walks")
531+
fs.BoolVar(&config.smartAffix, "smart-affix", false, "add smart affixes (years, 123, symbols)")
532+
fs.BoolVar(&config.toggleVariations, "toggle-variations", false, "add toggle case permutations")
533+
508534
fs.Parse(args)
509535
return config
510536
}
@@ -545,6 +571,10 @@ func showUsage() {
545571
fmt.Fprintf(os.Stderr, "\t%s-ss%s, %s--suffix-strings%s %s<S>%s: add strings to the end (comma-separated)\n", y, r, y, r, b, r)
546572
fmt.Fprintf(os.Stderr, "\t%s-t%s, %s--leet%s: l33t speak the word\n", y, r, y, r)
547573
fmt.Fprintf(os.Stderr, "\t%s-T%s, %s--full-leet%s: all possibilities l33t\n", y, r, y, r)
574+
fmt.Fprintf(os.Stderr, "\t%s--seed%s %s<words>%s: inject seed words (comma-separated)\n", y, r, b, r)
575+
fmt.Fprintf(os.Stderr, "\t%s--walks%s: add common keyboard walks\n", y, r)
576+
fmt.Fprintf(os.Stderr, "\t%s--smart-affix%s: add smart affixes (years, 123, symbols)\n", y, r)
577+
fmt.Fprintf(os.Stderr, "\t%s--toggle-variations%s: add toggle case permutations\n", y, r)
548578
fmt.Fprintf(os.Stderr, "\t%s-u%s, %s--upper%s: uppercase the word\n", y, r, y, r)
549579
fmt.Fprintf(os.Stderr, "\t%s-v%s: show version\n", y, r)
550580
fmt.Fprintf(os.Stderr, "\t%s-x%s, %s--max%s %s<N>%s: maximum word length\n", y, r, y, r, b, r)
@@ -645,12 +675,17 @@ func showLongUsage() {
645675
fmt.Fprintf(os.Stderr, " %s-ac%s, %s--all-cases%s Generate all case permutations (warning: huge output).\n", y, r, y, r)
646676
fmt.Fprintf(os.Stderr, " %s-d%s, %s--double%s Append word to itself.\n", y, r, y, r)
647677
fmt.Fprintf(os.Stderr, " %s-A%s, %s--acronym%s Create acronyms from input words.\n", y, r, y, r)
648-
fmt.Fprintf(os.Stderr, " %s--space%s Add spaces between words (for permutations).\n\n", y, r)
678+
fmt.Fprintf(os.Stderr, " %s--space%s Add spaces between words (for permutations).\n", y, r)
679+
fmt.Fprintf(os.Stderr, " %s--seed%s %s<words>%s Inject seed words (comma-separated).\n", y, r, b, r)
680+
fmt.Fprintf(os.Stderr, " %s--walks%s Add common keyboard walks.\n", y, r)
681+
fmt.Fprintf(os.Stderr, " %s--toggle-variations%s Add toggle case permutations.\n\n", y, r)
649682

650683
// TEXT MANIPULATION (APPEND/PREPEND)
651684
fmt.Fprintf(os.Stderr, "TEXT MANIPULATION (APPEND/PREPEND):\n")
652685
fmt.Fprintf(os.Stderr, " %s-C%s, %s--common%s %s[file]%s\n", y, r, y, r, b, r)
653686
fmt.Fprintf(os.Stderr, "\tAdd common words (admin, sys, etc) or load from file.\n")
687+
fmt.Fprintf(os.Stderr, " %s--smart-affix%s\n", y, r)
688+
fmt.Fprintf(os.Stderr, "\tAdd smart affixes (years, 123, symbols).\n")
654689
fmt.Fprintf(os.Stderr, " %s-ps%s, %s--prefix-strings%s %s<S>%s\n", y, r, y, r, b, r)
655690
fmt.Fprintf(os.Stderr, "\tAdd comma-separated strings to the start of each word.\n")
656691
fmt.Fprintf(os.Stderr, " %s-ss%s, %s--suffix-strings%s %s<S>%s\n", y, r, y, r, b, r)
@@ -703,6 +738,20 @@ func run(config *Config, inputPaths []string) error {
703738
}
704739
}
705740

741+
if config.seedWords != "" {
742+
seeds := strings.Split(config.seedWords, ",")
743+
for _, s := range seeds {
744+
s = strings.TrimSpace(s)
745+
if s != "" {
746+
allWords = append(allWords, s)
747+
}
748+
}
749+
}
750+
751+
if config.keyboardWalks {
752+
allWords = append(allWords, getKeyboardWalks()...)
753+
}
754+
706755
if len(allWords) == 0 {
707756
return fmt.Errorf("no words loaded from input")
708757
}
@@ -1013,6 +1062,14 @@ func (m *Mangler) mangleWord(word string) {
10131062
res[word+string(p)] = struct{}{}
10141063
}
10151064
}
1065+
if m.config.smartAffix {
1066+
m.addSmartAffixes(word, res)
1067+
}
1068+
if m.config.toggleVariations {
1069+
for _, v := range generateToggleVariations(word) {
1070+
res[v] = struct{}{}
1071+
}
1072+
}
10161073
if m.config.yearsCount != "" {
10171074
m.addNumberRange(word, m.config.yearsCount, true, res)
10181075
m.addNumberRange(word, m.config.yearsCount, false, res)
@@ -1580,5 +1637,102 @@ var lengthChances = map[int]float64{
15801637
var comboChances = map[int]float64{
15811638
16: 0.78, 4: 0.76, 20: 0.76, 256: 0.49, 272: 0.29, 260: 0.29, 276: 0.29,
15821639
32: 0.28, 288: 0.28, 48: 0.27, 304: 0.27, 36: 0.27, 52: 0.27, 292: 0.27,
1583-
1024: 0.19, 1280: 0.19, 8: 0.03, 1: 0.02, 9: 0.02, 128: 0.019,
1640+
1024: 0.19, 1280: 0.19, 8: 0.03, 1: 0.02, 9: 0.02, 128: 0.019,
1641+
}
1642+
1643+
func getKeyboardWalks() []string {
1644+
return []string{
1645+
"qwerty", "asdfgh", "zxcvbn", "123456", "qazwsx",
1646+
"qwer", "asdf", "zxcv", "1234", "1qaz", "zaq1",
1647+
"wsx", "edc", "rfv", "tgb", "yhn", "ujm", "ik,", "ol.", "p;/",
1648+
"plm", "okn", "ijb", "uhv", "ygc", "tfx", "rdz", "esz", "waq",
1649+
"!@#$", "!@#$%", "qwertyuiop", "asdfghjkl", "zxcvbnm",
1650+
}
1651+
}
1652+
1653+
func (m *Mangler) addSmartAffixes(word string, res map[string]struct{}) {
1654+
// Years: current and past 5
1655+
cur := time.Now().Year()
1656+
for i := 0; i <= 5; i++ {
1657+
y := cur - i
1658+
ys := fmt.Sprintf("%d", y)
1659+
res[word+ys] = struct{}{}
1660+
res[ys+word] = struct{}{}
1661+
// Short year
1662+
if len(ys) >= 4 {
1663+
sys := ys[2:]
1664+
res[word+sys] = struct{}{}
1665+
res[sys+word] = struct{}{}
1666+
}
1667+
}
1668+
1669+
// 123 variations
1670+
seqs := []string{"1", "12", "123", "1234", "12345", "123456", "0", "01", "012"}
1671+
for _, s := range seqs {
1672+
res[word+s] = struct{}{}
1673+
res[s+word] = struct{}{}
1674+
}
1675+
1676+
// Common symbols
1677+
syms := []string{"!", ".", "?", "*", "#", "@", "$"}
1678+
for _, s := range syms {
1679+
res[word+s] = struct{}{}
1680+
res[s+word] = struct{}{}
1681+
}
1682+
}
1683+
1684+
func generateToggleVariations(word string) []string {
1685+
if len(word) == 0 {
1686+
return nil
1687+
}
1688+
var res []string
1689+
1690+
// Toggle first char
1691+
runes := []rune(word)
1692+
if len(runes) > 0 {
1693+
r0 := runes[0]
1694+
if r0 >= 'a' && r0 <= 'z' {
1695+
runes[0] = r0 - 32
1696+
} else if r0 >= 'A' && r0 <= 'Z' {
1697+
runes[0] = r0 + 32
1698+
}
1699+
res = append(res, string(runes))
1700+
}
1701+
1702+
// Toggle last char
1703+
runes = []rune(word)
1704+
if len(runes) > 0 {
1705+
last := len(runes) - 1
1706+
rl := runes[last]
1707+
if rl >= 'a' && rl <= 'z' {
1708+
runes[last] = rl - 32
1709+
} else if rl >= 'A' && rl <= 'Z' {
1710+
runes[last] = rl + 32
1711+
}
1712+
res = append(res, string(runes))
1713+
}
1714+
1715+
// Alternating case 1: aBcD
1716+
runes = []rune(word)
1717+
for i := range runes {
1718+
if i%2 == 0 {
1719+
runes[i] = []rune(strings.ToLower(string(runes[i])))[0]
1720+
} else {
1721+
runes[i] = []rune(strings.ToUpper(string(runes[i])))[0]
1722+
}
1723+
}
1724+
res = append(res, string(runes))
1725+
1726+
// Alternating case 2: AbCd
1727+
runes = []rune(word)
1728+
for i := range runes {
1729+
if i%2 != 0 {
1730+
runes[i] = []rune(strings.ToLower(string(runes[i])))[0]
1731+
} else {
1732+
runes[i] = []rune(strings.ToUpper(string(runes[i])))[0]
1733+
}
1734+
}
1735+
res = append(res, string(runes))
1736+
1737+
return res
15841738
}

0 commit comments

Comments
 (0)