seoxys.com» Hacking http://www.seoxys.com Sun, 30 Sep 2012 22:34:18 +0000 en hourly 1 http://wordpress.org/?v=3.0.1 3 Easy Tips to Prevent a Binary Crack http://www.seoxys.com/3-easy-tips-to-prevent-a-binary-crack/ http://www.seoxys.com/3-easy-tips-to-prevent-a-binary-crack/#comments Fri, 27 Jun 2008 11:14:17 +0000 kenneth http://www.seoxys.com/?p=88 When coding anti-piracy prevention measures, your goal should be to keep honest users honest.
It is important to make the user experience pleasing and simple for your paid customers.

While in an ideal world, people would buy everything legally, reality is very different.
Most people, if tempted with an easy free way to get your app, will pirate even though they know it is wrong.

Here are three easy tips that will help your app resist to binary cracks, but do not take much work to implement.

You can grab the sample code for the first two tips.

Strip debug symbols

Stripping debug symbols will remove all the method names from the executable, which makes it a lot harder for anyone to reverse-engineer your app using gdb. (I showed how this is usually done here) Now, instead of seeing all your method names, which method the app is currently in, and instead of being able to breakpoint the app at that spot, they’ll only see hexadecimal addresses.

You can still get around this by class-dumping the executable and getting new method’s hex addresses from there, (although they might be off by a certain difference which you’d have to calculate) but this already makes it a lot harder for crackers to attack.

So, without further ado, here’s how you do this: Apple’s documentation has a detailed explanation, so instead of rewriting it myself, I’ll just copy-paste it here:

Xcode provides several built-in options for stripping executables of their debugging symbols. One of these is the Strip Linked Product build setting. While typically set, it has no effect unless the Deployment Postprocessing setting is also set. Deployment Postprocessing is a master switch that enables the action of a host of other build settings. It’s approximately analogous to running the xcodebuild tool with the install command.

Again, open the target build settings and turn on debugging symbols for the Release configuration. Open the project build settings; in the Release configuration, enable both Strip Linked Product (if it isn’t on already) and Deployment Postprocessing. Your project settings should now resemble those shown in Table 2.

Build Setting Value
Deployment Postprocessing YES
Strip Linked Product YES

PT_DENY_ATTACH

Behind this barbaric name is a very useful flag which lets you prevent gdb from attaching to your app. Ever tried debugging iTunes? Give it a try now, but be prepared for a disappointment, it crashes gdb when it tries to attach to it.

One step further in protecting your app after striping debug symbols is to activate PT_DENY_ATTACH. Note that this doesn’t make stripping debug symbols useless. While in theory it does, there are ways to get around it.

Activating this protection is really easy, and only involves editing your main.m.

//
//  main.m
//  ProtectionSample
//
//  Created by Kenneth Ballenegger on 2008/06/27.
//  Copyright Azure Talon 2008. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#include <sys/ptrace.h>

int main(int argc, char *argv[])
{
    //Build settings -> Other C Flags: -DDEBUG
#ifdef DEBUG
    //do nothing
#else
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
#endif
    return NSApplicationMain(argc,  (const char **) argv);
}

This code should be pretty self-explanotary…

You need to have a flag that differs for release build and debug builds. You want to be able to debug your app while you code it. That’s why I set Other C Flags for the Debug build settings to “-DDEBUG” and used an #ifdef to activate it only for release builds.

Test it if it works quickly, fire up terminal and try to use gdb.

seoMac:~ kenneth$ gdb /Users/kenneth/Desktop/ProtectionSample/build/Release/ProtectionSample.app/Contents/MacOS/ProtectionSample
GNU gdb 6.3.50-20050815 (Apple version gdb-952) (Sat Mar 29 03:33:05 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries ..... done

(gdb) r
Starting program: /Users/kenneth/Desktop/ProtectionSample/build/Release/ProtectionSample.app/Contents/MacOS/ProtectionSample
Reading symbols for shared libraries ++++....................................................................... done

Program exited with code 055.
(gdb)

Congratulations, it works! Your app cannot be loaded into gdb anymore. (Note: there are workarounds. Experienced hackers who really want to will still manage to get in.)

Checksum your binary

The last tip for today is of a different kind, and it is probably the most effective of the three.

Basically, all you need to do is to checksum your binary. Put the md5 somewhere in your .app, preferably well hidden. Preferably use a salted hash, or double-hash it. Make it hard for a potential hacker to figure out how to get the correct hash for a given hash. Hide the file in which you store this hash well, or store it in your Info.plist. Where you store it doesn’t matter, but you can’t put it in the binary. Preferably set up a build script that will re-generate the new hash at every build (when your binary changes), so you don’t have to do it yourself.

In your code, check the stored hash against the binary, and if they are different, it means the binary has been modified. In that case, display an error message asking to re-download the app from your site, and quit.

]]>
http://www.seoxys.com/3-easy-tips-to-prevent-a-binary-crack/feed/ 9
Registration Schemes: Asymmetrical Cryptography http://www.seoxys.com/registration-schemes-asymmetrical-cryptography/ http://www.seoxys.com/registration-schemes-asymmetrical-cryptography/#comments Sat, 05 Apr 2008 22:13:05 +0000 kenneth http://www.seoxys.com/?p=86 One challenge that most developers face when nearing release of their first application is how to implement registration and piracy protection. This three-part article will describe three common types of registration schemes: Serial Numbers, Asymmetrical Cryptographic Keys and Product Activation.


