When creating a reverse engineering project, how to make the project easier to use and expand, as well as compiler recognition, can greatly improve our daily development efficiency and the quality of the code. This article mainly describes how to create a project project that can be identified by the Xcode compiler when using The Tweak project from Theos, and the common configurations used in the project.

Setting up a reverse environment

www.onezen.cc/2017/09/16/…

Once the environment is set up, create the corresponding Tweak project

Create an Xcode project

Create an Xcode static library project based on the tweak project name you created earlier, then mix tweak with the Xcode project you created

Create a Config Folder (New Group Without Folder) in your Xcode project and put makefiles, corresponding plist files, and control configuration files in this directory. Do not copy them. Then in Xcode, create the corresponding folder, and replace all the generated.xm files with.xmi, and put them in the outermost layer of the project as the only entry class

Set mu.xmi to objective-C ++ in Xcode

Set up the XcodeTheos header file to let the compiler recognize logos syntax, corresponding to the address of the header file: github.com/onezens/Xco… After importing the project, create a global header file and place it in tweake. xmi. The code in the header file is black and not recognized by the compiler. When closing the project and opening it again, Xcode will recognize it again

Then set theXcodeTheosLet Xcode recognize the logos macro

Once all is set up together, start writing the Logos hook code. If all goes well, you will find that Xcode is super smooth in writing the Logos code and that compiling Xcode will indicate success

Synchronize Xcode’s configuration with the Makefile

Modify the build file of the Makefile first and always name it xMI when creating the corresponding logos-syntax file later and write it to the Makefile

WeChatBot_FILES = tweake. xm => Change this parameter to WeChatBot_FILES = tweake. xmiCopy the code

Compiling failed due to a header file reference path problem in the project

➜ WeChatBot git:(master) qualify make > Making all for tweaks 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 2Copy the code

The Makefile contains the directory for the header file

# header file WeChatBot_OBJCFLAGS + = - i. / WeChatBot/Headers/wechatHeaders/WeChatBot_OBJCFLAGS + = - i. / WeChatBot/Headers /Copy the code

If we use the latest version of TheOS, we will find compilation.xmiThe file will contain the following error

➜ WeChatBot git:(master) qualify make > Making all for tweaks WeChatBot... = = > Preprocessing Tweak. Xmi... = = > the 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 2Copy the code

Solutions:

  1. All of the.xmiChange to.xiFile, and import the header file#include <substrate.h>
  2. Using older versions of TheOS:https://github.com/onezens/theos.gitReplace the original version to compile

Resolve compilation warnings that cause errors

➜ WeChatBot git:(master) qualify make > Making all for tweaks WeChatBot... = = > Preprocessing Tweak. Xmi... = = > the 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: the cruse: 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: the cruse: 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 2Copy the code

Solutions:

  1. Lower the version number in the Makefile:TARGET = iphone: 11.2:7.0
  2. Set ignore method expiration warnings in Makefile:
# ignore OC warning WeChatBot_OBJCFLAGS += -wno -deprecated-declarationsCopy the code

Configuration of dynamic and static libraries in the project

System libraries

WeChatBot_LIBRARIES = stdc++ ++Copy the code

Configure the third library

# import the Frameworks of the third party. Dynamic Libraries need to handle WeChatBot_LDFLAGS += -f./Libraries/dynamic -f./Libraries/static # -f./Libraries/dynamic -f./Libraries/static # header file WeChatBot_FRAMEWORKS += WCBFWStatic WCBFWDynamic # import third-party lib WeChatBot_LDFLAGS += -l./Libraries/dynamic -L./Libraries/static # Implement WeChatBot_CFLAGS += -i./Libraries/include # The header file identifies WeChatBot_LIBRARIES += WCBStatic WCBDyLibCopy the code

Corresponding local folder description

Include includes all the.a and.dylib header files. Include includes all the.dylib header files. Include includes all the.dylib header files

Dynamic library problem

When we added the dynamic library to the project, we found that running our tweak plugin would not work in the host APP, and the log message was:

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
Copy the code

It can be seen from this log message that the host is in its own bundle and is not loaded into our dynamic library, so the function of our plug-in is not effective

View the generated dynamic library:

➜ 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, /usr/lib/libobjc.a. dylib (Compatibility version 1.0.0, The current version 228.0.0)/System/Library/Frameworks/Foundation. The framework/Foundation (compatibility version 300.0.0, The 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, The 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, compatibility version 1.0.0) Rpath /libWCBDyLib. Dylib (Compatibility version 0.0.0, The current version 0.0.0)/Library/Frameworks/CydiaSubstrate framework/CydiaSubstrate (compatibility version 0.0.0, The current version 0.0.0)/usr/lib/libSystem B.d ylib (compatibility version 1.0.0, current version 1252.0.0)Copy the code

We found that the tweak project’s dynamic library, whose dependencies are all RPath, is the host’s bundle path, so we need to change this path

The solution, via script, is to change the dynamic library dependency path:

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
Copy the code

Run this script before each package and view the information when the package is complete:

➜ 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, /usr/lib/libobjc.a. dylib (Compatibility version 1.0.0, The current version 228.0.0)/System/Library/Frameworks/Foundation. The framework/Foundation (compatibility version 300.0.0, The 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.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, The current version 0.0.0)/usr/lib/libSystem B.d ylib (compatibility version 1.0.0, current version 1252.0.0)Copy the code

Common command configuration

Simplify common commands to improve daily development efficiency

before-package:: /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 installCopy the code

Common script description

The postinst script is the script that is executed before each DEB package is installed. The Postrm script is the script that is executed after each DEB package is installed

Note: You need to change the execution permissions of these two before packaging

chmod 755 .theos/_/DEBIAN/postinst
chmod 755 .theos/_/DEBIAN/postrm
Copy the code

The script for the related description: iphonedevwiki.net/index.php/P…

Use scenario: Install the plugin in Cydia and display the return button postrm script & remove control’s Depend dependency:

#! /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 0Copy the code

Parameter Description:

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

Import resource files

Map the file to the mobile device through the Layout directory in the root directory of the project, and then read the resource file

#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];
Copy the code

Other Configurations

Makefile

THEOS_DEVICE_IP = localhost THEOS_DEVICE_PORT = 2222 -fobjc-arc # ignore the OC warning, WeChatBot_OBJCFLAGS += -wno -deprecated-declarations -Wno-unused-variableCopy the code

control

Wechatbot Package: cc.onezen. Wechatbot The strate library and the plugin can be deleted if the plugin is needed after cydia installation without restarting the Springboard. iphoneos-arm Description: An awesome MobileSubstrate tweak! Maintainer: wz Author: wz Section: # cydia Tweaks classification Icon in the source: file:///Library/AppSupport/WeChatBot/imgs/wcb_icon.png # IconCopy the code

project

Git address: github.com/onezens/WeC…