实战:干掉高德地图7.2.0版iOS客户端的反动态调试保护


#1

高德是中国领先的数字地图内容、导航和位置服务解决方案提供商。苹果自带的地图采用的就是高德的数据,足见高德之权威 :+1:
昨天突发奇想,对高德地图上中一个官方不提供的功能产生了浓厚的兴趣,试图通过hack的方式来实现这个功能。谁知刚架上LLDB,竟然就出现了这样的一幕……

1. LLDB附加失败

FunMaker-5:~ root# debugserver *:1234 -a "AMapiPhone"
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for armv7.
Attaching to process AMapiPhone...
Segmentation fault: 11

很显然,高德地图做了反动态调试保护。为了干掉这层保护,我们先得搞清楚它采用了什么保护方法。因为现有的公开反动态调试保护只有ptrace方法这一种,所以自然而然地,我们先从它下手。

2. 用LLDB启动AMapiPhone

FunMaker-5:~ root# debugserver -x backboard *:1234 /var/mobile/Containers/Bundle/Application/1C86F6A1-E50A-434E-B08E-C39C200EFA0A/AMapiPhone.app/AMapiPhone
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
for armv7.
Listening to port 1234 for a connection from *...
(lldb) process connect connect://localhost:1234
Process 5171 stopped
* thread #1: tid = 0x1433, 0x1feb8000 dyld`_dyld_start, stop reason = signal SIGSTOP
    frame #0: 0x1feb8000 dyld`_dyld_start
dyld`_dyld_start:
-> 0x1feb8000:  mov    r8, sp
   0x1feb8004:  sub    sp, sp, #16
   0x1feb8008:  bic    sp, sp, #7
   0x1feb800c:  ldr    r3, [pc, #112]            ; _dyld_start + 132

LLDB停了下来,我们先“c”一下,看看是什么效果:

(lldb) c
Process 5171 resuming
Process 5171 exited with status = 45 (0x0000002d) 

进程直接退出,进一步验证了高德地图中含有反动态调试的功能。没什么好说的了,我们这就来看看怎么干掉这层保护。

3. 在ptrace上下断点,找到调用ptrace的地方

依据这个帖子,可以知道定位调用ptrace地方的方法很简单,就是在ptrace上下个断点:

FunMaker-5:~ root# debugserver -x backboard *:1234 /var/mobile/Containers/Bundle/Application/1C86F6A1-E50A-434E-B08E-C39C200EFA0A/AMapiPhone.app/AMapiPhone
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for armv7.
Listening to port 1234 for a connection from *...
Got a connection, launched process /var/mobile/Containers/Bundle/Application/1C86F6A1-E50A-434E-B08E-C39C200EFA0A/AMapiPhone.app/AMapiPhone (pid = 678).
snakeninnysiMac:~ snakeninny$ /Applications/OldXcode.app/Contents/Developer/usr/bin/lldb 
(lldb) process connect connect://localhost:1234
Process 6907 stopped
* thread #1: tid = 0x1afb, 0x1fe54000 dyld`_dyld_start, stop reason = signal SIGSTOP
    frame #0: 0x1fe54000 dyld`_dyld_start
dyld`_dyld_start:
-> 0x1fe54000:  mov    r8, sp
   0x1fe54004:  sub    sp, sp, #16
   0x1fe54008:  bic    sp, sp, #7
   0x1fe5400c:  ldr    r3, [pc, #112]            ; _dyld_start + 132
(lldb) b ptrace
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) c
Process 6907 resuming
1 location added to breakpoint 1
Process 6907 stopped
* thread #1: tid = 0x1afb, 0x37031e64 libsystem_kernel.dylib`__ptrace, queue = 'com.apple.main-thread, stop reason = breakpoint 1.1
    frame #0: 0x37031e64 libsystem_kernel.dylib`__ptrace
libsystem_kernel.dylib`__ptrace:
-> 0x37031e64:  ldr    r12, [pc, #4]             ; ptrace + 12

libsystem_kernel.dylib`ptrace + 4:
   0x37031e68:  ldr    r12, [pc, r12]
   0x37031e6c:  b      0x37031e74                ; ptrace + 16
   0x37031e70:  rsbeq  pc, r11, #48
(lldb) p/x $lr
(unsigned int) $0 = 0x000dbd19
(lldb) image list -o -f
  0] 0x000d1000 /private/var/mobile/Containers/Bundle/Application/1C86F6A1-E50A-434E-B08E-C39C200EFA0A/AMapiPhone.app/AMapiPhone(0x00000000000d5000)

所以ptrace的调用者位于0xdbd19 - 0xd1000 = 0xAD19处,如图所示:


这段代码的含义很明显了,动态调用ptrace,来达到反动态调试的目的。这段代码位于sub_ACF0内部,我们来看看sub_ACF0的显式调用者:
image
只有一个sub_AD24。看看它内部的实现:

它是main函数。好了,高德地图通过在main函数中动态调用ptrace函数来达到反动态调试目的,大家可以参考学习。

4. 干掉sub_ACF0

根据这个帖子,我们可以hook在IDA的Functions window中看到的任意形如sub_xxx的函数。tweak的核心代码如下:

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

void (*old_sub_ACF0)(void);

