Saturday, February 24, 2007

Behind The Curtain With Display Eater

You may have seen the discussion recently about an app called Display Eater by Reza Hussain. While the author has not responded to the latest discussion, he allegedly admitted that the whole thing was a hoax to deter potential pirates. Reza has just replied with a public letter. While the discussion has been lively, the investigation has been nonexistant. So here it is.

First, the legal stuff:

According to the Display Eater 1.8.5 license agreement:

3. License Restrictions
b. You may not alter, merge, modify, adapt or translate the Software, or decompile, reverse engineer, disassemble, or otherwise reduce the Software to a human-perceivable form.


But I wanted to disassemble the app! Fortunately, the license is not really a legal agreement:

THIS SOFTWARE END USER LICENSE AGREEMENT(EULA) IS A LEGA AGREEMENT BETWEEN YOU(EITHER AN INDIVIDUAL OR, IF PURCHASED OR OTHERWISE AQUIRED BY OR FOR AN ENTITY, AN ENTITY) AND THE AUTHOR OF THIS SOFTWARE.


Since LEGA AGREEMENTs don't hold up in court, we're free to do what we want with the app*. I'd also like to suggest to John Stansbury that while his assertion that users don't have the right to reverse engineer an app is correct in most cases, it's not applicable here, for the above reason.

Reza, fix your license.

Second, the fun stuff:

This is one of those apps that writes copious amounts of crap to the console for no reason. For example, after simply launching the app, declining to register, and quitting, I got this:

display_eater[3338] help me Start Recording
display_eater[3338] no file
display_eater[3338] mmmkay
display_eater[3338] mmmmm
display_eater[3338] selfmutilation DVC PAL
display_eater[3338] lettesta /Applications/Display Eater 1.85/Display Eater.app/Contents/Resources/cursor2.gif
display_eater[3338] onenationunderfuck 640x480
display_eater[3338] cheated--20 fps
display_eater[3338] loadedrender

Yes, that says onenationunderfuck. In my console log. Is it still cursing if you don't use camelCase? Well, at least he's a South Park fan. Here are a few other nice ones I found in the disassembly:

This "emailDeveloper:" method doesn't actually send any mail, but at least it further pollutes my log.

-(void)[mainWindowController emailDeveloper:]
3c600003 lis r3,0x3
38639500 addi r3,r3,0x9500 emailz0r
4801e6d8 b 0x21bd0 _NSLog


And from other methods:

386395e0    addi     r3,r3,0x95e0     FATTTTTTTTTY>>>>>>>
4801e005 bl 0x21bd0 _NSLog

386395a0 addi r3,r3,0x95a0 not saved lol
4801e1a1 bl 0x21bd0 _NSLog

3863a5a0 addi r3,r3,0xa5a0 lawl
4800f438 b 0x21bd0 _NSLog

3863b2c0 addi r3,r3,0xb2c0 OMGFWTFBBQxinFINITY
48003ee8 b 0x21bd0 _NSLog

38639e60 addi r3,r3,0x9e60 SDKNLLLLLLLLLLLLL
480161d5 bl 0x21bd0 _NSLog


And on and on and on. People, mescaline can be loads of fun, but it's not conducive to a healthy programming environment.

Ok, so Reza likes to make jokes at the expense of my log file, but that's not a capital offense. Allegedly deleting user data should be. While we're talking about spurious log data, I should note that Display Eater actually logs the customer's name, email and serial number on every launch. I'll give you one guess why that's a Bad Idea™.

Finally, the good stuff:

Ok, so Reza beat me to the punch by admitting that Display Eater does not really delete your home directory. But it does delete something, and those users who watch their console logs already know what it is. I had planned to present the complete annotated assembly of the methods involved, but that would bloat this post incredibly and bore most of you. Here's a higher level explanation:

The C function that does the deleting is called "destroy". In otool or otx output, search for "_destroy:". Its C declaration would look like this:

void destroy(NSString* inString);


It is called only from itself, and from one Obj-C method in the "recordCreateController" class:

- (id)addRecordWithPath: (NSString*)inPath
andRect: (NSRect*)inRect;


(class-dump says inPath should be of type "id" but the code in Display Eater assumes an NSString*. We'll have to wait for the GPL'd code, but I suspect this is just more sloppy code- see below for the rest)

