16-bit debugger goodness

It’s Saturday around Noon.  A friend is building a new server and wants to add 8 gigs of RAM to his MSI mother board but needs to flash the motherboard.  I’m bored and seems easy plus he hasn’t seen Afro Samurai so I figure we’ll upgrade his motherboard watch some anime and it will be a Saturday afternoon well spent.

Well, turns out the instructions say use a floppy…guess what?  He has no floppy drives.  He has ten computers counting the laptop I brought but no floppy drives.  Ah ok,  well this is for a Linux server but we supposedly need windows to install.  He installed windows before I got there but no go.  The software won’t run and without a floppy, and we can’t make a DOS floppy.  Believe it our not I keep a small win98boot.img file on my server for just such a reason but without a floppy I’ve got nothing.

So I go back to my house where I have tons of computers, all with floppies.  Now that I think about it I have no idea why I always add a floppy when I build a machine… but I do.  Plus I have extra drives so I grab one and some blank disks.  Hey I still have blanks from the days of Slackware boot floppies, and Novell server.exes… yeah, you remember 😉

So get this, the mother board doesn’t boot with the floppy attached.  Whatever.  We figure it should be trivial to modify the installer to use another drive letter rather than A:.  We divided our efforts.  He goes to task making a USB DOS bootable thumbdrive and I go to modify the motherboard’s installer.

As you can probably guess from this post that it was a 16-bit installer.  No problem, right?  I do 32-bit in Olly and IDA so trivial eh?  Nope,  only IDA can open such a thing but it can’t run as a debugger.  Which wouldn’t be a big deal but the binary is packed.  Packed!  Yeah for real, 16-bit and packed.

At this stage there is no turning back for me.  Meanwhile he already has his thumbdrive in DOS mode.  But I can’t debug 16-bits even in IDA.  Huh, who knew?  Well probably a lot of you but I didn’t.  So I figure, well I start up debug.exe and do it from there…nope.  No breakpoint support or anything useful.  Hmmmm, well I stumble on GRDB.  It stands for ‘Get Real’ Debugger and I have to say I was impressed.  It can handle 16-bit apps as well as 32-bit functionality.  It actually has a lot of cool functionality like PCI bus support but I didn’t need that.  What it did have was breakpoints, single stepping and step over commands.  Plus in comments it would show if a jump was taken or the contents of ES:[ax+dx].  GRDB, I love you!  🙂  And just for icing on the cake they have ANSI colors.  Now how can you not love that?

GRDB comes with source:  All in ASM and it can be compiled with MASM.  All code is licensed under the GPL as well!  Woot!  By now my friend has already updated his motherboard and is intalling Linux but I’m still in fascinated mode.  I missed the RE scene from back in the 16-bit DOS days.  Granted I used debug.exe to change binaries but it was based on offsets about which people had told me.  I was not in the scene that set the precedent for debuggers today.  Now to only modify the binary to support Ruby and a .gdbinit script… 😉

But if you are stuck with a 16-bit app I recommend GRDB, or if you want to write a packer that modern debuggers choke on…go old school.  (PS.  I laughed when I unpacked it and fired up ImpRec just to see NTVDM.EXE was all that was running :P)  I forget how spoiled I am nowadays but this Saturday afternoon I found a surprisingly useful gem.

–Craig

MiniVM RECON Release

Here are the slides for the talk I gave at RECON.  The talk was on “Creating Code Obfuscating Virtual Machines”.  The videos of all the talks will also be made available on the RECON website as well.  To get started writing your own virtual machine or programing for the MiniVM you’ll need to download the MiniVM suite (See below).  This has the core CPU (aka VM) under core/minivm.inc.  This file was intended to be compiled by MASM.  You could of course compile this to an object file and link it into your C code.

There is also a directory for compilers.  There is currently just one and it’s Ruby based.  This compiler is easily extensible so you can use this compiler for any VM you decide to create yourself.  This should speed up and give you a lot more flexibility when writing your own VMs.  Both the Compiler and the VM core *should* be able to compile on other platforms but I haven’t tested compiling the core with NASM yet.

