SHELL脚本
shell是一种特殊的交互式工具,它为用户提供了启动程序、管理文件系统中文件以及运行在系统上的进程的途径。Shell一般是指命令行工具。它允许你输入文本命令,然后解释命令,并在内核中执行。
Shell脚本,也就是用各类命令预先放入到一个文本文件中,方便一次性执行的一个脚本文件。
查看shell
在iTerm2中先cd /private/etc
到这个目录下,里面有很多文件,其中就有一个叫shells
文件,查看cat shells
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
Sh:Bourne Shell(即sh)是UNIX最初使用的shell,平且在每种UNIX上都可以使用。Bourne Shell在shell编程方便相当优秀,但在处理与用户的交互方便作得不如其他几种shell。
Bash:Unix shell的一种,在1987年由布莱恩·福克斯为了GNU计划而编写。1989年发布第一个正式版本,原先是计划用在GNU操作系统上,但能运行于大多数类Unix系统的操作系统之上,包括Linux与Mac OS X v10.4都将它作为默认shell,是Bourne Shell的扩展,简称bash,与Bourne Shell完全兼容,并且在Bourne Shell的基础上增加,增强了很多特性。可以提供命令补全,命令编辑和命令历史等功能。它还包含了很多C Shell和Korn Shell中的优点,有灵活和强大的编辑接口,同时又很友好的用户界面。
Csh:C shell 是一个交互式命令解释器和一种命令编程语言,采用的语法类似于 C 编程语言。shell 是交互式地从终端键盘或者是从一个文件来执行命令的。这个 csh 命令调用了 C shell。
Tcsh:tcsh是csh的增强版,并且完全兼容csh。它不但具有csh的全部功能,还具有命令行编辑、拼写校正、可编程字符集、历史纪录、作业控制等功能,以及C语言风格的语法结构。
Ksh:Korn Shell集合了C Shell和Bourne Shell的优点并且和Bourne Shell完全兼容。Linux系统提供了pdksh(ksh的扩展),它支持人物控制,可以在命令行上挂起,后台执行,唤醒或终止程序。
Zsh:是基于ksh开发的,功能更加多,可以自己定制。
脚本执行相关命令
$source FileName
意思:在当前shell环境中读取并执行FileName中的命令
特点:
1、命令可以强行让一个脚本去立即影响当前的环境(一般用于加载配置文件)。
2、命令会强制执行脚本中的全部命令,而忽略文件的权限。$bash FileName
、$zsh FileName
意思:重新建立一个子shell,在子shell中执行脚本里面的句子。$./FileName
意思:读取并执行文件中的命令。但有一个前提,脚本文件需要有可执行权限。
用户、组、权限
Unix和Linux都是多用户、多任务的系统,所以这样的系统里面就拥有了用户、组的概念。那么同样文件的权限也就有相应的所属用户和所属组了。
Unix早期是开源的,后面就开源了。
Linux是开源的,服务器用Linux最多。
Windows的目录结构:
Linux的目录结构:
Linux分了多用户,每个用户有自己的桌面和文档等,每个用户都不相同,并且只能在自己的目录下玩,除非你有超级权限,才能访问别的用户下面的目录,这样就更加安全。
Mac文件属性
改变权限:chmod
文件权限的改变使用chmod命令。设置方法有两种:数字类型改变 和 符号类型改变。
由于文件权限分为:
三种身份: [user][group][other]
三个权限: [read] [write] [execute]
- 数字类型:
各个权限数字对照:r:4 w:2 x:1
如果设置一个文件权限为 [–rwxr-xr-x ]
User : 4+2+1 = 7
Group: 4+0+1 = 5
Other: 4+0+1 = 5
终端命令:$chmod 755 文件名
注意:
这里数字权限采用的是位移枚举。当有多种选项,并且可以叠加的时候,就用位移枚举(1,2,4,8…),这就是位移枚举:
1 0001 2^0 1<<0 往左移0位
2 0010 2^1 1<<1 往左移1位
4 0100 2^2 1<<2 往左移2位
因为位移枚举不同的数叠加的结果也是不相同的,方便一些计算。
- 符号类型:
chmod [u、g、o、a] [+(加入)、-(除去)、=(设置)] [r、w、x] 文件名称
如下:
$chmod +x 123.sh
: 当不写的时候,就是默认给a加,也就是all,即所有用户
$chmod o+x 123.txt
给other增加执行权限
注意:
这里的o+x
必须要连着写
代码注入
脚本自动重签
我们上面了解了shell脚本,下面我们可以利用shell脚本对越狱的APP包,实现自动重新签名。步骤如下:
1、首先新建一个工程,名字随便取,先真机运行,将描述文件装到手机上。
- 如上图,在工程目录下新建一个APP文件夹,并将越狱APP的包放进去。至于为什么要新建APP文件,并且放的是越狱APP的.ipa包,因为
app.sh
里面的脚本是这样写的,如果要改,就需要对应的改脚本内容 - 导入写好的
app.sh
脚本,签名的步骤还是和前面文章中的手动签名一样,只是写成了脚本的方式,脚本内容如下:
# ${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文件的路径WeChat,拿到info.plist中二进制对应的Key
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 判断Frameworks是否有值,有就循环签名,没有就不签
TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
then
for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
do
#签名 "$EXPANDED_CODE_SIGN_IDENTITY" 这个相当于证书名称 "$FRAMEWORK" 这个相当于Frameworks的名称
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
done
fi
#注入 用脚本注入自定义库
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/HankHook.framework/HankHook"
3、- 如上图,在工程的targets的Build Phases里面添加Run Script脚本。
- shell随便用哪个都可以,可以是sh,也可以说zsh,也可以是bash等。
- 注意,这里最好加上
chmod +x app.sh
这句,给app.sh
可执行权限,不然就手动在终端里面给它加上可执行权限。./app.sh
是执行这个脚本的意思,如果路径不对,可以换成这个${SRCROOT}/app.sh
,也是执行这个脚本的意思。
最后运行工程就行。
代码注入
一般修改原始的程序,是利用代码注入的方式,注入代码就会选择利用FrameWork或者Dylib等三方库的方式注入。
应用执行代码,一般会执行下面三个,我们想要应用执行自己的代码,就可以选择第二种方式。
- MachO (改二进制文件)
- Frameworks (加一个三方库)
- 系统库 (不好改)
注入原理:dylb加载machO文件,也就是主程序,里面有一个Load Commands列出来所有要依赖的三方库,列出来的都会去加载,注入就是注入一个我们自己的库到Frameworks中。
Framwork注入
Framwork注入也是最常用的一种,因为它本身就是iOS环境下的。
1、如上图,通过Xcode新建Framwork,然后运行工程,Xcode就将新建的Framwork库安装进入APP包的Framworks文件下。
2、使用工具yololib注入Framwork库路径。终端命令:$yololib(空格)MachO文件路径(空格)库路径
也可以写在刚刚上面的app.sh
的脚本中:
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/HankHook.framework/HankHook"
- 所有的Framwork加载都是由DYLD加载进入内存被执行的
- 注入成功的库路径会写入到MachO文件的LC_LOAD_DYLIB字段中
Dylib注入
1、通过Xcode新建Dylib库(注意:Dylib属于MacOS所以需要修改属性)
如果是Xcode11以下需要将这里选择为iOS Developer
2、添加Target依赖,让Xcode将自定义Dylib文件打包进入APP包。
只有添加了依赖,当运行工程的时候,才会将dylib文件加载到Framworks文件下。
3、使用工具yololib注入Framwork库路径。终端命令:$yololib(空格)MachO文件路径(空格)库路径
也可以写在刚刚上面的app.sh
的脚本中:
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/libHankHook.dylib"
注意:路径和上面用Framework注入的路径不一样了
如果运行的时候报:image not found
所以的machO文件都叫image,所以很有可能是注入的库,没有到APP包的Framworks中去,可以clean一下Xcode,再重新运行,或者重新注入。
如果报这个错误,那么Load Commands中肯定有找不到的这个库,所以它才会去找。