In the disassembled code, "addRecordWithPath:andRect:" immediately follows "_destroy:".

Note the interestingly named "emptyEntireClipOnAllOfThem" that follows "addRecordWithPath:andRect:". While it smacks of gangland violence, it is not involved with deleting any files. My good conscience prevents me from revealing its purpose :)

So, when does "addRecordWithPath:andRect:" call "destroy"? The Obj-C code looks something like this:

    id  delegate = [[NSApplication sharedApplication] delegate];

// Reza, you may want to call [delegate respondsToSelector:] first...
NSString* support = [delegate applicationSupportFolder];

// "ninjakiller" is the reg file.
// Reza, use stringByAppendingPathComponent, mmmkay?
NSString* regFile = [support stringByAppendingString: @"/ninjakiller"]
NSArray* regArray = [NSUnarchiver unarchiveObjectWithFile: regFile];

if (![[regArray objectAtIndex: 1] compare: @"Special [K]"] ||
![[regArray objectAtIndex: 1] compare: @"KCN"])
{
NSLog(@"BUT I FALTER");
destroy(@"~/Library/Application Support/display_eater/");

// and then show the pirate dialog...
}


Ok, nothing surprising. Whoever Special [K](nice name, btw) and KCN are, they're screwed. So what happens inside "destroy"? It seems clear already that Display Eater's app support folder will get nuked, but is that all that happens?

void destroy(NSString* inString)
{
NSFileManager* manager = [NSFileManager defaultManager];

NSString* path = [inString stringByExpandingTildeInPath];
// Believe it or not, 'path' is only used for the following call.

NSArray* files = [manager directoryContentsAtPath: path];
unsigned int curFile; // I assume this is unsigned.

for (curFile = 0; curFile < [files count]; curFile++)
{
// Reza, you've already expanded this- you don't need to do it twice.
NSString* basePath = [inString stringByExpandingTildeInPath];
NSString* curFileName = [files objectAtIndex: curFile];

// Reza, please use stringByAppendingPathComponent.
NSString* curPath = [NSString stringWithFormat: @"%@/%@"
basePath, curFileName];

NSLog(@"%@", curPath);

// Reza, you did this already...
NSFileManager* manager2 = [NSFileManager defaultManager];

// ...and this, too.
// I'm not sure why passing just the name and not the path works,
// but it does.
if ([manager2 isDeletableFileAtPath: [files objectAtIndex: curFile]])
{
// Calling default manager yet again. At least we're using
// the full path this time.
[[NSFileManager defaultManager]
removeFileAtPath: curPath handler: nil];
NSLog(@"DELETABLE");
}
else
{
destroy(curPath);
}
}
}


So there it is. Display Eater recursively deletes the contents of its own Application Support folder(but not the folder itself), and nothing else. If the user was silly enough to put anything in that folder, it would have been nuked. But in that case, one might argue that they deserved it.

Note that the "piratekiller" file, whose contents seem to indicate a perverted TCL function call(kilo transform ar reza) is never used for anything.

Ultimately, the worst thing about this app is the sloppy Obj-C code. Reza, I would be happy to optimize your code a bit, if you're so inclined.

* I'm no lawyer- if anyone can prove me wrong about this point, please do so.

27 comments:

Peter Hosey said...

“(class-dump says inPath should be of type "id" but the code in Display Eater assumes an NSString*. We'll have to wait for the GPL'd code, but I suspect this is just more sloppy code- see below the rest)”

Can't (definitively) blame Reza for this one. Static type declarations aren't encoded in Obj-C type encodings, so all class-dump can ever see is “id”. This is one of the hard parts of figuring out an API from a class-dump. The proof of it can be seen by class-dumping the Cocoa frameworks: lots and lots of ids.

Blake C. said...

Good point, thanks. And I'm glad that you stuck around after my previous embarassment :)

Anonymous said...

Swedish Mac news site MacNytt.se called Reza for an interview. He admitted that the software did delete the full home directory up until the 7th of Feburary, when it was changed to only delete the registration files for the program.

The level of investigation has, as you say, been nearly nonexistent. Fact checking and independent investigation isn't as prevalent as it should be in the blogosphere, which sometimes expresses journalistic ambitions.