Part Two: Asymmetrical Cryptography

Asymmetrical Cryptographic Keys are a great way to secure you app, because the code used to generate serials is not included in your app, thus removing the risk of a keygen. Using a private key, you sign (or encrypt) some of the user’s details. You then use this singed data as the key to your software, either in the form of a serial, a file, or even an image with the data embedded. You then verify that the signature is valid using the public key in your app.

Example

Start off by generating a set of private and public RSA keys. You can do this by using the following in Terminal.app:

openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -out public.pem -outform PEM -pubout

You can use different size keys. Using a shorter key, such as 512 will make your software more vulnerable to brute-force attack, but has the advantage of making the signature smaller (Which is useful if you wish to display it in the form of a Serial Number).

I believe I used the following set of keys. The keys are also included as files in the source code of this example (available at the bottom of this article).

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwKhjrkHmaupDGERSHdgZuSwBWBr4kufBGz0Dk5sn3PR3ZtaP
Vrv6+5Mdz1gAEBYbUVH3m+4+dHcwol5xNckKBT8M5Zy6GPoV9dBUS/1wQBzgdTzf
jvV4uE9S0pofQWw3faZ904tTOjbM0qUko2nd7yyjYBhh/m1ABEFHuL62BvRp13na
vv6534OqqeExEb9VD3K9+Rr4+YQVRUpqZSz2xwhqfLgAzFVQ9bmSG8yTVKmF/vQA
t+N8ThN2WO5qYtCbPawkmIpwvUCTXkxAiiTPNOiU3G1vwtzBoma9TL6dgGmhq6P7
0KBcQNGUEpA2PFC7MEBeNyVyiMIOAvrkHjY/VQIDAQABAoIBABUNET9EMiIykLxB
Etvx9fWWylrPL6QVsLMCOrbROEzbZYSWIzlt9uGwVIyIaBFZ6Qg8tZqTML3XHDhR
q3seCXtDRWx9cJQ0F1wxtFRNUAuhXCFTUnYzekphWIJslse2RGX1YEBSM/jjbgQC
SXuVoMt2jC9+2o5Lb7hHTcfxBsDBmZpghArT5seTOwDOOhTULqoh2wgZYB2IpgTI
UV2CPpAqRVECRnPNdE5UcNIeHc7g4aji5BO0G0u8uM4RUffuRcLaPymuxpU9vwd1
gjVaG6BF/2odW7GEBU3FNLUtvr9MxT+HC+hwOJUuk8NWxU7DqMdyiwSs7W3Nnx7R
5RPvj8ECgYEA34DZjy5EMm7QyPZA6DvAZv6RIecFEwEkwFG+mQgoCy4VfLikkwzC
bI8M8fc6Xiix7ZTjSmvuHt1D4HSRHMOVYgDzY0A5+F+8X657mN5TwNlYMOUkDX3I
rNwc3cRVqtLZYGX0H7cR6eEomGJ7fA9gKuTpaXI0IJz5DsqsgTaGvfECgYEA3Ktr
Q53i52jnssL9c3JsxQO+I/2fWKgo3bZeBI/5zLsz3itVjFjMVldrIK1QZWXI4z7l
dPYwh6qCa1unsizuuzeAhW6NcuUjGPBlBqlo/a9WfOo16ExPXBoH3PH2DXz/YS+D
DOp4Wl8ePhO7C46t3zmGahchysx3kCGkAmNkA6UCgYEA0upvZNUOemFlGiB5RC8O
9KMLJukyOqr7mZoKubOexl4o3NgKRtLlrziXyMe8Bxt0PXYhwBt2TR4Vbf3S60gO
8rte86yqiB8gT1MDRFGazATPWuUCTtECzU2y1/ztsxTjGjtcU4mZmBJpEtTtHzgL
Uq9PLbkeRCCeUD0m6ZEhOqECgYB85jFyNh1F6aSrE56tB2j1Iicu69CTN6rZwuz4
HB3BeXvkFhb3txMBE7244yAMJE5OAT2Ss/3H7AShi2EhgjklkkaWP3qkO3lgFkC4
Qo8Ad4u2bEJS105bzQgCUJl6DPPnKCM+3j98tzXA4R4PbpSPMloYFju0M4LA+6l/
CI6FWQKBgQCWr4Py/GBhgoYOlY/f41NzOfsttwcCBum3uPbiPq6gM/AQQRjzdUmK
QRgG9XXs/33KUMiU+/15hK8ShrOWRSx+zHdgeMhVmuYJdEeygANI9dkonJ3+Olth
77beMQrKIY9kw4bVRFtLWhxfAHXvnksnBg79PX05joVvoHFgVxuwlg==
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwKhjrkHmaupDGERSHdgZ
uSwBWBr4kufBGz0Dk5sn3PR3ZtaPVrv6+5Mdz1gAEBYbUVH3m+4+dHcwol5xNckK
BT8M5Zy6GPoV9dBUS/1wQBzgdTzfjvV4uE9S0pofQWw3faZ904tTOjbM0qUko2nd
7yyjYBhh/m1ABEFHuL62BvRp13navv6534OqqeExEb9VD3K9+Rr4+YQVRUpqZSz2
xwhqfLgAzFVQ9bmSG8yTVKmF/vQAt+N8ThN2WO5qYtCbPawkmIpwvUCTXkxAiiTP
NOiU3G1vwtzBoma9TL6dgGmhq6P70KBcQNGUEpA2PFC7MEBeNyVyiMIOAvrkHjY/
VQIDAQAB
-----END PUBLIC KEY-----

