Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Tweak 工程创建、配置教程 & 实现logos语法自动补全

License

Notifications You must be signed in to change notification settings

onezens/WeChatBot

Repository files navigation

在创建一个逆向工程项目时,如何让工程使用起来更加便捷和易于扩展,以及编译器识别,能够大大提升我们日常的开发效率以及代码的质量。本文主要描述了,如果使用Theos的tweak工程,创建一个可以被Xcode编译器识别的项目工程,以及工程中常用的配置。

搭建逆向环境

https://www.onezen.cc/2017/09/16/iosrevert/revdevconfig.html

搭建好环境之后,创建对应的tweak工程项目

创建Xcode项目

根据前面创建好的tweak项目名称,创建一个Xcode静态库项目,然后将tweak和创建的Xcode项目混合到一起

在Xcode项目里面创建一个Config文件夹(New Group Without Folder),将Makefile、对应的plist文件、control配置文件,不要copy放到此目录下。 然后在Xcode里面,创建对应的文件夹,然后将生成的.xm文件的后缀名,全部替换为.xmi ,并且放到项目的最外层,作为唯一的入口类

设置Tweak.xmi在Xcode编译器识别类型为Objective-C++

设置XcodeTheos头文件,让编译器识别logos语法,对应的头文件的地址:https://github.com/onezens/Xcode-Theos,导入项目之后,创建一个全局头文件,并且到该头文件放到tweak.xmi里面,发现里面的代码是黑色的,没有被编译器识别,这时候,关闭项目重新打开后发现会被Xcode重新识别了

接着设置XcodeTheos的宏,让Xcode识别logos宏

一起设置好之后,开始写logos的hook代码,一切正常的话,你会发现Xcode写起logos代码超级顺畅,并且编译Xcode提示成功

将Xcode的配置和Makefile进行同步

首先修改Makefile的编译文件 在以后创建对应的logos语法的文件时,始终命名为xmi文件,并且写入Makefile里面

WeChatBot_FILES = Tweak.xm
=> 修改为:
WeChatBot_FILES = Tweak.xmi

在项目中头文件引用路径问题,导致编译失败

➜ WeChatBot git:(master) ✗ make
> Making all for tweak WeChatBot...
==> Preprocessing Tweak.xmi...
Tweak.xmi:2:9: fatal error: 'wechatbot-prefix-header.h' file not found
#import "wechatbot-prefix-header.h"
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
make[3]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/armv7/Tweak.mii] Error 1
make[2]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/armv7/WeChatBot.dylib] Error 2
make[1]: *** [internal-library-all_] Error 2
make: *** [WeChatBot.all.tweak.variables] Error 2

发现是头文件,引入的原因,Makefile里面设置头文件目录

#头文件
WeChatBot_OBJCFLAGS += -I./WeChatBot/Headers/wechatHeaders/ 
WeChatBot_OBJCFLAGS += -I./WeChatBot/Headers/

如果使用最新版的theos,我们会发现编译.xmi 文件会包下面的错误

➜ WeChatBot git:(master) ✗ make
> Making all for tweak WeChatBot...
==> Preprocessing Tweak.xmi...
==> Compiling Tweak.xmi (arm64)...
Tweak.xmi:18:104: error: use of undeclared identifier 'MSHookMessageEx'
{Class _logos_class$_ungrouped$MicroMessengerAppDelegate = objc_getClass("MicroMessengerAppDelegate"); MSHookMessageEx(_logos_class$_ungro...
 ^
1 error generated.
make[3]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/Tweak.xmi.ca6fefe9.o] Error 1
make[2]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/WeChatBot.dylib] Error 2
make[1]: *** [internal-library-all_] Error 2
make: *** [WeChatBot.all.tweak.variables] Error 2

解决办法:

  1. 将所有的.xmi更改为.xi文件, 并且导入头文件 #include <substrate.h>
  2. 使用老版本的theos: https://github.com/onezens/theos.git 替换原版进行编译

解决编译警告,导致报错的问题

➜ WeChatBot git:(master) ✗ make
> Making all for tweak WeChatBot...
==> Preprocessing Tweak.xmi...
==> Compiling Tweak.xmi (arm64)...
Tweak.xmi:8:4: error: 'UIAlertView' is deprecated: first deprecated in iOS 9.0 - UIAlertView is deprecated. Use UIAlertController with a preferredStyle
 of UIAlertControllerStyleAlert instead [-Werror,-Wdeprecated-declarations]
 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Works for hook" message:__null delegate:__null cancelButtonTitle:@"cancel" otherBu...
 ^
