在运行时检测 iPhone 上的 UDID 欺骗

发布于 2024-10-02 20:25:58 字数 2260 浏览 6 评论 0原文

越狱的 iPhone 让我很恼火,因为它使用 MobileSubstrate 污染了 iOS 上的一些基本 API。

http://www.iphonedevwiki.net/index.php/MobileSubstrate

我相信很多应用程序使用 UDID 作为验证设备和/或用户的方法,因为它是半自动且方便的,但您应该意识到这个问题:UIDevice 并不像应有的那样防篡改。有一个名为 UDID Faker 的应用程序,它可以让您轻松地在运行时欺骗别人的 UDID。

http://www.iphone-network.net/ how-to-fake-udid-on-ios-4/

这是它的源代码:

//
//  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<Hook> *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)&$UIDevice$uniqueIdentifier, "orig_");
        }

    [pool release];
}

如您所见,UIDevice 类中的 uniqueIdentifier 方法现在在任何应用程序上返回 fakeUDID。

Skype 和其他一些应用程序似乎可以检测到这种污点,但我不知道该怎么做。

我想做的是:当启动时检测到受污染的 UIDevice 时,发出警报并退出(0)。

有想法吗?

Jailbroken iPhones get on my nerve as it taints some fundamental APIs on iOS, by using MobileSubstrate.

http://www.iphonedevwiki.net/index.php/MobileSubstrate

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.

http://www.iphone-network.net/how-to-fake-udid-on-ios-4/

Here's the source code of it:

//
//  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<Hook> *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)&$UIDevice$uniqueIdentifier, "orig_");
        }

    [pool release];
}

As you can see, uniqueIdentifier method in the UIDevice class now returns fakeUDID on any apps.

It seems that Skype and some other apps detect this sort of taint, but I don't know how to do it.

What I wanted to do is: When tainted UIDevice is detected upon launch, alert and exit(0).

Ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

极度宠爱 2024-10-09 20:25:58

没有真正安全的方法来检查 UDID 是否真实。 UDID 是通过 liblockdown 获取的,它通过安全通道与lockdownd 通信以接收 UDID:

+-----------+
| your code |
+-----------+
      |
+----------+       +-------------+       +-----------+
| UIDevice |<----->| liblockdown |<=====>| lockdownd |   (trusted data)
+----------+       +-------------+       +-----------+
         untrusted user                   trusted user

当设备越狱时,所有 4 个组件都可以更换。


检测 UDID Faker 是否存在的一种方法是检查其特有的某些标识(文件、函数等)是否存在。这是一种非常具体且脆弱的反击,因为当检测方法暴露时,欺骗者可以简单地更改标识来隐藏其存在。

例如,UDID Faker 依赖于 plist 文件 /var/mobile/Library/Preferences/com.Reilly.UDIDFaker.plist。因此,您可以检查此文件是否存在:

NSString* fakerPrefPath = @"/var/mobile/Library/Preferences/com.Reilly.UDIDFaker.plist";
if ([[NSFileManager defaultManager] fileExistsAtPath:fakerPrefPath])) {
   // UDID faker exists, tell user the uninstall etc.
}

它还定义了方法 -[UIDevice orig_uniqueIdentifier] ,该方法可用于绕过伪造者:

UIDevice* device = [UIDevice currentDevice];
if ([device respondsToSelector:@selector(orig_uniqueIdentifier)])
   return [device orig_uniqueIdentifier];
else
   return device.uniqueIdentifier;

当然,欺骗者可以简单地重命名这些内容。


更可靠的方法在于 Mobile Substrate 的工作原理。注入的代码必须位于 dylib/bundle 中,该代码加载到与 UIKit 不同的内存区域中。因此,您只需检查-uniqueIdentifier方法的函数指针是否在可接受的范围内。

// get range of code defined in UIKit 
uint32_t count = _dyld_image_count();
void* uikit_loc = 0;
for (uint32_t i = 0; i < count; ++ i) {
   if (!strcmp(_dyld_get_image_name(i), "/System/Library/Frameworks/UIKit.framework/UIKit")) {
     uikit_loc = _dyld_get_image_header(i);
     break;
   }
}

....

IMP funcptr = [UIDevice instanceMethodForSelector:@selector(uniqueIdentifier)];
if (funcptr < uikit_loc) {
   // tainted function
}

无论如何,UDID Faker 是一个非常高级的黑客(即它可以很容易地避免)。它通过提供虚假 ID 劫持 UIDevice 和 liblockdown 之间的链接。

+-----------+
| your code |
+-----------+
      |
