# Cydia
**Repository Path**: ugle/Cydia
## Basic Information
- **Project Name**: Cydia
- **Description**: 🔥🔥🔥我的微信公众号: Cydia 🔥🔥🔥=> Cydia插件 Logos语言 开发Tweak.xm Cydia Substrate 注入dylib iOS逆向工程开发 越狱Jailbreak deb插件 - fishhook / Frida / iOSOpenDev / Cycript / MachOView /  IDA / Hopper Disassembler / MonkeyDev / Class-dump / Theos / Reveal / Dumpdecryptd / FLEX / 汇编Assembly / CaptainHook / lldb/LLVM/XNU/Darwin/iOS Reverse
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2022-09-21
- **Last Updated**: 2022-09-21
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# iOS逆向工程越狱开发教程  
# [iOS逆向请加QQ群号: 751433362]
# iOS Jailbreak Develop/hook/Reverse
# 我的微信公众号: Cydia
 # 我的私人公众号: XLsn0w
# 我的私人公众号: XLsn0w
 
 ```
                                               .=====__
                                           /==Z' .===_ ~~=,_===\
                                         _/  |   |    YZ, `\,   ~\
                                         |   |   | _/=j'\   !,   d
                                  __====_|   |   b/    V`;  /'  .M ,
                          `5\==/~~       W,  t   d+,  .D4| /   /'|/~~~\=__     .-
                           `\            t~\ |   |t`~~T/'|Z  :/  |        ~~\=/V
                             \           |  \4,  | ~/~' :Z  -!   |             |
                              \,      /\__|   \\.!     :XG   \   / ._,       ./'
                               `L    |    ~;    V;  _//' |    \ .f~' `~;    .b_
                              ./ \\__JL    `;    Y7~     |    / /     d   //'  \,
                             .!       `D\,  `\,   |     .!   .t/    .(_/=~      \
                             /         `;`~~~=+=qLb,   jK_L==f'    j''          `;
                           ./          .(r,        `~\5'   ~\\,._r/              |
                        ~=m!         ./D' `\,          \,     !G~                 t
                           ~==___===/'/   .!`\__       /! __=~\\~=_                TG=
                                     |   .|     ~\=\=r@/~5 \   !,  ~=_,        __//'
                                     |./~V           ||  `| \,  t     ~~~~\==~~
                                     t|  |           | |  |  !\, \=_,
                                     !   t          .! !, \    `\/~~~
                                         |          /   !\/\
                                         `;       ./      `~-
                                          t      .!
                                           N,  ./'
                                            `\/'
```
## -----------------------------------
## -----------------------------------
iOS动态库注入工具:cynject、yololib、insert_dylib、optool、install_name_tool
## Cycript
cycript是大神saurik开发的一个非常强大的工具,
可以让开发者在命令行下和应用交互,在运行时查看和修改应用。
底层实现: 是通过苹果的JavaScriptCore.framework来打通iOS与javascript的桥梁(OC和JS互相调用)
## -----------------------------------
## install_name_tool 注入动态库 使用说明
     (1)@executable_path。这个path很少用,本质上就是可执行程序的路径。在动态库中基本上不使用这个path.
      (2) @loader_path。这个path在之前的应用中用的非常多,可以通过这个path来设置动态库的install path name。
      但是它有自己的局限性,就是当一个动态库同时被多个程序引用时,如果位置不一样的话仍然需要手动修改。这个在参考链接中有说明。  
      (3) @rpath  它是run path的缩写。本质上它不是一个明确的path,甚至可以说它不是一个path。
      它只是一个变量,或者叫占位符。这个变量通过XCode中的run path选项设置值,或者通过install_name_tool的-add_rpath设置值。
      设置好run path之后,所有的@rpath都会被替换掉。此外,run path是可以设置多个值的
      
```
INSTALL_NAME_TOOL(1)					      General Commands Manual					      INSTALL_NAME_TOOL(1)
NAME
       install_name_tool - change dynamic shared library install names
SYNOPSIS
       install_name_tool [-change old new ] ... [-rpath old new ] ... [-add_rpath new ] ... [-delete_rpath new ] ... [-id name] file
DESCRIPTION
       Install_name_tool  changes the dynamic shared library install names and or adds, changes or deletes the rpaths recorded in a Mach-O binary.
       For this tool to work when the install names or rpaths are larger the binary should be built with  the  ld(1)  -headerpad_max_install_names
       option.
       -change old new
	      Changes  the dependent shared library install name old to new in the specified Mach-O binary.  More than one of these options can be
	      specified.  If the Mach-O binary does not contain the old install name in a specified -change option the option is ignored.
       -id name
	      Changes the shared library identification name of a dynamic shared library to name.  If the Mach-O binary is not	a  dynamic  shared
	      library and the -id option is specified it is ignored.
       -rpath old new
	      Changes  the  rpath  path  name old to new in the specified Mach-O binary.  More than one of these options can be specified.  If the
	      Mach-O binary does not contain the old rpath path name in a specified -rpath it is an error.
       -add_rpath new
	      Adds the rpath path name new in the specified Mach-O binary.  More than one of these options can be specified.  If the Mach-O binary
	      already contains the new rpath path name specified in -add_rpath it is an error.
       -delete_rpath old
	      deletes  the  rpath  path  name old in the specified Mach-O binary.  More than one of these options can be specified.  If the Mach-O
	      binary does not contains the old rpath path name specified in -delete_rpath it is an error.
```
## 基于cynject注入dylib
```
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
extern char ***_NSGetEnviron(void);
extern int proc_listallpids(void *, int);
extern int proc_pidpath(int, void *, uint32_t);
static const char *cynject_path = "/usr/bin/cynject";
static const char *dispatch_queue_name = NULL;
static int process_buffer_size = 4096;
static pid_t process_pid = -1;
static boolean_t find_process(const char *name, pid_t *ppid_ret) {
    pid_t *pid_buffer;
    char path_buffer[MAXPATHLEN];
    int count, i, ret;
    boolean_t res = FALSE;
    
    pid_buffer = (pid_t *)calloc(1, process_buffer_size);
    assert(pid_buffer != NULL);
    
    count = proc_listallpids(pid_buffer, process_buffer_size);
    if (count) {
        for (i = 0; i < count; i++) {
            pid_t ppid = pid_buffer[i];
            
            ret = proc_pidpath(ppid, (void *)path_buffer, sizeof(path_buffer));
            if (ret < 0) {
                printf("(%s:%d) proc_pidinfo() call failed.\n", __FILE__, __LINE__);
                continue;
            }
            
            if (strstr(path_buffer, name)) {
                res = TRUE;
                *ppid_ret = ppid;
                break;
            }
        }
    }
    
    free(pid_buffer);
    return res;
}
static void inject_dylib(const char *name, pid_t pid, const char *dylib) {
    char **argv;
    char pid_buf[32];
    int res;
    pid_t child;
    
    argv = calloc(4, sizeof(char *));
    assert(argv != NULL);
    
    snprintf(pid_buf, sizeof(pid_buf), "%d", pid);
    
    argv[0] = (char *)name;
    argv[1] = (char *)pid_buf;
    argv[2] = (char *)dylib;
    argv[3] = NULL;
    
    printf("(%s:%d) calling \"%s %s %s\"\n", __FILE__, __LINE__, argv[0], argv[1], argv[2]);
    
    res = posix_spawn(&child, argv[0], NULL, NULL, argv, (char * const *)_NSGetEnviron());
    assert(res == 0);
    
    return;
}
int main(int argc, char *argv[]) {
    printf("***** pp_inject by piaoyun ***** \n");
    if (geteuid() != 0) {
        printf("FATAL: must be run as root.\n");
        return 1;
    }
    
    if (argc < 3 ) {
        printf("FATAL: ppinject  .\n");
        return 2;
    }
    
    const char *process_name = argv[1];
    const char *dylib_path = argv[2];
    
    
    printf("Creating queue...\n");
    dispatch_queue_t queue = dispatch_queue_create(dispatch_queue_name, 0);
    
    printf("Finding %s PID...\n", process_name);
    dispatch_async(queue, ^{ while (!find_process(process_name, &process_pid)); });
    
    printf("Waiting for queue to come back...\n");
    dispatch_sync(queue, ^{});
    
    printf("%s PID is %d\n", process_name, process_pid);
    
    printf("Injecting %s into %s...\n", dylib_path, process_name);
    inject_dylib(cynject_path, process_pid, dylib_path);
    
    return 0;
}
```
## Mach-O注入/删除动态库 insert_dylib  optool
如果要让现成的App,执行自己的代码可以通过注入动态库,
静态的注入可以使用optool工具修改MachO的Load Commands然后重签,
动态运行时可以使用dlopen   或    Bundle(path: "**.bundle").load()加载
```
通过 otool -L命令查看你生成的.dylib文件
otool -L ioswechatselectall.dylib
查看CPU框架
lipo -archs ioswechatselectall.dylib
首先要找到libsubstrate.dylib文件,该文件应该在/opt/thoes/lib/目录下,然后将其拷贝到与你生成的的.dylib一个目录下,通过下面的指令修改依赖,
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/libsubstrate.dylib wx.dylib
添加可执行文件的依赖
此处用的是insert_dylib 下载地址在https://github.com/Tyilo/insert_dylib
编译后,将其与其他两个文件拷贝到同一目录下
然后将其插入到执行文件中
1.将wx.dylib 和libsubstrate.dylib拷贝进你的WeChat.app 
2.记住要把WeChat_patched的名字改回来WeChat
@executable_path是一个环境变量,指的是二进制文件所在的路径
insert_dylib命令格式: ./insert_dylib 动态库路径 目标二进制文件
//注入动态库
./insert_dylib @executable_path/ioswechatselectall.dylib WeChat 
./yololib  Wechat wxhbts.dylib
//打包成ipa 
xcrun -sdk iphoneos PackageApplication -v WeChat.app -o `pwd`/WeChat.ipa
注入神器optool
编译获取
因为 optool 添加了 submodule,因为需要使用 --recuresive 选项,将子模块全部 clone 下来
git clone --recursive https://github.com/alexzielenski/optool.git
cd optool
xcodebuild -project optool.xcodeproj -configuration Release ARCHS="i386 x86_64" build
使用 optool 把 wx.dylib 注入到二进制文件中
./optool install -c load -p "@executable_path/wx.dylib" -t WeChat
codesign签名dylib
errSecInternalComponent 错误
在Mac终端上运行codesign命令,并“始终允许” /usr/bin/codesign访问密钥
security unlock-keychain login.keychain
解锁命令移至,~/.bash_profile以便在SSH客户端启动时对钥匙串进行解锁
AppleWWDRCAG3 不收信任证书
获取证书
security find-identity -v -p codesigning 
签名Dylib 
codesign -f -s B3C14FC452E835C09B70D5C24961EBAFC0A2C4B9 hook.dylib 
ldid -S dumpdecrypted.dylib
1.安装 Xcode 
2.安装 Command Line Tools 
xcode-select --install 
codesign --force --deep --sign - /xxx/xxx.app 
签名错误 resource fork, Finder information, or similar detritus not allowed 
解决方法 xattr -lr  
查看 xattr -cr  删除 
或者 find . -type f -name '*.jpeg' -exec xattr -c {} \; find . -type f -name '*.png' -exec xattr -c {} \; 
find . -type f -name '*.tif' -exec xattr -c {} \; 
整个App签名 codesign -fs "授权证书" --no-strict --entitlements=生成的plist文件 WeChat.app 
验证Dylib签名 codesign –verify hook.dylib codesign -vv -d WeChat.app
Xcode升级到8.3后 用命令进行打包 提示下面这个错误
后面根据对比发现新版的Xcode少了这个PackageApplication  (QQ群下载)
先去找个旧版的Xcode里面copy一份过来
放到下面这个目录:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/
然后执行命令
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer/
chmod +x /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication
theos
ARCHS = armv7 armv7s arm64
TARGET = iphone:8.4:7.0
#指定路径,否则默认在 /Library/MobileSubstrate/DynamicLibraries
LOCAL_INSTALL_PATH = /usr/bin
include theos/makefiles/common.mk
TWEAK_NAME = oooo
oooo_FILES = oooo.xm
#指定版本
_THEOS_TARGET_LDFLAGS += -current_version 1.0
_THEOS_TARGET_LDFLAGS += -compatibility_version 1.0
#tweak2.mk是我修改过的,去掉了CydiaSubstrate链接,因为这个dylib用不到
include $(THEOS_MAKE_PATH)/tweak2.mk
-current_version、-compatibility_version参数参考自苹果官方!!
https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/CreatingDynamicLibraries.html
theos编译不越狱可用的dylib
SUBSTRATE ?= yes
instance_USE_SUBSTRATE = $(SUBSTRATE)
把上面的instance替换成你的TweakName
在上面的这个例子中就是XXXX 
include _USE_SUBSTRATE = no,请转换为使用include _LOGOS_DEFAULT_GENERATOR = internal
编译:make SUBSTRATE=no
编译DEB:make SUBSTRATE=no package
编译DEB并安装:make SUBSTRATE=no package  install
```
## 打包deb
```
find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch
echo .DS_Store >> ~/.gitignore
xcode-select --install 
sudo xcodebuild -license    手动输入 agree
安装 Macports ,网址:http://www.macports.org/install.php
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
sudo port -f install dpkg
dpkg 降级
brew remove dpkg  
HOMEBREW_NO_AUTO_UPDATE=1 brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/7a4dabfc1a2acd9f01a1670fde4f0094c4fb6ffa/Formula/dpkg.rb
brew pin dpkg 
$ brew remove dpkg  
# remove latest dpkg 
$ brew install --force-bottle https://raw.githubusercontent.com/Homebrew/homebrew-core/7a4dabfc1a2acd9f01a1670fde4f0094c4fb6ffa/Formula/dpkg.rb  
# install dpkg as a bottle from the old commit 
$ brew pin dpkg  
# block homebrew from updating dpkg till you `brew unpin dpkg`
postinst写法(直接复制)(权限755)
#!/bin/bash
mkdir -p /private/var/mobile/Documents/
chown -R mobile:mobile /private/var/mobile/Documents/
/bin/su -c uicache mobile
cd Desktop
sudo chmod -R 755 *
dpkg-deb -Z gzip -b ./{标识符} 
dpkg-deb -Z xz -b ./{标识符}
mac 解包 打包
dpkg-deb -x ./abc.deb ./tmp
dpkg-deb -e ./abc.deb ./tmp/DEBIAN
dpkg-deb -b ./tmp false8.deb
解包.sh
#!/bin/sh
dpkg-deb -x ./a.deb ./a
dpkg-deb -e ./a.deb ./a/DEBIAN
chmod -R 755 ./a/DEBIAN
打包.sh
#!/bin/sh
find . -name '*.DS_Store' -type f -delete
dpkg-deb -Z lzma -b ./a b.deb
```
### optool神器就是命令行注入
```
optool install -c load -p "@executable_path/RedEnvelop.dylib" -t WeChat
//这就是给WeChat加载抢红包插件
//如果要unstall,要这样:
optool uninstall -p "@executable_path/RedEnvelop.dylib" -t WeChat
//具体 dylib 的路径可以用 otool 查看:
otool -L WeChat
```
```
使用方法:
  install -c  -p  -t  [-o=
```
                                               .=====__
                                           /==Z' .===_ ~~=,_===\
                                         _/  |   |    YZ, `\,   ~\
                                         |   |   | _/=j'\   !,   d
                                  __====_|   |   b/    V`;  /'  .M ,
                          `5\==/~~       W,  t   d+,  .D4| /   /'|/~~~\=__     .-
                           `\            t~\ |   |t`~~T/'|Z  :/  |        ~~\=/V
                             \           |  \4,  | ~/~' :Z  -!   |             |
                              \,      /\__|   \\.!     :XG   \   / ._,       ./'
                               `L    |    ~;    V;  _//' |    \ .f~' `~;    .b_
                              ./ \\__JL    `;    Y7~     |    / /     d   //'  \,
                             .!       `D\,  `\,   |     .!   .t/    .(_/=~      \
                             /         `;`~~~=+=qLb,   jK_L==f'    j''          `;
                           ./          .(r,        `~\5'   ~\\,._r/              |
                        ~=m!         ./D' `\,          \,     !G~                 t
                           ~==___===/'/   .!`\__       /! __=~\\~=_                TG=
                                     |   .|     ~\=\=r@/~5 \   !,  ~=_,        __//'
                                     |./~V           ||  `| \,  t     ~~~~\==~~
                                     t|  |           | |  |  !\, \=_,
                                     !   t          .! !, \    `\/~~~
                                         |          /   !\/\
                                         `;       ./      `~-
                                          t      .!
                                           N,  ./'
                                            `\/'
```
## -----------------------------------
## -----------------------------------
iOS动态库注入工具:cynject、yololib、insert_dylib、optool、install_name_tool
## Cycript
cycript是大神saurik开发的一个非常强大的工具,
可以让开发者在命令行下和应用交互,在运行时查看和修改应用。
底层实现: 是通过苹果的JavaScriptCore.framework来打通iOS与javascript的桥梁(OC和JS互相调用)
## -----------------------------------
## install_name_tool 注入动态库 使用说明
     (1)@executable_path。这个path很少用,本质上就是可执行程序的路径。在动态库中基本上不使用这个path.
      (2) @loader_path。这个path在之前的应用中用的非常多,可以通过这个path来设置动态库的install path name。
      但是它有自己的局限性,就是当一个动态库同时被多个程序引用时,如果位置不一样的话仍然需要手动修改。这个在参考链接中有说明。  
      (3) @rpath  它是run path的缩写。本质上它不是一个明确的path,甚至可以说它不是一个path。
      它只是一个变量,或者叫占位符。这个变量通过XCode中的run path选项设置值,或者通过install_name_tool的-add_rpath设置值。
      设置好run path之后,所有的@rpath都会被替换掉。此外,run path是可以设置多个值的
      
```
INSTALL_NAME_TOOL(1)					      General Commands Manual					      INSTALL_NAME_TOOL(1)
NAME
       install_name_tool - change dynamic shared library install names
SYNOPSIS
       install_name_tool [-change old new ] ... [-rpath old new ] ... [-add_rpath new ] ... [-delete_rpath new ] ... [-id name] file
DESCRIPTION
       Install_name_tool  changes the dynamic shared library install names and or adds, changes or deletes the rpaths recorded in a Mach-O binary.
       For this tool to work when the install names or rpaths are larger the binary should be built with  the  ld(1)  -headerpad_max_install_names
       option.
       -change old new
	      Changes  the dependent shared library install name old to new in the specified Mach-O binary.  More than one of these options can be
	      specified.  If the Mach-O binary does not contain the old install name in a specified -change option the option is ignored.
       -id name
	      Changes the shared library identification name of a dynamic shared library to name.  If the Mach-O binary is not	a  dynamic  shared
	      library and the -id option is specified it is ignored.
       -rpath old new
	      Changes  the  rpath  path  name old to new in the specified Mach-O binary.  More than one of these options can be specified.  If the
	      Mach-O binary does not contain the old rpath path name in a specified -rpath it is an error.
       -add_rpath new
	      Adds the rpath path name new in the specified Mach-O binary.  More than one of these options can be specified.  If the Mach-O binary
	      already contains the new rpath path name specified in -add_rpath it is an error.
       -delete_rpath old
	      deletes  the  rpath  path  name old in the specified Mach-O binary.  More than one of these options can be specified.  If the Mach-O
	      binary does not contains the old rpath path name specified in -delete_rpath it is an error.
```
## 基于cynject注入dylib
```
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
extern char ***_NSGetEnviron(void);
extern int proc_listallpids(void *, int);
extern int proc_pidpath(int, void *, uint32_t);
static const char *cynject_path = "/usr/bin/cynject";
static const char *dispatch_queue_name = NULL;
static int process_buffer_size = 4096;
static pid_t process_pid = -1;
static boolean_t find_process(const char *name, pid_t *ppid_ret) {
    pid_t *pid_buffer;
    char path_buffer[MAXPATHLEN];
    int count, i, ret;
    boolean_t res = FALSE;
    
    pid_buffer = (pid_t *)calloc(1, process_buffer_size);
    assert(pid_buffer != NULL);
    
    count = proc_listallpids(pid_buffer, process_buffer_size);
    if (count) {
        for (i = 0; i < count; i++) {
            pid_t ppid = pid_buffer[i];
            
            ret = proc_pidpath(ppid, (void *)path_buffer, sizeof(path_buffer));
            if (ret < 0) {
                printf("(%s:%d) proc_pidinfo() call failed.\n", __FILE__, __LINE__);
                continue;
            }
            
            if (strstr(path_buffer, name)) {
                res = TRUE;
                *ppid_ret = ppid;
                break;
            }
        }
    }
    
    free(pid_buffer);
    return res;
}
static void inject_dylib(const char *name, pid_t pid, const char *dylib) {
    char **argv;
    char pid_buf[32];
    int res;
    pid_t child;
    
    argv = calloc(4, sizeof(char *));
    assert(argv != NULL);
    
    snprintf(pid_buf, sizeof(pid_buf), "%d", pid);
    
    argv[0] = (char *)name;
    argv[1] = (char *)pid_buf;
    argv[2] = (char *)dylib;
    argv[3] = NULL;
    
    printf("(%s:%d) calling \"%s %s %s\"\n", __FILE__, __LINE__, argv[0], argv[1], argv[2]);
    
    res = posix_spawn(&child, argv[0], NULL, NULL, argv, (char * const *)_NSGetEnviron());
    assert(res == 0);
    
    return;
}
int main(int argc, char *argv[]) {
    printf("***** pp_inject by piaoyun ***** \n");
    if (geteuid() != 0) {
        printf("FATAL: must be run as root.\n");
        return 1;
    }
    
    if (argc < 3 ) {
        printf("FATAL: ppinject  .\n");
        return 2;
    }
    
    const char *process_name = argv[1];
    const char *dylib_path = argv[2];
    
    
    printf("Creating queue...\n");
    dispatch_queue_t queue = dispatch_queue_create(dispatch_queue_name, 0);
    
    printf("Finding %s PID...\n", process_name);
    dispatch_async(queue, ^{ while (!find_process(process_name, &process_pid)); });
    
    printf("Waiting for queue to come back...\n");
    dispatch_sync(queue, ^{});
    
    printf("%s PID is %d\n", process_name, process_pid);
    
    printf("Injecting %s into %s...\n", dylib_path, process_name);
    inject_dylib(cynject_path, process_pid, dylib_path);
    
    return 0;
}
```
## Mach-O注入/删除动态库 insert_dylib  optool
如果要让现成的App,执行自己的代码可以通过注入动态库,
静态的注入可以使用optool工具修改MachO的Load Commands然后重签,
动态运行时可以使用dlopen   或    Bundle(path: "**.bundle").load()加载
```
通过 otool -L命令查看你生成的.dylib文件
otool -L ioswechatselectall.dylib
查看CPU框架
lipo -archs ioswechatselectall.dylib
首先要找到libsubstrate.dylib文件,该文件应该在/opt/thoes/lib/目录下,然后将其拷贝到与你生成的的.dylib一个目录下,通过下面的指令修改依赖,
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/libsubstrate.dylib wx.dylib
添加可执行文件的依赖
此处用的是insert_dylib 下载地址在https://github.com/Tyilo/insert_dylib
编译后,将其与其他两个文件拷贝到同一目录下
然后将其插入到执行文件中
1.将wx.dylib 和libsubstrate.dylib拷贝进你的WeChat.app 
2.记住要把WeChat_patched的名字改回来WeChat
@executable_path是一个环境变量,指的是二进制文件所在的路径
insert_dylib命令格式: ./insert_dylib 动态库路径 目标二进制文件
//注入动态库
./insert_dylib @executable_path/ioswechatselectall.dylib WeChat 
./yololib  Wechat wxhbts.dylib
//打包成ipa 
xcrun -sdk iphoneos PackageApplication -v WeChat.app -o `pwd`/WeChat.ipa
注入神器optool
编译获取
因为 optool 添加了 submodule,因为需要使用 --recuresive 选项,将子模块全部 clone 下来
git clone --recursive https://github.com/alexzielenski/optool.git
cd optool
xcodebuild -project optool.xcodeproj -configuration Release ARCHS="i386 x86_64" build
使用 optool 把 wx.dylib 注入到二进制文件中
./optool install -c load -p "@executable_path/wx.dylib" -t WeChat
codesign签名dylib
errSecInternalComponent 错误
在Mac终端上运行codesign命令,并“始终允许” /usr/bin/codesign访问密钥
security unlock-keychain login.keychain
解锁命令移至,~/.bash_profile以便在SSH客户端启动时对钥匙串进行解锁
AppleWWDRCAG3 不收信任证书
获取证书
security find-identity -v -p codesigning 
签名Dylib 
codesign -f -s B3C14FC452E835C09B70D5C24961EBAFC0A2C4B9 hook.dylib 
ldid -S dumpdecrypted.dylib
1.安装 Xcode 
2.安装 Command Line Tools 
xcode-select --install 
codesign --force --deep --sign - /xxx/xxx.app 
签名错误 resource fork, Finder information, or similar detritus not allowed 
解决方法 xattr -lr  
查看 xattr -cr  删除 
或者 find . -type f -name '*.jpeg' -exec xattr -c {} \; find . -type f -name '*.png' -exec xattr -c {} \; 
find . -type f -name '*.tif' -exec xattr -c {} \; 
整个App签名 codesign -fs "授权证书" --no-strict --entitlements=生成的plist文件 WeChat.app 
验证Dylib签名 codesign –verify hook.dylib codesign -vv -d WeChat.app
Xcode升级到8.3后 用命令进行打包 提示下面这个错误
后面根据对比发现新版的Xcode少了这个PackageApplication  (QQ群下载)
先去找个旧版的Xcode里面copy一份过来
放到下面这个目录:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/
然后执行命令
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer/
chmod +x /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication
theos
ARCHS = armv7 armv7s arm64
TARGET = iphone:8.4:7.0
#指定路径,否则默认在 /Library/MobileSubstrate/DynamicLibraries
LOCAL_INSTALL_PATH = /usr/bin
include theos/makefiles/common.mk
TWEAK_NAME = oooo
oooo_FILES = oooo.xm
#指定版本
_THEOS_TARGET_LDFLAGS += -current_version 1.0
_THEOS_TARGET_LDFLAGS += -compatibility_version 1.0
#tweak2.mk是我修改过的,去掉了CydiaSubstrate链接,因为这个dylib用不到
include $(THEOS_MAKE_PATH)/tweak2.mk
-current_version、-compatibility_version参数参考自苹果官方!!
https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/CreatingDynamicLibraries.html
theos编译不越狱可用的dylib
SUBSTRATE ?= yes
instance_USE_SUBSTRATE = $(SUBSTRATE)
把上面的instance替换成你的TweakName
在上面的这个例子中就是XXXX 
include _USE_SUBSTRATE = no,请转换为使用include _LOGOS_DEFAULT_GENERATOR = internal
编译:make SUBSTRATE=no
编译DEB:make SUBSTRATE=no package
编译DEB并安装:make SUBSTRATE=no package  install
```
## 打包deb
```
find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch
echo .DS_Store >> ~/.gitignore
xcode-select --install 
sudo xcodebuild -license    手动输入 agree
安装 Macports ,网址:http://www.macports.org/install.php
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
sudo port -f install dpkg
dpkg 降级
brew remove dpkg  
HOMEBREW_NO_AUTO_UPDATE=1 brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/7a4dabfc1a2acd9f01a1670fde4f0094c4fb6ffa/Formula/dpkg.rb
brew pin dpkg 
$ brew remove dpkg  
# remove latest dpkg 
$ brew install --force-bottle https://raw.githubusercontent.com/Homebrew/homebrew-core/7a4dabfc1a2acd9f01a1670fde4f0094c4fb6ffa/Formula/dpkg.rb  
# install dpkg as a bottle from the old commit 
$ brew pin dpkg  
# block homebrew from updating dpkg till you `brew unpin dpkg`
postinst写法(直接复制)(权限755)
#!/bin/bash
mkdir -p /private/var/mobile/Documents/
chown -R mobile:mobile /private/var/mobile/Documents/
/bin/su -c uicache mobile
cd Desktop
sudo chmod -R 755 *
dpkg-deb -Z gzip -b ./{标识符} 
dpkg-deb -Z xz -b ./{标识符}
mac 解包 打包
dpkg-deb -x ./abc.deb ./tmp
dpkg-deb -e ./abc.deb ./tmp/DEBIAN
dpkg-deb -b ./tmp false8.deb
解包.sh
#!/bin/sh
dpkg-deb -x ./a.deb ./a
dpkg-deb -e ./a.deb ./a/DEBIAN
chmod -R 755 ./a/DEBIAN
打包.sh
#!/bin/sh
find . -name '*.DS_Store' -type f -delete
dpkg-deb -Z lzma -b ./a b.deb
```
### optool神器就是命令行注入
```
optool install -c load -p "@executable_path/RedEnvelop.dylib" -t WeChat
//这就是给WeChat加载抢红包插件
//如果要unstall,要这样:
optool uninstall -p "@executable_path/RedEnvelop.dylib" -t WeChat
//具体 dylib 的路径可以用 otool 查看:
otool -L WeChat
```
```
使用方法:
  install -c  -p  -t  [-o=