关闭

CydiaSubstrate的简单使用

标签: iOS安全CydiaSubstMobileHookTweak
1453人阅读 评论(0) 收藏 举报
分类:

CydiaSubstrate

CydiaSubstrate 是绝大部分tweak正常工作的基础,主要分为三部分:MobileHooker,CydiaSubstrate,Safe mode

MobileHooker

MobileHooker的作用是替换系统函数(即hook)

// 作用于OC函数,可直接替换掉方法  
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP *result);

(Logos语法对此函数进行了封装,但底层实现完全基于MSHookMessageEx)

// 作用于C , C++
void MSHookFunction(void* function, void* replacement, void** original);

(通过编写汇编指令,在进程执行到function时转而执行replacement,同时保存function的指令返回其地址,可选择性的执行function,并保证进程能够执行完replacement后继续正常执行)
ps:之前hook必须进行越狱才能操作,现在直接汇编就能实现hook

repalce替换进程—>下表进程由上向下执行进程

正常执行的进程1 勾住函数A替换为函数B的进程2
☟Instructions ☟Instructions
☟FunctionA ☟FunctionB (FunctionA暂存)
☟Instructions ☟Instructions

进程先执行一些指令,在原本应该执行的函数A的地方跳转到了函数B的位置执行函数B,同时函数A的 代码被MobielHooker暂时保存了下来。在函数B中,可以选择是否执行函数A,在函数B执行完成 后,则会继续执行剩下的指令。(ps:MSHookFunction的指令长度是有限制的,至少为8字节,如 果要hook住那些段函数该怎么办?—->一种变通的方法是hook住短函数内部调用的其他函数—- 短函数之所以短,是因为内部一般都是调用了其他函数,由其他函数来做出实际操作。因此,把长度 符合要求的其他函数作为MSHookFunction的目标,然后在replacement里做一些逻辑判断,将它 与函数关联上,再把对应的短函数的修改写在这里)

MobileLoader

MobileLoader的作用是加载第三方dylib。在iOS启动时,会由launched将MobileLoader载入内存,然后MobileLoader会根据dylib的同名plist文件指定的作用范围,有选择的在不同进程里通过dlopen函数打开目录/Library/MobileSubstrate/DynamicLibraries/下的所有dylib.

Safe mode

应用的质量良莠不齐,程序崩溃再说难免,因为tweak的本质是dylib,寄生在别的进程里,一旦出错,可能导致整个进程崩溃,而一旦崩溃的是SpringBoard等系统进程,则会造成iOS瘫痪,所以CydiaSubstrate引入了Safe mode,它会补获SIGTRAP、SIGTBRT、SIGILL、SIGBUS、SIGSEGV、SIGSYS这六种信号,然后进入安全模式。
(ps:在安全模式里,所有基于CydiaSubstrate的第三方dylib会被禁用,便于查找于修复;如果设备因为dylib的原因无法进入系统,比如,开机一直卡在白苹果上,或者进度圈不停地转—>home+lock+然后音量上键禁用CydiaSubstrate,系统重启后再查错与排修,修复后重启iOS,CydiaSubstrate会自动重启)

demo1核心代码



// MSFindSymbol的作用--->查找待hook的symbol,函数的指令被放在内存中,当进程需要执行这个函数时,它必须要知道去内存的哪个地方找到这个函数,然后执行它的指令,也就是说
// 进程要根据函数名,找到它在内存中的地址,而这个名称与地址的映射关系,是存储在"symbol table"中的-----"symbol table" 中的symbol就是这个函数的名称,进程会根据这个
// symbol找到它在内存中的地址.然后跳转过去执行.

#import <substrate.h>

void (*old_ZN8CPPClass11CPPFuctionEPKc)(void *, const char *);

void new__ZN8CPPClass11CPPFunctionEPKc(void *hiddenThis, const char *arg0)
{
    if (strcmp(arg0,"this is a short C function!") == 0) 
        old_ZN8CPPClass11CPPFuctionEPKc(hiddenThis,"this is a hijacked short C function form new__ZN8CPPClass11CPPFunctionEPKc!");
    else old_ZN8CPPClass11CPPFuctionEPKc(hiddenThis,"this is a hijacked c++ function");
}

void (*old_CFunction)(const char *);

void new_CFunction(const char *arg0)
{
    old_CFunction("this is a hijacked C function!");  // call the original CFunction
}

void (*old_ShortCFuntion)(const char *);

void new_ShortCFunction(const char *arg0)
{
    old_ShortCFuntion("this is a hijacked short C function form new_ShortCFunction!"); // call the original ShortCFunction
}

%ctor

