Don’t Let An Auto-Elevating Bot Spoil Your Christmas

Ho ho ho! Christmas is coming, and for many people it’s time to do some online shopping.
Authors of banking Trojans are well aware of this yearly phenomenon, so it shouldn’t come as a surprise that some of them have been hard at work preparing some nasty surprises for this shopping season.

And that’s exactly what TrickBot has just gone and done. As one of the most prevalent banking malware for Windows nowadays, we’ve recently seen it diversify into attacking Nordic banks. We’ve blogged about that a couple of times already.

As usual, the Trojan is being delivered via spam campaigns. According to this graph, based on our telemetry, most spam was distributed between Tuesday afternoon and Wednesday morning:


The spam emails we’ve seen typically have a generic subject like “Your Payment – 1234”, a body with nothing but “Your Payment is attached”, and indeed an attachment which is a Microsoft Word document with instructions in somewhat poor English…


Clicking the button will not reveal any document content, but launch a macro that will eventually download and run the TrickBot payload.
Same old trick, but some people who have just bought a Christmas gift might still fall for it and end up with another ‘gift’ installed on their computer.

And that ‘gift’ is the most interesting part of this story. The newest payload underwent some changes which are, well, remarkable…


Since its initial appearance during Fall 2016, the actors have been actively developing the malware, and are constantly expanding and changing the targets. Here a short summary of the recently spotted changes:

  • Removed: banks in Australia, New Zealand, Argentina, Italy
  • Changed: a few Spanish, Austrian and Finnish targets are now found in the Dynamic Injection list (adding interception code to the actual web page) instead of using Static Injection (replacing the complete web page)
  • Added: new banks, particularly in France, Belgium and Greece.

Anti-sandbox checks

Up till now, we were not aware of any features in TrickBot that were checking if the malware is run in a virtual machine or a sandboxed environment used for automatic analysis. The new version has introduced a few simple checks against some known sandboxes by calling GetModuleHandle for the following DLLs:


(More info about every DLL can be found here)

If any of these modules are found, the payload just quits.

Interestingly, we have also found a few encrypted strings that seem to indicate detection of the Windows virtual machine images that Microsoft provides for web developers to test their code in Internet Explorer and Edge, however, these strings are not used anywhere (yet). Let’s see if the actors will expand their sandbox evasion attempts in a future version.



But we have saved the best for last. When the payload was running, we noticed that it didn’t run with user rights, as it always did before. Instead, it was running under the SYSTEM account, i.e. with full system privileges. There was no UAC prompt during the infection sequence, so TrickBot must have used an auto-elevation mechanism to gain admin rights.

A little search in the disassembly quickly revealed an obvious clue:


Combined with a few hard-coded CLSIDs …


… we found out that the actors have implemented a UAC bypass which was (as far as we are aware of) publicly disclosed only a few months ago. The original discovery is explained here:
And later implemented as a standalone piece of code, and most likely the main inspiration for the TrickBot coders:

In short: this bypass is a re-implementation of a COM interface to launch ShellExec with admin rights, and it is used in a standard Windows component “Component Manager Administrator Kit” to install network connections on machine level.

It works everywhere from Windows 7 up to the latest Windows 10 version 1709 with default UAC settings, and considering it’s basically a Windows feature, probably hard to address. In other words, perfect for usage in malware, and it wouldn’t surprise us if we’ll see the same bypass in more families soon.

Thanks to Päivi for the spam graph.


Necurs’ Business Is Booming In A New Partnership With Scarab Ransomware

Necurs’ spam botnet business is doing well as it is seemingly acquiring new customers. The Necurs botnet is the biggest deliverer of spam with 5 to 6 million infected hosts online monthly, and is responsible for the biggest single malware spam campaigns. Its service model provides the whole infection chain: from spam emails with malicious malware downloader attachments, to hosting the payloads on compromised websites.


Necurs is contributing a fair bit to the malicious spam traffic we observe.

The Necurs botnet is most renown for distributing the Dridex banking Trojan, Locky ransomware, and “pump-and-dump” penny-stock spam. Since 2016 it has expanded its deliverables beyond these three and have included other families of ransomware, such as GlobeImposter and Jaff, and the banking trojan Trickbot to its customer base, with Locky being its brand-image malware deliverable with multiple malware spam campaigns per week.

This morning at 9AM (Helsinki time, UTC +2) we observed the start of a campaign with malicious .vbs script downloaders compressed with 7zip. The email subject lines are “Scanned from (Lexmark/HP/Canon/Epson)” and the attachment filename is formatted as “image2017-11-23-(7 random digits).7z“.

The final payload (to our surprise) was Scarab ransomware, which we haven’t seen previously delivered in massive spam campaigns. Scarab ransomware is a relatively new ransomware variant first observed last June, and its code is based on the open source “ransomware proof-of-concept” called HiddenTear.

This version doesn’t change the file names, but appends a new file extension to the encrypted files with “.[].scarab”, and drops the following ransom note after the encryption:


The spam campaigns from Necurs are following the same format from campaign to campaign, consisting of social engineering subject line themes varying from financial to office utilities, with very minimal text body contents and spiced up usually with malicious attachments, sometimes just URLs. And as the simple social engineering themes are effective, Necurs tends to re-use the spam themes in its campaigns, sometimes within a rather short cycle. In this particular case, the subject lines used in this spam campaign were last seen in a Locky ransomware campaign exactly two weeks ago, the only difference being the extension of the attached downloader.


