前言
本篇文章繼續(xù)討論App的安全防護
的原理塌碌,主要講解關于動態(tài)調試
的防護。我們知道旬盯,App可以被lldb
動態(tài)調試台妆,因為App被設備中的debugserver
附加進程翎猛,它會跟蹤我們的應用進程(trace process)
,我們可以利用這點接剩,動態(tài)的修改App進程中的數(shù)據(jù)切厘,達到我們想要的結果,而這一過程利用的就是ptrace
函數(shù)懊缺。
一疫稿、ptrace防護
接著上篇文章26-越獄防護的末尾,我們知道????
-
ptrace(process trace)
其實是系統(tǒng)內核函數(shù)
鹃两,系統(tǒng)提供一個進程監(jiān)察和控制
另一個進程遗座,并且還能讀取和修改
被控制的進程的內存和寄存器
里的數(shù)據(jù),因此它可以決定應用能否被debugserver
附加俊扳。 - 如果我們在項目中途蒋,調用
ptrace
函數(shù),將程序設置為拒絕附加
拣度,即可對lldb動態(tài)調試
進行有效的防護
碎绎。
1.1 防護代碼示例
- 搭建App項目
antiDebug
- 導入
MyPtraceHeader.h
頭文件????
/*
* Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
/*-
* Copyright (c) 1984, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ptrace.h 8.2 (Berkeley) 1/4/94
*/
#ifndef _SYS_PTRACE_H_
#define _SYS_PTRACE_H_
#include <sys/appleapiopts.h>
#include <sys/cdefs.h>
enum {
ePtAttachDeprecated __deprecated_enum_msg("PT_ATTACH is deprecated. See PT_ATTACHEXC") = 10
};
#define PT_TRACE_ME 0 /* child declares it's being traced */
#define PT_READ_I 1 /* read word in child's I space */
#define PT_READ_D 2 /* read word in child's D space */
#define PT_READ_U 3 /* read word in child's user structure */
#define PT_WRITE_I 4 /* write word in child's I space */
#define PT_WRITE_D 5 /* write word in child's D space */
#define PT_WRITE_U 6 /* write word in child's user structure */
#define PT_CONTINUE 7 /* continue the child */
#define PT_KILL 8 /* kill the child process */
#define PT_STEP 9 /* single step the child */
#define PT_ATTACH ePtAttachDeprecated /* trace some running process */
#define PT_DETACH 11 /* stop tracing a process */
#define PT_SIGEXC 12 /* signals as exceptions for current_proc */
#define PT_THUPDATE 13 /* signal for thread# */
#define PT_ATTACHEXC 14 /* attach to running process with signal exception */
#define PT_FORCEQUOTA 30 /* Enforce quota for root */
#define PT_DENY_ATTACH 31
#define PT_FIRSTMACH 32 /* for machine-specific requests */
__BEGIN_DECLS
int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
__END_DECLS
#endif /* !_SYS_PTRACE_H_ */
- 打開ViewController.m文件,寫入以下代碼????
#import "ViewController.h"
#import "MyPtraceHeader.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ptrace(PT_DENY_ATTACH, 0, 0, 0);
}
@end
- Xcode運行項目抗果,啟動后立即退出筋帖。使用
ptrace
設置為拒絕附加
,只能手動啟動
App冤馏。
也就是說日麸,用戶在使用App
時一切正常,不會有任何影響逮光。一旦被debugserver
附加代箭,就會閃退
。
越獄情況
以上是非越獄
手機涕刚,如果在越獄
機上進行debugserver
附加呢嗡综?
- 找到
antiDebug
進程????
ps -A | grep antiDebug
-
手動
對App進行debugserver
附加
debugserver localhost:12346 -a 15289
-------------------------
debugserver-@(#)PROGRAM:LLDB PROJECT:lldb-900.3.87
for arm64.
Attaching to process 15289...
Segmentation fault: 11
附加失敗,無論以何種方式杜漠,都會被ptrace
函數(shù)阻止极景。
1.2 破解ptrace 防護
ptrace
是系統(tǒng)內核函數(shù)
,被開發(fā)者所熟知
驾茴。ptrace
的防護痕跡也很明顯
???? 手動
運行程序正常
盼樟,Xcode
運行程序閃退
。
因此锈至,我們在逆向
一款App
時晨缴,遇到上述情況,第一時間就會想到ptrace防護
峡捡。那么怎么破解這個呢击碗?
- 從MachO符號角度思考筑悴,由于
ptrace
是系統(tǒng)函數(shù),需要間接符號表
延都,我們可以試探性的下一個ptrace的符號斷點
????
- 運行雷猪,
ptrace
的斷點命中????
上圖驗證了我們的想法,現(xiàn)在確定了對方的防護手段晰房,想要破解并非難事。
- 針對
antiDebug
項目射沟,模擬應用重簽名殊者,注入動態(tài)庫
- 創(chuàng)建
Inject
動態(tài)庫,創(chuàng)建InjectCode類
- 在
Inject
動態(tài)庫中验夯,導入fishhook
猖吴,導入MyPtraceHeader.h
頭文件 - 打開
InjectCode.m
文件,寫入以下代碼????
#import "InjectCode.h"
#import "MyPtraceHeader.h"
#import "fishhook.h"
@implementation InjectCode
+(void)load{
struct rebinding reb;
reb.name="ptrace";
reb.replacement=my_ptrace;
reb.replaced=(void *)&sys_ptrace;
struct rebinding rebs[]={reb};
rebind_symbols(rebs, 1);
}
int (*sys_ptrace)(int _request, pid_t _pid, caddr_t _addr, int _data);
int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){
if(_request==PT_DENY_ATTACH){
return 0;
}
return sys_ptrace(_request, _pid, _addr, _data);
}
@end
在ptrace_my
函數(shù)中挥转,如果是PT_DENY_ATTACH
枚舉值海蔽,直接return返回
。如果是其他類型绑谣,系統(tǒng)有特定的作用党窜,需要執(zhí)行ptrace原始函數(shù)
。
- 運行項目借宵,進入lldb動態(tài)調試幌衣,
ptrace
破解成功!??????????
二壤玫、sysctl
由于系統(tǒng)并沒有公開ptrace
函數(shù)豁护,使用的時候需額外手動引入頭文件
,該頭文件還不是系統(tǒng)公開的欲间,這點就比較麻煩楚里,那有沒有別的函數(shù)可以直接使用進行防護呢?當然有猎贴,接下來班缎,介紹另一個系統(tǒng)內核函數(shù)sysctl
。
2.1 sysctl定義
首先來看看該函數(shù)的定義 ????
??注意:使用前需引入系統(tǒng)的頭文件 ????
#import <sys/sysctl.h>
int sysctl(int *, u_int, void *, size_t *, void *, size_t);
明顯可見有6個參數(shù)嘱能,分別如下????
- 查詢信息的數(shù)組吝梅,給它的指針
- 數(shù)組中元素的數(shù)據(jù)類型的大小
- 接收信息結構體的指針
- 接收信息結構體的大小的指針
- 第5個和第6個參數(shù) ???? 直接寫
0
就行
接下來我們來解釋下這幾個參數(shù)具體的含義。
第一個參數(shù)int *
因為是int *
類型惹骂,所以該數(shù)組的元素是int類型
苏携,代表字節(jié)碼
的意思,存儲的就是調用方需要查詢的信息
对粪。例如可以這么寫????
int name[4];//里面放字節(jié)碼右冻。查詢的信息
name[0] = CTL_KERN;//內核查詢
name[1] = KERN_PROC;//查詢進程
name[2] = KERN_PROC_PID;//傳遞的參數(shù)是進程的ID
name[3] = getpid();//PID的值
第二個參數(shù)u_int
u_int
是無符號整型装蓬,可以這么計算 ???? sizeof(name)/sizeof(*name)
第三個參數(shù)void *
代表一個接收信息的結構體指針,一般使用kinfo_proc
結構體????
struct kinfo_proc {
struct extern_proc kp_proc; /* proc structure */
struct eproc {
struct proc *e_paddr; /* address of proc */
struct session *e_sess; /* session pointer */
struct _pcred e_pcred; /* process credentials */
struct _ucred e_ucred; /* current credentials */
struct vmspace e_vm; /* address space */
pid_t e_ppid; /* parent process id */
pid_t e_pgid; /* process group id */
short e_jobc; /* job control counter */
dev_t e_tdev; /* controlling tty dev */
pid_t e_tpgid; /* tty process group id */
struct session *e_tsess; /* tty session pointer */
#define WMESGLEN 7
char e_wmesg[WMESGLEN + 1]; /* wchan message */
segsz_t e_xsize; /* text size */
short e_xrssize; /* text rss */
short e_xccount; /* text references */
short e_xswrss;
int32_t e_flag;
#define EPROC_CTTY 0x01 /* controlling tty vnode active */
#define EPROC_SLEADER 0x02 /* session leader */
#define COMAPT_MAXLOGNAME 12
char e_login[COMAPT_MAXLOGNAME]; /* short setlogin() name */
int32_t e_spare[4];
} kp_eproc;
};
其中纱扭,我們需要重點關注一個flag
參數(shù)牍帚,在extern_proc
結構體中????
有哪些定義呢?往下翻到155行????
上圖紅框處的P_TRACED
乳蛾,看注釋就知道暗赶,是debug調試跟蹤進程信息的,這個就是我們想要的肃叶。而且它的值是0x800
蹂随,其它的類似0x100,0x200因惭,0x400
岳锁,一看就知道是按照byte(位)
定義的枚舉
類型,可以多種狀態(tài)疊加蹦魔。
使用的時候采用&與操作符
激率。例如????
struct kinfo_proc info;//接受查詢結果的結構體
(info.kp_proc.p_flag & P_TRACED) != 0 //判斷結果中是否包含了P_TRACED狀態(tài),即當前App是否正在被第三方動態(tài)調試
第四個參數(shù)size_t *
size_t info_size = sizeof(info);
??注意:是
size_t *
勿决,所以使用的時候是&info_size
乒躺。
完整的使用示例
BOOL isDebugger(){
int name[4];//里面放字節(jié)碼。查詢的信息
name[0] = CTL_KERN;//內核查詢
name[1] = KERN_PROC;//查詢進程
name[2] = KERN_PROC_PID;//傳遞的參數(shù)是進程的ID
name[3] = getpid();//PID的值
struct kinfo_proc info;//接受查詢結果的結構體
size_t info_size = sizeof(info);
if(sysctl(name, 4, &info, &info_size, 0, 0)){
NSLog(@"查詢失敗");
return NO;
}
//看info.kp_proc.p_flag 的第12位剥险。如果為1聪蘸,表示調試狀態(tài)。
//(info.kp_proc.p_flag & P_TRACED)
return ((info.kp_proc.p_flag & P_TRACED) != 0);
}
調用處????
- (void)viewDidLoad {
[super viewDidLoad];
if (isDebugger()) {
NSLog(@"檢測到有調試表制!");
} else {
NSLog(@"沒有調試健爬!");
}
}
進階版
上面在viewDidLoad
中,只能執(zhí)行一次么介,我們更希望定時檢查
娜遵,所以可以這么改,采用dispatch_source_t
的定時器方式????
static dispatch_source_t timer;
void debugCheck(){
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
if (isDebugger()) {
NSLog(@"調試狀態(tài)H蓝獭设拟!");
}else{
NSLog(@"正常!");
}
});
dispatch_resume(timer);
}
然后調用處????
- (void)viewDidLoad {
[super viewDidLoad];
debugCheck();
}
運行????
當然久脯,也不用一直開啟定時器檢查纳胧,在App啟動的時候
檢查一段時間即可!
與ptrace的不同
-
ptrace
的特點:- 重簽名(Xcode)運行之后閃退帘撰!
- 手動打開正常運行跑慕!
-
sysctl
???? 可擴展性更強,檢測到調試后,可以做自己想做的事核行。
2.2 破解sysctl
因為sysctl
是系統(tǒng)的內核函數(shù)牢硅,所以我們很自然就想到 ???? fishHook
,因此這么做????
- 創(chuàng)建一個動態(tài)庫
inject.framework
芝雪,再創(chuàng)建一個類InjectCode
减余,專門用來hooksysctl
????
- 實現(xiàn)hook
sysctl
????
#import "InjectCode.h"
#import "fishhook.h"
#import <sys/sysctl.h>
@implementation InjectCode
//原始函數(shù)指針
int (*sysctl_p)(int *, u_int, void *, size_t *, void *, size_t);
//新函數(shù)地址
int my_sysctl(int *name, u_int namelen, void *info, size_t *infosize, void *newInfo, size_t newInfoSize){
if (namelen == 4
&& name[0] == CTL_KERN
&& name[1] == KERN_PROC
&& name[2] == KERN_PROC_PID
&& info
&& (int)*infosize == sizeof(struct kinfo_proc)) {
int err = sysctl_p(name,namelen,info,infosize,newInfo,newInfoSize);
struct kinfo_proc * myinfo = (struct kinfo_proc *)info;
if ((myinfo->kp_proc.p_flag & P_TRACED) != 0) {
//使用異或可以取反
myinfo->kp_proc.p_flag ^= P_TRACED;
}
return err;
}
return sysctl_p(name,namelen,info,infosize,newInfo,newInfoSize);
}
+(void)load
{
//交換
rebind_symbols((struct rebinding[1]){{"sysctl",my_sysctl,(void *)&sysctl_p}}, 1);
}
@end
run????
三、破解
現(xiàn)在我們知道惩系,使用ptrace
和sysctl
2種方式都能檢測到當前App是否被調試位岔,那有沒有方法能破解
這些檢測呢?當然可以蛆挫。
3.1 動態(tài)注入破解
首先赃承,我們要清楚,之所以能檢測到被調試悴侵,是因為我們在動態(tài)庫
中使用fishHook
,替換了sysctl
的方式實現(xiàn)拭嫁,核心在于時機
???? 動態(tài)庫的load
方法肯定比主工程的早
執(zhí)行可免! 只要我們的破解比這個更早
,是不是就能實現(xiàn)了做粤?接下來我們用代碼來驗證????
- 同樣的浇借,新建一個工程
antiDebug
,在工程中新建動態(tài)庫antiDebug.framework
- 引入
ptrace
和sysctl
- 引入頭文件
MyPtraceHeader.h
- 新建類
antiDebugCode
- 引入頭文件
#import "antiDebugCode.h"
#import <sys/sysctl.h>
#import "MyPtraceHeader.h"
#import <mach-o/dyld.h>
#import <mach-o/loader.h>
@implementation antiDebugCode
//檢測是否存在調試
BOOL isDebugger(){
int name[4];//里面放字節(jié)碼怕品。查詢的信息
name[0] = CTL_KERN;//內核查詢
name[1] = KERN_PROC;//查詢進程
name[2] = KERN_PROC_PID;//傳遞的參數(shù)是進程的ID
name[3] = getpid();//PID的值
struct kinfo_proc info;//接受查詢結果的結構體
size_t info_size = sizeof(info);
if(sysctl(name, 4, &info, &info_size, 0, 0)){
NSLog(@"查詢失敗");
return NO;
}
//看info.kp_proc.p_flag 的第12位妇垢。如果為1,表示調試狀態(tài)肉康。
//(info.kp_proc.p_flag & P_TRACED)
return ((info.kp_proc.p_flag & P_TRACED) != 0);
}
static dispatch_source_t timer;
void debugCheck(){
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
printf("檢查INSERT:%s\n",getenv("DYLD_INSERT_LIBREARIES"));
if (isDebugger()) {
// NSLog(@"調試狀態(tài)4彻馈!");
}else{
// NSLog(@"正常吼和!");
}
});
dispatch_resume(timer);
}
+(void)load
{
debugCheck();
//不允許調試附加!
// ptrace(PT_DENY_ATTACH, 0, 0, 0);
//檢查Cycript
int count = _dyld_image_count();
for (int i = 0; i < count; i++) {
printf("%s\n",_dyld_get_image_name(i));
}
}
- 新建一個
MonkeyApp
工程MonkeyDemo
涨薪,使用上面的antiDebug
工程生成的app包進行重簽名,例如????
- 打開MonkeyApp中
sysctl
的檢測功能????
- run ????
上圖可見炫乓,sysctl
的檢測功能已被破解刚夺!????????????
?? 綜上所述,所有的防護手段的關鍵點在于 ????
提前執(zhí)行末捣!
3.2 靜態(tài)破解
接著上面的例子繼續(xù)侠姑,既然App中已經提前預防了ptrace
和sysctl
,那么我們所有的想以注入
的方式去修改代碼的這條路肯定就走不通
了箩做,不論是動態(tài)庫注入
還是靜態(tài)庫注入
莽红,因為你的時機點不可能比App中的還早,是吧卒茬!
那有沒有別的方式去破防呢船老?當然也有 ???? 靜態(tài)破解咖熟!
我們嘗試直接修改它的Mach-O文件(即修改二進制
)。
3.2.1 ptrace靜態(tài)破解
接下來我們示例演示一下柳畔,如何靜態(tài)調試App中使用的ptrace
檢測馍管。
- 首先,我們把上述工程
antiDebug
中的ptrace檢測的注釋放開????
- 重新編譯生成新的app包
001--antiDebug
薪韩,當做我們要破解的App????
- 新建Monkey工程确沸,取名
test
,重簽名app包001--antiDebug
????
此時俘陷,直接run罗捎,肯定無法動態(tài)調試,會直接崩潰(每次finish running 就會自動斷開調試)????
- 此時我們猜測拉盾,是否是ptrace防護了桨菜?于是添加符號斷點????
再次run,果然斷住了????
根據(jù)調用棧信息捉偏,是在[antiDebugCode load]
之中調用的倒得,因為我們本地電腦有antiDebug
的工程源碼,并且源碼工程并沒有去符號
,所以能查看到。真實的情況下备燃,是沒有源碼的,我們可以通過lldb指令
來查看 ???? bt
查看調用棧????
一樣能找到[antiDebugCode load]
, 是在動態(tài)庫antiDebug
中菩彬,還有動態(tài)庫的地址0x000000010431fd20
,這個是虛擬地址潮梯,包含了偏移量的地址骗灶,那如何得到偏移前的地址呢????? image list
指令得到首地址來計算酷麦!????
得到了首地址0x0000000104318000
矿卑,然后相減得到偏移量0x7D20
。
- 使用hopper打開
antiDebug.framework
的Mach-O二進制文件沃饶,搜索偏移量0x7D20
????
?? 注意:將
antiDebug
拷貝出來母廷,方便查看。
找到了糊肤!
- 接著修改該匯編指令 ????
option + A
????
修改成nop
空指令的意思琴昆。
- 導出生成新的二進制???? (需要將Hopper升級為正版)
替換原有的antiDebug.framework
的Mach-O二進制文件,再次runtest工程
馆揉,就不會斷開調試了业舍!
以上就是通過修改Mach-O文件的方式,靜態(tài)暴力
破解ptrace
。
3.2.2 sysctl靜態(tài)破解
接下來就輪到sysctl
了舷暮,還是一樣态罪,先打符號斷點,看看????
bt
查看調用棧信息????
上圖可見下面,在gcd的block之中复颈,,看不到任何的調用的觸發(fā)點等信息沥割,無法繼續(xù)往下深究了耗啦。
換一種思路,從原始App包入手机杜,Hopper看看Mach-O文件中帜讲,搜索sysctl
????
直接搜索,在真實的工程中這是一個很耗時的過程椒拗,因為我們是demo似将,所以很快就能知道。
主工程
找不到就找動態(tài)庫
????
上圖就找到了蚀苛,我們繼續(xù)往下翻玩郊,找到debugCheck
函數(shù)????
繼續(xù)往下翻,找到___debugCheck_block_invoke
枉阵,就是調用sysctl
的地方????
?? 注意:但是此時還是在
GCD的block
之中,我們還是無法確定App
之中是哪個方法調用的sysctl
预茄。
3.3 破解防護與block
上述sysctl
破解過程中兴溜,我們也發(fā)現(xiàn)了個好處????
防護代碼寫到GCD的block
中執(zhí)行,即使第三方破解能拿到地址
耻陕,也只是block_invoke
調用處的地址拙徽,并不是真正的調用的地址,仍然無法繼續(xù)斷點跟進诗宣,難以破防膘怕,除非你對GCD的源碼流程了如指掌。
總結
-
ptrace
- 可阻止
App
被debugserver
附加 - 在iOS系統(tǒng)中召庞,無法直接使用岛心,需要
導入頭文件
-
ptrace
函數(shù)的定義
?int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
- 破解
ptrace
? 使用ptrace符號斷點
試探
? 使用fishhook
對ptrace
函數(shù)HOOK
? 是PT_DENY_ATTACH
枚舉值,直接返回篮灼。其他類型忘古,執(zhí)行原始函數(shù)
- 可阻止
-
sysctl
- 使用前需引入系統(tǒng)的頭文件 ????
#import <sys/sysctl.h>
-
sysctl
函數(shù) ????int sysctl(int *, u_int, void *, size_t *, void *, size_t);
? 查詢信息的數(shù)組,給它的指針
? 數(shù)組中元素的數(shù)據(jù)類型的大小
? 接收信息結構體的指針 ????kinfo_proc
結構體指針诅诱,其中重點關注p_flag
參數(shù)髓堪,在extern_proc
結構體中
? 接收信息結構體的大小的指針
? 第5個和第6個參數(shù) ???? 直接寫0就行 - 與ptrace的不同
?ptrace
特點 ????重簽名
(Xcode)運行之后閃退
!手動打開
正常運行!
?sysctl
????可擴展性
更強干旁,檢測到調試后驶沼,可以做自己想做的事。 - 破解
sysctl
? 同樣在framework
中使用fishhook
進行方法交換
? 判斷查詢信息的數(shù)組
中各個元素的條件是否是追蹤當前進程
?kinfo_proc
結構體的判斷 ????(p_flag & P_TRACED) != 0
則p_flag ^= P_TRACED
異或取反
- 使用前需引入系統(tǒng)的頭文件 ????
- 破解
- 動態(tài)注入破解 ???? 在
framework
中新建類争群,在load
方法中進行ptrace
和sysctl
的防護 - 靜態(tài)破解
-
ptrace
靜態(tài)破解
? 符號斷點得到ptrace
偏移后的地址回怜,image list
得到庫的首地址,計算偏移地址offsetAddress
? 使用hopper
打開Mach-O
二進制文件祭阀,搜索offsetAddress
鹉戚,并將其對應的匯編指令修改為nop
空指令,導出新的Mach-O
专控,替換原有的 -
sysctl
靜態(tài)破解 ???? 如果在GCD的Block中執(zhí)行抹凳,則很難破解,因為block_invoke
的地址即使知道伦腐,但不清楚GCD底層的調用邏輯
-
- 動態(tài)注入破解 ???? 在