# Интенсив 3 ## Задание 1 :::info Написать детект по событиям (в синтаксисе SIGMA) на скачивание файла с помощью certutil.exe ::: По данным иснтсрукция настроили сисмон и сделали событие: ![](https://i.imgur.com/xk93ieB.png) Это событие даже ближе к инциденту, так как утилита certutil по своему функционалу должна использоваться только для проверки сертификатов, но никак не для загрузки приложений. Поэтому чтобы выполнить команду выше пришлось отключать весь защитник винды, иначе он отказывал в доступе даже с правами админа нашли его в логах event viewer в раздела симон. ![](https://i.imgur.com/FqAHeIf.png) Далее установили сигму с гитхаба. пытались использовать конвентор в запрос для powershell, но ничего не работало. Я не знаю, где именно всё было сломано, но помогла установка *sigmatools* в папку *tools* через pip. В этоге нам выдали запрос запрос для powershell ![](https://i.imgur.com/8mq0fnx.png) Этот запрос я чуть подкорректировала: * добавила -LogName Microsoft-Windows-Sysmon/Operational (откуда смотреть логи) * поставила [^t] перед Image, чтобы он искал image бeз t, то есть не родителя дедект в синтаксисе сигма ``` title: certutil download # название id: c19be249-4dd2-48ec-a0f9-a6a98e4ef4c8 # генерируем id с помощью сайта description: rule for determining the download via certutil # описание references: - https://lolbas-project.github.io/lolbas/Binaries/Certutil/#download # ссылка на страницу с информацией об этом приложении tags: - attack.execution # example MITRE ATT&CK category - attack.t1059 # example MITRE ATT&CK technique id author: mini_kit' date: 2022/09/29 # Rule date logsource: # important for the field mapping in predefined or your additional config files category: process_creation # In this example we choose the category 'process_creation' product: windows # the respective product detection: selection: Image: '*/certutil.exe' ParentImage: '*/cmd.exe' condition: selection fields: - CommandLine - Image - ParentImage - ProcessGuid falsepositives: level: hight ``` Для этого события я не увидела положительных ложных сработок, так как на скриншоте видно, что вывелись только нужные события, поэтому то поле я и не заполняла ## Задание 2 :::info Написать сетевой детект (в синтаксисе suricata) на активность из 1 задания. ::: Событие и захват его трафика ![](https://i.imgur.com/V2dNLTS.png) Правило будем писать по этому потоку. Единственной пакет, который нам пригодится также на скриншоте. Самое главное - записать в поле content строку User-Aget: Certutil Url Agent, так как именно она и говорит о том, что произошло. Но вместо двоеточия мы должны написать |3A|, это экранирует его. Также мы смотрим именно на http пакет, который всегда будет идти с домашнего компа в инет (логично же, чтобы скачать что-то, нужно выйти в инет), ip нам не важны. msg даём +- отражающий суть события: загрузка через Certutil. Также если обратить внимание на поток, у нас было установленно tcp соединение, поэтому можем написать established (но можно и не писать, так как ложных сработок в дополнительном тесте ниже не выявлено) ![](https://i.imgur.com/LWe7neB.png) Правило для детекта в синтаксисе суриката ``` alert http $HOME_NET any -> $EXTERNAL_NET any (msg: "Download via certutil"; flow: established; content: "User-Agent|3A| CertUtil URL Agent"; sid: 12000435; rev: 1; classtype: bad-unknown;) ``` Далее начались приколы с установкой далтона. Скачать репозиторий с гитхаба и запустить команду старт оказалось недостаточно. Для начало пришлось включить впн, далее ему не хватило 20 гб, пришлось увеличивать до 40, затем установленный и запущенный докер не мог найти и запустить своего демона. Пришлось переустанавливать докер компоуз. И только после двух дней я наконец получила это: ![](https://i.imgur.com/MZro1BN.png) Так как в трафике было одно событие правило сработало 1 раз. Посмотрим в http логах событие и сравним с алертом. Сработка произошла на верное событие. ![](https://i.imgur.com/S1DQm31.png) Теперь проверим правило на ложную сработку изменим файл с трафиком на другой, в котором нет нашего события, но есть много http-трафика было: ![](https://i.imgur.com/NBiNQdr.png) стало: ![](https://i.imgur.com/mvJpeRa.png) Отработка правила - ничего не найдено: ![](https://i.imgur.com/G5aIEb4.png) ## Задание 3 :::info Написать программу, выдающую строку по заданным произвольному началу md5-хеша и длине этой строки ::: Язык программирования - **Python**. Так как встроенных функций для расхэширования нет, потому что сами хэши по идее должны быть необратимыми, то придётся использовать лазейки :) Небольшая заметка про md5: это 128 битный алгоритм хеширования, а следовательно он может содержать только 16-ричные символы - от a до f (регистр не важен), от 0 до 9. ### Библиотеки Первая библиотека *hashlib*, необходима, чтобы мы могли использовать функции хэширования. *random* - необходим для реализации рандомной строки. *string* - чтобы мы использовали символами ascii. ![](https://i.imgur.com/qozkHEw.png) ### Проверки на дурачка Начнём разбор с цикла while на 16-25 строчках. :::warning снова нашла косяк: чтобы цикл был бесконечным, мы можем использовать просто True. Исправила в листинге ::: Чтобы он был бесконечным, инициализироуем переменную *а* (строка 5), равную 1 и пишем условие "до тех пор, пока *а* равна 1", а так как в самом теле цикла мы *а* не изменяем, цикл завершится только с помощью break. На строке 18 просто происходит инициализация ввода, причём сразу определяем тип - целочисленный, так как длина может быть указана только целым числом. :::warning В процессе тестирования выявилась ошибка при нажатии таба, поэтому написали ловца ошибки (17-21). ::: Длина строки должна быть строго больше 0, но пользователь может ввести всё, что душе угодно. Поэтому пишем условную конструкцию (строки 22-25), которая сравнивает введёную длину с 0 и, если длина больше, вызывает *break*, прерывающий цикл. Иначе просто выводится сообщение о том, что было не так, а цикл начинается заново и пользователя просят ввести длинну снова. ![](https://i.imgur.com/WomLum9.png) Теперь перейдём к первому циклу (строки 9-14). Как уже упоминалось выше, хэш может содержать только определённые символы (принимать символы верхнего регистра не будем, но если это необходимо, то мы в строку 7 должны добавить "*or all('A' <= x <= 'F' or '0' <= x <= '9' for x in s)*" и изменить потом комментарии об ошмбки для пользователя). Поэтому нам необходимо сделать функцию, возвращающую "True" при отсутствии некорректных символов. Определим ламбда функцию *tst*. Она принимает один аргумент (s), затем с помощью функции all() отберём "истинные" элементы. Внутри неё просто идёт сравнение *х* с допустимыми символами при прогоне чрез цикл в строке-начале хэша. Далее (строчки 9-14) написаны по аналогии с циклом выше, единственное, в условии мы сравниваем результат функции *tst* (обратите внимание, её аргумент - введёное пользователем начало хэша) с 1 (True). А функция вернёт нам правду только если все символы в строке-начеле хэша допустимы. ![](https://i.imgur.com/ITMKPY1.png) ### Создание строки и её хэширование Переменная *letters* (строка 23)- ссылается на константу *printable* библиотеки string (можно использовать и другие константы этой библиотеки). Взяли именно её, так как она содержит цифры, символы ascii (верхний и нижный регистр), знаки препинания и пробелы. Это всё нам необходимо для генерации строк. Далее опять бесконечный цикл (25-35). На строке 26 создаем рандомную строку (*random_str*) с помощью метода join, присоединяющему к изначально пустой строке рандомный символ, выбранный из letters. Всё это идет в цикле, который работает пока i меньше длины строки (меньше, потому что отсчёт идёт от 0 и цикл считает ДО введённой длины, но при отсчёте от 0 как раз выходит длинна). hash_str (строка 27) - хэширование строки. Во-первых, сразу определим строковый тип (он нам понадобится при сравнении с началом хэша). Перед тем, как передать строку функции хэширования, мы должны использовать метод *encode()*, который вернет закодированную версию строки str как объект байтов, так как функция хэширования принимает только такую строку. Затем с помощью метода *.hexdigest()* получим хэш в нормальном виде (иначе будет такое "<md5 _hashlib.HASH object @ 0x0000017EFE2F2C70>"). Далее просто увеличим счётчик (строка 28), он нам нужен для написания условия выхода (строки 33-35). Оно максимально простое: если было проверено 10000000 строк (я подумала, что этого хватит, чтобы не сильно долго выполнять поиск), то скорее всего нет такой строки, удовлетворяющей входным данным, поэтому завершить выполнение цикла, а следовательно и работу программы. Сообщение об этом будет выведено. Теперь самый главное условие (29-32). Здесь мы применяем метод find к нашей захэшированной строке. Он возвращает индекс, где впервые встретился искомый символ или набор символов. Мы же даём ему в аргумент начало хэша. Если find вернёт 0, то выведется строка и её хэш, а выполнение цикла прервётся. Иначе цикл будет идти до тех пор, пока не выполнится усовие на строчках 33-35. ![](https://i.imgur.com/UbyUeY8.png) ### Запуск Обычный ![](https://i.imgur.com/DbuccY9.png) Намеренно сделаем вид, что мы пенёчки, чтобы посмотреть отработку проверок ![](https://i.imgur.com/UyEo0yl.png) А теперь введём начало хэша такое, чтобы программа не смогла подобрать для него строку заданной длинны. Грустный результат ![](https://i.imgur.com/ucOM2T7.png) ### Листинг: ``` import hashlib import random import string c = 0 tst = lambda s: all('a' <= x <= 'f' or '0' <= x <= '9' for x in s) while True: beginning_for_hash = input('Введите начало хэша:\n') if tst(beginning_for_hash) == 1: break else: print('Хэш может содержать только такие символы: 0-9, a-f') while True: try: length_for_str = int(input('Введите длину строки:\n')) except ValueError: print('вы что нажали??') length_for_str = 0 if length_for_str > 0: break else: print('Введите число больше 0') letters = string.printable while True: random_str = ''.join(random.choice(letters) for i in range(length_for_str)) hash_str = str(hashlib.md5(random_str.encode()).hexdigest()) c += 1 if hash_str.find(beginning_for_hash) == 0: print('Мы нашли строку! \n' + random_str) print('А это её хэш:\n' + hash_str) break if c > 10000000: print('Мы не смогли найти строку для таких входных данных :((') break ```