其他工程引用monkey dev的动态库dylib用法

我们可能会经常使用monkey dev来进行逆向,操作基本是创建一个monkey dev工程并且写好自己的hook代码后,放入target app,此时便可以直接编译使用了。但也存在我们想改用以类似于sdk的形式集成到其他业务工程代码内,则需要做下特殊处理。以下会介绍下这个操作流程

步骤一:生成动态库(双架构)

此步骤是针对monkey dev的工程

release 编译

monkey dev工程本身包含一个编译target app的工程和一个编译动态库的工程,我们可以选中编译动态库的target,使用release编译出一个双架构包。

debug 编译

或者我们也可以修改编译选项中的architectures中的build active architecture only,将其改为NO,这样debug时候就会编译出双架构包了

值得注意的是,用debug编译时会把cycript和RevealServer的依赖也加进去,这时候实际使用也需要有这个依赖。这里暂未试验

因为debug的other linker flag内容如下

$(inherited) -weak_library /usr/lib/libc++.dylib -weak_library /usr/lib/libstdc++.dylib -weak_library $(MonkeyDevPath)/Frameworks/libsubstrate.dylib -lcycript -framework RevealServer

步骤二:修改动态库依赖

首先我们可以查看动态库依赖,使用otool命令,一下篇幅都以libMyDylib.dylib作为我们生成的dylib

otool -L libMyDylib.dylib

内容如下

libMyDylib.dylib (architecture armv7):
	@executable_path/Frameworks/libMyDylib.dylib/libMyDylib.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	@executable_path/Frameworks/libsubstrate.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
	/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 606.2.104)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1560.10.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1560.10.0)
	/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 1245.9.2)
	/System/Library/Frameworks/ImageIO.framework/ImageIO (compatibility version 1.0.0, current version 0.0.0)
	/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.11.0)
	/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.20.0)
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
libMyDylib.dylib (architecture arm64):
	@executable_path/Frameworks/libMyDylib.dylib/libMyDylib.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	@executable_path/Frameworks/libsubstrate.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
	/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 606.2.104)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1560.10.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1560.10.0)
	/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 1245.9.2)
	/System/Library/Frameworks/ImageIO.framework/ImageIO (compatibility version 1.0.0, current version 0.0.0)
	/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.11.0)
	/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.20.0)
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)

发现动态库对自身的依赖有些问题,如果直接编译则可能会报错

dyld: Library not loaded: @executable_path/Frameworks/libMyDylib.dylib/libMyDylib.dylib
  Referenced from: /var/containers/Bundle/Application/931E314D-61F3-4F37-B9E8-99695BE08C66/Laputa.app/Laputa
  Reason: image not found

这时候我们需要修改动态库的依赖,使用install_name_tool命令

install_name_tool [-id name] input 修改对自身的依赖

install_name_tool [-change old new] input 修改对第三方库的依赖


如:

install_name_tool -id  @executable_path/Frameworks/libMyDylib.dylib libMyDylib.dylib

这样就把动态库对自身的依赖修改正确了,@executable_path为mach-o文件夹的路径

可以看到动态库对@executable_path/Frameworks/libsubstrate.dylib有依赖,所以我们也需要将libsubstrate.dylib放到frameworks目录下

步骤三:动态库导入工程,修改编译选项并重签名

此步骤是针对我们的业务工程。

可以直接把自己的动态库和libsubstrate.dylib放入到工程中,然后在other linker flags中增加命令

-force_load ${SRCROOT}/CapMock/libMyDylib.dylib

让工程强制加载我们的动态库,因为动态库本身只有在使用时候才会加载

执行完上述命令后,再使用otool查看我们编译好的业务app的可执行文件,发现多了下面的依赖,说明当业务app跑起来时会加载下面的动态库

@executable_path/Frameworks/libMyDylib.dylib

但是这样做了以后大概率会报错

Library not loaded: [...] Reason: no suitable image found.

因为动态库不是系统动态库,如果我们不把它放入到mach-o中,是没有地方可以找到该动态库的,所以我们需要修改编译脚本,将其加入到@executable_path/Frameworks/目录下

在build phases中增加run script即可,主要含义是将动态库拷贝到mach-o中的frameworks目录下并重签名

rm -rf $BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/libMyDylib.dylib
rm -rf $BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/libsubstrate.dylib

if [[ "${CONFIGURATION}" == "Debug" ||  "${CONFIGURATION}" == "DailyBuild" ]]; then
echo "begin copy my dylibs into product"
cp -R $PROJECT_DIR/CapMock/libMyDylib.dylib $BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH
cp -R $PROJECT_DIR/CapMock/libsubstrate.dylib $BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH

if [ "${CODE_SIGNING_REQUIRED:-}" != "NO" ]; then
/usr/bin/codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY}" "$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/libMyDylib.dylib"
/usr/bin/codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY}" "$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/libsubstrate.dylib"
fi
fi

至此,大功告成!!!

附run script其中一些环境变量

BUILT_PRODUCTS_DIR --- 最终编译的文件路径
FRAMEWORKS_FOLDER_PATH --- framework存放路径

EXPANDED_CODE_SIGN_IDENTITY --- code sign identity

CODE_SIGNING_REQUIRED --- 是否需要签名

CONFIGURATION --- 是Debug还是DailyBuild或Release

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券