Eu tenho um arquivo binário e devo quebrar sua senha (lição de casa). Também foi fornecida uma função (uma função que faz parte do arquivo binário). Essa função mostrou que a string de entrada foi comparada com a senha correta caractere por caractere e retornou false instantaneamente quando um caractere estava errado (essa não é uma maneira segura de fazer isso, acho porque está vazando tempo e temos uma ideia do comprimento correto da senha como exemplo). Mas nosso professor adicionou um cronômetro aleatório que retorna o resultado (Correto / Errado) para tornar um pouco mais difícil para nós...
De qualquer forma, já fiz isso com sucesso com engenharia reversa e obtive a senha correta. Agora estou brincando com ele na linha de comando:
/usr/bin/time -v ./program_name enter_password
Com este comando, obtenho muitas informações como hora do sistema, trocas, tempo de execução. " Eu recebo!
Quanto mais caracteres errados eu inserir, mais "mudanças voluntárias de contexto" eu recebo.
Levei quase duas horas para quebrar a senha apenas digitando esse comando, inserindo caracteres e observando "Mudanças voluntárias de contexto". Sempre que UM caractere estava correto, as "mudanças de contexto voluntárias" diminuíam em um.
Minha pergunta, o que exatamente são "interruptores de contexto voluntários" e por que eles me ajudaram a quebrar a senha?
A página man
time
explica o conceito de trocas de contexto voluntárias e involuntárias:(a citação é do meu sistema Debian, a página de manual vinculada tem um texto ligeiramente diferente)
Ou seja, uma troca de contexto é voluntária, se o processo sai da CPU porque não tem mais o que fazer (enquanto espera que algo externo aconteça). Involuntário, se quiser continuar alguma computação, mas o sistema operacional decide que é hora de mudar para algum outro processo.
Como isso está relacionado ao programa de verificação de senha depende do que o programa realmente faz.
A partir do código-fonte vinculado nos comentários, vemos que o programa chama
usleep()
uma vez para cada caractere não correspondente, continuando o loop de comparação no próximo caractere depois. Dormir é tão voluntário quanto render a CPU, então essas chamadas serão exibidas como trocas de contexto voluntárias para cada caractere não maching.No Linux, você também poderá ver as chamadas com
strace
.O atraso final vem de um sono aleatório de
T * (rand() % 3)
, ou seja, 0, 1 ou 2 vezes uma constante. Essa é uma granularidade bastante grosseira, por isso deve ser fácil calcular a média fazendo várias tentativas com a mesma senha.