{
    @autoreleasepool
    {
        MSImageRef image = MSGetImageByName("/Application/iostargetapphhly.app/iostargetapphhly");

        void *__ZN8CPPClass11CPPFunctionEPKc = MSFindSymbol(image,"__ZN8CPPClass11CPPFunctionEPKc");
        if (__ZN8CPPClass11CPPFunctionEPKc) NSLog(@"iosre : found cppfunction!");
        MSHookFunction((void *)__ZN8CPPClass11CPPFunctionEPKc, (void *)&new__ZN8CPPClass11CPPFunctionEPKc, (void **)&old_ZN8CPPClass11CPPFuctionEPKc);

        void *_CFunction = MSFindSymbol(image,"_CFunction");
        if (_CFunction) NSLog(@"iosre:found CFunction");
        MSHookFunction((void *)_CFunction, (void *)&new_CFunction, (void **)&old_CFunction);

        void *_ShortCFunction = MSFindSymbol(image, "_ShortCFunction");
        if (_ShortCFunction) NSLog(@"iosre: found ShortCFunction");
        MSHookFunction((void *)_ShortCFunction, (void *)&new_ShortCFunction, (void **)&old_ShortCFuntion); // This MSHookFunction will fail because ShortCFunction is too short to be hooked

    }
}

demo2核心代码

//
//  RootViewController.cpp
//  ssd
//
//  Created by esirnus on 16/5/23.
//  Copyright © 2016年 esirnus. All rights reserved.
//

#import "RootViewController.h"


class CPPClass
{
public:
    void CPPFunction(const char *);
};

void CPPClass::CPPFunction(const char *args0)
{
    for (int i = 0; i < 66; i++) // 这个循环可以有足够长的时间来验证 MSHookFunction
    {
        u_int32_t randomNumber;
        if (i % 3 == 0) randomNumber = arc4random_uniform(i);
        NSProcessInfo *processInfo = [NSProcessInfo processInfo];
        NSString *hostName = processInfo.hostName;
        int pid = processInfo.processIdentifier;
        NSString *globallyUniqueString = processInfo.globallyUniqueString;
        NSString *processName = processInfo.processName;
        NSArray *junks = @[hostName,globallyUniqueString,processName];
        NSString *junk = @"";
        for (int j = 0; j < pid; j++)
        {
            if (pid % 6 == 0) junk = junks[j % 3];
        }
        if (i % 68 == 1) NSLog(@"Junk: %@",junk);
    }
    NSLog(@"HHLY: CPPFunction:%s",args0);
}

extern "C" void CFunction(const char *args0)
{
    for (int i = 0; i < 66; i++)
    {
        u_int32_t randomNumber;
        if (i % 3 == 0) randomNumber = arc4random_uniform(i);
        NSProcessInfo *processInfo = [NSProcessInfo processInfo];
        NSString *hostName = processInfo.hostName;
        int pid = processInfo.processIdentifier;
        NSString *globallyUniqueString = processInfo.globallyUniqueString;
        NSString *processName = processInfo.processName;
        NSArray *junks = @[hostName,globallyUniqueString,processName];
        NSString *junk = @"";
        for (int j = 0; j < pid; j++)
        {
            if (pid % 6 == 0) junk = junks[j % 3];
        }
        if (i % 68 == 1) NSLog(@"Junk: %@",junk);
    }
    NSLog(@"HHLY: CFunction:%s",args0);
}

extern "C" void shortCFunction(const char *args0) // shortCFunction is too short to be hooked
{
    CPPClass cppclass;
    cppclass.CPPFunction(args0);
}


@implementation RootViewController


- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
    //    self.view  = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.view.backgroundColor = [UIColor redColor];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    CPPClass cppclass;
    cppclass.CPPFunction("this is cpp function");
    CFunction("this is c function");
    shortCFunction("this is a short C function");
}


@end

Demo说明

Demo—>iostargetapphhly目的:验证MSHookFunction对Function的指令总长度有限制

  • 说明:针对MobileHooker的使用,CPPClass::CPPFunction,一个CFunction和一个ShortCFunction,作为hook的对象,CPPClass::CPPFunction和CFunction的目的是为了增加这两个函数的长度,使得针对它们俩的MSHookFunction生效,而ShortCFunction会因长度太短,导致针对它的MSHookFunction失效

Demo—>hhlydemoioshookertweak目的:间接hook短函数

  • 对函数(ShortCFunction)直接hook失败了,而对短函数内部调用的其他函数hook是有效的,可通过判断参数,检测它的调用者是ShortCFunction,这样既可实现间接hook短函数

  • MSHookFunction的指令长度是有限制的,至少为8字节,如果要hook住那些段函数该怎么办?—->一种变通的方法是hook住短函数内部调用的其他函数—-短函数之所以短,是因为内部一般都是调用了其他函数,由其他函数来做出实际操作。因此,把长度符合要求的其他函数作为MSHookFunction的目标,然后在replacement里做一些逻辑判断,将它与函数关联上,再把对应的短函数的修改写在这里)

本文代码及相关包完整版本上传在github上Demo/MobileHooker文件夹下(https://github.com/Esirnus/iOSSecurity-Attack)

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:17330次
    • 积分:343
    • 等级:
    • 排名:千里之外
    • 原创:16篇
    • 转载:1篇
    • 译文:0篇
    • 评论:6条
    文章分类