Bedep’s DGA: Trading Foreign Exchange for Malware Domains

As initially researched by Trend Micro [1] [2], Zscaler [1] [2], Cyphort, and Malware don’t need Coffee, the Bedep malware family focuses on ad / click fraud and the downloading of additional malware. ASERT’s first sample dates from September 22, 2014, which is in line with when Trend Micro started seeing it in their telemetry. In early 2015, the family got some more attention when it was being observed as the malware payload for some instances of the Angler exploit kit, leveraging the Adobe Flash Player exploit (CVE-2015-0311) which at the time was a 0day. It was also observed that this newer version was using a domain generation algorithm (DGA) to generate its command and control (C2) domain names.

This post provides some additional notes on the DGA including a proof of concept Python implementation, a look at the two most recent sets of DGA generated domains, and concludes with some sinkhole data.


The following Bedep samples were used for this research:

  • MD5 e5e72baff4fab6ea6a1fcac467dc4351
  • MD5 1b84a502034f7422e40944b1a3d71f29

The former was originally sourced from KernelMode.


I’ve posted a proof of concept (read: works for me) Python implementation of the DGA to ASERT’s Github.

At the time of writing, I’m aware of two DGA configs. Each config contains three constants and a table of magical dwords used throughout the algorithm. The screenshot below highlights the table from the first sample:


Bedep’s DGA starts by downloading an XML file from:


This legitimate web service provides the time zone and local time at latitude zero and longitude zero. The <utctime> timestamp is parsed out and converted to milliseconds since year zero (0000-00-00). Then, 1-3 days are subtracted from it (depending on tick count timing–this feels like an anti-analysis technique) and it is converted to days since year zero. This value will be used in the next step.

Next, Bedep downloads an XML file from:


This legitimate file from the European Central Bank (ECB) contains the last 90 days of “Euro foreign exchange reference rates” and is updated daily. Each date is extracted from the <Cube time=”…”> tags then the days since year zero is calculated for “date minus one”. If the days since value is less than or equal to the value calculated in the first step AND if it falls on a Monday, then the foreign exchange reference rates for “date” are extracted and used. Here’s a visual showing this process:


After testing, my analysis reveals that Bedep updates using “last Tuesday’s” foreign exchange reference rates—where “last Tuesday” refers to “the preceding week’s Tuesday” until “this week’s Thursday”. After this, it means “this week’s Tuesday.”

From here, the algorithm becomes a bit opaque. Various values such as “days since,” the first parsed currency’s abbreviation, the low dword of the first parsed currency’s rate, the magical dword values from the extracted table (noted above), and various other constant and calculated values are transformed a number of times. I wasn’t able to deduce the “big picture” of these transforms, so I’m treating them as a blackbox where the output is the number of domains to generate and three values that that will be used to calculate a modular exponent starting seed. If anyone has more details on this blackbox, please reach out!

The number of domains to generate is 22 for the first config and 28 for the second for a total of 50 domains per set. To generate each domain, the starting seed and foreign exchange reference rates are transformed a number of times to calculate the domain length and the domain characters themselves:


The minimum domain length is 12 and the maximum is 18. I’ve only seen “.com” TLDs so far.


At the time of writing and using the foreign exchange rates from 2015-04-07, here are the eight registered domains from this set:


The first two were registered on 2015-04-13, the next two on 2015-04-11, then 2015-04-10, and the last two on 2015-04-08. All of them used the following registrant info:


This info is inline with what Zscaler observed.

Using the foreign exchange rates from 2015-04-14, here are the domains registered out of the set, so far:

  • (
  • (

The first two were registered on 2015-04-19, then 2015-04-17, and the last two on 2015-04-15. All six used the same registrant noted above.


To get a better idea of how active and widespread the above campaign is, we setup a sinkhole. The sinkhole was and from 2015-04-13 13:47 UTC to 2015-04-16 17:06 UTC (about 3 days) it received phone homes from about 82,127 unique source IPs. The top 10 TLDs of the resolved source IPs were:

  1. net (31578)
  2. com (11952)
  3. de (3193)
  4. mx (2611)
  5. tr (2104)
  6. it (1521)
  7. pl (1500)
  8. fr (1440)
  9. br (1360)
  10. au (1247)
  11. ca (1107)
  12. jp (1054)
  13. es (769)

And, except for Russia, infections were all over the map:



This post has taken a closer look at Bedep’s DGA and the recent campaign around it. Compared to some of the other date based DGAs we’ve looked at in the past, this algorithm is quite a bit more complicated and involved—effectively relying on the foreign exchange markets to generate its C2 domains. Based on the domain registration and sinkhole activity, Bedep is a current and active threat and will likely remain so for the foreseeable future.

Comments are closed.