Ресёрч. Детектируем какие АВ стоят на ПК юзера, если он просто перешёл по ссылке

  • Автор темы Admin

Admin

#1
Администратор
Регистрация
31.12.2019
Сообщения
6,656
Реакции
23
Оглавление (для быстрого поиска по CTRL+F)
- Предисловие
- Как работает скрипт
- Как исследовать АВ
- Тестирование АВ
- Выводы


Предисловие
Я задался вопросом, можно ли детектировать какой именно Антивирус стоит у юзера на машине если он просто перейдёт по моей ссылке? Хорошо обдумав этот вопрос мне на ум пришли 4 гипотизы как это потанциально можно провернуть.


1) Так как ав всегда добавляют свои SSL серты в браузер для снифинга HTTPS трафика, то в теории можно это детектить. Но я сразу откинул эту идею так как точно знаю что браузеры не предоставляют каких либо API для доступа к инфе какие у юзера стоят сертификаты в браузере. Такое API есть вроде как только для браузерных расширений, но это вообще не вариант.
2) Некоторые АВ при своей установке ещё автоматически устанавливают своё расширение в браузер. Я предположил что эти расширения могут инжектить что-то в DOM всех HTML страниц и таким образом их наличие в браузере можно детектировать с любой старницы через JS. Гипотиза могла потанциально выстрелить, но после некоторых тестов на которые я убил сутки, эта гипотиза оказалась не удачной. Причина в том что только несколько АВ уставливают свои расширения в браузер при их установке на сам ПК. Но все они ничего не инжектят в DOM страницы.
3) В теории можно детектировать наличие определённого АВ путём создание 10-ти фишинговых доменов, повесить на них фишинги и каждый из доменов отправить в АВ лабу и таким образом у нас будет 10 доменов каждый из которых детектится разными АВ. Но в этой гипотизе есть два узких места. Первый - если мы будем добавлять эти домены в айфрейме на нашем основном домене, то как АВ поведут себя, будут ли они сразу лочить мейн домен по которому перешёл юзер, или только айфрейм в коде HTML? А если с этих доменов подгружать ресурсы (CSS/JS/картинки) будет ли такая-же проблема? Просто если АВ будет лочить не какой-то линк в самом HTML мейн страницы, а саму страницу - то в теории на первый взгляд это не обойти и задетектить так не удастся. Второе узкое место - наверняка я бы столкнулся с проблемой что АВ шарят свои базы чёрных списков доменов другим АВ и потанциально отдав 1 фиш домен условному Авасту, он может отдать его-же всем остальным АВ, или к примеру Google Safe Browsing, а от него уже этот детект получат другие АВ. Из-за этих сложностей я откинул этот вариант, так как реализовать такой концепт само по себе труднозатратно, так ещё и вероятнее всего любая из этих потанциальных проблем с слишком большой вероятностью безповоротно зафейлит сам концепт.
4) И последнее что мне пришло в голову - это детектить АВ по наличию открытых на прослушивание портов. То есть мы из JS можем чекать определённые порты и понимать открыты ли они на прослушивание или нет. Такая техника используется в различных анти-фрод скриптах которые проверяют прослушиваются ли на машине популярные порты, такие как VNC, что косвенно может говорить о том что машина протроянена всяким троянским софтом на подобии HVNC. Ну и собственно мне и пришла мысль делать такие-же проверки, но детектя сами антивирусы. Эта гипотизу я и начал ресёрчить и добился некоторых положительных результатов, о чём поделюсь с вами в этой статье.




Я точно не знал как именно происходит детект открытых портов из JS из-за этого начал гуглить уже рабочие скрипты для детекта, но ничего рабочего не нагуглил, что меня на самом деле удивило и отсюда пришлось веселиться с деобфускацией и отладкой антифрод скриптов где это реализовано. Что и как я деобфусцировал говорить не буду так как по мне это не нужная инфа. Переписав скрипт под себя я получил на выходе такой рабочий код, в него сразу добавлены порты для детекта Аваста/AVG и Касперского.


Как работает скрипт
1) Инициализируется соединение WebSocket Secure (wss) через JS по адресу 127.0.0.1 по списку портов который находится в массиве “ports”, а так же запоминается время, когда был инициализирован WebSocket. Обязательно нужно использовать wss (то есть шифрованное соединение с сокетом), иначе тайминги будут непредсказуемы. Подозреваю что это как раз и связано с TLS-ом.
2) Скрипт ожидает вызова CallBack функций WebSocket, а именно: onopen, onerror, onclose
3) Скрипт получает CallBack на одну из данных функций и подсчитывает время формулой (данное время минус время инициализирования вебсокета)
4) Закрывает WebSocket запоминая время, которое было подсчитано в предыдущем пункте
5) Если коллбеки не были вызваны, вызывается функция, переданная в setTimeout с интервалом в 1500, который принудительно закрывает сокет, логируя это
6) После того как скрипт отработал, он в синхронном режиме переходит на следующий порт


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


Код:
// Массив портов которые детектим
var ports = [
    12025, 12110, 12119, 12143, // AVG + AVAST
    49676 // KASPERSKY
];


// Сюда складируются тайминги запросов
window.ports_timings = {}


