iOS 攻防(二)ptrace

在破解一款App的時候胀瞪,在實(shí)際破解之前肯定是在做調(diào)試溉愁。LLDB之所以能附加進(jìn)程時因?yàn)?code>debugserver菇篡,而debugserver附加是通過ptrace函數(shù)來trace process的丘跌。
ptrace是系統(tǒng)函數(shù),此函數(shù)提供一個進(jìn)程去監(jiān)聽和控制另一個進(jìn)程挡育,并且可以檢測被控制進(jìn)程的內(nèi)存和寄存器里面的數(shù)據(jù)。ptrace可以用來實(shí)現(xiàn)斷點(diǎn)調(diào)試和系統(tǒng)調(diào)用跟蹤朴爬。

一即寒、反調(diào)試ptrace

iOS#import <sys/ptrace.h>頭文件不能直接導(dǎo)入,所以需要我們自己導(dǎo)出頭文件引入調(diào)用。當(dāng)然也可以聲明ptrace函數(shù)直接調(diào)用母赵。

1.1 ptrace 頭文件

  1. 直接創(chuàng)建一個macOS程序?qū)?code>#import <sys/ptrace.h>頭文件逸爵,點(diǎn)進(jìn)去拷貝生成一個.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_ */
  1. 直接聲明函數(shù):
int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
  • _request:要處理的事情
  • _pid:要操作的進(jìn)程
  • _addr_data:取決于_pid參數(shù),要傳遞的數(shù)據(jù)地址和數(shù)據(jù)本身凹嘲。

1.2 ptrace調(diào)用

//告訴系統(tǒng)當(dāng)前進(jìn)程拒絕被debugserver附加
ptrace(PT_DENY_ATTACH, 0, 0, 0);
//ptrace(31, 0, 0, 0);

PT_DENY_ATTACH表示拒絕附加师倔,值為31。如果僅僅是聲明函數(shù)就傳31就好了周蹭。_pid0表示當(dāng)前進(jìn)程趋艘。這里不傳遞任何數(shù)據(jù)。

分別在以下方法中調(diào)用

  1. load方法中調(diào)用:
+ (void)load {
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
}
  1. constructor中調(diào)用:
__attribute__((constructor)) static void entry() {
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
}
  1. main函數(shù)中調(diào)用:
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;

    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
        ptrace(PT_DENY_ATTACH, 0, 0, 0);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
  1. didFinishLaunchingWithOptions中調(diào)用:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
    return YES;
}

1凶朗、2致稀、3情況下Xcode啟動調(diào)試后調(diào)試直接斷開,App能正常操作不能調(diào)試俱尼。4在調(diào)試情況下App直接閃退抖单,正常打開沒問題。同時調(diào)用的情況下以第一次為準(zhǔn)遇八。

也就是說 :ptracemain函數(shù)之后調(diào)用App會直接閃退矛绘,main以及之前調(diào)用會停止進(jìn)程附加,以第一次調(diào)用為準(zhǔn)刃永。正常打開App沒有問題货矮,只影響LLDB調(diào)試。

通過上面的驗(yàn)證說明在程序沒有加載的時候調(diào)用ptrace會設(shè)置一個標(biāo)志斯够,后續(xù)程序就不會被附加了囚玫,如果在已經(jīng)被附加了的情況下調(diào)用ptrace會直接退出(因?yàn)檫@里ptrace附加傳遞的pid0主程序本身)。

PT_DENY_ATTACH
This request is the other operation used by the traced process; it allows a process that is not currently being traced to deny future traces by its parent. All other arguments are ignored. If the process is currently being traced, it will exit with the exit status of ENOTSUP; otherwise, it sets a flag that denies future traces. An attempt by the parent to trace a process which has set this flag will result in a segmentation violation in the parent.
原文地址
ENOTSUP含義如下:
define ENOTSUP 45 //Operation not supported
之前在手機(jī)端通過debugserver附加程序直接報(bào)錯11读规,定義如下:
PT_DETACH 11 // stop tracing a process

二抓督、 破解ptrace

ptrace的特征:附加不了、Xcode運(yùn)行閃退/停止附加束亏、使用正常铃在。

既然ptrace可以組織調(diào)試,那么我們只要Hook了這個函數(shù)繞過PT_DENY_ATTACH的調(diào)用就可以了碍遍。首先想到的就是fishhook定铜。

#import "fishhook.h"

int  (*ptrace_p)(int _request, pid_t _pid, caddr_t _addr, int _data);

int  hp_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){
    if (_request != 31) {//不是拒絕附加
        return ptrace_p(_request, _pid, _addr, _data);
    }
    return 0;
}

void hp_hook_ptrace() {
    struct rebinding ptrace_rb;
    ptrace_rb.name ="ptrace";
    ptrace_rb.replacement = hp_ptrace;
    ptrace_rb.replaced = (void *)&ptrace_p;
    
    struct rebinding bds[] = {ptrace_rb};
    rebind_symbols(bds, 1);
}

+ (void)load {
    hp_hook_ptrace();
}

這樣就能夠進(jìn)行附加調(diào)試了。

三怕敬、防止ptrace被破解