void new_sub_ACF0(void)
{
        // old_sub_ACF0();
        NSLog(@"iOSRE: anti-anti-debugging");
}

%ctor
{
        @autoreleasepool
        {
                unsigned long _sub_ACF0 = (_dyld_get_image_vmaddr_slide(0) + 0xACF0) | 0x1;
                if (_sub_ACF0) NSLog(@"iOSRE: Found sub_ACF0!");
                MSHookFunction((void *)_sub_ACF0, (void *)&new_sub_ACF0, (void **)&old_sub_ACF0);
        }
}

编译打包安装,我们看看有了这个tweak的加持,动态调试的效果:

(lldb) process connect connect://localhost:1234
Process 10222 stopped
* thread #1: tid = 0x27ee, 0x1fea3000 dyld`_dyld_start, stop reason = signal SIGSTOP
    frame #0: 0x1fea3000 dyld`_dyld_start
dyld`_dyld_start:
-> 0x1fea3000:  mov    r8, sp
   0x1fea3004:  sub    sp, sp, #16
   0x1fea3008:  bic    sp, sp, #7
   0x1fea300c:  ldr    r3, [pc, #112]            ; _dyld_start + 132
(lldb) c
Process 10222 resuming
(lldb) 2015-02-09 19:55:05.129 AMapiPhone[737:10222] iOSRE: Found sub_ACF0!
2015-02-09 19:55:05.478 AMapiPhone[737:10222] iOSRE: anti-anti-debugging
2015-02-09 19:55:06.598 AMapiPhone[737:10222] DiskCookieStorage changing policy from 2 to 0, cookie file: file:///private/var/mobile/Containers/Data/Application/6AE478A8-7838-4C33-B716-D2810ED78CB9/Library/Cookies/Cookies.binarycookies
2015-02-09 19:55:07.596 AMapiPhone[737:10222] reInit /var/mobile/Containers/Data/Application/6AE478A8-7838-4C33-B716-D2810ED78CB9/Documents/autonavi/data/cache/vmap4res/style-icons-upate-recorder.data
vmap_basedb_create-offline /var/mobile/Containers/Data/Application/6AE478A8-7838-4C33-B716-D2810ED78CB9/Documents/autonavi/data/vmap/

LLDB成功进入了高德地图内部,misson complete~开始hack吧!


直接在lldb上修改寄存器即可
#2

多谢分享,前排沙发!


#3

:smile:,感谢分享,我来了。


#4

这个真猛,授人以渔啊


#5

你好,我用相同的方法调试支付宝,地址相减到了7495这个地址,可是这里什么都没有是怎么回事啊,谢谢
00007491 db 0x00 ; ‘.’
00007492 db 0x00 ; ‘.’
00007493 db 0x00 ; ‘.’
00007494 db 0x00 ; ‘.’
00007495 db 0x00 ; ‘.’
00007496 db 0x00 ; ‘.’
00007497 db 0x00 ; ‘.’
00007498 db 0x00 ; ‘.’
00007499 db 0x00 ; ‘.’

我用的是hopper


#6

可能是支付宝做了保护,也可能是你自己的操作问题。建议把你的操作流程描述一下,让大家看看有没有问题


#7

仔细看了下的确是我的问题,减的时候减错了


#9

#11

第二步还是报Segmentation fault: 11


#12

debugserver -x backboard *:1234 /var/mobile/......
把这个backboard改成posix试试


#13

不错啊,有空再介绍几个例子呗!


#14

基本知识
操作系统提供了一种标准的服务来让程序员实现对底层硬件和服务的控制(比如文件系统),叫做系统调用(system calls)。当一个程序需要作系统调用的时候,它将相关参数放进系统调用相关的寄存器,然后调用软中断0x80,这个中断就像一个让程序得以接触到内核模式的窗口,程序将参数和系统调用号交给内核,内核来完成系统调用的执行。

http://blog.csdn.net/edonlii/article/details/8717029


#15

(lldb) b ptrace
Breakpoint 4: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.
(lldb) c
Process 62692 resuming
Process 62692 exited with status = 0 (0x00000000) Terminated due to signal 9

我用上面的方法报上面的错误,用的是最新的高德地图(8.0.2)估计有更新新的技术了。这个怎么解决
刚才网站崩了,吓死我了。。。:fearful:

@snakeninny


#16

我还尝试了 b sysctl.
也是报同样的错误


#17

有没有人遇到这个问题啊。help。。。这个为什么一直被禁止啊。:scream:
Yyy:~ root# debugserver -x posix *:1234 /var/containers/Bundle/Application/73094EEE-F303-48B4-A8A8-D924D1B849BC/AlipayWallet.app/AlipayWallet

狗神可以帮我看下吗?


#18

这里为什么不可以直接勾ptrace呢


#19

一般这种旧版本的app要到哪里下


#20

Cydia上好像有插件,可以选择AppStore里的旧版本下载,google一下


#21

也可以自己上传个app,自己破解着玩


#22

狗神好,按照此教程方法检测到sysctl反动态调试,并且位于入口函数 int main(),
int main(int argc, char * argv[]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//sysctl反动态调试
});
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
不在一个单独的方法里,该如何hook它呢?