// Функция получения таймингов портов
function checkPorts(ports) {
    self.addr = "wss://127.0.0.1";
    self.timeout = 1500;
    self.i = 0;
    function onopen(_) {
        console.log("Open:", self.port);
    }
    function onerror(_) {
        var timeAfterStart = Date.now() - self.startTime;
        console.log("Error:", self.port, timeAfterStart)
    }
    function onclose(_) {
        var timeAfterStart = Date.now() - self.startTime;
        console.log("Close:", self.port, timeAfterStart);
        window.ports_timings[self.port] = timeAfterStart;
        if (i !== ports.length)
            check(ports[i++]);
    }
    function ontimeout() {
        var timeAfterStart = Date.now() - self.startTime;
        if (timeAfterStart > self.timeout) {
            console.debug("Timeout: ", self.port)
            close();
        } else {
            setTimeout(ontimeout, 10);
        }
    }
    function close() {
        self.isDone = true;
        if (self.ws !== null) {
            self.ws.close();
            self.ws = null;
        }
    }
    function check(port) {
        console.debug("Check port: " + port);
        try {
            self.ws = new WebSocket(self.addr + ":" + port);
            self.ws.onopen = onopen;
            self.ws.onerror = onerror;
            self.ws.onclose = onclose;
            self.port = port;
            self.startTime = Date.now();
            setTimeout(ontimeout, 5);
        } catch (exc) {
            console.error(exc.message);
        }
    }


    check(ports[i++]);
};


// Функция получения открытых портов
function getOpenPorts() {
    var opened = [];
    for (i in window.ports_timings)
        if (window.ports_timings[i] < 500) opened.push(i);
    return opened;
}


// Запуск сканирования портов
checkPorts(ports);


P.s. - я пытался реализовать скрипт асинхронным, чтобы можно было одновременно детектить сразу несколько детектов, а не по очереди как это работает сейчас в синхронном режиме, но на практике если делать детекты асинхронными, то можно словить несколько ложных срабатываний.


Как исследовать АВ (или любой другой софт) на наличие детекта на Windows
• Качаем софт Process Explorer.
• Запускаем Process Explorer с правами администратора (ПКМ > запуск от имени администратора)
• Находим все процессы программы которую исследуем на этот детект. В колонке Company Name видим название компании к которой принадлежит запущенный процесс.
11562

• Дважды кликаем по интересующему нас процессу, открывается окно с свойствами данного процесса, открываем вкладку TCP/IP
• Ищем порты, что имеет статус LISTENING как на скрине ниже с примером на главном процессе аваста. LISTENING - означает что аваст открывает порт на самом ПК и прослушивает его, именно такие порты мы и можем детектить.
11563

• Далее просто берём и записываем в моём JS скрипте в массиве Ports нужный нам порт для детекта.


Тестирование АВ
Я взял десяток популярных АВ для теста, раскатил их на изолированных виртуалках и начал тестить


Список АВ учавствующих в моих тестах - Kaspersky, Avast, AVG, Node32, Qihoo360, MacAfee, Comodo, Avira, DrWeb. (оттестированы были самые базовые редакции ав)


Результаты: из протестированых АВ открытые порты на прослушивание устанавливают Kaspersky, Avast и AVG. Причём с последними двумя интересная картина произошла т.к. у них одинаковые процессы и они оба открывают одинаковые порты. Сначало меня это привело в ступор, но потом я вспомнил что Аваст когда-то покупал AVG и видимо они как-то унифицировали свои интерфейсы. Таким образом мы хоть и можем задетектить Аваста и АВГ, но кто именно из них был задетекчен понять нельзя. Все остальные АВ не открывали порты на прослушивание.


Мейн процесс Аваста (AvastSvc.exe) открывает на прослушивает много разных портов, я взял четыре из них (12025, 12110, 12119, 12143) и добавил в скрипт
11563



Касперский открывает один порт на прослушивание (49676)
11564



Процессы АВГ аналогично авасту, разницы между ними нету (12025, 12110, 12119, 12143)
11565



Выводы
В целом ресёрч выдался удачным, так как удалось реализовать надёжный детект касперского и аваста/авг. Это два самых популярных АВ в СНГ, а Аваст на сколько я знаю вообще самый популярный ав во всём мире. Так-же я тестировал только самые базовые редакции антивирусов, к примеру у касперского я взял из AntiVirus Free, я не тестировал Kaspersky Internet security/Premium и т.п. из-за этого потанциально другие АВ открывают порты, но в расширеных своих редакциях, со всякими там фаерволами и т.п. Я тестировал именно базовые редакции с мыслью о том, что если в базе есть детект то он будет и в расширеных версиях АВ. Расширеные версии детектить я не стал так как это заняло бы гораздо больше времени.
Так-же стоит не забывать что с помощью этого готового кода и мануала можно детектить любой другой софт установленный на компе юзера который открывает порт на прослушивание. К примеру вы хотите атаковать таргет эксплуатируя какой-то не по умолчанию устанавливаемый на всех машинах софт, предположем торрент. То при переходе таргетом по вашей ссылке у человека детектится наличие utorrent-а на компе и ему отдаётся *.torrent, вместо *.exe, а если детекта торрента не произошло то можно сразу отдавать *.exe. Тем самым не будет потерян в пустую ценный момент атаки в случае если у юзера нету торрент клиента, а мы ему отдаём торрент файл. То есть можно придумать много полезных применений такой технике детекта.


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


UPD - эта методика была проверена на Google Chrome, там она отрабатывает надёжно. Так-же всё должно работать на Chromium based браузерах (Opera, Yandex, Edge)
Так-же надёжно работает в старом Edge не на движке хрома
Не работает в Firefox (там не предсказуемые тайминги)
IE не тестил.


Автор: Rubicon
 

Members, viewing this thread

Сейчас на форуме нет ни одного пользователя.