This has already given Scarab-ransomware a massive popularity bump, according to ransomware submissions ID ransomware.

We’re interested to see the future affiliations of this massive botnet and observe how it’s able to change the trends and popularity of malware types and certain families. In the meanwhile, we’ll keep blocking these threats, keeping our customers safe.



RickRolled by none other than IoTReaper

IoT_Reaper overview

IoT_Reaper, or the Reaper in short, is a Linux bot targeting embedded devices like webcams and home router boxes. Reaper is somewhat loosely based on the Mirai source code, but instead of using a set of admin credentials, the Reaper tries to exploit device HTTP control interfaces.

It uses a range of vulnerabilities (a total of ten as of this writing), from years 2013-2017. All of the vulnerabilities have been fixed by the vendors, but how well are the actual devices updated is another matter. According to some reports, we are talking about a ballpark of millions of infected devices.

In this blogpost, we just wanted to add up some minor details to good reports already published by Netlab 360 [1], CheckPoint [2], Radware [3] and others.

Execution overview

When the Reaper enters device, it does some pretty intense actions in order to disrupt the devices monitoring capabilities. For example, it just brutally deletes a folder “/var/log” with “rm -rf”.
Another action is to disable the Linux watchdog daemon, if present, by sending a specific IOCTL to watchdog device:


After the initialization, the Reaper spawns a set of processes for different roles:

  • Poll the command and control servers for instructions
  • Start a simple status reporting server listening on port 23 (telnet)
  • Start apparently unused service in port 48099
  • Start scanning for vulnerable devices

All the child processes run with a random name, such as “6rtr2aur1qtrb”.

String obfuscation

The Reaper’s spawned child processes use a trivial form of string obfuscation, which is surprisingly effective. The main process doesn’t use any obfuscation, but all child processes use this simple scheme when they start executing. Basically, it’s a single-byte XOR (0x22), but the way the data is arranged in memory makes it a bit challenging to connect the data to code.

Main process allocates a table in heap and copies the XOR-encoded data in. Later when the child processes want to reference to particular encoded data, it decodes it in heap and references the decoded data with a numeric index. After usage, the data is decoded back to its original form.

The following screenshot is a good presentation of the procedure:


Command and Control

The Reaper polls periodically a fixed set of C2 servers:,, and

The control messages and replies are transmitted over a clear-text HTTP, and the beacons are using the following format:


The protocol is very simple: basically there are only two major functions – shutdown or execute arbitrary payload using the system shell.

Port scanning

One of the child processes starts to scan for vulnerable victims. In addition to randomly generated IP addresses, Reaper uses nine hard-coded addresses for some unkown reason. The addess is scanned with a set of apparently random-looking set of ports, and then with a set of bit more familiar ports:

80, 81, 82, 83, 84, 88, 1080, 3000, 3749, 8001, 8060, 8080, 8081, 8090, 8443, 8880, 10000

In fact, the randomish ports are just byte-swapped presentation of the above port list. So for example, 8880 = 0x22b0 turns to 0xb022 = 45090. The reason for this is still unknown.

It is possible that the author was just lazy and left off some endianness handling code, or maybe it is some other error in the programming logic. Some of the IoT-devices are big-endian, so the ports need to be swapped in order to use them with socket code.

Screenshot of the hard-coded list of ports:


This is the list of hard-coded IP-addresses:


If the Reaper finds promising victim, it next tries to send HTTP-based exploit payload to the target. A total of ten different exploits have been observed so far, and they are related to IoT devices HTTP-based control interface. Here’s a list of the targeted vulnerabilities and HTTP requests associated with them:

1 – Unauthenticated Remote Command Execution for D-Link DIR-600 and DIR-300

Exploit URI: POST /command.php HTTP/1.1


2 – CVE-2017-8225: exploitation of custom GoAhead HTTP server in several IP cameras

GET /system.ini?loginuse&loginpas HTTP/1.1


3 – Exploiting Netgear ReadyNAS Surveillance unauthenticated Remote Command Execution vulnerability

GET /upgrade_handle.php?cmd=writeuploaddir&uploaddir=%%27echo+nuuo+123456;%%27 HTTP/1.1


4 – Exploiting of Vacron NVR through Remote Command Execution

GET /board.cgi?cmd=cat%%20/etc/passwd HTTP/1.1


5 – Exploiting an unauthenticated RCE to list user accounts and their clear text passwords on D-Link 850L wireless routers

POST /hedwig.cgi HTTP/1.1


6 – Exploiting a Linksys E1500/E2500 vulnerability caused by missing input validation

POST /apply.cgi HTTP/1.1


7 – Exploiting of Netgear DGN DSL modems and routers using an unauthenticated Remote Command Execution

GET /setup.cgi?next_file=netgear.cfg&todo=syscmd&curpath=/&currentsetting.htm=1cmd=echo+dgn+123456 HTTP/1.1


8 – Exploiting of AVTech IP cameras, DVRs and NVRs through an unauthenticated information leak and authentication bypass

GET /cgi-bin/user/Config.cgi?.cab&action=get&category=Account.* HTTP/1.1


9 – Exploiting DVRs running a custom web server with the distinctive HTTP Server header ‘JAWS/1.0’.

GET /shell?echo+jaws+123456;cat+/proc/cpuinfo HTTP/1.1


10 – Unauthenticated remote access to D-Link DIR-645 devices

POST /getcfg.php HTTP/1.1


