shell技巧4 - nm命令解决AppStore2.5.2被拒问题

简介: 1、前言最近App Store审核被拒,2. 5 Performance: Software Requirements,Guideline 2.5.2 - Performance - Software Requirements,遇到这样的问题,回信问苹果,肯定得不到答案,苹果就是礼貌的回复。

1、前言

最近App Store审核被拒,2. 5 Performance: Software Requirements,Guideline 2.5.2 - Performance - Software Requirements,遇到这样的问题,回信问苹果,肯定得不到答案,苹果就是礼貌的回复。经过一个星期的重复被拒,只能自己找问题,热更新问题,苹果拒审信一直长这样:

....
This code, combined with a remote resource, can facilitate significant changes to your app’s behavior compared to when it was initially reviewed for the App Store. While you may not be using this functionality currently, it has the potential to load private frameworks, private methods, and enable future feature changes. This includes any code which passes arbitrary parameters to dynamic methods such as dlopen(), dlsym(), respondsToSelector:, performSelector:, method_exchangeImplementations(), and running remote scripts in order to change app behavior and/or call SPI, based on the contents of the downloaded script. Even if the remote resource is not intentionally malicious, it could easily be hijacked via a Man In The Middle (MiTM) attack, which can pose a serious security vulnerability to users of your app.
...

从中找到了一些关键点:

 dlopen(), dlsym(), respondsToSelector:, performSelector:, method_exchangeImplementations(),

然后在 「iOS」热更新审核被拒的解决方法 文章中,找到可以打印下第三方的.a文件看看,看有没有 dlopen(), dlsym(),命令行:

nm -u libwechaat.a >> xxx.txt

注:nm -u path:Display only undefined symbols。更多 nm 命令可查看我之前总结的文章 Mac查看文件内容常用的命令小结

2、定位和查到问题

找到了方向,就是利用 nm 命令查到所有第三方的 .a / .framework是否有相关的方法。

但是如果一个一个库用nm命令去查找,效率非常低,而且每一个库的目录不一样,所以,想到用sehll脚本,整个工程遍历全部的文件,查到到库的,然后打印出来!这才是万利的方法啊!!

3、shell 编程

这里思路大家应该也想到,就是遍历目录,一个一个文件判断,问题的关键出来了!就是怎么判断一个文件是不是.a.framework

其实,可以利用 file 打印当前读取的文件的类型,如果是 Mach-O 类型,就是库文件。比如终端执行 file libWeChatSDK.a 会打印如下:

libWeChatSDK.a: Mach-O universal binary with 5 architectures: [i386:current ar archive] [arm64]
libWeChatSDK.a (for architecture i386): current ar archive
libWeChatSDK.a (for architecture armv7):    current ar archive
libWeChatSDK.a (for architecture armv7s):   current ar archive
libWeChatSDK.a (for architecture x86_64):   current ar archive
libWeChatSDK.a (for architecture arm64):    current ar archive

然后用管道 grep 查找 'Mach-O' 关键字,如果存在,就执行 nm -u file_path 查看所有的方法,最后通过 grep -E 'dlopen|method_exchangeImplementations|performSelector|respondsToSelector|dlsym' 查找包含匹配 dlopen method_exchangeImplementations performSelector respondsToSelector dlsym 其中一个关键字就算包含,最后打印出包含的字段和路径。

最后,在终端执行脚本 sh nm_find.sh 就会得到下面的检查结果,非常的方便和高效!

================================================
 Enter project path: /Users/HTC/Desktop/ThirdSDK 
-----------------------------

/Users/HTC/Desktop/ThirdSDK/Adjust/Adjust-4.12.3/AdjustSdk.framework/AdjustSdk
包含字段:
U _dlsym

-----------------------------

/Users/HTC/Desktop/ThirdSDK/Chartboost/Chartboost-v6.0.1/Chartboost.framework/Chartboost
包含字段:
U _method_exchangeImplementations U _dlopen U _dlsym

-----------------------------

/Users/HTC/Desktop/ThirdSDK/Facebook/Facebook/FBSDKCoreKit.framework/FBSDKCoreKit
包含字段:
U _dlopen U _dlsym


-----------------------------