/opt/theos/sdks/iPhoneOS11.2.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAlertView.h:26:12: note: 'UIAlertView' has been explicitly marked
 deprecated here
@interface UIAlertView : UIView
 ^
Tweak.xmi:8:27: error: 'UIAlertView' is deprecated: first deprecated in iOS 9.0 - UIAlertView is deprecated. Use UIAlertController with a
 preferredStyle of UIAlertControllerStyleAlert instead [-Werror,-Wdeprecated-declarations]
 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Works for hook" message:__null delegate:__null cancelButtonTitle:@"cancel" otherBu...
 ^
/opt/theos/sdks/iPhoneOS11.2.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAlertView.h:26:12: note: 'UIAlertView' has been explicitly marked
 deprecated here
@interface UIAlertView : UIView
 ^
2 errors generated.
make[3]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/Tweak.xmi.6c3ff448.o] Error 1
make[2]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/WeChatBot.dylib] Error 2
make[1]: *** [internal-library-all_] Error 2
make: *** [WeChatBot.all.tweak.variables] Error 2

解决办法:

  1. 将Makefile里面的版本号降低:TARGET = iphone:11.2:7.0
  2. Makefile里面设置忽略方法过期警告:
#忽略OC警告
WeChatBot_OBJCFLAGS += -Wno-deprecated-declarations

项目中动态和静态库的配置

系统库

#导入系统的frameworks
WeChatBot_FRAMEWORKS = Foundation UIKit
#导入系统库
WeChatBot_LIBRARIES = stdc++ c++

配置第三库

#导入第三方Frameworks, 动态库需特殊处理
WeChatBot_LDFLAGS += -F./Libraries/dynamic -F./Libraries/static # 识别的库实现
WeChatBot_CFLAGS += -F./Libraries/dynamic -F./Libraries/static # 头文件识别
WeChatBot_FRAMEWORKS += WCBFWStatic WCBFWDynamic
#导入第三方lib
WeChatBot_LDFLAGS += -L./Libraries/dynamic -L./Libraries/static 	# 识别的库实现
WeChatBot_CFLAGS += -I./Libraries/include 						# 头文件识别
WeChatBot_LIBRARIES += WCBStatic WCBDyLib 

对应的本地文件夹说明

include 放置所有的.a和.dylib库的头文件 dynamic 放置所有的动态库的文件夹,动态库放一起,方便脚本处理 static 防止所有的静态库的文件夹

动态库问题

当我们把,动态库加入的项目中,我们发现运行我们的tweak插件,在宿主APP中不起作用,通过log提示信息为:

Apr 9 15:55:28 wz5 WeChat[5329] <Error>: MS:Error: dlopen(/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib, 9): Library not loaded: @rpath/WCBFWDynamic.framework/WCBFWDynamic
	 Referenced from: /Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib
	 Reason: image not found

该日志信息中可以看出,宿主在自己的bundle里面,没有加载到我们的动态库,所以导致我们整个插件的功能不生效

查看生成的动态库:

➜ WeChatBot git:(master) ✗ otool -L .theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib
.theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib:
	/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1450140)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1450140)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3698336)
	@rpath/WCBFWDynamic.framework/WCBFWDynamic (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)
	@rpath/libWCBDyLib.dylib (compatibility version 0.0.0, current version 0.0.0)
	/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125200)

我们发现tweak项目的动态库,依赖都是rpath,是宿主的bundle路径,所以我们要更改这个路径

解决办法,通过脚本,更改动态库依赖路径:

TWEAK_NAME=WeChatBot
cydiaLibPath=/Library/MobileSubstrate/DynamicLibraries/$TWEAK_NAME
dylibPath=Libraries/dynamic
oriDylibPath=$dylibPath/ori
tweakLayoutPath=layout$cydiaLibPath
echo $tweakLayoutPath
if [[ ! -d $oriDylibPath ]]; then
	mkdir $oriDylibPath
fi
if [[ ! -d $tweakLayoutPath ]]; then
	mkdir $tweakLayoutPath