Other details and The Roll

  • Reaper makes connection checks to google DNS server It won’t run without this connectivity.
  • There is no hard-coded payload functionality in this variant. The bot is supposedly receiving the actual functionality, like DDoS instructions, over the control channel.
  • The code contains an unused rickrolling link (yes, I was rickrolled)

Output from IDAPython tool that dumps encoded strings (rickrolling is the second one):


Sample hash

Analysis on this post is based on a single version of the Reaper (md5:37798a42df6335cb632f9d8c8430daec)



Facebook Phishing Targeted iOS and Android Users from Germany, Sweden and Finland

Two weeks ago, a co-worker received a message in Facebook Messenger from his friend. Based on the message, it seemed that the sender was telling the recipient that he was part of a video in order to lure him into clicking it.

Facebook Messenger message and the corresponding Facebook Page

The shortened link was initially redirecting to, but was later on changed to redirect to yet another shortened link –

Changes in the Picsee short link

The shortened link supported two types of redirection links – original link and smart links. If the device that accessed the URL was running in iOS or Android, it was redirected to the shortened link, otherwise it was redirected to

The short link with the smart links

So for the iOS and Android users, they were served with the following phishing page:

Phishing page for short link

For the rest of the devices, the users ended up with the link that went through several redirections which eventually led to That page contained an ad-affiliate URL which redirected to, a mobile advertising company.

Phishing page’s ad-affiliate URL

Based on the data from the links, the campaign began last October 15th when it targeted mostly Swedish users. On the 17th, it moved to targeting Finnish users. Then from 19th onwards, it mostly went after German users.

The total number of clicks for the entire campaign reached almost 200,000, where close to 80% of the visitors were from Germany, Sweden and Finland.

Statistics from tracking page

The campaign ran for two weeks with a main motive of stealing Facebook credentials from iOS and Android users. The cybercriminals used those stolen credentials to spread the malicious links, and subsequently gather more credentials. However, while in the process of stealing the credentials, the cybercriminals also attempted to earn from other non-iOS and non-Android users through ad-fraud.

This practice of using email addresses in place of unique names as account credentials creates a big opportunity for phishers. Just by launching this Facebook phishing campaign, they can mass harvest email and password credentials that are later on used for secondary attacks such as gaining access to other systems or services that could have a bigger monetary value because of password reuse.

We highly recommend the affected users to change their passwords as soon as possible, including other systems and services where the same compromised password was used.


  • hxxp://lnk[.]pics/19S3Y
  • hxxp://lnk[.]pics/18JDK
  • hxxp://lnk[.]pics/196OV
  • hxxp://lnk[.]pics/18XH7
  • hxxp://lnk[.]pics/196PN
  • hxxp://lnk[.]pics/19LBP
  • hxxp://lnk[.]pics/18YZV
  • hxxp://lnk[.]pics/18QZW
  • hxxp://lnk[.]pics/196PA
  • hxxp://lnk[.]pics/19XK7
  • hxxp://lnk[.]pics/18HFX
  • hxxp://lnk[.]pics/19S3L
  • hxxp://lnk[.]pics/18J7S
  • hxxp://lnk[.]pics/19XKF
  • hxxp://lnk[.]pics/19K94
  • hxxp://lnk[.]pics/19LBW
  • hxxp://pics[.]ee/188g7
  • hxxp://pics[.]ee/18cdl
  • hxxp://po[.]st/ORyChA
  • hxxp://smarturl[.]it/02xuof
  • hxxp://utm[.]io/290459
  • hxxp://at.contenidoviral[.]net

The big difference with Bad Rabbit

Bad Rabbit is the new bunny on the ransomware scene. While the security community has concentrated mainly on the similarities between Bad Rabbit and EternalPetya, there’s one notable difference which has not yet gotten too much attention. The difference is that Bad Rabbit’s disk encryption works.

EternalPetya re-used the custom disk encryption method from the original Petya. Although it didn’t implement the actual ECDH key delivery mechanism, it installed the Petya boot loader, and effectively just rendered the machine useless.

Petya’s disk encryption had one specific weakness: it only encrypted some parts of the key file system structures, not the whole disk. This design obviously lead to speculations about whether it is possible to recover the disk using a known clear-text attack, and in fact researchers have made significant progress in investigating this recovery technique.

At least on the surface, things look quite different with Bad Rabbit. Instead of using a custom encryption mechanism, it follows the current trend in the ransomware community of leveraging known legitimate encryption tools.

Bad Rabbit uses DiskCryptor, a full disk partition encryption software for locking the user disk. The ransomware ships with an unmodified DiskCryptor driver (borrowed from ReactOS) and implements relevant parts of the DiskCryptor user-mode code for communicating with the driver. The ReactOS driver is a signed, valid driver, so it gets loaded by the Windows cleanly with the elevated privileges required by Bad Rabbit’s fake Flash installer dropper.

Key generation

Bad Rabbit uses Windows’ crypto API to generate random key data for the disk encryption. This key data is converted to a human-readable encryption key, which is a 32-bytes long ASCII encoded string, presenting around 165 bits of entropy for the stream cipher AES used by DiskCryptor.

The following screenshot represents the random disk encryption key as it is being generated by the malware:


Running dispci.exe under user-mode debugger

Along with the random key, Bad Rabbit packages some other information like the victim computer name and domain, then forms the so-called installation key that will be presented after the reboot. In Petya, this code was relatively short code that was protected by the public EC key. In Bad Rabbit, it is a much longer blob of data that is protected by the RSA public key shipped with the malware installer.

After packaging the installation key, the random key data is just discarded. The installation key is written to the disk so that the Bad Rabbit boot loader can present it on the boot screen:


