C# - Aplicando a Força Bruta para hacker senhas


Hoje veremos o conceito e a implementação do método da força bruta usando a linguagem C#.

A pesquisa de força bruta ou pesquisa exaustiva, também conhecida como gerar e testar, é uma técnica de solução de problemas muito geral que consiste em enumerar sistematicamente todos os candidatos possíveis à solução e verificar se cada candidato satisfaz a afirmação do problema.

O que é o método da força bruta ?

O método da força bruta significa encontrar o caminho para a solução desejada o mais rápido possível, "não importa" como. Para resolver o problema, teremos basicamente 3 partes envolvidas:

  1. Entrada: os dados que você receberá para obter o resultado desejado;
  2. Algoritmo: aqui é onde transformamos a entrada na saída e é onde a força bruta é aplicada, usando um algoritmo que pode levar à solução desejada;
  3. Saída: a solução desejada.

Parece ser bem simples, e a chave do processo esta no algoritmo que é aplicado para a solução do problema.

O que vamos fazer neste artigo é usar um algoritmo muito simples para descobrir senhas fracas.

Assim, este artigo tem como objetivo te alertar do seguinte fato:

"Se um programinha feito com umas poucas linhas de código usando uma codificação básica pode descobrir senhas simples de maneira usando um PC com baixo poder de processamento, imagine o que não pode fazer um programa sofisticado usado em um ataque coordenado com múltiplo processamento"

O objetivo do programa que iremos usar será encontrar a senha usando a força bruta.

Então vamos criar uma aplicação console do tipo .NET Core e criar a classe Cracker com seguinte código:

public class Cracker
{
        public static char primeirochar = 'a';
        public static char ultimochar = 'z';
        public static int tamanhoSenha = 8;
        public static long tentativas = 0;
        public static bool concluido = false;
        public static string password = "abc";

        public static void QuebraSenha(string chaves)
        {
            if (chaves == password)
            {
                concluido = true;
            }
            if (chaves.Length == tamanhoSenha || concluido == true)
            {
                return;
            }
            for (char c = primeirochar; c <= ultimochar; c++)
            {
                tentativas++;
                QuebraSenha(chaves + c);
            }
        }
 }

Este é o algoritmo que vamos aplicar parar descobrir as senhas.

O código acima é bem simples, podendo ser otimizado de diversas formas, e, até um iniciante seria capaz de criar este código, mas você verá que para senhas mais simples o tempo que ele leva para descobrir a senha é bem rápido.

Então vamos agora iniciar o teste criando o código abaixo no método Main da classe Program :

using System;
using System.Diagnostics;
namespace CShp_ForcaBruta
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Teste de Força Bruta");
            Console.Write("\nInforme uma senha  > ");

            Cracker.password = Convert.ToString(Console.ReadLine());
            Cracker.password = Cracker.password.ToLower();
            Console.WriteLine("\nQuebrando a senha...");
            Stopwatch timer = Stopwatch.StartNew();

            Cracker.tamanhoSenha = Cracker.password.Length;
            Cracker.QuebraSenha(string.Empty);

            timer.Stop();
            long elapsedMs = timer.ElapsedMilliseconds;
            double tempoGasto = elapsedMs / 1000;

            if (tempoGasto > 0)
            {
                Console.WriteLine("\n\nA senha foi hackeada! Estatísticas:");
                Console.WriteLine("----------------------------------");
                Console.WriteLine("Password: {0}", Cracker.password);
                Console.WriteLine("Tamanho Senha: {0}", Cracker.tamanhoSenha);
                Console.WriteLine("Tentativas: {0}", Cracker.tentativas);
                string plural = "segundos";
                if (tempoGasto == 1)
                {
                    plural = "segundo";
                }
                Console.WriteLine("Tempo gasto para hackear a senha: {0} {1}", tempoGasto, plural);
                Console.WriteLine("Senhas por segundo : {0}", (long)(Cracker.tentativas / tempoGasto));
            }
            else
            {
                Console.WriteLine("\n\nA senha foi hackeada ! Estatísticas:");
                Console.WriteLine("----------------------------------");
                Console.WriteLine("Senha: {0}", Cracker.password);
                Console.WriteLine("Tamnho da Senha: {0}", Cracker.tamanhoSenha);
                Console.WriteLine("Tentativas: {0}", Cracker.tentativas);
                Console.WriteLine("Tempo para hackear : {0} segundos", tempoGasto);
            }
            Console.ReadKey();
        }
    }
}

Vou fazer 2 testes apenas para mostrar o funcionamento do programa.

1- Usando uma senha bem simples como : 123abc

A senha foi descoberta em 20 segundos e foram feitos 321272406 tentativas para isso.

2- Usando uma senha mais forte, alternando números e letras : nu1s5y

Aqui foi gasto 19 segundos com 321272406 tentativas.

Naturalmente, devido a simplicidade do algoritmo uma senha mais forte pode demorar horas para ser descoberta.

Embora seja apenas um brincadeira este artigo mostra a importância em usar senhas fortes. Caso contrário até um iniciante será capaz de quebrar a sua senha.

Para tentar mitigar um pouco o problema da senha fraca, e, forçar o usuário a criar uma senha mais robusta, podemos criar uma classe chamada ChecaSenha com o método Verifica usando o seguinte código:

using System.Linq;
namespace CShp_ForcaBruta
{
    public class ChecaSenha
    {
        public static bool Verifica(string senha)
        {
            //min 6 e max 15 caracteres
            if (senha.Length < 6 || senha.Length > 15)
                return false;
            //Sem espaços em branco
            if (senha.Contains(" "))
                return false;
            //Pelo menos um caracter caixa alta
            if (!senha.Any(char.IsUpper))
                return false;
            //Pelo menos um caracter caixa baixa
            if (!senha.Any(char.IsLower))
                return false;
            //Não permite dois caracteres iguais sequencialmente
            for (int i = 0; i < senha.Length - 1; i++)
            {
                if (senha[i] == senha[i + 1])
                    return false;
            }
            //Pelo menos um caractere especial
            string specialCharacters = @"%!@#$%^&*()?/>.<,:;'\|}]{[_~`+=-" + "\"";
            char[] specialCharactersArray = specialCharacters.ToCharArray();
            foreach (char c in specialCharactersArray)
            {
                if (senha.Contains(c))
                    return true;
            }
            return false;
        }
    }

Agora podemos verificar se a senha informada atende alguns critérios que tornam uma senha mais forte.

Pegue o projeto completo aqui:   CShp_ForcaBruta.zip

"Muitas são, Senhor meu Deus, as maravilhas que tens operado para conosco, e os teus pensamentos não se podem contar diante de ti; se eu os quisera anunciar, e deles falar, são mais do que se podem contar."
Salmos 40:5


Referências:


José Carlos Macoratti