# 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
```
.=====__
/==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=