Bad Rabbit’s boot loader

The user is expected to grab the installation key from the boot screen, paste it to the attacker’s TOR site, which then will use its own private RSA key to extract the 32-bytes password (typed in the screenshot above).

After the boot screen

Because the disk encryption software used is pretty much similar to any other disk encryption used by businesses around the globe, like TrueCrypt or Microsoft BitLocker, the disk is in fact *still* encrypted, although it has been mounted by the DiskCryptor driver transparently.

So if the user now reboots the machine, the same password prompt will be presented as long as the disk decryption routine is initiated. The DECRYPT tool referenced by the boot loader is actually just a shortcut to the dispci.exe tool dropped by the malware. This tool borrows code from legit DiskCryptor sources for implementing the relevant parts of the code for communicating with the disk encryption driver.

Even though all this is quite apparent by just looking at the code, we wanted to demonstrate the encryption scheme by catching the password inline, at the time it was generated by Bad Rabbit. When this password is used for unlocking the machine, it is possible to install the real DiskCryptor GUI tool and initiate the disk decryption process.


Using DiskCryptor to verify encrypted volume

DiskCryptor identifies the disk presented by the virtual machine (QEMU HARDDISK in the above screenshot) as an AES-encrypted volume, and accepts the random password.

It works now

We have speculated before that the flawed disk encryption in EternalPetya was due to problems in the malware development process. Or it may be that they just didn’t care. People will pay anyways, right?

Whatever was the reason, they have now fixed this issue (if they are the same group of malware developers, which seems to be the consensus in the research community).

At least the developers of Bad Rabbit have noted the recent developments in research on Petya’s disk encryption weaknesses and decided to use something different.

Recovery considerations

As we have demonstrated in this blog post, Bad Rabbit seems to use a sound principle in its disk encryption, a full disk encryption scheme familiar to all businesses.

We don’t yet have the full details of this scheme, so there might be bugs in the implementation. But at least its design enables a strong mechanism for locking the machine until the correct password is really typed to the boot screen.


For screenshots used in this blog post, we DID NOT go to the attacker TOR site and pay for the recovery key.

The procedures presented in this text DO NOT mean there’s an easy way to unlock the disk protected by the Bad Rabbit. We just present them as proof of the encryption scheme. Catching the password inline to the encryption process is not practical in a general sense, because it requires software that is aware of the exact password generation mechanism prior to the infection. It is used here just for a relatively easily reproducible proof-of-concept.

Following The Bad Rabbit

On October 24th, media outlets reported on an outbreak of ransomware affecting various organizations in Eastern Europe, mainly in Russia and Ukraine. Identified as “Bad Rabbit”, initial reports about the ransomware drew comparisons with the WannaCry and NotPetya (EternalPetya) attacks from earlier this year. Though F-Secure hasn’t yet received any reports of infections from our own customers, we’re actively investigating. And while the investigation is still ongoing, initial results from our analysis did find similarities between Bad Rabbit and the NotPetya ransomware that hit companies late last June.

We think there’s good evidence that suggests the same person or group is responsible for both last June’s NotPetya attacks and what we’re seeing now with Bad Rabbit. Malware authors often learn from what works, so finding the same characteristics in different families is not uncommon. But the similarities we’re seeing here are too much to be just one attacker copying another.

Without getting too technical, here’s a handful of the similarities between NotPetya and Bad Rabbit:

  • Overall code structure is similar
  • File encryption code is VERY similar
  • Similar method of checking existing processes and encrypting files
  • Similar method used to reboot computers
  • Same trick used to launch the malware’s main component as a DLL
  • Identical code used to parse the command line
  • Similar propagation methods, including an identical “library” of other computers found in the network, and use of Mimikatz to gather credentials
  • Out of 113 file extensions used by BadRabbit, 65 are shared with NotPetya (Bad Rabbit has an additional 48)

There are also some notable differences between the two, including:

  • Bad Rabbit doesn’t use EternalBlue/EternalRomance exploit
  • Bad Rabbit doesn’t use PsExec to spread
  • Bad Rabbit also encrypts “home user” files, such as .jpgs
  • Bad Rabbit adds “.encrypted” to the contents of affected files (NotPetya didn’t do this, making it harder to distinguish between encrypted and non-encrypted files)
  • Bad Rabbit’s infection vector is via compromised websites. While NotPetya was reported to be via MeDoc
  • Bad Rabbit brute-forces using a set of predefined credentials to available SMB shares
  • The list of process hashes to be compared to are different from NotPetya. NotPetya compares against Symantec and Kaspersky processes, while Bad Rabbit compares against McAfee and DrWeb

Like NotPetya, Bad Rabbit will display the two ransom note – one for MBR encryption.

Bad Rabbit Message

And a text note for file encryption.

Oops! Your files have been encrypted.

If you see this text, your files are no longer accessible.
You might have been looking for a way to recover your files.
Don't waste your time. No one will be able to recover them without our
decryption service.

We guarantee that you can recover all your files safely. All you
need to do is submit the payment and get the decryption password.

Visit our web service at caforssztxqzf2nm.onion

Your personal installation key#2: [REDACTED]

Users are directed to pay the ransom at a specified payment site, which also provides the amount of the ransom to be paid.

Bad Rabbit Payment Site

A threat description of the Bad Rabbit ransomware is available at Trojan:W32/Rabbad and will be updated as and when more details are confirmed.

In the meantime… our endpoint protection products have a variety of measures baked in that prevent Bad Rabbit infections.

