title: Detect UDID spoofing on the iPhone at runtime
body: <p>Jailbroken iPhones get on my nerve as it taints some fundamental APIs on iOS, by using MobileSubstrate.</p>
  
  <p><a href="http://www.iphonedevwiki.net/index.php/MobileSubstrate" rel="noreferrer">http://www.iphonedevwiki.net/index.php/MobileSubstrate</a></p>
  
  <p>I believe many apps use UDID as a mean to authenticate a device and/or a user since it's semi-automatic and handy, but you should be aware of this problem: UIDevice is not as tamper-proof as it should be. There's an app called UDID Faker, which easily enables you to spoof someone else's UDID at runtime.</p>
  
  <p><a href="http://www.iphone-network.net/how-to-fake-udid-on-ios-4/" rel="noreferrer">http://www.iphone-network.net/how-to-fake-udid-on-ios-4/</a></p>
  
  <p>Here's the source code of it:</p>
  
  <pre><code>//
  //  UDIDFaker.m
  //  UDIDFaker
  //
  
  #include "substrate.h"
  
  #define ALog(...) NSLog(@"*** udidfaker: %@", [NSString stringWithFormat:__VA_ARGS__]);
  #define kConfigPath @"/var/mobile/Library/Preferences/com.Reilly.UDIDFaker.plist"
  
  @protocol Hook
  - (NSString *)orig_uniqueIdentifier;
  @end
  
  NSString *fakeUDID = nil;
  
  static NSString *$UIDevice$uniqueIdentifier(UIDevice&lt;Hook&gt; *self, SEL sel) {  
  
      if(fakeUDID != nil) {
                   ALog(@"fakeUDID %@", fakeUDID);
          /* if it's a set value, make sure it's sane, and return it; else return the default one */
                  return ([fakeUDID length] == 40) ? fakeUDID : [self orig_uniqueIdentifier];
  
      }
      /* ... if it doesn't then return the original UDID */
      else {
          return [self orig_uniqueIdentifier];
      }
  }
  
  __attribute__((constructor)) static void udidfakerInitialize() {  
  
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
          NSString *appsBundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
          ALog(@"Loading UDID Faker into %@", appsBundleIdentifier);
  
  
          NSDictionary *config = [NSDictionary dictionaryWithContentsOfFile: kConfigPath];
          fakeUDID = [config objectForKey: appsBundleIdentifier];
          [fakeUDID retain];
  
          if(fakeUDID != nil) {
  
                  ALog(@"Hooking UDID Faker into %@", appsBundleIdentifier);
                  MSHookMessage(objc_getClass("UIDevice"), @selector(uniqueIdentifier), (IMP)&amp;$UIDevice$uniqueIdentifier, "orig_");
          }
  
      [pool release];
  }
  </code></pre>
  
  <p>As you can see, uniqueIdentifier method in the UIDevice class now returns fakeUDID on any apps.</p>
  
  <p>It seems that Skype and some other apps detect this sort of taint, but I don't know how to do it.</p>
  
  <p>What I wanted to do is: When tainted UIDevice is detected upon launch, alert and exit(0).</p>
  
  <p>Ideas?</p>