Next, we will create the generator. We will start by concatenating the details (full name and email address) into a single string:

First Last+email@address.com

Then, we will use RSA to sign this string using the private key generated above:

lFZpwJ6GPLXz8sDez033RIxJsN072lOEa0qF+8hQ5KCcZEPQqSBU4MKbW+UJxIfSmKMOBYnVfy/wwAoSxTtqn2JIuAPEJvsTlb0mGH5u7mpxH+FDj2TicoBKephWv7UXP9k10OPA45247+j/u4yKT1UZcq7WjChQ3JoE3wBtEoFucQm8vLk/VqvNaBM1TyNEgwT8FmrKlbK1FNUI8nQ0QOEJ9P8oMAblkWE5kALZZqWnAs6xE7c73sex73t5FvxYRqRDzRDzkjTwK0anXCv8dmeLvnaaHAFcfD5llx09oa89q+wzWucE7V1TsPRYKH1sZsSz5G2xTt2pZrjIoTw5ew==

Note: for this sample app, I explicitly turned off creating newlines in the base64 signature.

The code used for this generator is:

-(IBAction)generate:(id)sender
{
    NSData *privateKeyData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"private" ofType:@"pem"]]];
    NSData *publicKeyData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"public" ofType:@"pem"]]];
    NSString *details = [NSString stringWithFormat:@"%@+%@", [name stringValue], [email stringValue]];

    SSCrypto *crypto = [[SSCrypto alloc] initWithPublicKey:publicKeyData privateKey:privateKeyData];
    [crypto setClearTextWithString:details];

    NSData *signedTextData = [crypto sign];
    NSString *string = [signedTextData encodeBase64WithNewlines:NO];

    [serial setStringValue:string];

    [crypto release];
}

As you can see, I used Septicus Software’s great SSCrypto framework for this task… It makes things so much easier… Unfortunately it doesn’t support base32 or DSA, which would both have helped make more human-friendly keys.

The other piece needed is the validator, used in your software to validate serial numbers. Include only the public key in your app, and use RSA to verify the key.

-(IBAction)validate:(id)sender
{
    NSData *publicKeyData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"public" ofType:@"pem"]]];
    NSString *details = [NSString stringWithFormat:@"%@+%@", [name stringValue], [email stringValue]];
    NSData *number = [[[serial stringValue] dataUsingEncoding:NSUTF8StringEncoding] decodeBase64WithNewLines:NO];

    SSCrypto *crypto = [[SSCrypto alloc] initWithPublicKey:publicKeyData];
    [crypto setCipherText:number];

    [crypto verify];

    if([[crypto clearTextAsString] isEqualToString:details])
        NSRunAlertPanel(@"Result", @"Good serial!", @"OK", nil, nil);
    else
        NSRunAlertPanel(@"Result", @"Wrong serial!", @"OK", nil, nil);

    [crypto release];
}

Important Note: In this sample code, I included both the generator and the validator in the same application. I included the private.pem file in the bundle. You should never do this. If the private key is ever leaked, it compromises the whole security of your application.