Edited to update: Struckthrough EternalRomance mention above. We have verified the same observations as Cisco Talos Security about EternalRomance exploited by Bad Rabbit.

Twitter Forensics From The 2017 German Election

Over the past month, I’ve pointed Twitter analytics scripts at a set of search terms relevant to the German elections in order to study trends and look for interference.

Germans aren’t all that into Twitter. During European waking hours Tweets in German make up less than 0.5% of all Tweets published.

Data collected from the 1% sample stream (gardenhose)

Over the last month, Twitter activity around German election keywords has hovered at between 2 and 5 Tweets per second. Exceptions only occurred during the TV Debate (Sunday September 3rd 2017) and the day of voting (Sunday September 24th 2017). Surprisingly, Tweets volumes were still low on Saturday September 23rd 2017 – the day before votes were cast.

Here’s how things looked on Friday and Saturday:

Prior to polls closing on Sunday, Tweet volumes reached a sustained 10 Tweets per second. Once exit polls were announced, volumes exploded.

That sudden drop is my script not handling the volume all too well

Over the past month, topics related to the AfD party were pushed rather heavily on Twitter. This snapshot, taken on Thursday 21st September, is pretty similar to every one observed during the whole month.

Here’s an example of another trend I observed throughout the entire month regarding #afd hashtag volumes:

Notice that the Tweet volumes follow an organic pattern, trailing off during night hours. This contrasts what I observed during the French elections earlier this year, where #macronleaks hashtags were pushed by bots, and maintained a constant volume regardless of the time of day. Despite the high volume of AfD-related Twitter content being posted, AfD didn’t show up in Twitter’s own German trends at any point.

The terms “migrant”, “refugee”, “islam” were mentioned a fair bit in Tweets. Here’s what happened over the weekend.

Ben Nimmo of @DFRLab noticed that a hashtag named #wahlbetrug (election fraud) was being amplified by commercial Twitter bots on Saturday. This story was also picked up by the German publication Bild. My scripts also saw the hashtag briefly enter the top 10 during that day.

Here’s a Tweet timeline of this hashtag, since it’s appearance.

Looking at a timeline of Tweets using this hashtag shows the presence of certain more active accounts pushing this message.

Accounts retweeting Tweets containing the #wahlbetrug hashtag

Accounts replying to Tweets containing #wahlbetrug

Shortly after exit polls were published, the hashtag #fckafd surfaced.

The timeline of this particular hashtag is distinctly different.

However a number of highly active amplifiers were involved in both cases.

Highly active amplifiers of the #fckafd hashtag

Highly active amplifiers of the #wahlbetrug hashtag

This data illustrates how tricky it is to automate the discovery of artificially amplified Tweets. While the #wahlbetrug hashtag was indeed amplified by paid commercial botnets, it didn’t make a splash, and Twitter users would have most likely have needed to go searching for pro-AfD Tweets to find it.

A few Twitter users posted very actively during the campaign. Over the weekend, @Teletubbies007, @Jensjehagen, and @nanniag were very active.

@Teletubbies007 was the top tweeter of the #AfD, #btw17, #gehwaehlen, #reconquista, #traudichdeutschland, #wahlbeobachter, #wahlbeobachter, and #weidel hashtags.

Jensjehagen published the most retweets over the weekend.

The @AfD account was the most mentioned Twitter account.

Tools for automating Twitter activity (such as IFTTT) appeared in the top 10 of sources captured during the weekend.

Tweets published by highly active accounts made up about 3.5% of all traffic during the weekend. I had no accurate way of measuring the number of Tweets originating from commercial bot nets, and hence can’t give an estimation as to how much traffic those were responsible for.

My scripts were also configured to look for specific patterns in Tweets and metadata associated with users’ accounts in order to calculate how much activity originated from “alt-right” groups pushing right-wing agenda. Rough calculations from this data suggest that as much as 15% of all Twitter traffic associated with the German election fit this pattern.

Of the roughly 1.2 million Tweets processed between Friday afternoon and Sunday night, about 170,000 Tweets were matched by that bit of logic. These Tweets originated from about 3,300 accounts. This traffic was enough to generate the results seen in this article, but only to those looking at Twitter streams with automated tools, such as the ones I’m using.

Of note were a few videos and URLs that received a fair amount of retweets. The most obvious of these was a video posted by V_of_Europe showing an immigrant removing election campaign posters.

This was the second most retweeted Tweet I could find from the weekend (pertaining to the election itself). This Tweet was also pushed in other languages.

Another notable Tweet that showed up earlier in the weekend was a story about Merkel being booed at her final campaign rally in Munich. It didn’t get a whole lot of traction, though.

Plenty of links were shared to non-authoritative news sources. Here’s just one example…

…which was shared by this account…

Pay close attention to this user’s profile description

And on the same note, during the weekend, I saw plenty of non-German accounts Tweeting in German, and pushing links to questionable news sources.

I also captured plenty of pro-Trump accounts posting in English.

Another interesting story that failed to gain traction was one about an election results leak prior to the end of voting.

Across the duration of my analysis, 200,000 individual URLs were shared. Around 418,000 Tweets contained those URLs. Of those Tweets, only some 500 linked to questionable political content, which were shared in about 4,000 Tweets. Of the 400,000 unique Twitter users observed participating in this discussion, about 3,000 users were responsible for sharing “fake news” links. By and large, the accounts sharing these links didn’t look like bots.

Merkel was the most seen word in Tweets that shared links to political agenda articles.

