Нечеткое хеширование на Python#

Сравнение подозрительного файла с ранее проанализированными образцами или образцами, хранящимися в публичном либо частном хранилище, может дать представление о семействе вредоносных программ, их характеристиках и сходстве с предварительно проанализированными образцами.

Хотя криптографические хеш-функции (MD5/SHA1/SHA256) являются отличным методом для обнаружения идентичных образцов, они не помогают в идентификации схожих образцов. Очень часто авторы вредоносных программ меняют мелкие аспекты вредоносных программ, что полностью меняет значение хеш-функции.

Нечеткое хеширование – отличный способ сравнить файлы на схожесть.

Ssdeep – полезный инструмент для создания нечеткого хеша для образца, и он также помогает в определении процентного сходства между образцами. Этот метод полезен при сравнении подозрительного файла с образцами из хранилища для идентификации похожих. Это может помочь определить образцы, принадлежащие к одному семейству вредоносных программ или к одной и той же группе субъектов.

Исходные файлы для блокнота находятся по ссылке.

Скачиваем весь архив с файлами для работы в Colab:

!wget https://dfedorov.spb.ru/infosec/re/samples.zip
!unzip samples.zip
!apt-get -y install libfuzzy-dev
!apt-get install ssdeep
!pip install ssdeep

Чтобы определить нечеткий хеш образца, выполните следующую команду:

!ssdeep samples/test
ssdeep,1.1--blocksize:hash:hash,filename
96:RZTmB6WBilMGIlZIpMRiUHsTgZ6uQ7fTuB3eoBqSitrqN:RZioWQMZMpLfgZ8+4osSi,"/content/samples/test"

Чтобы продемонстрировать использование нечеткого хеширования, рассмотрим в качестве примера директорию, состоящую из трех образцов вредоносного ПО.

В следующем фрагменте кода видно, что все три файла имеют совершенно разные значения хеш-функций MD5:

