zoukankan      html  css  js  c++  java
  • 代码注入及其拓展--逆向开发

    今天继续讲述逆向开发中另一个比较重要的课程是代码注入内容,本篇篇幅比较长,但还是有很多干货的,希望大家通过此篇文章更加了解逆向开发中的要点和知识点.我们将分解几个内容,进行讲解:

    1. Framework注入
    2. Dylib注入
    3. MethodSwizzle
    4. 微信示例讲解
    5. 总结

    让代码执行自己的代码,整体方案如下:

    如何让别人的app来执行自己的代码呢? 这就要通过代码注入的方式来达到,而代码注入的方式有两种: 一种是通过framework, 一种是dylib方式,另种方案,可以通过Runtime机制

    代码注入思路:

    DYLD会动态加载动态库Framework中所有动态库,在frameworks中加入自己的一个动态库,然后在动态库中hook和注入代码.

    一、FrameWork注入

     1.准备工作

    • 微信6.6.5(越狱应用)
    • MachOView软件

      MachOView的下载地址:http://sourceforge.net/projects/machoview/

      如果想看源码如下:MachOView源码:https://github.com/gdbinit/MachOView

    • yololib工具(给MachOView注入framework)

      yololib工具下载地址:https://github.com/KJCracks/yololib?spm=a2c4e.11153940.blogcont63256.9.5126420eAJpqBD

    • 签名文件appsign文件

    2.流程

    2.1 加入准备工作,导入微信6.6.5版本以及脚本appSign.sh重签名文件

    2.2 将appSign导入到项目脚本中

     2.3 有了上面的两个步骤后,然后编译一下工程,会出现一个temp工程,里面包含了payload文件

    2.4 显示包内容,查看可执行文件

     2.5 我们通过MachOView软件查看WeChat

    我们看到有很多的DYLIB,代表的是加载动态库

    2.6  我们在项目中新建framework

    2.7 新建文件用于验证

    2.8 想要达到刚加载就运行,代码要写在load方法

     2.9 编译一下,查看app包位置会多出一个framework

    2.10 显示包内容,在framework查看

    由上可知,WJHookFrameWork已经加入成功。

    2.11 但是运行并没有成功,没有执行load里的代码

    原因:用MachOView打开可执行的WeChat,没有找到WJHookFrameWork

    下面我们讲述怎么将WJHookFramework写入到MachoView文件中?

    3. WJHookFramework写入到MachOView文件中

    需要使用yololib工具,建议将yololib放到 /usr/local/bin

    3.1 解压越狱包

    3.2 将WeChat.app显示包内容,找到WeChat可执行的文件

    需要增加执行权限: chmod +x WeChat

    3.3 写入WeChat可执行文件

    yololib WeChat Frameworks/WJHookFrameWork.framework/WJHookFrameWork

    通过上面的过程,查看MachOView文件Load commands中是否有WJHookFrameWork

    上面图显示已经加入成功。

    3.4 删除原有的ipa,打包payload

    zip -ry WeChat.ipa Payload

    将WeChat.ipa放入App目录中,删除其他的文件夹。

    3.5 再次运行,发现成功!!!

    上面就是framework方式代码注入。大家可以私信我,如有不懂!!!

     二、Dylib注入

    2.1 新建工程,添加脚本到build phases 


    加入脚本文件

    2.2添加第三方库dylib(mac os的,非ios)

    2.3 添加依赖

    2.4 修改第三方类库仅限mac使用,修改Base SDK

    2.5 修改signing 

    2.6 脚本中注入动态库的代码

    # ${SRCROOT} 它是工程文件所在的目录
    TEMP_PATH="${SRCROOT}/Temp"
    #资源文件夹,我们提前在工程目录下新建一个APP文件夹,里面放ipa包
    ASSETS_PATH="${SRCROOT}/APP"
    #目标ipa包路径
    TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
    #清空Temp文件夹
    rm -rf "${SRCROOT}/Temp"
    mkdir -p "${SRCROOT}/Temp"
    
    #----------------------------------------
    # 1. 解压IPA到Temp下
    unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
    # 拿到解压的临时的APP的路径
    TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
    # echo "路径是:$TEMP_APP_PATH"
    
    #----------------------------------------
    # 2. 将解压出来的.app拷贝进入工程下
    # BUILT_PRODUCTS_DIR 工程生成的APP包的路径
    # TARGET_NAME target名称
    TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
    echo "app路径:$TARGET_APP_PATH"
    
    rm -rf "$TARGET_APP_PATH"
    mkdir -p "$TARGET_APP_PATH"
    cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH"
    
    #----------------------------------------
    # 3. 删除extension和WatchAPP.个人证书没法签名Extention
    rm -rf "$TARGET_APP_PATH/PlugIns"
    rm -rf "$TARGET_APP_PATH/Watch"
    
    #----------------------------------------
    # 4. 更新info.plist文件 CFBundleIdentifier
    #  设置:"Set : KEY Value" "目标文件路径"
    /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
    
    #----------------------------------------
    # 5. 给MachO文件上执行权限
    # 拿到MachO文件的路径
    APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d>|cut -f1 -d<`
    #上可执行权限
    chmod +x "$TARGET_APP_PATH/$APP_BINARY"
    
    #----------------------------------------
    # 6. 重签名第三方 FrameWorks
    TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
    if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
    then
    for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
    do
    
    #签名
    /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
    done
    fi
    
    #注入
    yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/libHankHook.dylib"

    2.7 编译运行成功(也和上面一样在类中加入load代码)

    上面就是dylib方式代码注入,希望对大家有所帮助!!!

     通过上面的两种方式实现代码注入,让别人的app运行自己的app,下面总结如下:

     三、MethodSwizzle

    3.1 概念

    iOS 中实现AOP编程思想的方式其中之一是Method Swizzling,而 Method Swizzling 是利用Runtime特性把一个方法和另个方法的实现做替换,程序运行时修改Dispatch Table里SEL和IMP之间的映射关系.

    通过swizzling method改变目标函数selector所指向实现,在新的实现中来实现所要改的内容即可.

    3.2 特点

    • 继承: 修改较多,无法敢保证他人一定继承基类
    • 类别: 类别中重写方法会覆盖到原有的实现,其实,在真实的开发中,重写方法并不是为了取代它,而是为了添加一些实现; 如果几个类别实现了同样的方法, 但只有一个类别的方法会被调用.
    • AOP优势: 减少了重复代码

    3.3 代码

    @implementation NSURL (HKURL)
    
    +(void)load
    {
        Method URLWithStr = class_getClassMethod(self, @selector(URLWithString:));
        
        Method HKURL = class_getClassMethod(self, @selector(HKURLWithStr:));
        
        //交换
        method_exchangeImplementations(URLWithStr, HKURL);
    }
    
    +(instancetype)HKURLWithStr:(NSString *)str{
        //调用系统原来的方法
        NSURL * url = [NSURL HKURLWithStr:str];
        if (url == nil) {
            str = @"https://www.blog.com";
        }
        url = [NSURL HKURLWithStr:str];
        
        return url;
    }

    在上面的代码中,利用method swizzling的交换方法.其他Runtime的使用方法,以及为什么写在load方法中,请参考本人另篇博客https://www.cnblogs.com/guohai-stronger/p/9184356.html

    拓展: 为什么写在load中?

    • load方法在源文件被装载到程序中会被自动调用,不需要手动调用,也不需要该类使用不使用无关,在main()前被执行.
    • 当子类重写了load,假如子类的类别重写了load,load的调用顺序会这样: 父类、子类、子类类别
    • 但是如果有多个子类category都重写了load,每个子类category中load都会调用一次
    • 假如子类没有重写load,子类的默认load也不会去调用父类的load.此与正常继承不太一样.
    • 在正常的开发中, 除了method swizzle ,其他的逻辑代码尽量不放在load,load方法中的代码逻辑要尽量简单

    四、微信示例Demo

    4.1 微信--破坏注册

    4.1.1 将微信程序运行出来,如下图所示

    4.1.2 根据上面红色找出类名,方法名

    4.1.3 通过插件class-dump导出微信的.h文件

    class-dump是将OC运行时声明的信息导出来的工具, 其实可以导出.h文件. 用此工具将未经过加密的app的头文件导出来.

    使用它同样也要讲此工具拷贝到MAC的目录下/usr/local/bin下.

    4.1.4 经过sublime text来找出对应的文件

    4.1.5 通过第三部分讲解,利用runtime交换方法

    4.1.6 结果

    4.2 窃取微信密码

    4.2.1 找到输入密码框的内容

    从上面看出,登录按钮为一个FixTitleColorButton对象,Target名字存放的地址为0x280afaa40,Action名字存放地址是0x280afac00。

    4.2.2 查看账号密码的输入框

    发现账号密码输入框对象属于都一个对象,叫做WCUITextField

    4.2.3 利用LLDB查看登录具体的Target和Action

    从上面卡出,登录按钮在WCAccountMainLoginViewController页面中;

    登录点击方法叫做onNext

    4.2.4 利用Sublime查看WeChat文件

    发现确实有onNext()方法,并从中看出账号输入框和密码输入框都是WCAccountTextFieldItem中,但是并没有发现textFileld,但是可以看到WCAccountTextFieldItem是继承于WCBaseTextFieldItem,我们再看看WCBaseTextFieldItem文件内容

    看出一个m_textField对象,通过tex字段取出string。

    4.2.5 在账号栏中输入账号和密码

    po [(WCAccountMainLoginViewController *)0x1128bbc00 valueForKey:@"_textFieldUserPwdItem"]
    po [(WCAccountTextFieldItem *)0x28328e880 valueForKey:@"m_textField"]
    po [(WCUITextField *)0x112163a00 text]

    通过LLDB调试输入的密码是123456。

    4.2.6 Hook登录,获取密码

    + (void)load {
        NSLog(@"来了,老弟");
        Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), sel_registerName("onNext"));
        //1.保存原始的IMP
        old_onNext = method_getImplementation(onNext);
        //2.SET
        method_setImplementation(onNext, (IMP)my_next);
    }
    
    IMP (*old_onNext)(id self,SEL _cmd);
    
    void my_next(id self,SEL _cmd){
        // 获取密码
        NSString *pwd = [[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"] performSelector:@selector(text)];
        NSString *accountTF = [[[self valueForKey:@"_textFieldUserNameItem"] valueForKey:@"m_textField"] performSelector:@selector(text)];
        NSLog(@"密码是!%@",pwd);
        // 将密码追加在账号栏的后面
        [[[self valueForKey:@"_textFieldUserNameItem"] valueForKey:@"m_textField"] performSelector:@selector(setText:) withObject:[NSString stringWithFormat:@"%@+%@",accountTF,pwd]];
        //调用原来的方法
        old_onNext(self,_cmd);
    }

    上面用的是setIMP和getIMP的方式,对原方法进行Hook,也可以用class_replaceMethod(),method_exchangeImplementations()。

    五、总结

    首先从代码注入的方式:framework和dylib两种方式,然后讲到Method swizzling方式尝试Hook,最后又以demo的方式来阐述代码注入和Hook,希望对大家理解逆向开发的代码注入有所帮助!!!,欢迎大家继续关注!!!

  • 相关阅读:
    socket
    RBAC
    CMOS和BIOS
    canvas和SVG
    兼容IE,chrome,ff的设为首页、加入收藏及保存到桌面
    HTML标签marquee实现滚动效果
    百度判断手机终端并自动跳转uaredirect.js代码及使用实例
    JavaScript中常用的事件
    解决windows server 2008 r2 登录进入桌面只显示一片蓝色背景
    ng2自定义管道
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/11857012.html
Copyright © 2011-2022 走看看