عند إنشاء مشروع هندسة عكسية، فإن كيفية جعل المشروع أكثر ملاءمة للاستخدام وسهل التوسع، بالإضافة إلى تحديد المترجم، يمكن أن يؤدي إلى تحسين كفاءة التطوير اليومية وجودة التعليمات البرمجية بشكل كبير. توضح هذه المقالة بشكل أساسي كيفية استخدام مشروع تعديل Theos لإنشاء مشروع يمكن التعرف عليه بواسطة مترجم Xcode، بالإضافة إلى التكوينات شائعة الاستخدام في المشروع.
https://www.onezen.cc/2017/09/16/iosrevert/revdevconfig.html
بعد إعداد البيئة، قم بإنشاء مشروع التعديل المقابل
قم بإنشاء مشروع مكتبة Xcode الثابتة استنادًا إلى اسم مشروع التعديل الذي تم إنشاؤه مسبقًا، ثم قم بدمج القرص ومشروع Xcode الذي تم إنشاؤه معًا.
قم بإنشاء مجلد تكوين (مجموعة جديدة بدون مجلد) في مشروع Xcode، ثم ضع ملف Makefile وملف plist المقابل وملف تكوين التحكم في هذا الدليل دون نسخ. ثم قم بإنشاء المجلد المقابل في Xcode، ثم استبدل جميع لاحقات ملفات .xm
التي تم إنشاؤها بـ .xmi
، ووضعها في الطبقة الخارجية للمشروع كفئة الإدخال الوحيدة
قم بتعيين Tweak.xmi في برنامج التحويل البرمجي Xcode للتعرف على النوع كـ Objective-C++
قم بتعيين ملف رأس XcodeTheos للسماح للمترجم بالتعرف على بناء جملة الشعارات. عنوان ملف الرأس المقابل: https://github.com/onezens/Xcode-Theos. بعد استيراد المشروع، قم بإنشاء ملف رأس عام ووضع الرأس في ملف tweak.xmi
، وجدت أن الكود الموجود بداخله كان أسود ولم يتعرف عليه المترجم. في هذا الوقت، بعد إغلاق المشروع وإعادة فتحه، وجدت أنه سيتم التعرف عليه مرة أخرى بواسطة Xcode.
ثم قم بتعيين ماكرو XcodeTheos
للسماح لـ Xcode بالتعرف على ماكرو الشعارات.
بعد إعداده معًا، ابدأ في كتابة رمز ربط الشعارات، إذا كان كل شيء طبيعيًا، فستجد أن كتابة رمز الشعارات في Xcode أمر سلس للغاية، ويطالبك مترجم Xcode بذلك.
قم أولاً بتعديل ملف التحويل البرمجي الخاص بـ Makefile عند إنشاء ملف باستخدام صيغة الشعارات المقابلة في المستقبل، قم دومًا بتسميته كملف 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
حل:
.xmi
إلى .xi
وقم باستيراد ملف الرأس #include <substrate.h>
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
حل:
TARGET = iphone:11.2:7.0
#忽略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
تضمين جميع ملفات الرأس الخاصة بمكتبات .a و.dylib. يتم وضع جميع مجلدات المكتبة الديناميكية معًا لتسهيل معالجة البرامج النصية الثابتة.
عندما أضفنا المكتبة الديناميكية إلى المشروع، وجدنا أن تشغيل المكون الإضافي الخاص بنا لا يعمل في التطبيق المضيف، وكانت معلومات مطالبة السجل هي:
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
يمكن أن نرى من معلومات السجل أن المضيف موجود في حزمته الخاصة ولم يتم تحميله في مكتبتنا الديناميكية، وبالتالي فإن وظيفة المكون الإضافي الخاص بنا بالكامل لا تصبح سارية المفعول.
عرض المكتبة الديناميكية التي تم إنشاؤها:
➜ 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 1450.14.0)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1450.14.0)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3698.33.6)
@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 1252.0.0)
لقد وجدنا أن المكتبة الديناميكية لمشروع التعديل تعتمد على rpath، وهو مسار الحزمة للمضيف، لذلك نحن بحاجة إلى تغيير هذا المسار.
الحل هو تغيير مسار تبعية المكتبة الديناميكية من خلال برنامج نصي:
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
قبل كل حزمة، قم بتشغيل هذا البرنامج النصي واعرض المعلومات بعد اكتمال الحزمة:
➜ 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 1450.14.0)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1450.14.0)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3698.33.6)
/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 1252.0.0)
تبسيط الأوامر شائعة الاستخدام وتحسين كفاءة التطوير اليومي
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، وعرض البرنامج النصي لزر الرجوع وحذف تبعيات التحكم:
#!/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
قم بتعيين الملف على الجهاز المحمول من خلال دليل التخطيط في الدليل الجذر للمشروع، ثم اقرأ ملف المورد
#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];
#用于编译的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
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
عنوان البوابة: https://github.com/onezens/WeChatBot