iOS - 将“对象”添加到现有应用程序(越狱)

时间:2012-07-20 03:03:31

标签: ios jailbreak tweak tampering

如何将“对象”添加到现有应用程序?

例如,EasyRefresh for Chrome调整,在iOS Chrome应用中启用了一个新按钮,就像许多其他调整一样。

我如何添加一个简单的UIButton,例如,Twitter应用程序?

是否有任何GitHub项目可以帮助我理解它是如何完成的?


image

图片来源:ModMyI


感谢。

2 个答案:

答案 0 :(得分:52)

这个技巧涉及一些(非常基本的)逆向工程,由几个步骤组成;我会尽可能清楚地解释它们。

步骤零:如果从AppStore下载应用程序,则会加密。您必须使用通常用于破解应用程序的脚本/应用程序之一来解密它;一个命令行脚本是poedCrack.sh(google it,你可以在其中一个粘贴网站上快速找到它),一个GUI应用程序是Crakculous(它在Cydia中可用)。请注意,其中一个是简单(自动)解密所必需的 - 手动解密方法过于涉及到放入StackOverflow的答案,这就是我建议使用这些工具的原因。)但是,我不以任何方式鼓励你破解应用程序! (基本上我要求你不要将这些工具用于其原始目的:)如果你想看看手动解密过程,head here.

第一步:您需要执行应用程序使用/创建的类。为此,您需要class-dump或class-dump-z实用程序。此命令行应用程序反转应用程序的二进制可执行文件,并为应用程序使用并具有内部的所有Objective-C类生成接口声明。您可以找到class-dump-z,更高级和首选的变体here.

第二步:在你有了类声明之后,你将不得不猜测哪个类做了什么以及什么时候(是的,有点令人困惑)。例如,在上面的应用程序Google Chrome中,通过class-dump-z生成的其中一个文件,您可能会发现类似的内容:

@interface ChromeUrlToolbar: UIToolbar {
    UISearchBar *urlBar;
}

- (id)initWithFrame:(CGRect)frame;
- (void)loadURL:(NSURL *)url;

@end
嗯,听起来不错,不是吗?您可以看到它的实现有一个initWithFrame:方法(作为所有UIView子类) - 为什么不尝试修改它?

第三步:对于此次修改,您需要MobileSubstrate。 MobileSubstrate是由Cydia的创建者Saurik创建的开发人员库,用于简化应用程序的代码注入。您可以在网上找到一些非常好的教程,包括this one。 所以,你有一个课程,你想要“挂钩”它 - 所以你写了这样的代码:

static IMP __original_init; // A

id __modified_init(id __self, SEL __cmd, CGRect frame) // B
{
    __self = __original_init(__self, __cmd, frame); // C

    // D
    UIButton *newButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [newButton setTitle:@"Chrome Pwned"];
    newButton.frame = CGRectMake(0, 0, 100, 40);
    [__self addSubview:newButton];

    return __self;
}

// E
__attribute__((constructor))
void init()
{
    Class clazz = objc_getClass("ChromeUrlToolbar"); // F
    MSHookMessageEx(clazz, @selector(initWithFrame:), __modified_init, &__original_init); // G
}

说明:让我们从结束开始。 init函数(E)声明为__attribute__((constructor))。这意味着当我们将使用此代码创建的库加载到Chrome中时,它会自动调用。这正是我们想要的,因为我们想要在启动之前改变应用程序的行为。

在标记为// F的行上,我们捕获了我们想要修改的类对象本身。 Objective-C是一种高度动态的语言;这意味着我们可以在运行时获取和修改有关类和对象的信息。在标记为// G的行上,我们使用MobileSubstrate API最重要的功能:MSHookMes​​sageEx。要理解它是如何工作的(而不是它的作用),你必须知道以下内容:Objective-C本身是作为一个普通的C库实现的 - 语言本身,在简单的C之下。所以每个消息都在Obejctive中发送-C实际上是一个C函数调用。这些C函数有两个特殊参数:selfcmd - 前者是指向被消息对象的指针,后者是选择器(一个特殊的,唯一的指向消息名称的指针)发送)。所以MSHookMes​​sageEx所做的是它需要一个类和一个选择器,找到与它们对应的函数的实现,并用它的第三个参数本身(在这种情况下为__modified_init)中提供的函数交换该函数。为了不丢失数据,它还返回第4个参数中的函数(这里是__original_init)。

因此,现在Chrome网址工具栏的初始化会重定向到我们的功能,下一步该怎么做?好吧,没有什么特别之处:首先我们只调用原始初始化函数(注意前两个特殊参数,__ self和__cmd!),这就像正常情况一样创建工具栏(这行代码用// C表示)。然后,我们进行实际更改:在// D部分中,我们创建一个UIButton,设置其标题和位置,并将其作为子视图添加到我们新创建的工具栏中。然后,知道这是一个初始化函数,我们返回原始实例以及注入其中的按钮代码。

嗯,这基本上是你需要了解的;如果您对Objective-C如何工作的深层细节以及如何创建酷炫的iOS调整感兴趣,我建议您阅读Apple的official documentation on the topic,您也可以浏览some of my opensource Cydia tweaks.

我希望这会对你有所帮助!

答案 1 :(得分:11)

您需要这样做才能理解Objective-C运行时的工作原理。特别是消息传递系统(即调用方法)。特别是,调用方法是在运行时确定的,与编译时的其他语言相比。 这允许全局更改特定方法,即方法调配

使用Mobile Substrate library,您将被允许用您自己的方法替换任何方法实现,甚至可以调用原始实现。当然,您需要知道方法的名称和所需的参数,以及它所属的类。

因此,要修改SpringBoard,您必须知道包含哪个类以及哪个方法。您必须使用为您执行此操作的class-dumpclass-dump-z实用程序(class-dump-z更新,更多用于iOS开发,class-dump更通用且兼容使用较旧的二进制文件以及64位)。

因此,要对SpringBoard进行类转储,您需要输入Terminal.app

class-dump -H /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard

对于class-dump-z,-p选项将生成@property而不是getter / setter,这更清晰,所以你可能输入

class-dump-z -p -H /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard

该行将在桌面上创建一个文件夹,其中包含SpringBoard的所有类定义。 当然,您可能需要将路径更改为适合您系统的路径(关于此,对于Xcode的最新版本,Developer文件夹 Xcode中,因此您需要类似

的内容
/Applications/Xcode/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard

对于大多数现有框架,您也可以find on the internet people who did that for you这非常方便如果您确定它们是适合您系统的版本。

现在,对于AppStore应用程序,您首先需要解密它们,因为它们受到保护。您可能需要找到自己的名称和链接,因为这可能违反了Stack Overflow的ToS,尽管使用gdb可以达到这个目的。

为了简化工作,我们创建了一些工具,例如Logos(您可能还需要查看Theos),以减少所需的样板代码。还有一个(相当古老的)xcode template & tutorial for mobilesubstrate提供了很好的帮助。

Logos可以轻松地从类method挂钩方法classname

%hook classname //declares the class from your application you're going to override

-(void)method {

    dosomethingnew(); //put all your new code for the method here
    return %orig;     //this calls the original definition of the method
}
%end //end hooking classname

有关系统中框架的列表及其有用信息,请参阅here

最后一件事:开源的流行调整列表(尽可能链接到GitHub):

Some little tweaks

最后,看看the WeekTweak,他们每周都会发布开源调整,以便您可以通过查看其他人的来源来了解并尝试&做你自己的事情。 IRC(irc.saurik.com)上的#theos chan也会提供帮助,如果你善意的话。