These operands are currently support by MiniVM

  • MOV r32, r32
  • MOV [r1], r32
  • MOV r1, [r1]
  • MOV r32, value
  • CMP r32, value
  • INC/DEC r32
  • ADD/SUB r32, value
  • AND/OR r1
  • XOR r32,r32
  • PUSH/POP r32
  • JMP (Relative address / Direct Address)
  • JE, JL, JG value
  • CALL r1/value
  • EXIT

r32 in most cases means any of the registers.  If you are using the supplied compiler and you enter an unsupported use of an operand it will not only give an error but it will also show you all the possible valid ways to use that operand.

You basically have 4 general purpose registers: r1, r2, r3, and r4.  With r1 being a primary register.  Every operand works with that but not necessarily the others.  You also have the registers IP and SP for Instruction pointer and stack pointer manipulation.  As well as a few others.  See the slides for more information or simply look at the core source.

I will be maintaining both MiniVM and the compiler.  Please send me any patches or updates to either of these.  Also if you write anything really cool for MiniVM I would like to see that as well.  I’m sure the solutions for the Crackme will fill up quick but if you write up a good tutorial send that to me and I’ll post it as well.

Download:

miniVM

Slides

miniVMCrackme1

Send emails to: agent.craig  (at) gmail.com

RECON 2008

I will be giving a talk at the RECON conference in Montreal this weekend (June 13-15).  For those of you who haven’t been to RECON it is a fantastic conference.  RECON considers itself a security conference but it is much more than that.  There are many very technical talks that typical involve the different aspects of reverse engineering just about anything.  Perfect for security researchers, the anti-virus community or anybody interested on studying the inner workings of things.

I am very excited to be presenting in Montreal and have some fun tools to release after the talk.  My talk is about writing your own virtual machine for the purposes of code obfuscation.  It should be around Noon-ish on Saturday but that time may change.  The goal of the talk is to not just teach what an embedded virtual machine is or how it works but also to allow you to build your own.  I will be releasing a virtual CPU that you can play with as well as an assembler like language you can use to compile code for your virtual machine.  The compiler is written in Ruby and is easily extended so you can quickly write your own language for your own processor.  I will also have a crackme to release to play with as well 😀

Should be lots of fun!  I’ll be there on Friday but I will be taking off early morning on Sunday to get home for fathers day (Need to support the lil’ Neophites).  So be sure to ‘Hi’ at the party.

–Craig Smith

Updated to include posted link to crackme

Seed Racing

SeedRacing

The Art of Exploiting Race Conditions in Random Number Generators

Craig Smith, Patrick Toomey, Cris Necker

© 2008 Neohapsis

Overview

SeedRacing is an attack against standard pseudorandom number generators. A pseudorandom number generator (PRNG) is designed to generate a sequence of numbers that lack any predictable pattern. Attacks against non-cryptographically strong pseduorandom number generators are well known[1], but our often considered “good enough” for use in non-cryptographic systems. Most languages have a default method for generating pseudorandom numbers. These default methods rarely use a cryptographically sound random number generation routine, and by default rely on insecure seeding mechanisms. When initializing your random number generator the most important step is to “seed” the random number generator. Because, once seeded, all outputs from the PRNG are the result of a completely deterministic algorithm. Thus, seeding is the only step that differentiates one instantiation of a given PRNG from another. Stated more simply, a pseudorandom number generator that is seeded with identical values will produce the same sequence of outputs. Often times these default PRNGs implicitly seed themselves using a call to a system time or tick count function. This paper will focus on attacks against these default methods of producing random numbers when the initial seed value is based on time.

An Example in .NET

Most languages are susceptible to this attack to one degree or another. A list of other languages and there susceptibility is listed at the end of this document. We have chosen .NET because the default method is widely used and is more susceptible to this attack than most other languages that we have checked. Here is an example code in .NET that grabs a random number:

private static int GetDice(int min, int max)

{

Random rand = new Random();

return rand.Next(min, max + 1);

}

This code takes a min and max values that specify the range to return for the random number. For instance a call to GetDice(1,6) would return a standard 6-sided die roll. The fact that this is very simple to code and to read coupled with the fact that MSDN[2] does not seem to stress the dangers of using this method is probably why you see this done so much. We will go into more details as to why this is dangerous next.

