Vincent Gable’s Blog

July 21, 2010

Sneaking Malware Into the App Store

Filed under: Announcement,iPhone,Programming,Security | , , , ,
― Vincent Gable on July 21, 2010

It’s happened. An app that grossly violated Apple’s terms of service (by enabling free tethering) made it through Apple’s review process, onto the App Store, and into the #2 most-popular spot before being taken down. Although this app wasn’t malicious to users, it’s absolutely malicious to Apple’s agreements with AT&T and other phone-companies. It is a real demonstration that Apple can’t keep malware off the App Store.

A Few Sneaky Ideas

It’s not hard to come up with ways to fool App-Store reviewers.

You might just get lucky. With over 230,000 Apps in the store, reviewers are swamped. They’re only human and they might not notice some subtle evil — especially if it’s not on their naughty-behavior list.

Time-Bombs, apps that hide their bad-behavior for a few days, are undetectable without periodic audits, since they act normally during the pre-release review period.

Phoning home to a server that let’s an app know it’s passed review and can begin it’s life of crime, would let an app be even more precise.

With just a few minutes thought, I’m sure you can think of even more clever tricks, or combination of tricks.

Not a Fully Open Vulnerability

That’s not to say your iPhone is in as much danger as your PC. iOS apps don’t have the same free-reign that traditional computer programs have. That limits their usefulness, but it also limits the damage they can cause. An iOS App can’t stop you from killing it, and it can’t mess with other apps, so it can’t “take over” your phone. But it can do anything it likes with your Contacts, and secretly abuse the phone’s always-on network connection, and get up to other sorts of minor mischief.

I don’t have room here to fully analyze the risks of a rogue iPhone’s program. But generally, the danger isn’t too great: a little more than a what website can do, a lot less than what a PC program with administrator access can do.

Ultimately, Apple’s best defense against malware isn’t control of the App Store review process or iTunes payments (although they help), but control over iOS. A well-designed operating system limits what kinds of malware are possible. The review process can screen for egregious mistakes. But it can’t catch everything, and it’s least-able to catch the most clever malware, which ultimately, are the programs we should be most worried about. Apple’s review process doesn’t provide real security against modern malware.

July 19, 2010

#define String

When I need a string-constant, I #define it, instead of doing the “right” thing and using an extern const NSString * variable.

UPDATE 2010-07-20

Thanks to Elfred Pagen for pointing out that you should always put () around your macros. Wrong: #define A_STRING @"hello"

instead use (), even when you don’t think you have to:

#define A_STRING (@"hello")

This prevents accidental string concatenation. In C, string-literals separated only by whitespace are implicitly concatenated. It’s the same with Objective-C string literals. This feature lets you break long strings up into several lines, so NSString *x = @"A long string!" can be rewritten:

NSString *x =
	@"A long"
	@" string!";

Unfortunately, this seldom-used feature can backfire in unexpected ways. Consider making an array of two strings:

#define X @"ex"
#define P @"plain"
a = [NSArray arrayWithObjects:X
                              P,
                              nil];

That looks right, but I forgot a “,” after X, so after string-concatenation, a is ['explain'], not ['ex','plain'].

Moral of the story: you can never have too many ()’s in macros.

And, now, back to why I use #define

It’s less code

Using an extern variable means declaring it in a header, and defining it in some implementation file. But a macro is just one line in a header.

It’s faster to lookup

Because there’s only the definition of a macro, Open Quickly/command-double-clicking a macro always jumps to the definition, so you can see what it’s value is in one step. Generally Xcode jumps to a symbol’s declaration first, and then it’s definition, making it slower to lookup the value of a const symbol.

It’s still type safe

An @"NSString literal" has type information, so mistakes like,

#define X (@"immutable string")
NSMutableString *y = X;
[y appendString:@"z"];

still generate warnings.

It lets the compiler check format-strings

Xcode can catch errors like “[NSString stringWithFormat:@"reading garbage since there's no argument: %s"]“, if you let it. Unfortunately, the Objective-C compiler isn’t smart enough to check [NSString stringWithFormat:externConstString,x,y,z]; because it doesn’t know what an extern variable contains until link-time. But preprocessor macros are evaluated early enough in the build process that that the compiler can check their values.

It can’t be changed at runtime

It’s possible to change the value of const variables through pointers, like so:

const NSString* const s = @"initial";
NSString **hack = &s;
*hack = @"changed!";
NSLog(s);//prints "changed!"

Yes this is pathological code, but I’ve seen it happen (I’m looking at you AddressBook.framework!)

Of course, you can re-#define a preprocessor-symbol, so macros aren’t a panacea for pathological constant-changing code. (Nothing is!) But they push the pathology into compile time, and common wisdom is that it’s easier to debug compile-time problems, so that’s a Good Thing. You may disagree there, and you may be right! All I can say for sure is that in my experience, I’ve had bugs from const values changing at runtime, but no bugs from re-#define-ed constants (yet).

