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