Tuesday, March 27, 2012

Sometimes I think you should have to have a license to write protection.

Tonight's application was a database monitoring application written mostly in unobfuscated java. Is this 1999 and no one told me? I mean SERIOUSLY. And the thing that made it all that much better was that this code runs under Tomcat, and while running something called Jasper, it spit out .java versions of some of the important files. I didn't even have to decompile them! (shaking head). OK, so here's how it all works. You get a license key from the vendor when you register your trial, or buy a license from them. It comes in the form of a string of characters that you copy & paste into a form in the program. (It's all web based evidently). This license key contains a server name if you buy a license, or a string that they identify later as the "trial sentinel", and a number. This number is the time since the epoch in milliseconds for when your trial, or license expires. At runtime, in just about every module, they load this string from the key file, decrypt it, and pull the 2 halves out. (There is a delineation character between the fields). Then, they simply compare the time to now, if it comes back negative, your license has expired, and you need to get a new one.

So, as you see, the lynch pin of this WHOLE protection boils down to a simple string decryption routine. It was written in java as well, and unobfuscated for your reversing pleasure. A little while examining it, and I was able to write my very own ENcrypter, so that I can now make license files till the cows come home. Here's the pertinent code:


void EncryptString(char *s)
{
char temp[1026];
char output[2049];
unsigned char x, y;
unsigned char len = (strlen(s) & 0xFF);

memset(temp, 0x00, 1026);
memset(output, 0x00, 2049);

temp[0] = len ^ 0x95;
temp[1] = s[0] ^ 0x95;
temp[2] = s[1] ^ 0x59;

for(x = 3; x <= len; x++)
{
temp[x] = s[x - 1] ^ temp[x - 3];
}

for(x = 0, y = 0; x <= len; x++)
{
output[y++] = ((temp[x] & 0xF0) >> 4) | 0x40;
output[y++] = (temp[x] & 0x0F) | 0x40;
}

printf("[%s]\n", output);
}

The 1st byte of the license is the LENGTH xor'd with 0x95, followed by the serverID, followed by the expiration time. They do a pseudo rolling encryption where the value of THIS byte is xor'd with the value of another byte in the string, (3 bytes away). Once they have this, they simply walk through the string, pull out the upper nibble, shift it right, and OR it with 0x40, as that makes it printable, and then pull the lower nibble, and OR it with 0x40. Then, save those bytes, and move along. So, the resulting string ends up being twice as long as the actual payload.

I can only hope that these guys kick ass on database applications, and that it works better than their attempt at protection. Maybe they're finally wising up, and are only trying to "keep the honest people honest", as that's about all this scheme would do.

Sunday, September 11, 2011

Linux "Driverless dongles"

Recently, I've had the pleasure to examine the libraries, and implementation code associated with the new generation of "driverless dongles" under Linux. I've examined two different products from different companies, both with the same "feature" on their keys. This feature is the ability to plug it into the box, and not have it require a driver be loaded for your application to work. To facilitate this feat, they simple assign their dongle to the HID (Human Interface Device) class in their USB descriptors, and when it's plugged in, Linux enumerates it, adds it to the tree, and that's that. Then, when the time comes to talk to it from a protected application, you use a library provided by the publisher. It has mostly been this library that has allowed me to gain a full understanding of a key that I've never touched, and another that I have. It seems that both companies, NOT related, and THOUSANDS of miles apart, had the same idea. "Let's use libusb inside our library, so that the code will be simple!". Well, that it is. A little TOO simple. After finding the library online, and tossing it into IDA Pro, I was able to determine that it was libusb, determine the version, and then see how they used it. Now, for your protection to be simple enough that a guy like me can spend about 30 minutes with it, and have a complete grasp of it, is kinda sad.

The pitfalls that I saw included the following:

* Forgetting(?) to strip the symbols from the library before shipping. This allows IDA to label all the functions and makes the whole process MUCH simpler to understand.

* Publishing the entire API spec, and library to the net, so that ANYONE can get a copy of it. I understand that it's a delicate issue of "We want developers to be able to look at how easy it all it". But, you're also giving away the keys to the store at the same time. As this also allowed someone to see where this library is integrated into a customer's program, and have a COMPLETE understanding of the names of the functions, as well as what they do.

* Using libusb. I understand that you want the library to be as simple, yet robust as possible, and that using an available, and THOROUGHLY tested lib makes that process much easier, but it also makes the reverse engineering process much easier as well.

I heard you saying "Those are all interesting things, but what do these holes allow me to do?". Well, here's what I was able to do. I developed a driver that registered itself with the USB stack as a dongle. Then, when the applications enumerated the devices, they found ME, assumed I was a key, and began talking to me. A VERY little debugging of the target application, and I was able to return the "right" answers to the applications challenges.