Pierre Bernard said...

Please post a tutorial on decompiling / reverse engineering. You seem to be a wizard at it!

Blake C. said...

Anonymous- got an English translation besides the one at rixstep?

pierre- thanks, but all it takes is otx and a little experience with assembly language. There are several good books about copy protection and reverse engineering that can help you. If only Reza had bought one, he wouldn't be in this mess :)

Anonymous said...

Any way we can get out the code to Koingo's copy and see if the program really went after ~? Anyone glib with OTX?

Anonymous said...

The rixstep translation is accurate. (I'm not the previous anonymous, btw).

Blake C. said...

Rick- A friend of a friend supposedly has an old version of the app, and hopefully I'll get a copy soon. The problem with that is that it can be faked. I'd much rather have the author's own words(in English) to link to. Unfortunately, I can't do that if rixstep is the only source, as it's not the official source. Not to mention my opinion of the rixstep team.

Still looking for an official English language link...

Anonymous said...

No official translation of the article exists. Rixstep's translation was done without the involvement or approval of the interviewer / author (me), but is accurate. To certify this, I have appended a short statement in English to the article on MacNytt.

Blake C. said...

Thank you, anonymous! With your note and the author's comment to my open letter, I think we finally have all the facts. Keep up the good work :)

Anonymous said...

Thanks for the nice post!

Anonymous said...

Actually a legal agreement with such a misspelling would stand up in court. Perhaps you should stick to coding and drop your ignorant legal bravado.

Anonymous said...

According to laws quoted at http://www.chillingeffects.org/reverse/faq.cgi#QID195
he shouldn't have to worry anyway. This sort of reverse engineering is legal in the US.

Blake C. said...

To the most recent anonymous: Thanks much for the link! That is quite an interesting read, and I had not seen that before.

To the second most recent anonymous: Thanks much for the advice! It's unfortunate that you were unable to provide a URL to explain your defense of the original author's misspelling, or any legal precedent describing similar circumstances. Please feel free to provide such info here at any time. As for my bravado, I'm not sure that it exists, much less that it's legal or ignorant. If you can show evidence contrariwise, please contact my lawyers, or feel free to comment here at your leisure.

Anonymous said...

Is reverse engineering illegal? It entirely depends whose laws you are under.

Let's use America as an example.

Here it is:

http://thomas.loc.gov/cgi-bin/query/z?c105:H.R.2281:

That is the text of the DMCA. Reverse engineering can be illegal under certain provisions of this Act.

I suggest that if you needed to get around some sort of mechanism used to obscure the code or such (some sort of purposeful code obfuscation) then you are in violation of the Act. If the code was plain to see after reverse compiling then there was no circumvention as such and it would probably be legal - especially since this is for study purposes and not any financial advantage.

Unknown said...

wow!! this blog is absolutely amazing!!! i really liked, i think all the information contained in this blog are very useful and very interesting. i really enjoyed reading. i am very curious for everything, usually i want to know new things. this is the reason why i like to know

buy viagra

Careprost said...

Nice post, I would like to request you to one more post about that Keep it up

ファロム said...

Hi there,
Really nice job,There are many people searching about that now they will find enough sources by your tips.
Also looking forward for more tips about that

Mobile Computing said...

Wow, Great post,Nice work, I would like to read your blog every day Thanks

cialis 20mg said...

That is very good comment you shared.Thank you so much that for you shared those things with us.Im wishing you to carry on with ur achivments.All the best.

Caverta said...

Great information you got here. I've been reading about this topic for one week now for my papers in school and thank God I found it here in your blog. I had a great time reading this.

buy cialis said...

i love programing and all programing language is deffalt as well as possable

ptc said...

I am very much pleased with the contents you have mentioned.I wanted to thank you for this great article.

sell my house said...

Your blog is really very interesting. I am totally impressed with this. So keep posting.

Rug repair nyc said...

I want to start blogging too what do you think, which blog platform is good for noob

Unknown said...

Generic Xenical

Unknown said...

I have read a few of the articles on your website now, and I really like your style of blogging. I added it to my favorites blog site list and will be checking back soon. Please check out my site as well and let me know what you think.Please visit my site also customized corporate diwali gifts in mumbai