Making it safer

You can easily make it more secure by combining this technique with the technique explained in Part One. Instead of simple concatenating the details as I did here, you could use all the techniques applied in Part One, such as using a hash instead, or doing ROT13 on it, or rearranging the order of the characters.

Another thing you should do is to hardcode and obfuscate your public key. Having it as a file in the bundle makes you vulnerable to key substitution. (Basically, a cracker would replace the public key in your app by a different key they created using a private key they know, thus making their licenses valid instead of yours.)

Form Factors

While you may not realize it at first sight, this has become one of the most common methods in Mac shareware, thanks to the open-source framework AquaticPrime. AquaticPrime uses this technique behind the scenes, by embedding the signature in a plist file. AquaticPrime is a very easy way to use this. Unfortunately, if you decide to use AquaticPrime.framework in your app, it is very easy to replace the .framework file with a malicious one that will always claim your licenses are valid.

To date, as far as I know, there isn’t any HackuaticPrime.framework yet, but this might one day become a problem with AquaticPrime gaining popularity thanks to it’s extreme simplicity of implementation.

Update: Devon in the comments suggests implementing a hash check of the framework, which is a simple way of checking the framework’s integrity. Of course, there are still ways to get around it, but this makes it one step more difficult.

Another common form factor for Asymmetrical Cryptographic Keys is custom URL schemes. That’s actually a very clever and convenient way of doing it. To register, the users get to simple click on a link which looks like this: (All the user sees is a nice “Click here to register” link)

myapp://name:email:key

Another clever, but controversial form factor is Agile Web Solution’s 1Password License “Cards”.

And of course, if you find a way to make short base32 signatures (I hear DSA makes short signatures), you can even use longer Serial Numbers.

AHJ53-5HGJZ-8DG8R-284DF-56FJB-74FH4-FJUEH


Sample Code

The code used in this article can be downloaded here.
As always, licensed under MIT license. If you do use it, mention it in the About Box or readme.txt.


Part One: Serial Numbers
The next part will be coming soon.

]]>
http://www.seoxys.com/registration-schemes-asymmetrical-cryptography/feed/ 7
Registration Schemes: Serial Numbers http://www.seoxys.com/registration-schemes-serial-numers/ http://www.seoxys.com/registration-schemes-serial-numers/#comments Thu, 03 Apr 2008 21:26:56 +0000 kenneth http://www.seoxys.com/?p=85 One challenge that most developers face when nearing release of their first application is how to implement registration and piracy protection. This three-part article will describe three common types of registration schemes: Serial Numbers, Asymmetrical Cryptographic Keys and Product Activation.


Part One: Serial Numbers

Serial numbers are the simplest, most practical option. However, they are also the least secure. It consists of taking at least one of the customers’ details, and creating a serial number from it. The serial number is usually tied to either the customer’s name, or his email address, preferably both.

For example, let’s say the customer’s name “First Last” and his email address is “email@address.com”. The first step would be to strip his name and email address of any non-alphabetical characters, concatenate it and convert it to uppercase. (I put the email address first, because it’s less recognizable) Here’s what we get:

EMAILADDRESSCOMFIRSTLAST

Now map this string onto a XXXX-XXXX-XXXX-XXXX-XXXX key. If there are any character leftovers, just discard them. If there aren’t enough characters to fill all the Xs in, leave them as something constant. (they don’t have to be all the same, but they have to be the same for each position all the time. You could for example say you’re mapping it onto an QRST-ABCD-IJLK-EFGH-MNOP key, and leave unfilled spaces as is)

EMAI-LADD-RESS-COMF-IRST

Then, we’d apply ROT13 on it.

RZNV-YNQQ-ERFF-PBZS-VEFG

Lastly, we could replace any swearwords in the key by some random other constant text, just in case.

Another example, using a similar method: Using the same customer, here’s what we’d do. Take his details, concatenate and salt them:

First Last+random salt+email@address.com

Then, MD5 the result and add another salt:

salt+0fb61d4a0f894c63d3ddbd8388404b6c

Next, SHA1 the result:

28a8275bdcbca542f567efef9cc4db2150c38900

And finally, uppercase it and map it onto a XXXX-XXXX-XXXX-XXXX-XXXX serial:

28A8-275B-DCBC-A542-F567

When you have decided on a serial scheme, implementing it is easy. Upon registration, you take the buyer’s name and email address, and generate a serial from it. He then has to input this serial into you app, along with his name and email address. All you have to do in you app is take the name and email address he gave you, generate a serial from it, and check it against the serial he gave you.

Making it more secure