Overall, German language Tweets made up roughly 60% of all Tweets during the run-up to the election.

At the time of writing, the most retweeted Tweet I can find pertaining to the election is this one, which has already received over 10,000 retweets.

Also, it’s nice to see that Russians themselves have a sense of humor when it comes to all the allegations of election interference.

Given the lack of German participation on Twitter, it seems to me that the heavy right-wing messaging push that’s been going on during the German election cycle has been more about recruiting new members into the alt-right than it’s been about election interference.

TrickBot In The Nordics, Episode II

The banking trojan TrickBot is not retired yet. Not in the least. In a seemingly never ending series of spam campaigns – not via the Necurs botnet this time – we’ve spotted mails written in Norwegian that appear to be sent by DNB, Norway’s largest bank.

Trickbot Mail

The mail wants the recipient to believe that they have received an important “decision letter” and that they should open the attached document for more information. They also suggest that, if there are problems reading the content, you have to click the “Enable Content” button… uh oh, where have we heard that before?

Anyway, let’s take a look at the attachment “SikreDokumenter.doc” (“Secure Document”). Not that much to see here though.

Sikre Dokumenter

“Laster Innhold” translates to “Loading content”, but that content never appears. As if it is waiting for the user to click “Enable Content”, as the mail suggests, no? Unfortunately, clicking this button still never reveals anything (how disappointing!). Instead, a Visual Basic macro launches a PowerShell script which will download and execute the TrickBot loader.

And just like last time we wrote about TrickBot, a large spam campaign often goes hand in hand with a malware update. Now the authors are “celebrating” a brand new list of targets. Here’s a short summary:

  • More targeting of finance related sites which are no traditional banks: American Express, Amazon, …
  • A few banks in Mexico, Argentina and Chile. Middle and South America, some of the last parts of the world that TrickBot hadn’t visited yet.
  • New European countries: Croatia, Slovenia, Hungary, Turkey, …
  • More banks in countries targeted before, such as Belgium, The Netherlands, Luxembourg, Germany, Spain, Italy, Poland, Singapore, Australia, New Zealand, …
  • And last but not least: the Nordic countries are back in the game.

Wait, the Nordic banks were gone? That’s right! They appeared in June, but were removed again early August. Our guess was that attacking the Nordics turned out not that profitable – but now they are back. Which immediately explains the localized spam.

But fear not, our security products were already protecting you against this latest campaign.

Special thanks to Päivi for the help.

Working Around Twitter API Restrictions To Identify Bots

Twitter is by far the easiest social media platform to work with programmatically. The Twitter API provides developers with a clean and simple interface to query Twitter’s objects (Tweets, users, timelines, etc.) and bindings to this API exist for many languages. As an example, I’ve been using Tweepy to write Python scripts that work with Twitter data.

While seemingly powerful at first, developers will inevitably bump into one of the many restrictions imposed on usage of Twitter’s API, likely not all that long after they start using it. And if they’re like me, they’ll probably put a great deal of time and effort into figuring out if they can circumvent those restrictions. Here are a few that I’ve bumped into:

  • The Twitter API imposes rate limits on every action you can perform. These rate limits vary depending on what it is you’re trying to do. Here’s a table that lists them. Rate limits almost completely destroy one’s ability to create forensic tools that iterate follower/following lists looking for associations between accounts (that can sometimes be useful for mapping out bot networks.)
  • The number of results returned by queries is capped. A while back I tried to retrieve lists of followers for Twitter’s top 100 most followed accounts (all of which have millions of followers). The API only let me retrieve the most recent 5000 followers. Likewise, if you want to iterate Tweets published by a specific user, the API will only return about 3,200 items, even if the user’s Tweet history contains more.
  • Searches will only retrieve data from the last 7 days. This prevented me from creating a tool to retrieve the first Tweet that contains a specific string, URL, or hashtag (which would be useful for forensic purposes). In order to see back past 7 days, you’d have to save all Tweets, all the time. And that would be expensive, if it were even possible, but…
  • You can’t listen to a stream of all Tweets that are happening. That stream is referred to as “the firehose”, and Twitter only grants a few customers access to it. You can, however, listen to a stream of 1% of all Tweets. That’s referred to as “the garden hose”. Alternatively, and this is the method I use, you can listen to a stream based on a set of search terms. This is a more targeted approach, and ends up being more useful than listening to a ton of noise in most cases.
  • As I mentioned in a previous post, some objects aren’t returned as you might expect. In the case of a “Quote Tweet”, you can access a static representation of the quoted Tweet, but not the full Tweet object. This prevents a script from iterating through nested quote Tweets without performing multiple queries and, yeah, you guessed it, hitting the rate limit wall.
  • Some information is missing. At the time of querying, I’d like to see how many replies a Tweet has accrued. Not possible. You can retrieve an integer corresponding to the number of times a Tweet has been liked or Retweeted, but you’d have to perform additional queries to get a list of users or Tweets associated with that action.

Regardless of the numerous restrictions, working with the Twitter API is fun. And figuring out how to retrieve the data you need while working under these restrictions is often a nice challenge. Saying that, I can’t help but feel like I’ll never operate at a level above “hobbyist”. The data that Twitter themselves have access to puts them in a much better position to find patterns associated with bots. For instance, they’ll likely have direct access to data about when accounts followed/unfollowed other accounts, name changes, Tweet deletions, and perhaps even the IP addresses of clients connecting to Twitter. A recent Brian Krebs article alluded to the fact that Twitter do have automation in place to detect bot-like behavior. Twitter’s back end logic appears to, in some cases, take automatic action against bots. It makes sense that they can’t reveal the logic behind their bot-detection algorithms, but you can definitely see it in play. In a recent example, Joseph Cox‘s Twitter account was automatically restricted after bots targeted some of his Tweets.

