Não é possível descriptografar o AES com OpenSSL

3

Estou trabalhando em um jogo ctf:

Criptografado com o AES no modo ECB. Todos os valores base64 codificados

ciphertext = 8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L
key = 3q1FxGhuZ5fQYbjzDxgQ35==

Eu tentei descriptografá-lo no meu terminal deixando o cyphertext em base64 e usando o -base64 flag, sem sorte. Então eu fui para o link , onde, depois de converter os valores em hexadecimal eu consegui descriptografar:

key: DEAD45C4686E6797D061B8F30F1810DF 
text: F0B0545597C37C8EB09E0806D6E518B90B11A06774F291B01C237EF91E6B69B316F4F26658759C4AB8F2E537DF7E3E8B
out: 7B796F755F73686F756C645F6E6F745F706F73745F7468655F61637475616C5F6374665F76616C75657D5F5F5F5F5F5F

Depois voltei ao meu terminal tentando:

echo -n F0B0545597C37C8EB09E0806D6E518B90B11A06774F291B01C237EF91E6B69B316F4F26658759C4AB8F2E537DF7E3E8B | openssl enc -d -K DEAD45C4686E6797D061B8F30F1810DF -aes-128-ecb -nosalt

mas recebi o mesmo erro:

bad decrypt
140735124906848:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:531:

Eu tentei isso em um Ubuntu 17.04 e agora no meu MacOSX usando o OpenSSL 1.0.2l. Por que não posso descriptografar em meu próprio terminal?

    
por robert 04.07.2017 / 18:14

3 respostas

5

Porque openssl usa o preenchimento PKCS # 7 por padrão e seu texto não contém preenchimento PKCS # 7. Se o texto original foi preenchido, ele foi preenchido com bytes de valor 5F . Use a opção -nopad , preenchendo com o valor 5F não é nenhum esquema de preenchimento conhecido por mim; se precisar ser removido, você precisará removê-lo por conta própria.

Atualmente, você mostra a entrada em hexadecimais. Hexadecimal é a representação dos bytes, não os próprios valores de byte. Você precisa inserir diretamente o material de origem de um arquivo usando o < para seu arquivo ou decodificando hexadecimal a entrada.

A saída também será binária; não representará nenhum texto simples legível. Então você pode precisar converter a saída para hexadecimals antes de compará-la com os valores da sua pergunta.

    
por 04.07.2017 / 18:37
3

Bem, você pode querer considerar o uso de python ou qualquer outra linguagem de script / programação para fazer essas coisas.

As vantagens de fazer isso de forma programática são:

  • Sempre que precisar refazer algo semelhante, você terá seu código pronto.
  • Você pode escrever comentários para explicar o que está acontecendo, portanto, se você precisar entender o que fez anteriormente, esperamos que o código e os comentários o permitam.
  • Muitas coisas, como codificação, manipulação de bytes, etc., são mais fáceis do que no console
  • A maioria dos idiomas é de plataforma cruzada, por isso funcionará no Windows, no Linux e no Android facilmente, se você alternar seu dispositivo.

Em relação ao seu problema, pode ser resolvido usando o python para fazer tudo:

# we import the function we need from common librairies
from base64 import b64decode
from Crypto.Cipher import AES
from binascii import hexlify, unhexlify


# First we decode the message and the key from base64 into bytes:
msg = b64decode("8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L")
key = b64decode("3q1FxGhuZ5fQYbjzDxgQ35==")

# We then instantiate a cipher_suite using AES with the provided key, in ECB mode
cipher_suite = AES.new(key, AES.MODE_ECB)

# We can decrypt the message using our cipher_suite:
recovered = cipher_suite.decrypt(msg)

# We can print it:
print ("plaintext: ", recovered)

# There is some garbage at the end, but if we display it in hexadecimal form:
print ("in hex:", hexlify(recovered))
# We can see it's just padding using '5f', so let's create a function to remove such padding:
def unpad(padded):
  # we declare the value of our padding:
  paddingByte = unhexlify('5f')
  # we do a loop, while the last byte is padding
  while padded[-1:]==paddingByte:
    # we remove the last byte
    padded = padded[:-1]
  # once it's done, we return
  return padded

# We can now use our function to remove padding:
print ("unpadded: ", unpad(recovered))

Agora, se você não quer aprender Python ou qualquer outra linguagem, e / ou se você realmente quer fazer tudo no seu terminal, também é possível: então você poderia fazer tudo diretamente usando pipes para passar os dados de um comando para outro, substituição de comandos para alimentar a tecla correta para openssl, e os comandos base64 para manipular base64 mais xxd para converter dados binários em hex (para a chave em openssl) e, finalmente, use sed para remover o 5f padding:

echo "8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L" | base64 --decode | openssl enc -d -K $(echo "3q1FxGhuZ5fQYbjzDxgQ35==" | base64 --decode | xxd  -c 16 -ps) -aes-128-ecb -nosalt -nopad | sed 's/_*$//g'

Eu não sei porque, mas eu pessoalmente acho a abordagem de python mais limpa.

Você também mencionou que você obteve lixo usando a forma como Maarten Bodewes indicou você, isso está vindo do fato de você estar alimentando valores hexadecimais para o OpenSSL, enquanto você deve fornecer diretamente os dados binários (não o valor hexadecimal) para a mensagem, enquanto você deve fornecer a chave em hexadecimal:

echo -n f0b0545597c37c8eb09e0806d6e518b90b11a06774f291b01c237ef91e6b69b316f4f26658759c4ab8f2e537df7e3e8b | xxd -r -p | openssl ...

PS: você provavelmente deve evitar postar os valores reais encontrados nos CTFs, pois isso pode estragar o jogo para as pessoas cujo primeiro reflexo é pesquisar no Google os valores.

    
por 04.07.2017 / 23:19
2

decodificar base64 por

echo 8LBUVZfDfI6wnggG1uUYuQsRoGd08pGwHCN++R5rabMW9PJmWHWcSrjy5Tfffj6L | base64 -D > aesdata.dat

(o -D é uma peculiaridade do Mac OS. O Linux tende a usar -d ou --decode ).

Da mesma forma:

echo 3q1FxGhuZ5fQYbjzDxgQ35== | base64 -D > aeskey.dat

mas openssl espera valores hexadecimais em parâmetros (mas binários em arquivos cifrados):

xxd -p < aeskey.datdead45c4686e6797d061b8f30f1810df . Ou canalizado do comando anterior, se você quiser evitar a desordem.

Finalmente:

openssl enc -d -nopad -aes-128-ecb -K dead45c4686e6797d061b8f30f1810df -in aesdata.dat -out plain

irá descriptografá-lo. O -nopad evita o erro de decriptografia, já que o preenchimento não padrão é usado.

Agora, hd plain para verificar o resultado, que é exatamente o que você estava procurando.

    
por 05.07.2017 / 00:07