+----------+       +-------------+       +-----------+
| UIDevice |<--.   | liblockdown |<=====>| lockdownd |   (trusted data)
+----------+   |   +-------------+       +-----------+
               |   +------------+
               ‘-->| UDID Faker |
                   +------------+

因此,您可以将询问 UDID 的代码移至 liblockdown 级别。这可用于越狱平台的应用程序,但这不适用于 AppStore 应用程序,因为 liblockdown 是私有 API。此外,欺骗者还可以劫持 liblockdown(这很容易,我希望没有人这么做),甚至可以替换 lockd 本身。

                   +-----------+
                   | your code |
                   +-----------+
                         |
+----------+       +-------------+       +-----------+
| UIDevice |<--.   | liblockdown |<=====>| lockdownd |   (trusted data)
+----------+   |   +-------------+       +-----------+
               |   +------------+
               ‘-->| UDID Faker |
                   +------------+

(我不会在这里展示如何使用 liblockdown。您应该能够从您链接到的网站找到足够的信息。)

There isn't a truly safe way to check if the UDID is real. The UDID is got via liblockdown, which communicates to lockdownd via a secure channel to receive the UDID:

+-----------+
| your code |
+-----------+
      |
+----------+       +-------------+       +-----------+
| UIDevice |<----->| liblockdown |<=====>| lockdownd |   (trusted data)
+----------+       +-------------+       +-----------+
         untrusted user                   trusted user

When the device is jailbroken, all 4 components can be replaced.


One method to detect the presence of UDID Faker is to check if some identifications (files, functions etc.) unique to it exists. This is a very specific and fragile counter-attack, as when the method of detection is exposed, the spoofer could simply change the identification to conceal their existence.

For example, UDID Faker relies on a plist file /var/mobile/Library/Preferences/com.Reilly.UDIDFaker.plist. Therefore, you could check if this file exists:

NSString* fakerPrefPath = @"/var/mobile/Library/Preferences/com.Reilly.UDIDFaker.plist";
if ([[NSFileManager defaultManager] fileExistsAtPath:fakerPrefPath])) {
   // UDID faker exists, tell user the uninstall etc.
}

it also defines the method -[UIDevice orig_uniqueIdentifier] which could be used to bypass the faker:

UIDevice* device = [UIDevice currentDevice];
if ([device respondsToSelector:@selector(orig_uniqueIdentifier)])
   return [device orig_uniqueIdentifier];
else
   return device.uniqueIdentifier;

Of course the spoofer could simply rename these things.


A more reliable method lies in how Mobile Substrate works. Injected code must be located in a dylib/bundle, which is loaded into a memory region different from UIKit. Therefore, you just need to check if the function pointer of the -uniqueIdentifier method is within the acceptable range.

// get range of code defined in UIKit 
uint32_t count = _dyld_image_count();
void* uikit_loc = 0;
for (uint32_t i = 0; i < count; ++ i) {
   if (!strcmp(_dyld_get_image_name(i), "/System/Library/Frameworks/UIKit.framework/UIKit")) {
     uikit_loc = _dyld_get_image_header(i);
     break;
   }
}

....

IMP funcptr = [UIDevice instanceMethodForSelector:@selector(uniqueIdentifier)];
if (funcptr < uikit_loc) {
   // tainted function
}

Anyway UDID Faker is a very high level hack (i.e. it can be easily avoided). It hijacks the link between UIDevice and liblockdown by supplying a fake ID.

+-----------+
| your code |
+-----------+
      |
+----------+       +-------------+       +-----------+
| UIDevice |<--.   | liblockdown |<=====>| lockdownd |   (trusted data)
+----------+   |   +-------------+       +-----------+
               |   +------------+
               ‘-->| UDID Faker |
                   +------------+

Thus you could move the code asking the UDID lower to the liblockdown level. This can be used for apps for Jailbroken platforms, but this is not possible for AppStore apps because liblockdown is a private API. Besides, the spoofer could hijack liblockdown (it's very easy, I hope no one does it), or even replace lockdownd itself.

                   +-----------+
                   | your code |
                   +-----------+
                         |
+----------+       +-------------+       +-----------+
| UIDevice |<--.   | liblockdown |<=====>| lockdownd |   (trusted data)
+----------+   |   +-------------+       +-----------+
               |   +------------+
               ‘-->| UDID Faker |
                   +------------+

(I'm not going to show how to use liblockdown here. You should be able to find sufficient information from the site you've linked to.)

那片花海 2024-10-09 20:25:58

关键是检测 JB 设备并且不在其上运行。

The key is detecting a JB device and not running on it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文