You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:实现基于记忆密码的字典生成程序(递归写入文件)

解决递归生成密码字典的问题

你的思路完全没问题,现在就差把递归生成组合的核心逻辑补全,我来帮你完善代码并解释清楚:

现有代码的问题点

  1. Append方法里的换行符写错了:\\r \\n会被解析成字面量的\r \n(中间多了空格),应该用\r\n或者更通用的Environment.NewLine。
  2. Calc方法的递归逻辑未完成,没有处理到最后一个字符时的写入操作,也没有正确递归到下一个字符位置。
  3. 缺少对空输入/空路径的判断,容易导致程序崩溃。

完整修正后的代码

using System;
using System.Collections.Generic;
using System.IO;

namespace strGen
{
    class Program
    {
        static List<char[]> ls { get; set; }
        static string Path { get; set; }
        static string input { get; set; }
        static char[] inputChars { get; set; }

        static void Main(string[] args)
        {
            Console.Write("Enter tip: ");
            input = Console.ReadLine();
            // 空输入判断,避免后续报错
            if (string.IsNullOrEmpty(input))
            {
                Console.WriteLine("Input cannot be empty!");
                return;
            }

            Console.Write("Enter path: ");
            Path = Console.ReadLine();
            // 路径合法性简单判断
            if (string.IsNullOrEmpty(Path))
            {
                Console.WriteLine("Path cannot be empty!");
                return;
            }

            inputChars = input.ToCharArray();
            MakeList(inputChars);
            // 启动递归生成,初始字符串为空,从第0个字符位置开始
            Calc("", 0);
            Console.WriteLine("Password dictionary generated successfully!");
        }

        /// <summary>
        /// Makes list of all possible characters, for every character in a character array
        /// </summary>
        /// <param name="inputChars"></param>
        static void MakeList(char[] inputChars)
        {
            ls = new List<char[]>();
            foreach (char c in inputChars)
            {
                char cU;
                char cL;
                char[] tmp;

                if (char.IsLetter(c))
                {
                    if (c == 'a' || c == 'A')
                    {
                        tmp = new char[3];
                        cL = char.ToLower(c);
                        cU = char.ToUpper(c);
                        tmp[0] = cL;
                        tmp[1] = cU;
                        tmp[2] = '@';
                    }
                    else if (c == 's' || c == 'S')
                    {
                        tmp = new char[3];
                        cL = char.ToLower(c);
                        cU = char.ToUpper(c);
                        tmp[0] = cL;
                        tmp[1] = cU;
                        tmp[2] = '5';
                    }
                    else
                    {
                        tmp = new char[2];
                        cL = char.ToLower(c);
                        cU = char.ToUpper(c);
                        tmp[0] = cL;
                        tmp[1] = cU;
                    }
                }
                else if (char.IsDigit(c))
                {
                    if (c == '1')
                    {
                        tmp = new char[2];
                        tmp[0] = c;
                        tmp[1] = '!';
                    }
                    else
                    {
                        tmp = new char[1];
                        tmp[0] = c;
                    }
                }
                else if (c == '!')
                {
                    tmp = new char[2];
                    tmp[0] = c;
                    tmp[1] = '1';
                }
                else
                {
                    tmp = new char[1];
                    tmp[0] = c;
                }
                ls.Add(tmp);
            }
        }

        static void Append(string str)
        {
            // 使用Environment.NewLine适配不同系统的换行符
            File.AppendAllText(Path, str + Environment.NewLine);
        }

        static void Calc(string currentStr, int index)
        {
            // 递归终止条件:当index等于字符数组列表的长度时,说明已经生成了一个完整的密码
            if (index == ls.Count)
            {
                Append(currentStr);
                return;
            }

            // 遍历当前位置的所有可选字符
            foreach (char c in ls[index])
            {
                // 把当前字符加到现有字符串后面,递归处理下一个位置
                Calc(currentStr + c, index + 1);
            }
        }
    }
}

代码逻辑解释

  1. 递归核心逻辑:Calc方法是生成所有密码组合的关键:

    • 当index等于ls.Count时,意味着已经处理完所有字符位置,生成了一个完整的密码,调用Append写入文件。
    • 否则,遍历当前位置对应的所有可选字符,将每个字符追加到currentStr后,递归调用Calc处理下一个字符位置,以此遍历所有可能的组合。
  2. 细节优化:

    • 增加了输入和路径的空值判断,避免程序崩溃。
    • 简化了字母大小写转换的代码,不需要重复判断原字符的大小写。
    • 使用Environment.NewLine替代硬编码的换行符,让生成的文件在Windows/Linux系统下都能正常换行。

后续使用建议

生成字典文件后,你可以用Hydra进行暴力破解,示例命令(根据路由器登录页面调整):

# GET请求登录示例
hydra -L 生成的密码字典路径 -p '' http-get://你的路由器IP/login

如果路由器是POST登录,需要调整为http-post-form并指定登录参数,比如:

hydra -L pass.txt -p '' 路由器IP http-post-form "/login.php:username=admin&password=^PASS^:Invalid password"

内容的提问来源于stack exchange,提问作者AsPas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:33:09