我一直在研究一种做Brute Forcing的算法。它更多的是个人利益,而不是任何恶意使用tbh。我一直对加密和安全感兴趣。 我在应用程序上有一个模式,它将创建工作线程以执行给定长度的可能组合(每个长度1个线程)。
例如:你开始这个过程 - 然后它将以1,2,3,4,5,6,7,8的长度开始,依此类推。 当较低长度的线程完成时,它会将可疑密码长度增加1并生成一个新线程。 限制因素是ProcessorCount -1(为了避免线程锁定或GUI线程被冻结:通常发现系统在使用自由核心时更稳定)
因此,在4核系统上,您将使用密码长度1-3,当完成1,2和3时,它将继续运行到4,5,6,依此类推。 长度1-5实际上立即完成。 3-4秒内6-7。 长度8可能需要30-45秒。 (这些时间取决于它是否是数字/字母数字等) 更多可能的字符会增加我们需要检查的键空间。
好的,这是多线程的一种方法。 但我想介绍的另一种方法有点复杂。 它涉及使用多个线程来运行固定的可疑长度密码的完整密钥空间。 例如:我们知道它长8位,所以使用我们所有的线程来更快地通过8位密码密钥空间。
我不确定如何继续。
例如: 假设我们的密码是100(1000种组合?) 我们的处理器上有8个内核 所以这是7个潜在的线程 - 如果我们采用我的-1方法。 这大约有143个组合来测试每个线程。 我只是想知道如何有效地计算每个线程的起始位置。
例如:
线程1将以000开头并以142结束 线程2将以143开头并以285等结束
使用Numbers听起来很容易,但当你使用一系列可能的角色时 - 'abcdefghijklmnopqrstuvwxyz1234567890'
如何确定起点和终点?
该字符串中包含36个可能的字符。
对于3个字母的密码,它是36 x 36 x 36 = 46656个字符组合吗?
好的,如果我有7个线程,每个6666组合。 如何获取这些开始和结束位置并将它们转换为比较字符串。
我想我的主要问题是这个: 如何将组合索引转换为由可用字符构成的字符串?
例如:
答案 0 :(得分:0)
不会建议你这样做,但如果这是你想要的方式,那就这样考虑一下
对于角色1,角色1有36种可能性,角色2有36种。角色3也是如此。
所以。 。 。
取第一个角色的可能性并将其分为6(线程)(7将是凌乱的)为每个线程提供6个
这是角色1的6种不同的可能性,具有36X36个可能性
这意味着线程1会执行以a,b,c,d,e和f开头的所有内容
线程2然后将执行g,h,i,j,k和l
等等
答案 1 :(得分:0)
不要让每个线程完全搜索搜索空间中的1 / n ,而是考虑将其切换为“逻辑”部分(即对你有意义) 。这意味着您将创建比核心更多的作业,并且每个作业完成上一个作业后,每个作业都可以选择其中一个作业。
E.g。对于数字8位密码,您可以创建最多9个任务0,其中任务 n 是“搜索以数字 n 开头的所有8位数密码”。对于字母数字密码,您可以创建36个任务:“搜索所有以'a'开头的密码”,“......以'b'开头”,......,“以'0'开头”。
将所有任务抛入池中,根据需要激活多个线程,并从池中为其提供任务。任务完成后,让线程从池中获取新任务,直到它耗尽。
你可以使用Thread Pool,但坦率地说,我只想创建一个简单的机制,其中工作池是List<Action>
,你使用一个简单的lock
机制上一个操作完成后,将任务从列表中拉出。
编辑:掀起一个简单的例子。它看起来像很多代码,但它相当简单。没有真正测试,但应该给你一个线索我的意思。
private List<Action> jobs = new List<Action>();
private object jobsLock = new object();
// This is the CPU-intensive function that does the actual work of checking passwords
private void TestPasswords(int length) {
for(int i = 0; i < (1 << length); i++)
{
// Simulate testing the password.
Thread.Sleep(100);
}
}
// Each thread is dispatched with this action.
// It keeps pulling jobs from the queue and executing them until no more remain.
private void DoWork()
{
while(true)
{
Action job = null;
lock(this.jobsLock)
{
if(this.jobs.Count == 0)
{
return;
}
job = this.jobs[0];
this.jobs.RemoveAt(0);
}
if(job != null)
{
job();
}
}
}
// Tester method
public void Run()
{
// For all password lengths from 1 to 8, generate a job to test passwords.
// You probably want to divide these differently (e.g. let i be the job that tests
// all 1 - 8 character passwords starting with the character i, such that
// all jobs are approximately of equal length).
for(int i = 1; i <= 8; i++)
{
int length = i;
this.jobs.Add(() => TestPasswords(length));
}
// Create a background thread for each of the cores except one,
// and let them execute the DoWork loop until the queue is empty.
// You may build a ContinueWith or WaitAll mechanism to catch the results
// and build some callback stuff to get the progress.
int numberOfCores = 8;
for(int i = 0; i < numberOfCores - 1; i++)
{
Task.Run(DoWork);
}
}