Now lets modify the GetDice method to allow it to pick random characters in an array that holds letters a-z. It will pick 8 characters to add to a string to generate a random password.

private static string GetRandomPassword()

{

StringBuilder password = new StringBuilder();

char[] lCase = new char[] { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’, ‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’, ‘w’, ‘x’, ‘y’, ‘z’, };

int lCaseIndex = 0;

Random rand = new Random();

for(int cnt = 0; cnt < 8; cnt++ ) {

lCaseIndex = rand.Next(0, lCase.Length – 1);

password.Append(lCase[lCaseIndex]);

}

password.Append(0);

return password.ToString();

}

Now we will create a basic Web Application that has a login box. With a login box we will include a Forgot Password link that will reset the users password to a randomly generated password and email that password to the user. The Forgot Password link is called http://localhost/ForgotPassword.aspx and it takes one argument userid.

The Vulnerability

The problem comes from the call to initialize a new Random object. This line:

Random rand = new Random();

Implicitly calls:

Random rand = new Random(Environment.TickCount());

Where Environment.TickCount()[3] returns the number of milliseconds elapsed since the system startup. The problem is simple. If you call this random function in quick succession (in the same millisecond) you will get the EXACT same random value. This is because our application initializes every time before picking the next random number. This is very common in a web application because each time you connect the web server will likely create a new thread.

So how hard is it to call this function in the same millisecond? Its not too hard at all. A modern computer on a decent network can easily get out hundreds of requests in a millisecond. For our attack all we need is two.

In a localhost experiment Neohapsis sent 67,000 requests to a server with a random password generation routine similar to the one in our example. We only received 208 unique responses from the server. That is approximately 322 duplicate passwords. Again, that is under a rather ideal situation, you probably will not have that many duplicates in a real world scenario.


The Exploit

This is how the exploit would work. The attacker has an account on the target system with a valid email that they can check. Then the attacker locates a victims ID they want to target for the attack. The attacker needs to perform the following to successfully exploit this vulnerability:

1. Send two simultaneous (or close to it) web requests to the target system. One request with the attacks ID and one with the victims ID. Example: http://localhost/ForgotPassword.aspx?userid=attackerid and http://localhost/ForgotPassword.aspx?userid=victimid

2. That will reset both of their passwords and send both accounts an email. The attacker checks their email and users their generated password on the victims account.

3. If that fails, repeat.

Now that could be tedious, especially with a system that randomizes with microseconds instead of milliseconds like .NET does. However, luckily for the attacker, this is not very hard to automate. It is not only trivial to write a script to send out two simultaneous requests but also to have it check the mail and attempt to login.

This attack can potentially take several hours to execute and generate a LOT of email during that time. Won’t the users see hundreds of emails informing them that there password was reset? Sure, but by that time the attacker is already in and if the system was the mail system then the attacker can simply delete those messages. The truth of the matter is that the damage is already done and the only way to stop the attacker from breaking in is to fix the underlying code.

Remediation

Luckily this isn’t too difficult to fix. The best method of remediation is to use a more cryptographically sound Pseudo Random Number Generator (PRNG). For .NET this is the RandomNumberGenerator class[4]. For Java based systems this involves using SecureRandom[5] although as of Version 1.5 the default Random class seems greatly improved in this area. With PHP, rand and mt_rand are the same (mt_rand is faster), as the vulnerability is strictly based on what you seed mt_srand with. If the seed is set by the developer as microseconds you greatly reduce the window of exploit.

It should be noted that Microsoft’s documentation on MSDN[2] does state that Random is not a cryptographically secure class. That fact that Random has been insecure has been known for a long time but traditional attacks have been against cryptography. This paper shows that non-cryptographically sound pseudo random number generators should not be used in methods involving security or privacy.

References

[1] http://en.wikipedia.org/wiki/Random_number_generator_attack
[2] http://msdn2.microsoft.com/en-us/library/system.random.aspx
[3] http://msdn2.microsoft.com/en-us/library/system.environment.tickcount.aspx
[4] http://msdn2.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator.aspx
[5] http://java.sun.com/j2se/1.4.2/docs/api/java/security/SecureRandom.html