Once I acquired my own key of the 2nd type, I was able to write a VERY SMALL driver (400 lines of C code!), that was able to intercept all communications with the dongle, and "change" the data that my dongle was returning that wouldn't match what the application was expecting. (Login passwords that the dongle requires, GUIDs, etc.) So, now, the target application runs with a key that isn't the right one. It even reads the memory from the key, and everything else that it's supposed to do, and has no idea that I'm there.

I could write a BOOK on how bad the code was in the target application, but even had that NOT been the case, this still would have been an easy crack job.

If you are just starting Linux reverse engineering, and are faced with a dongle, I *HIGHLY* recommend that you look into an option called "usbfs_snoop". You can find it under the /proc tree. This will show you what types of IOCTLs are being sent to the key. Pair that up with strace, and you have a potent 1-2 punch.

Friday, May 20, 2011

Great moments in protection failure!

It seems that more and more these days I find protection to talk about here only because of the epic badness of it. I'm sure there's some good out there, but I haven't seen any of it lately. Anyway, on with today's installment of "Great moments in protection failure!"

Looking through an anonymous application that does a whole boat load of decryption of data from a source. The main application was compiled, and released with the symbols still in it, so IDA gives me not only function names, but function prototypes, and in a few places, variable names. You know, this could be a simple mistake, and crap happens, so I'll cut them some slack on this, as this isn't even the failure in question.

While digging through the application and analyzing the encryption bits (the only things really interesting in there to be honest), I find that the guts of the encryption routines have been pseudo-obfuscated. I'm assuming that this code is from a library that probably came this way from the original manufacturer. By the looks of it, it's some tool that they run after they compile the library, and it changes all the non-exported function names in the library to a long string of hex characters. For example, they might have a function named "000b00f05c86d185". So, when you're looking at the disassembly, you see:

call _00b00f05c86d185

This is fine, and a good idea if you're trying to hide what your functions do, but now to the facepalm moment.

In this code, they call the obfuscated functions, and if they return an error value, they print a nice debug string that contains all the details about the error. Including the original name of the function!

So, all their attempted obfuscation is undermined by their proficient use of error messages.

Let's use our example function from above. You'd see something like this (in C pseudo-code).

if(00b00f05c86d185() != 1)
{
printf("GetKeyValue() returned error\n");
return 1;
}

Gee. I wonder what the REAL name of "00b00f05c86d185" is?

Monday, March 21, 2011

*FACEPALM*

This was just too good to not share.