Conclusion

Preprocessor macros are damnably dangerous in C. Generally you should avoid them. But for NSString* constants in applications, I think they’re easier, and arguably less error prone. So go ahead and #define YOUR_STRING_CONSTANTS (@"like this").

Facilitated Learning

Filed under: Accessibility,Design,Quotes,Usability | , ,
― Vincent Gable on July 19, 2010

We made a world populated with objects that reacted to what humans did, but they didn’t interact very strongly. Whereas that isn’t enough, pure discovery learning took us 100,000 years to get to science. So you actually need learning that’s facilitated. And if you can’t make 1,000 good teachers in a year to save yourself, you have to have a user interface that can do that.

Alan Kay, answering questions on the OLPC project, November 5, 2008

“Ok”

Filed under: Design,iPhone,MacOSX,Programming,Usability | , , , , , ,
― Vincent Gable on July 19, 2010

It’s a small thing, but it breeds deep suspicion. Mac OS dialogs always had “OK” buttons (capital O, capital K). Windows dialogs had “Ok” buttons (Capital O, lowercase k). “Ok” buttons in Mac/iOS software are a sign of a half-assed port, by someone who doesn’t really know the platform.

July 16, 2010

“I Have No Apology”

Filed under: Quotes | , ,
― Vincent Gable on July 16, 2010

Q: Will you apologize for investors?
A: Steve: We are apologizing to our customers. We want investors for the long haul. To those investors who bought the stock and are down $5, I have no apology.

–Steve Jobs, taking questions at a press conference on antenna issues with the iPhone 4 design, July 16th, 2010.

That’s a CEO with his priorities straight.

July 8, 2010

NSDictionary Copies It’s Keys

Filed under: Bug Bite,Cocoa,iPhone,MacOSX,Objective-C,Programming | , , ,
― Vincent Gable on July 8, 2010

An NSDictionary will retain it’s objects, and copy it’s keys.

Here are some effects this has had on code I’ve worked on.

  • Sometimes you get the same object you put in, sometimes not.
    Immutable objects are optimized to return themselves as a copy. (But with some exceptions!). So the following code:

    	NSDictionary *d = [NSDictionary dictionaryWithObject:@"object" forKey:originalKey];
    	for(id aKey in d)
    		if(aKey == originalKey)
    			NSLog(@"Found the original key!");
    

    Might print “Found the original key!”, and might not, depending on how [originalKey copy] is implemented. For this reason, never use pointer-equality when comparing keys.

  • Mutable objects make bad keys. If x is a mutable NSObject, [x copy] is an immutable copy of x, at that point in time. Any changes to x are not reflected in the copy. For example,
    	[dict setObject:x forKey:key];
    	//...code that changes key, but not dict
    	assert([[dict objectForKey:key] isEqual:x]); //fails!
    

    Because the copy is an immutable object, it will blow up if you try to mutate it.

    	NSMutableString *key = //something...
    	[dict setObject:x forKey:key];
    	for(NSMutableString *aKey in dict)
    		[aKey appendString:@"2"]; //Error, aKey isn't mutable, even though key is!
    		
    
  • View objects make bad keys. Views have state related to the screen: their frame, position in the view hierarchy, animation layers, etc. When you copy a view object, the copy won’t (always) be isEqual: to the original, because it’s not on the screen in exactly the same way.
  • Your classes must support NSCopying to be used as a key in an NSDictionary, you can’t just implement -hash and -isEqual: in your custom classes.

Of course, this isn’t a complete list of every way key-copying can trip you up. But if you understand what copy means in Cocoa, and remember how NSDictionary works, you’ll be able to avoid or quickly solve any issues.

How to Document Such Behavior Better Than Apple Did

Given what we know about NSDictionary, what’s wrong with the following snippit from NSDictionary.h?

@interface NSMutableDictionary : NSDictionary
- (void)setObject:(id)anObject forKey:(id)aKey;
@end

Answer: aKey needs to implement NSCopying, so it should be of type (id<NSCopying>) instead of type (id). That way, the header is self-documenting, and, if like most smart programmers, you’re using autocomplete to type out Cocoa’s long method names, the auto-completed template will be self-documenting too.

July 7, 2010

Worthless on an Unimaginable Scale

Filed under: iPhone | , ,
― Vincent Gable on July 7, 2010

There are other App Farms we know of…. One example is Brighthouse Labs with 4568 Apps, all virtually worthless.
Brighthouse Labs in AppStore screenshot

Zee, writing for The Next Web

I have a hard time wrapping my head around that number. Nearly five thousand “apps”. Near as I can tell, it’s a solid 2% of the whole App Store. With an (optimistic) 5-day-per-app approval time, it would take Apple 86 years to approve them serially.

Powered by WordPress