Here’s another example. While writing this article, I pointed a script at the garden hose (1% of all Tweets) and collected some metadata about each Tweet I encountered. That metadata included a count of all hashtags seen in Tweets. Here’s the top 10 hashtags my script encountered during the run.

Top 10 hashtags seen from Twitter’s garden hose between 11:00 and 12:00 EEST on 31st August 2017.

Right at the top of that list is the hashtag #izmirescort, a tag used in predominantly Turkish language Tweets to advertise escort services. However, that hashtag doesn’t show up in global trends. During the last several months, every time I’ve run a script against the garden hose, #izmirescort was the top hashtag. So it seems obvious that Twitter has some behind-the-scenes filtering going on to prevent certain hashtags from showing up in trends.

The Twitter streaming API supplies a Tweet object for every Tweet retrieved from the stream. That object doesn’t just contain information about the Tweet, it also contains information about the user who published the Tweet. Hence, by listening to a stream, a script can harvest information about both Tweets and users. This is one of the best ways of getting around rate limiting. For the cost of one API transaction, you can listen to a stream as long as the connection holds, and gather interesting data. While attached to the garden hose stream, I configured my script to fetch a few pieces of metadata associated with the user who posted each Tweet. By obtaining the account creation date and number of Tweets that account has published, I can calculate an average value for Tweets per day over the lifetime of that account. There are some accounts out there that post a phenomenal number of Tweets per day. Here’s an example.

A snapshot of high activity Twitter users obtained from a few minutes of listening to the garden hose stream.

If you listen to a stream for long enough, you’ll observe some accounts Tweeting multiple times. Recording the time interval between Tweets allows you to build up an “interarrival” map. You can also build an interarrival map on a individual user by obtaining previous Tweets from that user and examining the timestamp of each Tweet. Here’s an interarrival map of the last 3200 Tweets from the top listed account above (Love_McD).

0 | 1396
1 | 1249
2 | 341
3 | 99
4 | 28
5 | 6
6 | 1
7 | 1

The above data shows that 1396 Tweets were published with less than one second interval between them, 1249 Tweets one second apart, 341 Tweets 2 seconds apart, and so on. This account literally tweets every few seconds, non-stop.

Performing a standard deviation calculation on the numbers from the second column, you can obtain a floating point number that represents the “machine-like” behavior of that account. Normal accounts tend to have a standard deviation value very close to zero. This account’s value was 549.79.

Of course, by visiting the above account’s Twitter page, you’ll notice that it’s a verified account belonging to McDonalds Japan. Simple numerical analysis on account activity isn’t enough to determine whether it’s a “bad” bot. And there are plenty of legitimate bots on Twitter.

Some bots attempt to hide their activity, while pushing an agenda, by replying to other users. Anyone with a high-profile enough Twitter account has probably had a random Tweet of theirs replied to by a p0rn bot. Thus, using a script to track the percentage of Tweets from an account that were replies to other Tweets is a useful way of determining suspiciousness.

As Ben Nimmo has pointed out, some Twitter botnets utilize multiple accounts to Retweet and Like specific Tweets in attempt to modify SEO on those posts. This is the tactic one botnet owner used to attack Joseph Cox’s account. Again, a script can be used to examine Retweet and Like behavior of an individual account, and by listening to a stream, one can build a list of suspicious accounts on-the-fly, as data arrives.

Another rather easy way of finding bots is to look at the “source” field in a Tweet. This field is set by the application that posted the Tweet. If you publish a Tweet from the Twitter app on your iPhone, source will be set to “Twitter for iPhone”, for example. If you are using the Twitter API to publish Tweets, you’ll create a name for the source field when you set up your API keys. Not all bots use the Twitter API to post Tweets, though, since it’s an obvious giveaway. The bots that recently harassed Ben Nimmo and others all report “legitimate” values in their source fields, indicating that the bot master has automated Tweeting from iPhones and web clients. However, since examining the source field of a Tweet is trivial, it’s still a nice way to determine suspisicousness. Here’s some interesting looking source fields I picked up, in conjunction with high-volume Tweeters.

Non-standard source fields (rightmost column) from high-volume Tweeters.

Note that IFTTT (If This Then That) is a legitimate service used by many companies and individuals to automate social media activities. Hence it’s also a great place for not so legitimate operations to hide.

As an aside, here’s a breakdown of the languages seen while my script was running (which can provide information about the popularity of Twitter in different regions at that hour of the day).

Language breakdown from the Twitter garden hose stream between 11:00 and 12:00 EEST August 31st 2017. The large brown segment is “ja”, but the legend got cut off (I’m still tweaking my visualization implementation).

The botnet recently examined by Ben Nimmo was evidently being used to promote content in multiple languages. Hence, and examination of the languages used in Tweets published by a single account may help determine suspiciousness. However, that particular form of analysis is somewhat at the whim of Twitter’s own language-determination algorithms. I did a language distribution analysis of my own Tweets and found this.

1: cs
1: de
807: en
3: es
3: fi
2: fr
1: ht
1: in
1: no
2: pt
1: tl
1: tr
36: und