Just had a look at an app for a friend that used a dongle. (Some weird brand/model of dongle that I'd never heard of before). So, I run the normal analysis on the application, and see that the author has chosen to pack his executable. Not a bad idea! If you want to do this for the protection/anti-tamper benefits of a compressed application, I would HIGHLY recommend not using an open source, and publicly available compressor. In this case, it was UPX. (http://upx.sourceforge.net/)

A quick look around the net, and I had an app that not only could tell you ALL about the compression on the app, but also removed it, cleaned up the .exe and everything else. Spit out a virgin looking executable.

So, on to the next step. Load it into IDA, and have a look around. I quickly find the "USB Dongle not found" string, and trace that back to a function that does a couple of things (calls ebp+xxx based functions), and makes a decision about the results. A little digging revealed that they were dynamically loading a DLL from inside themselves, (Almost like a resource), and then doing a loop of "GetProcAddress" to get the addresses of the functions they wanted. Each was stored in an ebp+xxx location. Turns out that he only called the dongle function from 2 places, once on startup, and then he spawned a thread that checked that the dongle was STILL attached every 3 seconds. Not bad dude, not bad at all.

Then, while looking at the functions that called the dongle function, I noticed a comparison of ebp+644, and if this value was 0, it skipped not only the startup check, but didn't create the thread to continuously check the key either. What's going on here?

It was ... A command line option to skip the protection completely. When the program started, one of the first things that he did was to get the command line, and to use strstr to search for his magic string. If found, it would clear the flag, and the protection routines never got executed.

FAIL!

Tuesday, March 1, 2011

The perils of commercial protection

I just finished up looking at a commercial package that runs on Linux, and uses a SmartKey dongle from some guys in Italy. The dongle design looks as good as any other, and as Rainbow used to advertise a long time ago, "people never attack the key". This was true in this case as well. There were 4 or 5 apps in the package that were protected. (They basically just read memory locations from the key to see if the options pertinent to their situation were enabled or not). For instance, the report generation module would check the key to see if the memory location set aside for it had the correct value in it, or not, and used this value to determine whether to generate the reports, or, I don't know, put a "this is a demo version" banner on them or something. Anyway, you get the idea.

Now, on to the perils of commercial protection. Specifically "off the shelf protection". The programmer who wrote the apps seemed like he knew how to write apps, but not really design a good protection system. And it's this scenario that exposes the peril most directly. As I said above, there were 4 or 5 apps that were protected. He wrote them in C, and linked against the library provided by the dongle manufacturer to implement his checks. The big problem here, is that you now have a big glob of code in each of your protected executables that's not only the SAME in every app, but is the heart of your protection system. In a posting prior to this one, I detail how I gutted and "repurposed" a function in the Sentinel .DLL in an app called SNMPc. This would certainly be possible with these apps as well, but instead of gutting a common library, you'd be doing a simple search and replace of some code in each executable. In this particular case, the library contained an error message that would print if something happened to cause the communications with the key to get out of sync. So, the procedure for each app was:

Run through IDA
Search for string
Trace backwards to find caller(s)

Using this technique, I was able to completely understand what data the dongle contained, and how each byte was used in each program. So, instead of providing the protection that the author expected, it actually made his apps EASIER to crack.

In the span of a couple of hours, I was able to rewrite the "checker program" that the client app used to verify your permissions in C, and have it work flawlessly. All with information that I had garnered thanks to the staticly linked routines in his apps.

Wednesday, June 9, 2010

Another thing to NOT do.

I just examined a protection system for folks who write apps in the Borland languages, and want to distribute demo versions. It's the "R & T Software Registration Control". I normally don't tell names of protection systems, but since their website is down, I assume they're out of business, and fair game.

The app that I was examining called 2 methods from their control. The first was to get the days remaining in the trial, and the 2nd was to get the "level" of your license key. (Evidently you can generate keys that are capable of enabling multiple items in an app.) The 1st function returned the number of days left in AX. Well, they populate AX with some huge number prior to the call, so the fix for that was to change the 1st byte of the function to a RETN. Now, when it returns, it checks the number of days left on the trial, and it's some astronomical number, and it doesn't bother to nag you about registering, and most importantly doesn't exit.

The 2nd call returned a value that was immediately and'ed with 3. (Evidently only 3 levels in this app.) Well, as fate would have it, they also passed in a huge value that had the lower 2 bits set, so I changed the 1st byte of that function to a RETN as well. It returned, and'ed off the rest of the bits, saw the 3, and said "Full access!".

Obviously this was more the fault of the main app itself, but it's completely possible that this control required those crazy values to be passed in in AX, and if that's the case, they were completely self defeating. I neutered their entire $99 protection system with a 2 byte change.

Tuesday, May 25, 2010

Fab tackles a Mac program.

While not technically my FIRST Mac app, this was an interesting diversion if nothing else. The first app was a Mac port of a protection system that I had conquered on the windows side YEARS before, and I knew it intimately. SO that didn't really count. Some of my friends used this app at the office, but would like to have a copy at home so as to become more proficient with it. So, out of sheer boredom, I decided to have a look at it. What I found excited me. If ALL Mac apps are this easy, I might have to start taking requests!

First a few notes about Mac apps in general. Most of the more modern apps are compiled for both x86 and PPC chips, and the resultant output files are stuffed into a single file together for distribution. So, I did both versions. Now, not being a PPC hacker, that took a few minutes, but the mistakes that they made in the x86 version were also present in the PPC version, so it was a lot easier than it should have been.

In this particular case, (and I hope all others!), the way that the Mac compiler generates executables, and probably the whole underlying architecture of OSX makes reversing MUCH simpler. It's almost like there's an API for everything! To wit, this code looks odd enough, nothing really to see here, right?

__text:000DB4CB mov eax, ds:off_1D2514
__text:000DB4D0 mov [esp], eax
__text:000DB4D3 call _objc_msgSend

If you checkout off_1D2514, you discover that it's a pointer to NSConditionLock. So, spend a few minutes labeling all these "pointers to message names", and the disassembly starts to look VERY different!

Of course, if the particular program that you're working on uses a license file protection technique, and offers a demo version, then it could be even easier. It could have a function like this:
char __cdecl _XXApplication_isDemo_()
{
return *pTrialByte == 3;
}

Variable name was supplied by me, function name was left in the executable by them. Don't get me wrong, I certainly APPRECIATE it! ;-)

So with this function telling me not only what variable in memory was responsible for determining the trial/registered status of the app, but also what the value was that was interpreted as being a trial, it allowed me to make a simple fix. Just locate all the places in memory where this memory location was set. I.E.

__text:000E0453 mov ds:TrialByte, 3

A little more tracing showed me that a value of "1" in TrialByte meant that the app was registered, and happy. So a simple search revealed 3 places where a value other than "1" was being placed in this location. A simple change of "2" to "1", and a couple of "3" to "1" changes, and we were done.

I heard that! You said "What about the PPC version?". Well, I found much the same code there:

__text:0000B470 __XXApplication_isDemo_:
__text:0000B470 lis %rtoc, ((pTrialByte+0x10000)@h)
__text:0000B474 lwz %rtoc, pTrialByte@l(%rtoc)
__text:0000B478 lwz %r3, 0(%rtoc)
__text:0000B47C xori %r3, %r3, 3
__text:0000B480 subfic %r0, %r3, 0
__text:0000B484 adde %r3, %r0, %r3
__text:0000B488 blr
__text:0000B488 # End of function __XXApplication_isDemo_

This is our handy function for locating the variable, and what do you know? A quick search shows that there are 3 places that need to be patched to make it work. The same as the x86 version.