!ls samples
all_hashes.txt	main_02.c  Makefile    test	test_02  v_01.txt
main_01.c	main_03.c  task-1.exe  test_01	test_03
!md5sum samples/*
273c2647cbbff0e05ad8d7a2ab988723  samples/all_hashes.txt
9cc4604b8bb026dbab1d72b17f9c5446  samples/main_01.c
e08e52b2653e222df3ef3270326b7524  samples/main_02.c
1022987df6fbc4684f5d7cec491b459f  samples/main_03.c
5ceae4f28514b491641684cc1f8c5079  samples/Makefile
a82a243ff5dbf90677c64eae4f0b6a8e  samples/task-1.exe
309d0bfa200e4a936157379357cdbf66  samples/test
7c2c629a6b03a1db0ad5f168c29317a3  samples/test_01
f8da20d939b7f10d2de94c22cf28f7dd  samples/test_02
aca771dc841b399b8dfb66fcdaae130d  samples/test_03
46877a90e977f2562bc3a22a47e67dec  samples/v_01.txt

Режим изящного сравнения (опция -p) в ssdeep может использоваться для определения процентного сходства. Из трех образцов два имеют сходство 93%, что предполагает, что они, вероятно, принадлежат к одному и тому же семейству вредоносных программ:

!ssdeep -pb samples/test_01 samples/test_02 samples/test_03
test_02 matches test_03 (93)

test_03 matches test_02 (93)

Как показано в предыдущем примере, криптографические хеш-функции не помогли установить связь между образцами, тогда как метод нечеткого хеширования выявил сходство.

Можно запустить ssdeep для каталогов и подкаталогов, содержащих вредоносные образцы, используя рекурсивный режим (-r):

!ssdeep -lrpa samples/
samples//test_03 matches samples//main_03.c (0)
samples//test_03 matches samples//task-1.exe (0)
samples//test_03 matches samples//test (0)
samples//test_03 matches samples//v_01.txt (0)
samples//test_03 matches samples//main_01.c (0)
samples//test_03 matches samples//Makefile (0)
samples//test_03 matches samples//all_hashes.txt (0)
samples//test_03 matches samples//test_02 (93)
samples//test_03 matches samples//test_01 (0)
samples//test_03 matches samples//main_02.c (0)

samples//main_03.c matches samples//test_03 (0)
samples//main_03.c matches samples//task-1.exe (0)
samples//main_03.c matches samples//test (0)
samples//main_03.c matches samples//v_01.txt (0)
samples//main_03.c matches samples//main_01.c (19)
samples//main_03.c matches samples//Makefile (0)
samples//main_03.c matches samples//all_hashes.txt (0)
samples//main_03.c matches samples//test_02 (0)
samples//main_03.c matches samples//test_01 (0)
samples//main_03.c matches samples//main_02.c (19)

samples//task-1.exe matches samples//test_03 (0)
samples//task-1.exe matches samples//main_03.c (0)
samples//task-1.exe matches samples//test (0)
samples//task-1.exe matches samples//v_01.txt (0)
samples//task-1.exe matches samples//main_01.c (0)
samples//task-1.exe matches samples//Makefile (0)
samples//task-1.exe matches samples//all_hashes.txt (0)
samples//task-1.exe matches samples//test_02 (0)
samples//task-1.exe matches samples//test_01 (0)
samples//task-1.exe matches samples//main_02.c (0)

samples//test matches samples//test_03 (0)
samples//test matches samples//main_03.c (0)
samples//test matches samples//task-1.exe (0)
samples//test matches samples//v_01.txt (0)
samples//test matches samples//main_01.c (0)
samples//test matches samples//Makefile (0)
samples//test matches samples//all_hashes.txt (0)
samples//test matches samples//test_02 (0)
samples//test matches samples//test_01 (88)
samples//test matches samples//main_02.c (0)

samples//v_01.txt matches samples//test_03 (0)
samples//v_01.txt matches samples//main_03.c (0)
samples//v_01.txt matches samples//task-1.exe (0)
samples//v_01.txt matches samples//test (0)
samples//v_01.txt matches samples//main_01.c (0)
samples//v_01.txt matches samples//Makefile (0)
samples//v_01.txt matches samples//all_hashes.txt (0)
samples//v_01.txt matches samples//test_02 (0)
samples//v_01.txt matches samples//test_01 (0)
samples//v_01.txt matches samples//main_02.c (0)

samples//main_01.c matches samples//test_03 (0)
samples//main_01.c matches samples//main_03.c (19)
samples//main_01.c matches samples//task-1.exe (0)
samples//main_01.c matches samples//test (0)
samples//main_01.c matches samples//v_01.txt (0)
samples//main_01.c matches samples//Makefile (0)
samples//main_01.c matches samples//all_hashes.txt (0)
samples//main_01.c matches samples//test_02 (0)
samples//main_01.c matches samples//test_01 (0)
samples//main_01.c matches samples//main_02.c (21)

samples//Makefile matches samples//test_03 (0)
samples//Makefile matches samples//main_03.c (0)
samples//Makefile matches samples//task-1.exe (0)
samples//Makefile matches samples//test (0)
samples//Makefile matches samples//v_01.txt (0)
samples//Makefile matches samples//main_01.c (0)
samples//Makefile matches samples//all_hashes.txt (0)
samples//Makefile matches samples//test_02 (0)
samples//Makefile matches samples//test_01 (0)
samples//Makefile matches samples//main_02.c (0)

samples//all_hashes.txt matches samples//test_03 (0)
samples//all_hashes.txt matches samples//main_03.c (0)
samples//all_hashes.txt matches samples//task-1.exe (0)
samples//all_hashes.txt matches samples//test (0)
samples//all_hashes.txt matches samples//v_01.txt (0)
samples//all_hashes.txt matches samples//main_01.c (0)
samples//all_hashes.txt matches samples//Makefile (0)
samples//all_hashes.txt matches samples//test_02 (0)
samples//all_hashes.txt matches samples//test_01 (0)
samples//all_hashes.txt matches samples//main_02.c (0)

samples//test_02 matches samples//test_03 (93)
samples//test_02 matches samples//main_03.c (0)
samples//test_02 matches samples//task-1.exe (0)
samples//test_02 matches samples//test (0)
samples//test_02 matches samples//v_01.txt (0)
samples//test_02 matches samples//main_01.c (0)
samples//test_02 matches samples//Makefile (0)
samples//test_02 matches samples//all_hashes.txt (0)
samples//test_02 matches samples//test_01 (0)
samples//test_02 matches samples//main_02.c (0)

samples//test_01 matches samples//test_03 (0)
samples//test_01 matches samples//main_03.c (0)
samples//test_01 matches samples//task-1.exe (0)
samples//test_01 matches samples//test (88)
samples//test_01 matches samples//v_01.txt (0)
samples//test_01 matches samples//main_01.c (0)
samples//test_01 matches samples//Makefile (0)
samples//test_01 matches samples//all_hashes.txt (0)
samples//test_01 matches samples//test_02 (0)
samples//test_01 matches samples//main_02.c (0)

samples//main_02.c matches samples//test_03 (0)
samples//main_02.c matches samples//main_03.c (19)
samples//main_02.c matches samples//task-1.exe (0)
samples//main_02.c matches samples//test (0)
samples//main_02.c matches samples//v_01.txt (0)
samples//main_02.c matches samples//main_01.c (21)
samples//main_02.c matches samples//Makefile (0)
samples//main_02.c matches samples//all_hashes.txt (0)
samples//main_02.c matches samples//test_02 (0)
samples//main_02.c matches samples//test_01 (0)

В следующем примере ssdeep-хеши всех файлов были перенаправлены в текстовый файл (all_hashes.txt), а затем подозрительный файл (test_03) сопоставляется со всеми хешами в файле:

!ssdeep samples/test_01 samples/test_02 samples/test_03 > samples/all_hashes.txt
!cat samples/all_hashes.txt
ssdeep,1.1--blocksize:hash:hash,filename
96:RZTWB6WBilMGIlZIpMRiUHs9ga7fNuB3eoBqSitrqN:RZ6oWQMZMpLrI4osSi,"/content/samples/test_01"
96:RIXTekB6WBn+ZZS9+MRSM8vKk7fAuBWeoBqSAXLgj:RIX9oWgZS9+bz7xosSA,"/content/samples/test_02"
96:RIXTtB6WBn+ZZSg+MRSM8vKk7fXuBWeoBqSAXLgj:RIXRoWgZSg+bzyxosSA,"/content/samples/test_03"

В следующем фрагменте кода видно, что подозрительный файл (test_03) идентичен test_03 (соответствие – 100%) и имеет сходство 93% с test_02. Можно использовать этот метод для сравнения любого нового файла с хешами ранее проанализированных образцов:

!ssdeep -m samples/all_hashes.txt samples/test_03
/content/samples/test_03 matches samples/all_hashes.txt:/content/samples/test_02 (93)
/content/samples/test_03 matches samples/all_hashes.txt:/content/samples/test_03 (100)

В Python нечеткий хеш может быть вычислен с использованием python-ssdeep:

!pip3 install ssdeep
import ssdeep
hash1 = ssdeep.hash_from_file('samples/test_03')
print(hash1)
96:RIXTtB6WBn+ZZSg+MRSM8vKk7fXuBWeoBqSAXLgj:RIXRoWgZSg+bzyxosSA
hash2 = ssdeep.hash_from_file('samples/test_02')
print(hash2)
96:RIXTekB6WBn+ZZS9+MRSM8vKk7fAuBWeoBqSAXLgj:RIX9oWgZS9+bz7xosSA
ssdeep.compare(hash1, hash2)
93