For security reasons, one important step to take is obfuscating how you create those serials, in case anyone tries to create a keygen for you app. The easiest way is adding dummy maths code in the middle of the code where you work out your serial. It will not affect your serial, but it will show up in the assembly code in case anyone tries to gdb your app (more on that in another blog post I have planned).

Another quick thing you could do is shuffle the characters a bit on a set pattern to make them less obvious.

For example you could use this pattern:

ABCD-EFGH-IJKL-MNOP-QRST

becomes

TMLN-DQGA-ISPC-BEOK-FJRH

Stand-alone serials

Sometimes, your serials cannot be tied to any of the customer’s data, for example for retail sales. In that case, you’d need a different serial scheme. You need to choose certain characteristics / rules that make a serial valid. It could be as simple as checking that the 19th character is a W.

Here’s a set of example rules you could use:

  • The ASCII value of the first character of all five blocks of four characters have to add up to 100.
  • The last character of all five blocks of four characters have to be vowels.
  • The first character of either block 3 or 4 has to be E.
  • The ASCII value to the third character of every block have to be even numbers.

In your apps, just check the serial against the rules, and if it’s correct, you can assume it is a correct serial.

For your generator, you can have a pre-made list of valid serials, and assign them to a customer or print them on a retail copy when needed. The problem with this method is that you can eventually run out of valid serials. In which case you would have to generate a new batch of serials, or reassign already used serials to a second customer.

Another (better) way of doing stand-alone serial numbers is splitting the serial number in two, and basing the second part on the first part. [thanks to tomasf from the #macsb IRC channel for this method]

For example, in a serial number ABCD-EFGH-D07A-A959-F269, separate the first eight characters from the rest of the serial:

ABCDEFGH

Salt it:

saltyABCDEFGH+123

MD5:

d07aa959f269104ab28e2a748c415c5c

Map it onto XXXX-XXXX-XXXX:

D07A-A959-F269

And check it against the second part of the serial. In this example, the serial is correct.


Part Two: Asymmetrical Cryptographic Keys
The last parts will be coming soon.

]]>
http://www.seoxys.com/registration-schemes-serial-numers/feed/ 7
Hacking mac apps: Direct Mail http://www.seoxys.com/hacking-mac-apps-direct-mail-archive/ http://www.seoxys.com/hacking-mac-apps-direct-mail-archive/#comments Tue, 18 Dec 2007 23:02:36 +0000 kenneth http://www.seoxys.com/2007/12/19/hacking-mac-apps-direct-mail/ Update: I rewrote this post with better language and better explanations. Please read the newer version first.

In this post, I will describe how to hack a mac shareware app.

The reason for this is to push the developers to create stronger protection, and to show common weaknesses in licensing code.

Before each hack is published, I get the concerned developer’s approval, and send them a note describing the hack, and suggesting ways to improve their protection. I also leave them some time to patch their app before I publish the hack.

I have no intention of promoting piracy, and this not meant to be used as a guide for would-be pirates to get those for free. What follows if of highly technical nature, and is intended for fellow developers.

Today is up: Direct Mail, a great app from e3 software useful for anyone doing mailing lists or press releases.

I did this hack on version 1.8.3, because it isn’t the latest.

First thing to do, is to class-dump the executable, which results in an interesting find:

@interface CAppDelegate : NSObject
{
    BOOL _registered;   // 4 = 0x4
    NSString *_registeredName;  // 8 = 0x8
    SUUpdater *sparkleUpdater;  // 12 = 0xc
}

+ (id)sharedDelegate;
+ (void)applyIconsToChangeStatusMenu:(id)fp8;
- (id)init;
- (BOOL)registered;
- (id)registeredName;
- (void)setRegisteredName:(id)fp8;
- (BOOL)validateMenuItem:(id)fp8;
- (void)loadRegistration;
- (BOOL)isValidCode:(id)fp8 forName:(id)fp12;
- (void)saveRegistrationCode:(id)fp8 forName:(id)fp12;
- (id)sparkleUpdater;
- (void)doPrefs:(id)fp8;
- (void)doRegister:(id)fp8;
- (void)doPurchase:(id)fp8;
- (BOOL)alertShowHelp:(id)fp8;
- (void)doAbout:(id)fp8;
- (void)doReportBug:(id)fp8;
- (void)doConnectionDoctor:(id)fp8;
- (void)openAppWebsite;
- (void)openRegisterWebsite;
- (void)runKRM;
- (id)lookupKagiAffiliate;
- (void)showPurchaseThankYou:(id)fp8;
- (void)showFirstRunAlert;
- (void)applicationWillFinishLaunching:(id)fp8;
- (void)applicationDidFinishLaunching:(id)fp8;
- (BOOL)crashReporterShouldDisplayException:(id)fp8;

@end

