我将在几周内为我的计算机和信息安全课程进行安全演示,在此演示文稿中,我将展示不同攻击的利弊(词典,彩虹和蛮力)。我做词典和彩虹攻击很好,但我需要即时产生蛮力攻击。我需要找到一种算法,该算法可以让我通过字母,符号和数字的每一个组合循环到某个字符长度。

因此,例如,对于12个字符长度,第一代和最后几代将是:

a
ab
abc
abcd
...
...
zzzzzzzzzzzx
zzzzzzzzzzzy
zzzzzzzzzzzz

但这也将使用数字和符号,因此我很难解释……但是我认为您明白了。仅使用ASCII表中的符号很好。

我可以使用ASCII功能与计数器进行图片,但我无法在脑海中解决这个问题。如果有人可以提供一些源代码(我可能会使用C#),甚至可以提供一些伪代码,我可以从中编程的功能很棒。

先感谢您。 :)

有帮助吗?

解决方案

递归函数将使您贯穿所有有效摄影的组合:

    int maxlength = 12;
    string ValidChars;
    private void Dive(string prefix, int level)
    {
        level += 1;
        foreach (char c in ValidChars)
        {
            Console.WriteLine(prefix + c);
            if (level < maxlength)
            {
                Dive(prefix + c, level);
            }
        }
    }

将有效字符集分配给有效角色,您想要的最大字符串的最大长度,然后调用 Dive("", 0); 你走了。

其他提示

您需要从一组有效字符中生成字符的所有组合;让我们称之为这套 validChars. 。基本上,长度为n的每组组合都是笛卡尔产物 validChars 与自己,n时。使用Linq很容易做到这一点:

char[] validChars = ...;

var combinationsOfLength1 =
    from c1 in validChars
    select new[] { c1 };

var combinationsOfLength2 =
    from c1 in validChars
    from c2 in validChars
    select new[] { c1, c2 };

...

var combinationsOfLength12 =
    from c1 in validChars
    from c2 in validChars
    ...
    from c12 in validChars
    select new[] { c1, c2 ... c12 };

var allCombinations =
    combinationsOfLength1
    .Concat(combinationsOfLength2)
    ...
    .Concat(combinationsOfLength12);

显然,您不想为每个长度手动编写代码,尤其是如果您不预先知道最大长度...

埃里克·利珀特(Eric Lippert)有 一篇文章 关于生成任意数量序列的笛卡尔产物。使用 CartesianProduct 本文提供的扩展方法,您可以生成长度n的所有组合,如下所示:

var combinationsOfLengthN = Enumerable.Repeat(validChars, N).CartesianProduct();

由于您需要从长度1到最大的所有组合,因此您可以做类似的事情:

var allCombinations = 
    Enumerable
        .Range(1, MAX)
        .SelectMany(N => Enumerable.Repeat(validChars, N).CartesianProduct());

allCombinations 是一个 IEnumerable<IEnumerable<char>>, ,如果您想将结果作为字符串序列,您只需要添加一个投影:

var allCombinations = 
    Enumerable
        .Range(1, MAX)
        .SelectMany(N => Enumerable.Repeat(validChars, N).CartesianProduct())
        .Select(combination => new string(combination.ToArray()));

请注意,这当然不是最有效的解决方案,但至少它是简短且可读性的。

您可以尝试使用此代码,该代码使用递归将所有可能的字符串打印到弦乐chars lenght,该字符串由从Firstrangechar到Lastrangechar的所有炭组成。

class BruteWriter
{
    static void Main(string[] args)
    {
        var bw = new BruteWriter();
        bw.WriteBruteStrings("");
    }

    private void WriteBruteStrings(string prefix)
    {
        Console.WriteLine(prefix);
        if (prefix.Length == stringsLenght)
            return;

        for (char c = firstRangeChar; c <= lastRangeChar; c++)
            WriteBruteStrings(prefix + c);

    }

    char firstRangeChar='A';
    char lastRangeChar='z';
    int stringsLenght=10;


}

这种外观比 @dthorpe的解决方案快。我已经使用此代码比较了algorthms:

class BruteWriter
    {
        static void Main(string[] args)
        {
            var st = new Stopwatch();
            var bw = new BruteWriter();
            st.Start();
            bw.WriteBruteStrings("");
            Console.WriteLine("First method: " + st.ElapsedMilliseconds);

            for (char c = bw.firstRangeChar; c <= bw.lastRangeChar; c++)
                bw.ValidChars += c;

            st.Start();
            bw.Dive("", 0);
            Console.WriteLine("Second method: " + st.ElapsedMilliseconds);

            Console.ReadLine();


        }

        private void WriteBruteStrings(string prefix)
        {
            if (prefix.Length == stringsLenght)
                return;

            for (char c = firstRangeChar; c <= lastRangeChar; c++)
                WriteBruteStrings(prefix + c);

        }

        char firstRangeChar='A';
        char lastRangeChar='R';
        int stringsLenght=5;



        int maxlength = 5;
        string ValidChars;
        private void Dive(string prefix, int level)
        {
            level += 1;
            foreach (char c in ValidChars)
            {
                if (level <= maxlength)
                {
                    Dive(prefix + c, level);
                }
            }
        }
    }

而且,在我的PC上,我得到了这些结果:

First method: 247
Second method: 910
public void BruteStrings(int maxlength)
{
   for(var i=1;i<i<=maxlength;i++)
      BruteStrings(Enumerable.Repeat((byte)0,i));

}

public void BruteStrings(byte[] bytes)
{
   Console.WriteLine(bytes
                       .Cast<char>()
                       .Aggregate(new StringBuilder(), 
                          (sb,c) => sb.Append(c))
                       .ToString());

   if(bytes.All(b=>b.MaxValue)) return;

   bytes.Increment();

   BruteStrings(bytes);
}

public static void Increment(this byte[] bytes)
{
   bytes.Last() += 1;

   if(bytes.Last == byte.MinValue)
   {
      var lastByte = bytes.Last()
      bytes = bytes.Take(bytes.Count() - 1).ToArray().Increment();
      bytes = bytes.Concat(new[]{lastByte});
   }
}

我做的另一个替代方案是返回字符串。

我不在乎这件事的表现,因为它不是针对现实世界的场景。

private void BruteForcePass(int maxLength)
    {
        var tempPass = "";
        while (tempPass.Length <= maxLength)
        {
            tempPass = GetNextString(tempPass);//Use char from 32 to 256
            //Do what you want
        }
    }

    private string GetNextString(string initialString, int minChar= 32, int maxChar = 256)
    {
        char nextChar;
        if (initialString.Length == 0)
        {
            nextChar = (char)minChar;//the initialString Length will increase
        }
        else if (initialString.Last() == (char)maxChar)
        {
            nextChar = (char)minChar;
            var tempString = initialString.Substring(0, initialString.Length -1);//we need to increment the char just before the last one
            initialString = GetNextString(tempString, minChar, maxChar); 
        }
        else
        {
            nextChar = (char)(initialString.Last() + 1);//Get the lash Char and increment it;
            initialString= initialString.Remove(initialString.Length - 1);//Remove the last char.
        }
        return initialString + nextChar;
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top