6

私は数週間後にコンピュータと情報セキュリティコースのセキュリティプレゼンテーションを行っています。このプレゼンテーションでは、さまざまな攻撃(辞書、レインボー、ブルートフォース)の長所と短所を示します。私は辞書とレインボー攻撃をうまくやっていますが、ブルートフォース攻撃をその場で生成する必要があります。文字、記号、数字のすべての組み合わせを特定の文字の長さまで循環させるアルゴリズムを見つける必要があります。

したがって、例として、文字の長さが12の場合、最初と最後の数世代は次のようになります。

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

でも、数字や記号も使われるので、説明するのはなかなか難しいですが…でも、あなたはその考えを理解していると思います。ASCIIテーブルのシンボルのみを使用することは問題ありません。

ASCII関数を使用してカウンターでこれを行うことができますが、頭の中でうまくいくことができません。誰かがソースコード(おそらくC#を使用しているでしょう)またはそれから関数をプログラムできる疑似コードさえも提供できれば素晴らしいでしょう。

前もって感謝します。:)

4

5 に答える 5

10

再帰関数を使用すると、ValidCharsのすべての組み合わせを実行できます。

    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);
            }
        }
    }

有効な文字のセットをValidCharsに割り当てます。これは、最大長にする文字列の最大長です。次に、呼び出しDive("", 0);て離れます。

于 2010-09-03T23:23:09.673 に答える
4

有効な文字のセットから文字のすべての組み合わせを生成する必要があります; このセットを呼びましょう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からMAXまでのすべての組み合わせが必要なので、次のようなことができます。

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()));

それは確かに最も効率的な解決策ではないことに注意してください、しかし少なくともそれは短くて読みやすいです...

于 2010-09-04T00:07:05.787 に答える
1

再帰を使用して、firstRangeCharからlastRangeCharまでのcharのすべての組み合わせで構成されるstringsLenghtcharslenghtに0のすべての可能な文字列を出力するこのコードを試すことができます。

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のソリューションよりも高速であるように見えます。このコードを使用してアルゴリズムを比較しました。

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
于 2010-09-03T23:35:27.943 に答える
0
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});
   }
}
于 2010-09-04T00:56:42.397 に答える
0

私が行ったもう1つの方法は、文字列を返すことです。

現実世界のシナリオではなかったので、私は物事のパフォーマンスを気にしませんでした。

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;
    }
于 2012-12-13T15:24:43.133 に答える