Now, there’s different ways to hack this. You could just edit the ivar _registered upon launch. Other option would be to hack registered or isValidCode:forName: to always return true.

I’m going to go with a slightly more complicated way, and hack the methods which call isValidCode:forName:.

Let’s set a breakpoint when isValidCode is called. Disassemble the whole thing, and check where isValidCode:forName: is called. For me, it returns at 0x00008fdc. Run. It hits the breakpoint immediately. Continue once, to let it finish its setting up etc. Now, using the app, go to the register menu and try to register (with a properly-formatted email-address). It will hit the breakpoint again. Do a nexti. You now are in “0x0002ffb7 in -[CRegisterPanelController doOK:] ()”

Let’s disassemble this method:

0x0002ff50 <-[CRegisterPanelController doOK:]+0>: push %ebp
0x0002ff51 <-[CRegisterPanelController doOK:]+1>: mov %esp,%ebp
0x0002ff53 <-[CRegisterPanelController doOK:]+3>: push %edi
0x0002ff54 <-[CRegisterPanelController doOK:]+4>: push %esi
0x0002ff55 <-[CRegisterPanelController doOK:]+5>: push %ebx
0x0002ff56 <-[CRegisterPanelController doOK:]+6>: sub $0x1c,%esp
0x0002ff59 <-[CRegisterPanelController doOK:]+9>: mov 0x8(%ebp),%edi
0x0002ff5c <-[CRegisterPanelController doOK:]+12>: mov 0x22091c,%eax
0x0002ff61 <-[CRegisterPanelController doOK:]+17>: mov %eax,0x4(%esp)
0x0002ff65 <-[CRegisterPanelController doOK:]+21>: mov 0x221fa4,%eax
0x0002ff6a <-[CRegisterPanelController doOK:]+26>: mov %eax,(%esp)
0x0002ff6d <-[CRegisterPanelController doOK:]+29>: call 0x21f395 <dyld_stub_objc_msgSend>
0x0002ff72 <-[CRegisterPanelController doOK:]+34>: mov %eax,%esi
0x0002ff74 <-[CRegisterPanelController doOK:]+36>: mov 0xc(%edi),%edx
0x0002ff77 <-[CRegisterPanelController doOK:]+39>: mov 0x221428,%eax
0x0002ff7c <-[CRegisterPanelController doOK:]+44>: mov %eax,0x4(%esp)
0x0002ff80 <-[CRegisterPanelController doOK:]+48>: mov %edx,(%esp)
0x0002ff83 <-[CRegisterPanelController doOK:]+51>: call 0x21f395 <dyld_stub_objc_msgSend>
0x0002ff88 <-[CRegisterPanelController doOK:]+56>: mov %eax,%ebx
0x0002ff8a <-[CRegisterPanelController doOK:]+58>: mov 0x8(%edi),%edx
0x0002ff8d <-[CRegisterPanelController doOK:]+61>: mov 0x221428,%eax
0x0002ff92 <-[CRegisterPanelController doOK:]+66>: mov %eax,0x4(%esp)
0x0002ff96 <-[CRegisterPanelController doOK:]+70>: mov %edx,(%esp)
0x0002ff99 <-[CRegisterPanelController doOK:]+73>: call 0x21f395 <dyld_stub_objc_msgSend>
0x0002ff9e <-[CRegisterPanelController doOK:]+78>: mov %ebx,0xc(%esp)
0x0002ffa2 <-[CRegisterPanelController doOK:]+82>: mov %eax,0x8(%esp)
0x0002ffa6 <-[CRegisterPanelController doOK:]+86>: mov 0x22084c,%eax
0x0002ffab <-[CRegisterPanelController doOK:]+91>: mov %eax,0x4(%esp)
0x0002ffaf <-[CRegisterPanelController doOK:]+95>: mov %esi,(%esp)
0x0002ffb2 <-[CRegisterPanelController doOK:]+98>: call 0x21f395 <dyld_stub_objc_msgSend>
0x0002ffb7 <-[CRegisterPanelController doOK:]+103>: test %al,%al
0x0002ffb9 <-[CRegisterPanelController doOK:]+105>: jne 0x2ffc7 <-[CRegisterPanelController doOK:]+119>
0x0002ffbb <-[CRegisterPanelController doOK:]+107>: add $0x1c,%esp
0x0002ffbe <-[CRegisterPanelController doOK:]+110>: pop %ebx
0x0002ffbf <-[CRegisterPanelController doOK:]+111>: pop %esi
0x0002ffc0 <-[CRegisterPanelController doOK:]+112>: pop %edi
0x0002ffc1 <-[CRegisterPanelController doOK:]+113>: pop %ebp
0x0002ffc2 <-[CRegisterPanelController doOK:]+114>: jmp 0x21f444 <dyld_stub_NSBeep>
0x0002ffc7 <-[CRegisterPanelController doOK:]+119>: mov 0x22091c,%eax
0x0002ffcc <-[CRegisterPanelController doOK:]+124>: mov %eax,0x4(%esp)
0x0002ffd0 <-[CRegisterPanelController doOK:]+128>: mov 0x221fa4,%eax
0x0002ffd5 <-[CRegisterPanelController doOK:]+133>: mov %eax,(%esp)
0x0002ffd8 <-[CRegisterPanelController doOK:]+136>: call 0x21f395 <dyld_stub_objc_msgSend>
0x0002ffdd <-[CRegisterPanelController doOK:]+141>: mov %eax,%esi
0x0002ffdf <-[CRegisterPanelController doOK:]+143>: mov 0xc(%edi),%edx
0x0002ffe2 <-[CRegisterPanelController doOK:]+146>: mov 0x221428,%eax
0x0002ffe7 <-[CRegisterPanelController doOK:]+151>: mov %eax,0x4(%esp)
0x0002ffeb <-[CRegisterPanelController doOK:]+155>: mov %edx,(%esp)
0x0002ffee <-[CRegisterPanelController doOK:]+158>: call 0x21f395 <dyld_stub_objc_msgSend>
0x0002fff3 <-[CRegisterPanelController doOK:]+163>: mov %eax,%ebx
0x0002fff5 <-[CRegisterPanelController doOK:]+165>: mov 0x8(%edi),%edx
0x0002fff8 <-[CRegisterPanelController doOK:]+168>: mov 0x221428,%eax
0x0002fffd <-[CRegisterPanelController doOK:]+173>: mov %eax,0x4(%esp)
0x00030001 <-[CRegisterPanelController doOK:]+177>: mov %edx,(%esp)
0x00030004 <-[CRegisterPanelController doOK:]+180>: call 0x21f395 <dyld_stub_objc_msgSend>
0x00030009 <-[CRegisterPanelController doOK:]+185>: mov %ebx,0xc(%esp)
0x0003000d <-[CRegisterPanelController doOK:]+189>: mov %eax,0x8(%esp)
0x00030011 <-[CRegisterPanelController doOK:]+193>: mov 0x220788,%eax
0x00030016 <-[CRegisterPanelController doOK:]+198>: mov %eax,0x4(%esp)
0x0003001a <-[CRegisterPanelController doOK:]+202>: mov %esi,(%esp)
0x0003001d <-[CRegisterPanelController doOK:]+205>: call 0x21f395 <dyld_stub_objc_msgSend>
0x00030022 <-[CRegisterPanelController doOK:]+210>: movl $0x219530,0x8(%esp)
0x0003002a <-[CRegisterPanelController doOK:]+218>: mov 0x220784,%eax
0x0003002f <-[CRegisterPanelController doOK:]+223>: mov %eax,0x4(%esp)
0x00030033 <-[CRegisterPanelController doOK:]+227>: mov 0x221fb4,%eax
0x00030038 <-[CRegisterPanelController doOK:]+232>: mov %eax,(%esp)
0x0003003b <-[CRegisterPanelController doOK:]+235>: call 0x21f395 <dyld_stub_objc_msgSend>
0x00030040 <-[CRegisterPanelController doOK:]+240>: mov 0x220780,%edx
0x00030046 <-[CRegisterPanelController doOK:]+246>: mov %edx,0x4(%esp)
0x0003004a <-[CRegisterPanelController doOK:]+250>: mov %eax,(%esp)
0x0003004d <-[CRegisterPanelController doOK:]+253>: call 0x21f395 <dyld_stub_objc_msgSend>
0x00030052 <-[CRegisterPanelController doOK:]+258>: mov 0x4(%edi),%edx
0x00030055 <-[CRegisterPanelController doOK:]+261>: mov 0x220900,%eax
0x0003005a <-[CRegisterPanelController doOK:]+266>: mov %eax,0xc(%ebp)
0x0003005d <-[CRegisterPanelController doOK:]+269>: mov %edx,0x8(%ebp)
0x00030060 <-[CRegisterPanelController doOK:]+272>: add $0x1c,%esp
0x00030063 <-[CRegisterPanelController doOK:]+275>: pop %ebx
0x00030064 <-[CRegisterPanelController doOK:]+276>: pop %esi
0x00030065 <-[CRegisterPanelController doOK:]+277>: pop %edi
0x00030066 <-[CRegisterPanelController doOK:]+278>: pop %ebp
0x00030067 <-[CRegisterPanelController doOK:]+279>: jmp 0x21f395 <dyld_stub_objc_msgSend>