3.1 提前Hook防止ptrace被Hook

既然ptrace能夠被Hook揣炕,那么自己先Hookptrace。調(diào)用的時候直接調(diào)用自己存儲的地址就可以了东跪。我們可以在自己的項(xiàng)目中增加一個Framework畸陡。這個庫在Link Binary With Libraries中盡可能的靠前矮烹。這與dyld加載動態(tài)庫的順序有關(guān)。
具體可以參考這個案例
這樣就可以不被ptrace Hook了罩锐。代碼邏輯和1.2中相同奉狈,只不過調(diào)用要換成ptrace_p
記的頭文件中導(dǎo)出ptrace_p

CF_EXPORT int (*ptrace_p)(int _request, pid_t _pid, caddr_t _addr, int _data);

創(chuàng)建一個Monkey工程涩惑,將3.1生成的.app包拖入工程重簽名仁期,這個時候主程序通過調(diào)用ptrace已經(jīng)不能阻止我們調(diào)試了,但是調(diào)用ptrace_p的地方Monkey Hook不到了竭恬。

3.2 修改二進(jìn)制破解提前Hook ptrace

Monkey的工程中打ptrace符號斷點(diǎn):

image.png

這個時候可以看到是didFinishLaunchingWithOptions中調(diào)用了ptrace_p函數(shù):
Hopper打開MachO文件找到didFinishLaunchingWithOptions方法:

image.png

然后一直點(diǎn)下去找到ptrace_p是屬于Inject.framework的:

image.png

.appFrameworks中找到Inject.frameworkHopper打開跛蛋,可以看到_rebind_symbols,上面的參數(shù)是ptrace

image.png

這里我們可以直接修改ptrace讓先Hook的變成另外一個函數(shù)痊硕,但是有風(fēng)險點(diǎn)是App內(nèi)部調(diào)用ptrace_p的時候如果沒有判斷空就crash了赊级。如果判斷了可以這么處理。
還有另外一個方式是修改didFinishLaunchingWithOptions代碼中的匯編岔绸,修改blr x8NOP這樣就繞過了ptrace_p的調(diào)用理逊。

修改blr x8NOP

image.png

替換00 01 3F D61F 20 03 D5

image.png

修改后就變?yōu)?code>NOP了:

image.png

再次運(yùn)行就繞過了ptrace_p的調(diào)用。這里不Hook didFinishLaunchingWithOptions的原因是它內(nèi)部可能還調(diào)用其它方法盒揉。

3.3 匯編調(diào)用ptrace

既然二進(jìn)制能被修改那么怎么能不暴露ptraceHook呢晋被?
答案是采用匯編:

__attribute__((constructor)) void entry() {
#ifdef DEBUG
    //
#else
    #ifdef __arm__
        __asm__(
                 "mov r0,#0x1F\n"
                 "mov r1,#0x0\n"
                 "mov r2,#0x0\n"
                 "mov r12,#0x1A\n"
                 "svc #0x80");
    #endif
    #ifdef __arm64__
        __asm__("mov X0, #0x1A\n"
                "mov X1, #0x1F\n"
                "mov X2, #0x0\n"
                "mov X3, #0x0\n"
                "mov X16,#0x0\n"
                "svc #0x80");
    #endif
    }
#endif

這里的1A就是26,也就是ptrace刚盈,在#import <sys/syscall.h>中有它的編號:

image.png

3.4 匯編ptrace破解

分析找到svc #0x80修改為nop就可以了羡洛,抖音的防護(hù)就是通過匯編調(diào)用的。

參考:
http://www.45fan.com/article.php?aid=18070914507358856843184900

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末藕漱,一起剝皮案震驚了整個濱河市欲侮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肋联,老刑警劉巖威蕉,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異牺蹄,居然都是意外死亡忘伞,警方通過查閱死者的電腦和手機(jī)薄翅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門沙兰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人翘魄,你說我怎么就攤上這事鼎天。” “怎么了暑竟?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵斋射,是天一觀的道長育勺。 經(jīng)常有香客問我,道長罗岖,這世上最難降的妖魔是什么涧至? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮桑包,結(jié)果婚禮上南蓬,老公的妹妹穿的比我還像新娘。我一直安慰自己哑了,他們只是感情好赘方,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著弱左,像睡著了一般窄陡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拆火,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天跳夭,我揣著相機(jī)與錄音,去河邊找鬼们镜。 笑死优妙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的憎账。 我是一名探鬼主播套硼,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胞皱!你這毒婦竟也來了邪意?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤反砌,失蹤者是張志新(化名)和其女友劉穎雾鬼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宴树,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡策菜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了酒贬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片又憨。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖锭吨,靈堂內(nèi)的尸體忽然破棺而出蠢莺,到底是詐尸還是另有隱情,我是刑警寧澤零如,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布躏将,位于F島的核電站锄弱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏祸憋。R本人自食惡果不足惜会宪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚯窥。 院中可真熱鬧狈谊,春花似錦、人聲如沸沟沙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矛紫。三九已至赎瞎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颊咬,已是汗流浹背务甥。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喳篇,地道東北人敞临。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像麸澜,于是被迫代替她去往敵國和親挺尿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容