iOS非越狱逆向--代码注入

在iOS逆向过程中代码的注入无非是一个最关键的步骤。只有把你的代码注入到别人的代码中才能实现你想实现的目的,才能算实现了逆向。那么怎么才能将自己的代码注入到别人的ipa 里边的?

代码注入原理

众所周知,iOS app 在打包的过程中将代码全部转换成了 可执行文件 Mach - O 文件,所以说我们直接改源码是万万不可能的(除非你拿到的源码,话说你源码都拿到了你还逆向个?)。那么我们可不可以以第三方 lib 的(之前的博客中可以看到 第三方的 lib 是独立的)方式注入呢?必须可以啊!!

那么怎么才能将第三方的lib 注入目标程序呢?这个我们要从二进制文件的结构说起,Mach-O文件的数据主体可分为三大部分,分别是头部(Header)、加载命令(Load commands)、和最终的数据(Data)。mobileloader会在目标程序启动时,会根据指定的规则检查指定目录是否存在第三方库,如果有,则会通过修改二进制的loadCommands,来把自己注入进所有的app当中,然后加载第三方库。

这样就结束了么?远远不是的,到这里我们只是把自己的动态库注入到了目标程序中,但是我们自己写的代码还没有执行的入口,所以我们还是不能搞事情。我们还需要一个”main”函数来执行我们自己的代码,这个”main”函数在oc里面称为构造函数,只要在函数前声明 “attribute((constructor)) static” 即可,这样我们就能搞事情了。

代码注入的方式

上边讲过了可以通过第三方的lib 来实现代码注入,那么第三方的lib怎么才能实现注入呢?下边来讲两种不同的注入方式:Framework 和 dylib:

一下两种注入的前提是先实现代码的重签名,具体方式可参照:iOS非越狱逆向– ipa重签名

通过 Framework 实现代码注入

  • 创建一个framework 文件 并将这个文件添加引用

创建一个FrameWork文件
创建Framework文件


创建CopyFiles文件

添加 Framework 文件引用 A


导入创建的FrameWork文件, Destination属性 改为FrameWorks

添加 Framework 文件引用 二


  • 在 framework中添加一个要注入的代码
  • 在 + load 方法中实现你需要实现的方法

创建需要注入的代码文件,并在 + load 方法中需要实现的方法
创建需要注入的代码.png



  • 编译之后找到 可行性文件 Mach - O ‘Products –> xxxx.app(show in Finder) – > 显示包内容’
  • 增加 Mach - O 文件的执行权限

chmod +x WeChat (微信为例)

  • 更改 Mach - O 文件 (将自己写的framework 加入到 Mach - O中)
    yololib WeChat Frameworks/自定义Framework文件名.framework/自定义Framework文件名
  • 重新打包 Payload 文件 可以直接压缩重新命名为 .ipa 格式
    zip -ry WeChat.ipa Payload
  • 将ipa 包放到 APP 文件夹中 编译运行 Bingo
  • 通过 dylib 实现代码注入

    其实dylib 的注入方式几乎一样,无非就是创建个lib 然后添加到 targets 里边然后命令行注入,但是使用 dylib 需要设置几个权限属性,因为iOS 现在默认不支持 dylib 了需要手动设置属性。

    • 创建一个 dylib 文件 并将这个文件添加引用

    添加文件的方法参考 FrameWork 的引入的方法

    添加新的 dylib 文件


    • 修改 dulib 的Base SDK 属性和 Signing 属性

    设置Base SDK 属

    设置Base SDK 属性


    设置 Signing 属性

    设置 Signing 属性

    • 编译 执行注入命令

    • 编译之后找到 可行性文件 Mach - O ‘Products –> xxxx.app(show in Finder) – > 显示包内容’

    • 增加 Mach - O 文件的执行权限

      chmod +x WeChat (微信为例)

    • 更改 Mach - O 文件 (将自己写的framework 加入到 Mach - O中)

      yololib WeChat Frameworks/libxxxxx.dylib

    • 编译运行 Bingo

    脚本修改

    为了以后能更方便的执行代码的注入 现将之前的脚本修改下
    想了解之前脚本(代码重签名)的可以参考 iOS非越狱逆向 – ipa 重签名

    
    # ${SRCROOT} 它是工程文件所在的目录
    TEMP_PATH="${SRCROOT}/Temp"
    #资源文件夹
    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
    
    # -------------------在之前脚本后边添加以下脚本--------------------------------
    # 7. 注入我们编写的动态库
    echo "开始注入"
    # 需要注入的动态库的路径 可以固定 也可以自己随工程修改
    INJECT_FRAMEWORK_RELATIVE_PATH="Frameworks/libLinkHook.dylib"
    #
    ## 通过工具实现注入
    yololib "$TARGET_APP_PATH/$APP_BINARY" "$INJECT_FRAMEWORK_RELATIVE_PATH"
    echo "注入完成"
    
    

    特别鸣谢

    *潭州学院 Hank 老师

    猜你喜欢

    转载自blog.csdn.net/AnTianyang/article/details/80337470