We now are at this line: “0x0002ffb7 <-[CRegisterPanelController doOK:]+103>: test %al,%al”

That, in the right, is assembly code. This is basically some kind of “if” statement. (a TEST followed by a JNE (jump if not equal)).

What interests me is the next line: “0x0002ffb9 <-[CRegisterPanelController doOK:]+105>: jne 0x2ffc7 <-[CRegisterPanelController doOK:]+119>”

If we just reverse this test (turn the JNE into a JE (jump if equal)), any invalid code will be considered valid, and vice-versa. Let’s examine the memory for this statement.



(gdb) x/x 0x0002ffb9

0x2ffb9 <-[CRegisterPanelController doOK:]+105>: 0xc4830c75

Now, I’m working on a intel machine. And for some dumb reason, every block of four bytes is inverted. What this means, is that the byte that interests me is the rightmost one: 0x75. This is what a JNE looks like. Do some more tests by setting breakpoints until you find a JE, and read the memory for it: you will find that a JE is 0x74.

Let’s test if our theory is correct by editing the memory live, before we edit it in the binary. Do the following:



(gdb) set {char}0x0002ffb9=0x74
(gdb) x/x 0x0002ffb9
0x2ffb9 <-[CRegisterPanelController doOK:]+105>: 0xc4830c74
(gdb) disassemble 0x0002ffb7
Dump of assembler code for function -[CRegisterPanelController doOK:]:
[...edited out...]
0x0002ff99 <-[CRegisterPanelController doOK:]+73>: call 0x21f395
0x0002ff9e <-[CRegisterPanelController doOK:]+78>: mov %ebx,0xc(%esp)
0x0002ffa2 <-[CRegisterPanelController doOK:]+82>: mov %eax,0x8(%esp)
0x0002ffa6 <-[CRegisterPanelController doOK:]+86>: mov 0x22084c,%eax
0x0002ffab <-[CRegisterPanelController doOK:]+91>: mov %eax,0x4(%esp)
0x0002ffaf <-[CRegisterPanelController doOK:]+95>: mov %esi,(%esp)
0x0002ffb2 <-[CRegisterPanelController doOK:]+98>: call 0x21f395
0x0002ffb7 <-[CRegisterPanelController doOK:]+103>: test %al,%al
0x0002ffb9 <-[CRegisterPanelController doOK:]+105>: je 0x2ffc7 <-[CRegisterPanelController doOK:]+119>
0x0002ffbb <-[CRegisterPanelController doOK:]+107>: add $0x1c,%esp
0x0002ffbe <-[CRegisterPanelController doOK:]+110>: pop %ebx
0x0002ffbf <-[CRegisterPanelController doOK:]+111>: pop %esi
0x0002ffc0 <-[CRegisterPanelController doOK:]+112>: pop %edi
0x0002ffc1 <-[CRegisterPanelController doOK:]+113>: pop %ebp
0x0002ffc2 <-[CRegisterPanelController doOK:]+114>: jmp 0x21f444
0x0002ffc7 <-[CRegisterPanelController doOK:]+119>: mov 0x22091c,%eax
[...edited out...]
End of assembler dump.
(gdb)

