• 科研人员发现新型光合作用 2019-12-05
  • 《进京城》等11部影片入围上影节传媒关注单元 2019-12-05
  • 俄罗斯:解决朝鲜问题已进入中俄制定的"路线图" 2019-11-27
  • 俞正声:推进政协协商民主建设,形成协商议政新局面 2019-11-24
  • 林地旅行地中国国家地理网 2019-11-24
  • 表白戒指不翼而飞 列车长掰开座椅为他“降火” 2019-11-21
  • 粽情粽意 传承文明———我们的节日2018端午节 2019-11-18
  • 安徽3年争取逾百亿资金 确保保障性安居工程建设 2019-11-18
  • 几十架战机起飞后消失,搜寻代价大,美军放弃寻找拿出巨额封口费 2019-11-16
  • 深入贯彻落实党中央治疆方略br坚定不移推进新疆社会稳定和长治久安 2019-11-12
  • 充分发挥人民政协职能优势 2019-11-04
  • 空腹吃荔枝会引发低血糖致死?专家:空腹才是真凶 2019-11-02
  • “通达系”转让丰巢股权 快递终端格局将变 2019-11-02
  • 中国环渤海帆船拉力赛招商发布会在京举行 2019-10-27
  • “一带一路”倡议开辟宗教学研究新境界 2019-10-27
  • 动态库注入

    yahib· 2019-10-21

    [一、前言]

    [二、注入思路]

    [三、动态库注入实现]

    [四、分析实现按钮监听]

    [五、实战修改微信步数]

    一、前言

    在文章《应用签名-脚本签名》中介绍了如何在真机上运行破壳应用(抖音、微信、支付宝等ipa包),来观察应用视图的层级结构,方法调用,类名称等,以便学习参考。应用主要与后台进行数据交互展示(数据拉取及提交数据),既然能对破壳应用重签名并在真机上运行,那么能不能修改应用数据和页面展示呢,如监听微信登录按钮,修改微信步数,下面就这两个功能拓展一下思路。

    二、注入思路

    ipa包中,主要包含了应用签名、资源文件、Frameworks文件、info.plist配置文件及与ipa包同名的可执行通用文件(这里包含了具体的业务执行指令)。在《Mach-O》中我们对Mach-O文件有一个初步了解,主要有Header、Load commands、Data三部分组成。

    Header:包含Mach-O文件的基本信息,字节顺序、架构类型、加载指令的数量等; Load commands:包含区域位置、符号表、动态符号表,加载Mach-O文件时使用这里的数据确定内存分布; Data:数据段segement,包含具体代码、常量、类、方法等。

    如果要向已有应用ipa中加入自己的代码,必须对Mach-O进行修改重组。根据已有开发经验有思路两个:

    1、修改功能代码,向Mach-O中的Data部分增删改数据段; 2、另一个是添加动态库,利用runtime对原始代码进行方法替换,数据、UI的修改。

    第一种方案需要分析Mach-O对应的汇编代码,来修改功能,操作较繁琐;第二种方案,需要我们向ipa包下的Frameworks中添加写好的动态库,并向Load commands添加动态库加载指令,同时还需要修改Header中对应的基本信息,相对于第一种不用做汇编指令分析了。

    以上只是个人的一些思考,这里就不去研究具体的注入过程,直接使用一个第三方库来完成动态库的注入,先完成微信登录按钮的监听,以后再对具体的操作进一步学习研究。

    第三方动态库注入工具:yololib

    三、动态库注入实现

    破壳ipa获?。?1、通过越狱手机获取破壳应用; 2、通过PP助手获取越狱应用。

    《应用签名-脚本签名》中实现了对破壳应用的重签名,并运行在真机上可供调试。

    1、创建新工程 常规创建,工程名InsertCode(工程名随意):

    2、插入签名脚本、获取破壳ipa包,放入app文件中

    • app内的ipa包不建议导入工程,放在文件中即可(可能要加入其他应用包)
    • 具体脚本在《应用签名-脚本签名》中查看

    3、真机运行,执行要查看的ipa包

    选择证书,在真机上运行,ipa会被安装至手机上,注意这里的ipa必须是破壳的,并具有相同架构配置的ipa否则安装失败。

    4、创建Frameworks文件

    在动态库文件下创建Insert类:

    • 创建动态库文件,用来做方法替换

    runtime中通?;崾褂?code>+load方法,该方法会在编译期被调用,因此在应用运行前,对应用内部方法动动手脚。下面先在load方法中插入打印代码,再向ipa包中插入动态库,看看是否能够插入到新包中。

    代码:

    @implementation Insert
    + (void)load {
        NSLog(@"插入成功");
    }
    @end

    5、引入注入工具yololib

    下载 yololib 并编译(或直接拿到可执行文件),将可执行文件复制到工程中的tool目录下,注意给执行权限。

    SignApp.sh脚本最后一行插入注入指令:

    #注入
    if [ -d "$BUILT_PRODUCTS_DIR/HBHook.framework" ]
    then
    ${SRCROOT}/tool/yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/HBHook.framework/HBHook"
    else
    echo "没有该文件"
    fi

    完整操作如下:

    准备工作完成,运行工程:

    打印“插入成功”,说明动态库已成功插入到ipa中,用 MachOView 打开.app中WeChat通用二进制文件,查看新的布局如下:

    Load commands中已经有了动态库的加载指令,接下来就对原登录按钮的点击方法做替换监听。

    四、分析实现按钮监听

    替换原登录方法,需要我们知道对应的方法名称。怎么查找?如下:

    • 通过层级关系立刻定位到了登录方法信息,Action onFirstViewLogin,所属类WCAccountLoginControlLogic

    瞬间感觉微信很友好???。?!

    那么开始编写方法替换代码:

    #import "Insert.h"
    #import <objc/message.h>
    @implementation Insert
    + (void)load {
        NSLog(@"插入成功");
        Method old_method = class_getInstanceMethod(objc_getClass("WCAccountLoginControlLogic"), sel_registerName("onFirstViewLogin"));
        Method new_method = class_getInstanceMethod(self, sel_registerName("my_onFirstViewLogin"));
        method_exchangeImplementations(old_method, new_method);
    }
    -(void)my_onFirstViewLogin {
        NSLog(@"我来了");
        [self my_onFirstViewLogin];
    }
    @end
    • 交换了交换了原始方法的imp指向
    • 通过runtime函数来获取类及类方法
    • my_onFirstViewLoginWCAccountLoginControlLogic的实例调用,因此self指的是WCAccountLoginControlLogic的实例

    运行工程,点击登录按钮,如下:

    第一行打印了“我来了”,说明,我们监听到了按钮的点击事件,但后面出现崩溃,此处很好理解,在原控制器中并没有找到对应的选择器?;匾渲暗姆椒ㄌ婊?,我们是在对应类的分类中去替换,方法在编译时会加入到该类的方法列表中,而此处并不是原类的分类。

    那么如何解决呢,这里有三种方法:

    1、给原类添加方法

    + (void)load {
        NSLog(@"插入成功");
        Method old_method = class_getInstanceMethod(objc_getClass("WCAccountLoginControlLogic"), sel_registerName("onFirstViewLogin"));
        BOOL result = class_addMethod(objc_getClass("WCAccountLoginControlLogic"),
                        sel_registerName("new_method"), (IMP)new_method, "[email protected]:");//添加新的方法
        NSLog(@"%@",[email protected]"添加成功":@"添加失败");
        method_exchangeImplementations(old_method, class_getInstanceMethod(objc_getClass("WCAccountLoginControlLogic"),sel_registerName("new_method")));
    }
    void new_method(id self, SEL _cmd){
        NSLog(@"我来了");
        [self performSelector:sel_registerName("new_method")];
    }
    1. 添加方法并替换方法的imp;
    2. imp实现中通过performSelector来调用原有类添加的方法,从而找到原方法对应的实现。
    class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, 
                    const char * _Nullable types) 
    • cls:为哪个类添加方法
    • name:设置方法名称
    • imp:设置方法对应的imp,此处imp设置在当前类,以便调用
    • types:定义方法类型

    2、设置原方法实现

    + (void)load {
        NSLog(@"插入成功");
        old_imp = class_getMethodImplementation(objc_getClass("WCAccountLoginControlLogic"), sel_registerName("onFirstViewLogin"));
        method_setImplementation(class_getInstanceMethod(objc_getClass("WCAccountLoginControlLogic"), sel_registerName("onFirstViewLogin")), (IMP)new_method);
    }
    IMP (*old_imp)(id self,SEL _cmd);
    void new_method(id self, SEL _cmd){
        NSLog(@"我来了");
         old_imp(self,_cmd);
    }
    1. class_getMethodImplementation:获取原有方法对应的imp;
    2. method_setImplementation:给原有类的方法设置新的imp指向;
    3. old_imp(self,_cmd):执行保留原类方法实现继续执行原有方法内部指令。

    3、 替换原方法实现

    + (void)load {
        NSLog(@"插入成功");
        old_imp = class_getMethodImplementation(objc_getClass("WCAccountLoginControlLogic"), sel_registerName("onFirstViewLogin"));
        old_imp = class_getMethodImplementation(objc_getClass("WCAccountLoginControlLogic"), sel_registerName("onFirstViewLogin"));
        class_replaceMethod(objc_getClass("WCAccountLoginControlLogic"), sel_registerName("onFirstViewLogin"), (IMP)new_method, "[email protected]:");
    }
    IMP (*old_imp)(id self,SEL _cmd);
    void new_method(id self, SEL _cmd){
        NSLog(@"我来了");
         old_imp(self,_cmd);
    }
    1. 保留原有方法的实现;
    2. 替换原方法的实现,当触发按钮,将调用该函数;
    3. 在新函数中,执行原方法实现。

    以上方法都能完美解决找不到实例方法的问题,点击登录,后打印并跳转到登录页面。

    注意:方法与实现是两个不同的概念,方法是SEL(选择器),实现是IMP具体的函数。方法(SEL)指向实现(IMP)。

    五、实战修改微信步数

    修改微信步数同上,通过替换方法,在微信上传步数时,监听方法,替换上传数据。

    首先介绍一个工具Class-dump:

    该方法利用runtime特性能够提取MachO文件中的信息,并产生原应用对应的所有头文件信息,通过这些信息,能够快速定位目标类,目标方法。下载地址://stevenygard.com/projects/class-dump

    先使用该工具获取.ipa中对应的头文件:

    class-dump -H WeChat -o apph

    目标WeChat.app包中的通用二进制文件,导出头文件到apph文件夹中。如下:

    以上就是WX的所有头文件信息,有属性,有方法,看到上面标注的就是前面通过页面找到的类即方法。 这里可以运行查看微信运动页面,找到相关的方法或属性,进行修改。这里就不运行查看了(害怕封号??)。直接定位到修改步数的类:

    找到类即属性名称,这里就直接替换原有的方法,直接返回相应的步数就行。代码如下:

    + (void)load {
        NSLog(@"插入成功");
        [self modifyWxStep];
    }
    +(void)modifyWxStep{
        //修改微信步数
        Class class = objc_getClass("WCDeviceStepObject");
        SEL select = sel_registerName("m7StepCount");
    
        Method method = class_getInstanceMethod(class, select);
        const char *typeEncoding = method_getTypeEncoding(method);
        NSLog(@"typeEncoding:%s",typeEncoding);
        class_replaceMethod(class, select, (IMP)my_m7StepCount, typeEncoding);
    }
    int my_m7StepCount(id self, SEL _cmd){
        return 56382;
    }

    安装后,停止xcode运行,再手机上启动应用,登录账号并来到微信运动公众账号,查看自己的步数,如果步数没有修改,杀死应用重新进入即可。如下:

  • 科研人员发现新型光合作用 2019-12-05
  • 《进京城》等11部影片入围上影节传媒关注单元 2019-12-05
  • 俄罗斯:解决朝鲜问题已进入中俄制定的"路线图" 2019-11-27
  • 俞正声:推进政协协商民主建设,形成协商议政新局面 2019-11-24
  • 林地旅行地中国国家地理网 2019-11-24
  • 表白戒指不翼而飞 列车长掰开座椅为他“降火” 2019-11-21
  • 粽情粽意 传承文明———我们的节日2018端午节 2019-11-18
  • 安徽3年争取逾百亿资金 确保保障性安居工程建设 2019-11-18
  • 几十架战机起飞后消失,搜寻代价大,美军放弃寻找拿出巨额封口费 2019-11-16
  • 深入贯彻落实党中央治疆方略br坚定不移推进新疆社会稳定和长治久安 2019-11-12
  • 充分发挥人民政协职能优势 2019-11-04
  • 空腹吃荔枝会引发低血糖致死?专家:空腹才是真凶 2019-11-02
  • “通达系”转让丰巢股权 快递终端格局将变 2019-11-02
  • 中国环渤海帆船拉力赛招商发布会在京举行 2019-10-27
  • “一带一路”倡议开辟宗教学研究新境界 2019-10-27
  • 安卓千炮捕鱼破解版 云南十一选五中奖规则 大丰彩票首页 公式规律区论坛 3d开奖组选 购齐鲁风采七乐彩复式金额表 有足球专家推荐的app 新疆35选7开奖结果查询82期 北京十一选五开奖信息 生肖藏宝图