C#Bruteforce - 多线程固定长度密码

时间:2016-07-27 09:43:41

标签: c# multithreading passwords brute-force

我一直在研究一种做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组合。 如何获取这些开始和结束位置并将它们转换为比较字符串。

我想我的主要问题是这个: 如何将组合索引转换为由可用字符构成的字符串?

例如:

  • 1可能是'a'
  • 2将是'b'
  • 37可能是'ab'等

2 个答案:

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