[ << ALL_FEED ]

Да что не так с этим AES?

Ещё в группе «Общее»

Да что не так с этим AES? ❔

Злоумышленники часто применяют шифрование для обфускации частей образцов ВПО, которые могут представлять наибольший интерес при исследовании. Когда аналитик обнаруживает такие участки кода, он изучает алгоритм шифрования, и иногда, быстро узнав алгоритм, не видит смысла изучать его полностью.

На примере одного из семейств ВПО, замеченного в атаках на Латинскую Америку, разберем случай, в котором применяется продвинутая техника шифрования, но прячется она внутри самой, казалось бы, классической.

👾 Grandoreiro — бразильский банковский троян, который активен с 2016 года по сегодняшний день. Он доставляется в систему с помощью загрузчика, который получает ссылку на скачивание полезной нагрузки от С2-сервера.

Предыдущие схемы дешифрования строк в Grandoreiro (в частности, в загрузчике) включали кастомное декодирование зашифрованных строк, ключа AES и IV путем простой замены. Эти компоненты дешифровались с помощью XOR, и далее шифротекст расшифровывался окончательно с помощью ключа AES и IV в режиме AES CBC 256 бит.

🧐 При анализе недавних образцов Grandoreiro была замечена новая для этого семейства техника шифрования, которая применяется для усложнения анализа, — Ciphertext Stealing (CTS). Это режим шифрования, который используется, когда открытый текст не кратен размеру блока.

Например, одна из наиболее известных схем паддинга (PKCS #7) дополняет последний блок байтами, чтобы гарантировать, что он по размеру совпадает с полным блоком. CTS работает без паддинга. Его работу мы заметим над последним неполным блоком данных (который не кратен размеру блока).

Что именно происходит:

1️⃣ Шифруется последний полный блок.

2️⃣ Зашифрованный последний полный блок «ксорится» с частичным (неполным) блоком.

Такой способ предоставляет возможность шифровать открытый текст произвольной длины без добавления паддинга, сохраняя исходный размер данных.

Чтобы на практике понять, как это работает, посмотрим на реализацию алгоритма:


cipher = AES.new(aes_key, AES.MODE_ECB)
    encr = b"\x00"*16
    initial_key = cipher.encrypt(encr) # your value here
 
    block_size = 16
    total_blocks = len(ciphered_data) // block_size
    decrypted_data = bytearray()
    previous_block = initial_key
 
    if total_blocks:
        # Decrypt all complete blocks
        for i in range(total_blocks):
            current_block = ciphered_data[i * block_size:(i + 1) * block_size]
            key = previous_block
            decr_block = cipher.decrypt(current_block)
            decrypted_data.extend(bytes(x ^ y for x, y in zip(decr_block, key)))
            previous_block = current_block
 
        # Handle the last block with ciphertext stealing
    if len(ciphered_data) % block_size > 0:
        last_full_block = previous_block
        if total_blocks:
            last_full_block = cipher.encrypt(last_full_block)[:len(ciphered_data) - (i + 1) * block_size] #take as much bytes off of the last full block (encrypted) as remained yet to decrypt (ciphertext)
            partial_block = ciphered_data[(i + 1) * block_size:len(ciphered_data)] #bytes left to decrypt, not a multiple of the block size
        else:
            last_full_block = cipher.encrypt(last_full_block)[:len(ciphered_data)]
            partial_block = ciphered_data[:len(ciphered_data)]
         
        stolen_block = bytes(x ^ y for x, y in zip(partial_block, last_full_block))
        decrypted_data.extend(stolen_block)
Code language: plaintext (plaintext)


Метод довольно оригинальный, и в Grandoreiro он прячется внутри функций, которые реализуют обычный, на первый взгляд, AES.

Поэтому, прежде чем начинать писать скрипты расшифровки, видя заветную аббревиатуру, следует посмотреть на код внимательно — убедиться, что используется действительно классическая версия алгоритма, и не тратить часы в поиске ответа на вопрос «ну почему оно не расшифровывается?».

#TI #tip #malware
@ptescalator

Ещё от ti_author

Ещё от ti_author

Ещё в группе «Общее»