Uma autópsia mostrará: Resolva um crackme leve e escreva um gerador de chave

Bom dia, leitor. Eu gostaria de falar sobre o algoritmo para resolver um crackme leve e compartilhar o código do gerador. Este foi um dos primeiros crackme que resolvi.



Na vastidão da rede, nosso pod foi encontrado. Isso é crackme . Naturalmente, é necessário estudá-lo. Para a autópsia, precisamos:



  • Um pouco de Assembler
  • Lógica com depurador (IDA PRO)


Vamos fazer um remédio com o veneno da cobra australiana usando Python. Não vamos perder tempo.



imagem







Este crackme não é muito complicado. Considere o algoritmo para gerar uma chave na chave correta 8365-5794-2566-0817 . No IDA Pro, adicionei comentários sobre o código.



Exame do paciente



À primeira vista, o comportamento é normal. Extensão .Exe. Não embalado. Vamos começar.











O que é isso? Requer uma chave. Precisa curar :)



Autópsia do paciente



Se houvesse um erro, havia uma inscrição “Fail, Serial is invalid!”. Tomemos um lugar onde ele é usado no programa.







Vemos 1 função key_check_func antes do desvio condicional. Vamos examiná-la.



Uma árvore interessante aparece.







Definimos um ponto de interrupção e iniciamos a depuração.



A chave deve ter 19 caracteres.







Em seguida, o programa verifica a presença de um travessão na chave a cada 5 caracteres, entrando no loop 3 vezes.











Depois de verificar a presença de um travessão, o programa examina se o bloco de teclas (tecla 1/4) consiste em números. Existe uma suposição para entender qual dígito foi passado para o compilador executando o comando. add eax, 0FFFFFFD0h







Por exemplo, adicione 8 (38h) com o número fornecido. O número resultante é muito grande ( 10000008h) e no final é 8, portanto, é cortado. Permanece 8. Este é o valor que demos. Isso acontece 4 vezes em um ciclo.







O que agora? Hoje em dia, os códigos de cada dígito do bloco verificado são somados, mas os 4 últimos dígitos são somados 3 vezes seguidas. O valor resultante é adicionado novamente. O código do último dígito do bloco + a quantidade resultante é 150h. O resultado é adicionado a r10d. Todo este ciclo é repetido 4 vezes para cada bloco de teclas.







Em nosso caso, considere o exemplo do primeiro bloco da chave 8365: 38h (8) + 33h (3) + 36h (6) + 35h (5) + 35h (5) + 35h (5) = 140h + 35h - 150h = 25h. 25 é adicionado a r10d e gravado na memória. Vamos marcar este local como A. A soma dos outros blocos da chave também é igual a 25h. Portanto, multiplicamos 25h * 4 = 94.



Em seguida, ocorre um deslocamento bit a bit para a direita de 2 bytes. Vamos marcar este local para nós como B.







Temos um valor designado como A (25h) e B (25h). Posteriormente, esses números serão comparados. Eles devem ser os mesmos. Esta operação ocorre para cada bloco de teclas.







A última coisa que o programa faz é verificar se os números nos blocos são semelhantes. Primeiro, os dígitos do 1º bloco são comparados com os dígitos do 2º bloco. Em seguida, verifique 2 blocos com 3 blocos. Verificação final 3 blocos com 4 blocos. Toda essa verificação não acontece imediatamente, mas gradualmente em um ciclo.











A análise acabou. O paciente foi estudado.



Hora de uma cura



Usaremos algo incomum para gerar a chave. Python + Biblioteca aleatória.

O código em si está abaixo. Comentários no código:



import random

def gen_key_part():
    #  
    num1 = str(random.randint(0, 9))
    num2 = str(random.randint(0, 9))
    num3 = str(random.randint(0, 9))
    num4 = str(random.randint(0, 9))

    #    (1 )
    final = num1 + num2 + num3 + num4
    return final

def sum_ord(key_part):
    #      
    num1 = key_part[0]
    num2 = key_part[1]
    num3 = key_part[2]
    num4 = key_part[3]

    #    crackme
    sum = ord(num1) + ord(num2) + ord(num3) + ord(num4) + ord(num4) + ord(num4)
    sum_final = ord(num4) + sum - 336
    return sum_final

def shr(key):
    #    
    a = key[0:4]
    b = key[5:9]
    c = key[10:14]
    d = key[15:19]

    #      crackme
    x = sum_ord(a) + sum_ord(b) + sum_ord(c) + sum_ord(d)
    x = x >> 2
    return x

def check_key(key):
    i = 0 # 
    while i != 4:
        #  i    1  4.      
        first = 0 + i
        second = 5 + i
        third = 10 + i
        four = 15 + i

        #           ( ,  A  B)
        if sum_ord(key[0:4]) != shr(key) or sum_ord(key[5:9]) != shr(key) or sum_ord(key[10:14]) != shr(key) or sum_ord(key[15:19]) != shr(key):
            return False

        #     
        if int(key[first]) == int(key[second]):
            return False
        if int(key[second]) == int(key[third]):
            return False
        if int(key[third]) == int(key[four]):
            return False
        i += 1 # #  

def generate_key():
    #  
    key = gen_key_part() + '-' + gen_key_part() + '-' + gen_key_part() + '-' + gen_key_part()

    #     true  false
    while True: #
        if check_key(key) == False:
            #     
            key = gen_key_part() + '-' + gen_key_part() + '-' + gen_key_part() + '-' + gen_key_part()
            print('Checking this key -> ' + key)
        else:
            #  
            print('This is the correct key -> ' + key)
            break


#  ,  
if __name__ == "__main__":
    generate_key()



Nós lançamos.







Digite a chave e veja.







O paciente está curado.



Obrigado pela atenção. Aguardo seus comentários e críticas. Não fique doente.



All Articles