fi
checkDylibID() {
	path=1ドル
	libFullPath=2ドル
	ckLibId=$(otool -L $path | grep rpath)
	if [[ -n $ckLibId ]]; then
		cp -r $libFullPath $oriDylibPath
		ckLibId=${ckLibId%' ('*}
		ckLibId=${ckLibId#*/}
		install_name_tool -id $cydiaLibPath/$ckLibId $path
		otool -L $path
	fi
	cp -r $libFullPath $tweakLayoutPath
}
for file in $dylibPath/*; do
	if [[ $file =~ ".dylib" ]]; then
		checkDylibID $file $file
	elif [[ $file =~ ".framework" ]]; then
		name=${file##*/}
		name=${name%.*}
		checkDylibID $file/$name $file
	fi
done

在每次package之前,运行此脚本,打包完成后查看信息:

➜ WeChatBot git:(master) ✗ otool -L .theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib
.theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib:
	/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1450140)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1450140)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3698336)
	/Library/MobileSubstrate/DynamicLibraries/WeChatBot/WCBFWDynamic.framework/WCBFWDynamic (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)
	/Library/MobileSubstrate/DynamicLibraries/WeChatBot/libWCBDyLib.dylib (compatibility version 0.0.0, current version 0.0.0)
	/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125200)

常用的编译命令配置

简化常用命令,提高日常开发效率

before-package::
	sh bin/check_dynamic_lib.sh #动态库处理脚本
	cp ./bin/postinst .theos/_/DEBIAN/
	cp ./bin/postrm .theos/_/DEBIAN/
	chmod 755 .theos/_/DEBIAN/postinst
	chmod 755 .theos/_/DEBIAN/postrm
after-install::
	install.exec "killall -9 SpringBoard"
p::
	make package
c::
	make clean
i::
	make
	make p
	make install

常用的脚本说明

postinst 脚本是每次deb包安装之前执行的脚本 postrm 脚本是每次deb包安装完成后执行的脚本

注意:打包前需要修改这两个的执行权限

chmod 755 .theos/_/DEBIAN/postinst
chmod 755 .theos/_/DEBIAN/postrm

相关的脚本描述:http://iphonedevwiki.net/index.php/Packaging

应用场景:在Cydia中安装插件,并且显示返回按钮 postrm脚本 & 删除control的depend依赖:

#!/bin/bash
declare -a cydia
cydia=($CYDIA)
if [[ ${CYDIA+@} ]]; then
 eval "echo 'finish:open' >&${cydia[0]}"
else
 echo "uninstall wk completed!"
 echo ""
fi
killall -9 WeChat
exit 0

参数说明:

Acceptable parameters for finish
# return - normal behaviour (return to cydia)
# reopen - exit cydia
# restart - reload springboard
# reload - reload springboard
# reboot - reboot device

资源文件的导入

通过项目根目录中的layout目录,映射文件到手机设备当中,然后读取资源文件

#define kWCBImgSrcPath @"/Library/AppSupport/WeChatBot/imgs"
UIImage *img = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/wcb_icon.png", kWCBImgSrcPath]];
NSLog(@"[WeChatBot] img: %@", img);
UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
[imgView sizeToFit];
imgView.center = CGPointMake(46, 60);
[self.window addSubview:imgView];

其他配置说明

Makefile

#用于编译的SDK和支持的ios最低版本
TARGET = iphone:11.2:9.0
#用于调试的设备地址
THEOS_DEVICE_IP = localhost
THEOS_DEVICE_PORT = 2222
# 打包命名不一样,正式包不会输出log等
DEBUG = 1
# 采用ARC内存管理
WeChatBot_CFLAGS = -fobjc-arc
#忽略OC警告,避免警告导致编译不过
WeChatBot_OBJCFLAGS += -Wno-deprecated-declarations -Wno-unused-variable

control

Package: cc.onezen.wechatbot #包名
Name: WeChatBot
Depends: mobilesubstrate #依赖库和依赖插件,如果需要插件在cydia安装后不重启springboard可以删掉,否则每次重新
Version: 0.0.1
Architecture: iphoneos-arm
Description: An awesome MobileSubstrate tweak!
Maintainer: wz
Author: wz
Section: Tweaks #cydia源中的分类
Icon: file:///Library/AppSupport/WeChatBot/imgs/wcb_icon.png #icon

项目

git 地址: https://github.com/onezens/WeChatBot

About

Tweak 工程创建、配置教程 & 实现logos语法自动补全

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

AltStyle によって変換されたページ (->オリジナル) /