/Users/HTC/Desktop/ThirdSDK/Firebase/Crashlytics/Crashlytics.framework/submit
包含字段:
_class_respondsToSelector _dlsym

img_a0b19b2c0a02501147f7d30d5cddcfd7.png
20180916-nm-show-lists.png

4、源代码

具体的代码,也可参考我的Github代码:

#!/bin/bash

# 定义用到的变量
project_path=""

# 定义读取输入字符的函数
function getProjectPath() {
    # 输出换行,方便查看
    echo "================================================"
    # 监听输入并且赋值给变量
    read -p " Enter project path: " project_path
    # 如果为空值,从新监听
    if test -z "$project_path"; then
        getProjectPath
    else
        read_dir ${project_path}
    fi
}

function read_dir(){
    for file in `ls $1`       #注意此处这是两个反引号,表示运行系统命令
    do
        if [ -d $1"/"$file ]  #注意此处之间一定要加上空格,否则会报错
        then
            read_dir $1"/"$file
        else
            #在此处处理文件即可
            file_path="$1/$file"
            if `file ${file_path} | grep -q 'Mach-O'` ; then
                find_world=$(echo `nm -u ${file_path} | grep -E 'dlopen|method_exchangeImplementations|performSelector|respondsToSelector|dlsym'`)
                # -n 字符串    字符串的长度不为零则为真
                if [ -n "$find_world" ] ; then
                    echo '-----------------------------\n'
                    echo ${file_path}
                    echo '包含字段:'
                    echo ${find_world}
                    echo '\n'
                fi
            fi
        fi
    done
}   

#读取第一个参数
getProjectPath

echo "------- end processing -------"

5、总结

最后,我们把这个脚本输出的全部内容截图,和这些第三方SDK的相关官网链接贴到回信中,告诉苹果审核员,我们应用不存在非法使用热更新 such as dlopen(), dlsym(), respondsToSelector:, performSelector:, method_exchangeImplementations() 等方法,最后苹果就通过了审核!!!

通过 nm 命令和 shell脚本,又让效率提升了n倍,和前面几篇技巧一样,大家应该能感受到shell脚本编程的魅力,希望大家能举一反三,授鱼不如授渔!生活工作中结合 sehll 脚本,提高效率和自动化,珍爱时间不是梦!

后续有更多技巧,会继续给大家分享,期待~

参考


  • 如有疑问,欢迎在评论区一起讨论!
  • 如有不正确的地方,欢迎指导!


注:本文首发于 iHTCboy's blog,如若转载,请注来源

目录
相关文章
|
20天前
|
人工智能 Shell iOS开发
AI Shell:在命令行里“对话” AI ,微软推出将 AI 助手引入命令行的 CLI 工具,打造对话式交互命令行
AI Shell 是一款强大的 CLI 工具,将人工智能直接集成到命令行中,帮助用户提高生产力。AI Shell 支持多种 AI 模型和助手,通过多代理框架提供丰富的功能和灵活的使用模式。
64 7
|
25天前
|
Java Shell Windows
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
37 1
|
2月前
|
Web App开发 网络协议 Linux
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
这篇文章是关于Linux命令的总结,涵盖了从基础操作到网络配置等多个方面的命令及其使用方法。
75 1
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
|
2月前
|
Shell 知识图谱
Shell printf 命令
10月更文挑战第3天
23 1
|
2月前
|
Unix Shell Linux
常见的shell命令
shell常用命令
51 11
|
3月前
|
Shell Linux
Linux shell编程学习笔记82:w命令——一览无余
Linux shell编程学习笔记82:w命令——一览无余
|
3月前
|
Java Shell Windows
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
116 5
|
2月前
|
Shell PHP
Shell echo命令
10月更文挑战第3天
23 0
|
2月前
|
JSON Java Shell
Dockerfile中RUN、CMD、ENTRYPOINT、SHELL命令的区别
理解这些指令的差异和应用场景,有助于构建高效、灵活且易于管理的Docker镜像。在实际应用中,根据需要选择合适的指令,可以有效地控制镜像构建和容器运行的行为。
199 0
|
2月前
|
SQL Shell 数据库
在TDengine容器中创建初始化数据库的Shell命令实例
以上就是在Docker容器环境中部署并初始化TDengine数据库的全过程,希望对你有所帮助。
84 0