Und means “undecided”. As you can see, Twitter may have incorrectly categorized the language of some of my Tweets. However, en is overwhelmingly represented. Accounts that have been used to push content in multiple languages may have double-digit percentage values for multiple languages, indicating that the account holder is either multilingual, or that the account is automated. Of course, Retweets should be factored into this calculation.

The use of scripts to analyze Twitter data opens up many ways to search for suspicious activity. This post has touched upon some of the simplest techniques one can use to build Twitter bot analysis scripts. I’ll cover some more complex techniques in future posts.

Trump Hating South Americans Hacked HBO

Last week – I read the message “Mr. Smith” reportedly sent to HBO… and it brought up a few questions. And also, it offered some “answers” to questions that I’m often asked. Questions such as “how much money do cyber criminals make?”

Here’s the start of the message.

It took about 6 months

First, let’s examine Mr. Smith and his colleagues’ persistence. How long did it take to infiltrate HBO? According to Mr. Smith, it took ~6 months and they considered it to be “difficult”.

Next, how much money to cyber criminals make? And how busy are they?

we are IT professionals

According to Mr. Smith’s claims…

  • Annual expenses: ~400 to 500 thousand dollars for 0-day exploits.
  • Annual income: ~12 to 15 million dollars.
  • Annual number of targets: often two major operations.
  • Total number of targets: 17.
  • Amount who paid extortion: 14.

But of course, it’s supposedly not all about the money.

Even we hate trump like other Americans do

Near the end of the message, Mr. Smith warns “Don’t go to FBI or other f–––ing IT Idiots. They are so busy or shoe makers!”

Now, I haven’t come across the term “shoe makers” before so I was curious. In what country or countries is that expression commonly used? I mentioned it to Andy and he checked with our language localization team, and they took a look at the entire message.

So what’s their best guess as to where in the world is Mr. Smith?

They suggested Spanish speaking parts of South America based on the punctuation and capitalization. The phraseology and style of communication… maybe Argentina? Also, there’s the Latin American culture insult about shoemakers (aha!) and the inclusive use of “Americans”.

Inclusive use of Americans? I didn’t notice this on my first reading, but the localization team did. See above and should notice Mr. Smith’s “Even we hate trump like other Americans do.”

And there you go, HBO was hacked by Trump hating South Americans.

Break your own product, and break it hard

Hello readers, I am Andrea Barisani, founder of Inverse Path, which is now part of F-Secure. I lead the Hardware Security consulting team within F-Secure’s Cyber Security Services. You may have heard of our USB armory product, an innovative compact computer for security applications that is 100% open hardware, open source and Made in Italy. […]


Retefe Banking Trojan Targets Both Windows And Mac Users

Based on our telemetry, customers (mainly in the region of Switzerland and Germany) are being targeted by a Retefe banking trojan campaign which uses both Windows and macOS-based attachments. Its massive spam run started earlier this week and peaked yesterday afternoon (Helsinki time). TrendMicro did a nice writeup on this threat earlier this week. The […]


How EternalPetya Encrypts Files In User Mode

On Thursday of last week (June 29th 2017), just after writing about EternalPetya, we discovered that the user-mode file encryption-decryption mechanism would be functional, provided a victim could obtain the correct key from the malware’s author. Here’s a description of how that mechanism works. EternalPetya malware uses the standard Win32 crypto API to encrypt data. […]


What Good Is A Not For Profit (Eternal) Petya?

Following up on our post from yesterday, as an intellectual thought experiment, let’s take the position that there’s something to the idea of (Eternal) Petya not being motivated by money/profit. Let’s also just go ahead and imagine that it’s been developed by a nation state. In my mind, it raises the following question: WTF WHY? […]


(Eternal) Petya From A Developer’s Perspective

In our previous post about Petya, we speculated that the short-cuts, design flaws, and non-functional mechanisms observed in the  malware could have arisen due to it being developed under a tight deadline. I’d now like to elaborate a little on what we meant by that. As a recap, this is what the latest version of Petya […]


Petya: “I Want To Believe”

There’s been a lot of speculation and conjecture around this “Petya” outbreak. A great deal of it seems to have been fueled by confirmation bias (to us, at least). Many things about this malware don’t add up (at first glance). But it wouldn’t be the first time that’s happened. And yet everyone seems to have […]


Processing Quote Tweets With Twitter API

I’ve been writing scripts to process Twitter streaming data via the Twitter API. One of those scripts looks for patterns in metadata and associations between accounts, as streaming data arrives. The script processes retweets, and I decided to add functionality to also process quote Tweets. Retweets “echo” the original by embedding a copy of the […]


Super Awesome Fuzzing, Part One

An informative guide on using AFL and libFuzzer. Posted on behalf of Atte Kettunen (Software Security Expert) & Eero Kurimo (Lead Software Engineer) – Security Research and Technologies. The point of security software is to make a system more secure. When developing software, one definitely doesn’t want to introduce new points of failure, or to […]


TrickBot Goes Nordic… Once In A While

We’ve been monitoring the banking trojan TrickBot since its appearance last summer. During the past few months, the malware underwent several internal changes and improvements, such as more generic info-stealing, support for Microsoft Edge, and encryption/randomization techniques to make analysis and detection more difficult. Unlike the very fast expansion of banks targeted during the first […]


OSINT For Fun And Profit: Hung Parliament Edition

The 2017 UK general election just concluded, with the Conservatives gaining the most votes out of all political parties. But they didn’t win enough seats to secure a majority. The result is a hung parliament. Both the Labour and Conservative parties gained voters compared to the previous general election. Some of those wins came from […]