Here we change the byte for the JNE, then test if we changed it correctly by re-reading it.

Then we disassemble the whole method again to see if the JNE was changed correctly. And yes — tah-da — - it now says JE. Perfect. Continue. You are now registered. To make this change permanent: do “x/8x 0x0002ffb9”. You will get 24 bytes of data. Open the binary in your favorite hex editor and find the bytes outputted by gdb. If you’re on intel, don’t forget you have to reverse all the blocks of four bytes before searching. When you find it, edit the 0x75 into 0x74. Bravo! You have now made the change permanent.

We are not finished yet. As you will now notice if you run the program, it makes your code valid, but you get an error message each launch, and you have to re-do the entering a code process every time. This is because the first check at launch doesn’t happen in doOk:.

Continue and quit normally (using cmd-Q in Direct Mail). Launch it again by doing run. But this time, don’t continue after hitting the breakpoint at launch. Do nexti. Ok, so now we are in loadRegistration. Disassemble this method. Similarly, there’s a JE this time, just after the call to isValidCode:forName: Turn this into a JNE by changing the 0x74 into a 0x75 at this location in memory. If you disassemble the method again, you can see that the JE turned into a JNE. Like before, change this in the binary.

Well Done! You have now fully hacked Direct Mail 1.8.3.

By now, the developer has probably fixed this security flaw, so you can’t use this to get this app for free. If you like it, buy it. It’s a great piece of software! Think about the poor developers who have to feed their family.

You can download the trial version here

]]>
http://www.seoxys.com/hacking-mac-apps-direct-mail-archive/feed/ 6