Anti ptrace:去掉AlipayWallet的ptrace 反調試保護,進行lldb調試---僅用於參考學習

新的博客

學習筆記

前言

codephp

軟件環境:Xcode
硬件環境:iPhone5越獄手機、Mac
開發工具: Cycript、LLDB、logos Tweak、hopper、MonkeyDev、AFLEXLoader、dumpdecrypted、debugserver、ssh、class_dump、hookhtml

本文采用tweak 的方式進行MSHookFunctionios

ptrace這個函數很容易修改,幾種破解方式

  • 運行時期,斷點ptrace,直接返回 :

初始化應用程序,而不是運行中附着git

iPhone:~ root#  debugserver -x posix *:12345  /var/mobile/Containers/Bundle/Application/A612F542-81EF-456A-A6A0-B23046EF57BA/AlipayWallet.app/AlipayWallet

初始化程序,目的是從程序入口就開始進行附着,這樣咱們就能夠在一些安全防禦代碼執行以前,進行破解。 最經常使用的就是跳過ptrace:
過命令thread return直接返回,以跳過函數的邏輯。程序員

(lldb) br set -n ptrace
 Breakpoint 2: where = libsystem_kernel.dylib`__ptrace, address = 0x00000001966af2d4
 (lldb) br command add 2
 Enter your debugger command(s).  Type 'DONE' to end.
 > thread return
 > c
 > DONE

iOS逆向 砸殼

iPhone:~ root# ps -e |grep AlipayWallet
  714 ??         0:26.44 /var/mobile/Containers/Bundle/Application/A612F542-81EF-456A-A6A0-B23046EF57BA/AlipayWallet.app/AlipayWallet
  736 ttys000    0:00.01 grep AlipayWallet
iPhone:~ root# cycript -p AlipayWallet
cy# [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]
#"file:///var/mobile/Containers/Data/Application/89313E1C-76C2-41E3-8ECD-F4BDC1A78524/Documents/"
devzkndeMacBook-Pro:decrypted devzkn$ scp /Users/devzkn/Downloads/kevin-software/ios-Reverse_Engineering/dumpdecrypted-master/dumpdecrypted.dylib iphone150:/var/mobile/Containers/Data/Application/89313E1C-76C2-41E3-8ECD-F4BDC1A78524/Documents/
devzkndeMacBook-Pro:decrypted devzkn$ scp iphone150:/var/mobile/Containers/Data/Application/89313E1C-76C2-41E3-8ECD-F4BDC1A78524/Documents/AlipayWallet.decrypted /Users/devzkn/decrypted/AlipayWallet
devzkndeMacBook-Pro:bin devzkn$ class-dump --arch armv7 /Users/devzkn/decrypted/AlipayWallet10.1.8/AlipayWallet.decrypted -H -o /Users/devzkn/decrypted/AlipayWallet10.1.8/head

定位目標app

TBSDKMTOPServer

bundleIdentifier

修改com.apple.springboard爲iphoneclientgithub

iPhone:~ root# cycript -p AlipayWallet
cy# [[NSBundle mainBundle] bundleIdentifier]
@"com.alipay.iphoneclient"

tweak

%hook DFClientDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    %log();
    
    // 打印某個類的全部方法的,查看全部方法的執行順序
    
     [KNHook hookClass:@"H5WebViewController"];//aluLoginViewController
     [KNHook hookClass:@"TBSDKServer"];//getUaPageName    aluMTopService _tokenLoginInvoker
    
     [KNHook hookClass:@"TBSDKMTOPServer"];//getUaPageName    aluMTopService _tokenLoginInvoker
    
    return %orig;
}
%end
Nov 28 18:36:20 iPhone AlipayWallet[1246] <Warning>: KNHooklog :-(void)loadJs:(have 1 value)
    return:(null)
    value1:__NSCFString-->(function(){if(window.NEBULAHASADDEDTOUCHEVENT){return;};function onDOMReady(callback){var readyRE=/complete|loaded|interactive/;if(readyRE.test(document.readyState)){setTimeout(function(){callback();},1);}else{document.defaultView.addEventListener('DOMContentLoaded',function(){callback();},false);}}
    onDOMReady(function(){document.addEventListener("touchstart",function(event){AlipayJSBridge.call("reportClickTime");},false);});window.NEBULAHASADDEDTOUCHEVENT=true;})();
    object:<H5WebViewController: 0x5a40800>

reportClickTimeweb

通信錄朋友

Nov 28 18:46:07 iPhone AlipayWallet[1246] <Warning>: KNHooklog :-(void)resetWebviewDomainLabelText:(have 1 value)
    return:(null)
    value1:NSURL-->https://render.alipay.com/p/f/fd-j6lzqrgm/addressbook.html?__webview_options__=canPullDown%3DNO%26showOptionMenu%3DNO%26transparent%3DNO%26networkIndicator%3DYES
    object:<H5WebViewController: 0x4a34600>
     ##########################################
https://render.alipay.com/p/f/fd-j6lzqrgm/addressbook.html?__webview_options__=canPullDown=NO&showOptionMenu=NO&transparent=NO&networkIndicator=YES
NSURLRequest *_originalHttpsRequest;

webView:shouldStartLoadWithRequest:navigationType

char -[AliH5WebViewController webView:shouldStartLoadWithRequest:navigationType:](void * self, void * _cmd, void * arg2, void * arg3, int arg4) {
else {
            sub_e0afcc(*ivar_offset(_originalHttpsRequest) + r8, stack[2051]);
            loc_e0afa4(@class(NSURLConnection), @selector(alloc), 0x39e724c);
            r8->_urlConnection = loc_e0afa4();
            loc_e0afa0(r8->_urlConnection, r8->_urlConnection);
            loc_e0afa4(r8->_urlConnection, @selector(start));
            r5 = 0x0;
    }
    goto loc_d14f42;
void -[H5WebViewController callExternNativeApi:](void * self, void * _cmd, void * arg2) {
    r6 = sub_2a0e18c();
    sub_2a0e184();
    r5 = sub_2a0e188();
    sub_2a0e184();
    sub_2a0e180();
    loc_2a0e1a4(r5, @selector(callExternNativeApi:webviewcontroller:), r6);
    return;
}

總結

總結下去掉ptrace的思路:

  • 當程序運行後,使用 debugserver *:1234 -a BinaryName 附加進程出現 segmentfault 11
    時,通常說明程序內部調用了ptrace 。
  • 爲驗證是否調用了ptrace 能夠 debugserver -x backboard *:1234 /BinaryPath
    (這裏是完整路徑),而後下符號斷點 b ptrace,c 以後看ptrace第一行代碼的位置,而後 p $lr 找到函數返回地址,再根據
    image list -o -f 的ASLR偏移,計算出原始地址。最後在 IDA
    中找到調用ptrace的代碼,分析如何調用的ptrace。
  • 開始hook ptrace。

步驟一:debugserver

iPhone:~ root#  debugserver *:12345 -a AlipayWallet
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for armv7.
Attaching to process AlipayWallet...
Segmentation fault: 11

當程序運行後,使用 debugserver *:1234 -a BinaryName 附加進程出現 segmentfault 11 時,通常說明程序內部調用了ptrace 。spring

http://everettjf.com/2015/12/...segmentfault

iPhone:~ root#  debugserver *:12345 -x backboard /var/mobile/Containers/Bundle/Application/A612F542-81EF-456A-A6A0-B23046EF57BA/AlipayWallet.app/AlipayWallet
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for armv7.
Segmentation fault: 11

步驟二:分析如何調用的ptrace

debugserver -x

iPhone:~ root# debugserver -x *:12345 /var/mobile/Containers/Bundle/Application/A612F542-81EF-456A-A6A0-B23046EF57BA/AlipayWallet.app/AlipayWallet
error: invalid TYPE for the --launch=TYPE (-x TYPE) option: '*:12345'
Valid values TYPE are:
  auto       Auto-detect the best launch method to use.
  posix      Launch the executable using posix_spawn.
  fork       Launch the executable using fork and exec.
  backboard  Launch the executable through BackBoard Services.

總共有四種類型api

debugserver -x backboard *:1234 /var/mobile/......
把這個backboard改爲posix試試

iPhone:~ root#  debugserver -x posix *:12345  /var/mobile/Containers/Bundle/Application/A612F542-81EF-456A-A6A0-B23046EF57BA/AlipayWallet.app/AlipayWallet
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for armv7.
Listening to port 12345 for a connection from *...
(lldb) process connect connect://127.0.0.1:12345

(lldb) 
error: Process 1657 is currently being debugged, kill the process before connecting.
Process 1657 stopped
* thread #1, stop reason = signal SIGSTOP
    frame #0: 0x1fe9b000 dyld`_dyld_start
dyld`_dyld_start:
->  0x1fe9b000 <+0>:  mov    r8, sp
    0x1fe9b004 <+4>:  sub    sp, sp, #16
    0x1fe9b008 <+8>:  bic    sp, sp, #7
    0x1fe9b00c <+12>: ldr    r3, [pc, #0x70]           ; <+132>
Target 0: (dyld) stopped.
  • 在ptrace上下斷點,找到調用ptrace的地方
(lldb)  b ptrace
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) c
Process 1657 resuming

關閉Target,從新啓動Target

1 location added to breakpoint 1
Process 1657 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x37a13e64 libsystem_kernel.dylib`__ptrace
libsystem_kernel.dylib`__ptrace:
->  0x37a13e64 <+0>:  ldr    r12, [pc, #0x4]           ; <+12>
    0x37a13e68 <+4>:  ldr    r12, [pc, r12]
    0x37a13e6c <+8>:  b      0x37a13e74                ; <+16>
    0x37a13e70 <+12>: rsbeq  r9, r11, #192, #2
Target 0: (AlipayWallet) stopped.
(lldb)  p/x $lr
(unsigned int) $0 = 0x0000bfbb

因而可知ptrace函數在libsystem_kernel.dylib這個動態庫中,使用時才進行加載,不是靜態放在本地的,因此咱們不能簡單地去tweak ptrace函數。

(lldb) image list -o -f |grep AlipayWallet
[  0] 0x00000000 /private/var/mobile/Containers/Bundle/Application/A612F542-81EF-456A-A6A0-B23046EF57BA/AlipayWallet.app/AlipayWallet(0x0000000000004000)

因此ptrace的調用者位於0x0000bfbb - 0x00000000 = 0x0000bfbb處,如圖所示:

在hopper使用go to add ,快捷鍵G

圖片描述

0x0000bfba

這段代碼的含義很明顯了,動態調用ptrace,來達到反動態調試的目的。這段代碼位於 sub_bf92:內部,咱們來看看 sub_bf92:的顯式調用者:

圖片描述

只有一個EnteryPoint+212,看看內部實現

圖片描述

高德地圖經過在main函數中動態調用ptrace函數來達到反動態調試目的,能夠參考學習。
支付寶如今作到的是經過inline函數調用ptrace

  • 幹掉sub_bf92(動態調用ptrace的地方)

基礎知識

其中MSHookMessageEx負責用來hook Objective-C函數,
MSHookFunction負責用來hook C/C++函數。

  • MSHookFunction實現Hook採用的是在內存中寫入彙編指令來達到目的:

簡單說來就是首先修改要Hook函數的前N個字節的內存,使其跳轉到替換後的函數頭,這樣就能執行本身的代碼;同時會保存原函數的前N個字節的內容以便執行完本身的邏輯後能正確執行原函數的邏輯。具體的彙編實現能夠參考這篇分析文章。

void MSHookFunction(void *symbol, void *hook, void **old);
  • 其中第一個參數爲所要Hook的函數地址,值得注意的是該地址不必定限於函數頭,也能夠是函數內部的任一代碼地址;
  • 第二個參數爲Hook後要替換的函數地址;
  • 第三個參數爲指向Hook地址的指針,用來保存被Hook函數替換掉的彙編指令方便執行完本身的代碼邏輯後可以繼續執行原函數的邏輯,若不須要調用原函數,則此處能夠設爲「NULL」
  • 模版MSHookFunction
void *(*oldConnect)(int, const sockaddr *, socklen_t);

void *newConnect(
    int socket, const sockaddr *address, socklen_t length
) {
    if (address->sa_family == AF_INET) {
        sockaddr_in *address_in = address;
        if (address_in->sin_port == htons(6667)) {
            sockaddr_in copy = *address_in;
            address_in->sin_port = htons(7001);
            return oldConnect(socket, &copy, length);
        }
    }

    return oldConnect(socket, address, length);
}

MSHookFunction(&connect, &newConnect, &oldConnect);

首先定義了一個名爲oldConnect的指針用於保存要Hook函數被替換的指令;
而後實現了新的newConnect方法,即Hook後實際想要執行的代碼邏輯;
最後使用MSHookFunction來對目標函數進行Hook。

第一個參數爲原方法connect的地址,第二個參數爲實現的新方法地址,第三個參數爲用於保存connect被替換的彙編指令的地址。
其中「&connect」是MSHookFunction內部調用了CydiaSubstrate的另外一個MSFindSymbol函數來實現根據函數名查找其函數地址,更多的MSHookFunction實現原理

此案例的hook prace 的代碼

// See http://iphonedevwiki.net/index.php/Logos

//http://everettjf.com/2015/12/20/amap-ios-client-kill-anti-debugging-protect/
//https://segmentfault.com/a/1190000006104602
//http://dev.qq.com/topic/5791da152168f2690e72daa4
//https://bbs.pediy.com/thread-185014.htm
//http://www.rainyx.com/archives/category/ios/reverse

#import <substrate.h>
#import <mach-o/dyld.h>
#import <dlfcn.h>

void (*old_sub_bf92)(void);

void new_sub_bf92(void)
{
    // old_sub_bf92();
    NSLog(@"KNiOSRE: anti-anti-debugging");
}
//sub_bf92
%ctor
{
    @autoreleasepool
    {
        unsigned long _sub_bf92 = (_dyld_get_image_vmaddr_slide(0) + 0xbf92) | 0x1;
        if (_sub_bf92) NSLog(@"KNiOSRE: Found sub_bf92!");
            MSHookFunction((void *)_sub_bf92, (void *)&new_sub_bf92, (void **)&old_sub_bf92);
    }
}

編譯打包安裝,咱們看看有了這個tweak的加持,動態調試的效果:

iPhone:~ root# debugserver  *:12345 -a AlipayWallet
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for armv7.
Attaching to process AlipayWallet...
Listening to port 12345 for a connection from *...

成功

(lldb) process connect connect://127.0.0.1:12345
Process 1721 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x37a004f0 libsystem_kernel.dylib`mach_msg_trap + 20
libsystem_kernel.dylib`mach_msg_trap:
->  0x37a004f0 <+20>: pop    {r4, r5, r6, r8}
    0x37a004f4 <+24>: bx     lr

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x37a004f8 <+0>:  mov    r12, sp
    0x37a004fc <+4>:  push   {r4, r5, r6, r8}
Target 0: (AlipayWallet) stopped.
Nov 28 21:53:46 iPhone kernel[0] <Notice>: xpcproxy[1815] Container: /private/var/mobile/Containers/Data/Application/89313E1C-76C2-41E3-8ECD-F4BDC1A78524 (sandbox)
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Notice>: MS:Notice: Injecting: com.alipay.iphoneclient [AlipayWallet] (1141.14)
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Notice>: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/AFlexLoader.dylib
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Warning>: AFlexLoader: injected successfully
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Notice>: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/AlipayWalletTweakF.dylib
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Warning>: KNiOSRE: Found sub_bf92!
Nov 28 21:53:46 iPhone locationd[103] <Notice>: Gesture EnabledForTopCLient: 0, EnabledInDaemonSettings: 0
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Notice>: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/TSTweakEx.dylib
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Warning>: MS:Warning: nil class argument for selector applicationDidFinishLaunching:
Nov 28 21:53:46 iPhone AlipayWallet[1815] <Warning>: KNiOSRE: anti-anti-debugging

H5WebViewController

cy# [#0xfc4e730 nextResponder]
#"<H5WebViewController: 0x537e600>"
cy# [#0x537e600 h5WebView]
#"<H5WebView: 0xfc4e240; baseClass = UIWebView; frame = (0 64; 320 504); autoresize = H; layer = <CALayer: 0xd4a8e70>>"
cy# [#0xfc4e240 delegate]
#"<PSDJsBridge: 0x13019ea0>"
cy# [#0x13019ea0 ]
[#"<PSDJsBridge: 0x13019ea0>"]
@property(retain, nonatomic) NSMutableDictionary *responseCallbacks; // @synthesize responseCallbacks=_responseCallbacks;
cy# [#0x13019ea0 webViewDelegate]
#"<PSDView: 0xfc4ed90>"

經過tweak,替換disable_gdb函數 的第二種方式(更簡單)

ptrace函數在libsystem_kernel.dylib這個動態庫中,使用時才進行加載,不是靜態放在本地的,因此咱們不能簡單地去tweak ptrace函數。因此咱們分析一下其代碼邏輯,通常這種反調試,代碼是這麼寫的 :

void disable_gdb() {
    void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
    ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
    ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
    dlclose(handle);
}

能夠經過hook dlsym,當其調用時,若是是獲取ptrace函數,則咱們返回一個假的ptrace函數回去 , tweak如此編寫 :

#import <substrate.h>
#import <mach-o/dyld.h>
#import <dlfcn.h>


int fake_ptrace(int request, pid_t pid, caddr_t addr, int data){
    return 0;
}

void *(*old_dlsym)(void *handle, const char *symbol);

void *my_dlsym(void *handle, const char *symbol){
    if(strcmp(symbol,"ptrace") == 0){
        return (void*)fake_ptrace;
    }

    return old_dlsym(handle,symbol);
}

%ctor{
    MSHookFunction((void*)dlsym,(void*)my_dlsym,(void**)&old_dlsym);
}

基本知識

操做系統提供了一種標準的服務來讓程序員實現對底層硬件和服務的控制(好比文件系統),叫作系統調用(system calls)。當一個程序須要做系統調用的時候,它將相關參數放進系統調用相關的寄存器,而後調用軟中斷0x80,這個中斷就像一個讓程序得以接觸到內核模式的窗口,程序將參數和系統調用號交給內核,內核來完成系統調用的執行。

相關文章
相關標籤/搜索