碳基体

奋斗在产品安全第一线的安全妹子

iOS重置root密码(通过修改/etc/master.passwd)

当忘记iOS系统的root密码后,可以采用修改/etc/master.passwd文件来修改root密码


可以使用iFiles的文本编辑器编辑 /etc/master.passwd文件,修改第二行 root:后,第一个:0前之间的部分 ,这部分的字符串是采用string crypt ( string $str [, string $salt ] )加密函数生成的


$str,就是root明文密码


$salt,就是2个字符的盐


可以使用在线函数运行工具http://www.functions-online.com/crypt.html来生成这段加密字符

 

以上图为例,$str部分的test为root的明文密码, $salt部分的ue为任意的2个长度的字符。ueu4r5eSydxzM这个长度为13个字符的字符串就是通过crypt加密后的密文


将该串字符填写在/etc/master.passwd文件的第二行,root: 与 第一个:0 之间


e.g.   root:ueu4r5eSydxzM:0:0:0:0:System Administrator:/var/root/:/bin/sh


即可将root密码修改为test



参考:

http://realityloop.com/blog/2009/12/31/recover-forgotten-iphone-root-password

来源:碳基体

解决iOS上Killed 9 错误

在越狱设备上运行命令工具例如sqlite3时,会出现“killed 9”的错误,SecurityLearn博客提供了很好的解决方法,从解决方法来看,是命令签名验证不通过导致的错误。

 

解决方法如下:


第一步:在mac上创建用于代码签名的自签名证书

选择钥匙串访问 keychain access—— 证书助理Certificate Assistant —— 创建证书Create a Certificate

名称随便写,身份类型选择自签名根证书,证书类型选择代码签名,勾选让我覆盖这些默认值,其他选项采取默认值

 

第二步:将iOS设备上的sqlite3命令拷贝到Mac上,该命令一般在/usr/bin/目录下


第三步:在Mac上采用第一步创建的证书签名该命令文件

dani-2:Downloads leedani$ codesign -fs tanjiti sqlite3

-f选项表示强制替换已存在的签名

-s选项表示使用指定证书(本例中证书identity是tanjiti)签名文件


第四步:将签名后的sqlite3拷贝回iOS设备,并增加其执行权限

danimato-iPod:/usr/bin root# chmod a+x sqlite3


   现在可以正常运行了,其他类似的命令工具错误同样可以采取这个办法,感谢SecurityLearn!


参考:

http://www.securitylearn.net/2013/03/29/ios-sqlite3-command-killed9-problem/?utm_source=rss&utm_medium=rss&utm_campaign=ios-sqlite3-command-killed9-problem

来源:碳基体

iOS设备安装Metasploit Framework的方法

原文:Mobile Pwning:Using Metasploit on iOS

Metasploit是我最喜欢的安全工具,没有之一,现在介绍如何在iOS设备上安装它。


一、安装准备条件

1. 越狱设备

2. SSH

SSH服务端:iOS设备上安装openssh (Cydia中搜索),开启SSH服务

SSH客户端:PC上安装SSH客户端软件(SecureCRT比较好),远程连接iOS设备。

由于我的PC机与iOS设备处于隔离网段,因此我采用的USB连接方式(itunnel mux+ SecureCRT)

 itunnel_mux.exe --lport 1234

 ssh -p 1234 root@127.0.0.1

3.APT(cydia中搜索)


二、正式安装

第一步:更新系统与安装wget与subversion

 apt-get update && apt-get dist-upgrade

 apt-get install wget subversion

第二步:安装ruby与Metasploit Frame依赖包

 wget http://ininjas.com/repo/debs/ruby_1.9.2-p180-1-1_iphoneos-arm.deb

 wget http://ininjas.com/repo/debs/iconv_1.14-1_iphoneos-arm.deb

 wget http://ininjas.com/repo/debs/zlib_1.2.3-1_iphoneos-arm.deb

 dpkg -i iconv_1.14-1_iphoneos-arm.deb

 dpkg -i zlib_1.2.3-1_iphoneos-arm.deb

 dpkg -i ruby_1.9.2-p180-1-1_iphoneos-arm.deb

安装结束后,为了节省空间,你可以删除这些安装包,注意:*表示上面的安装包,记得不要把有用的deb都删除掉了

 rm -rf *.deb 

检测ruby是否安装成功,查看ruby版本信息

 ruby -v

第三步:安装metasploit framework

 cd /private/var

 svn co https://www.metasploit.com/svn/framework3/trunk/  msf3

运行msf

 cd mfs3/

 ruby msfconsole


三、后记

最好在ipad和iPhone上安装,itouch就算了,系统空间小,会无法运行msf。其实,在iOS设备上安装MSF的方法早在去年网上就有攻略了,那个时候是MSF4.3版本,安装依赖包还是采用的apt.saurik.com/cydia/debs源。



参考资料:

Mobile Pwning:Using Metasploit on iOS

来源:碳基体

objective-c runtime安全措施之三:反汇编( -funroll-loops 编译选项

《O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记反汇编:通过优化编译器选项、去除符号表来复杂化编译后生成的汇编代码(使用反汇编工具结合动态调试工具弄清并篡改程序逻辑)

方法4:使用编译器的 -funroll-loops 选项 完全展开循环结构

原理: -funroll-loops编译选项使得程序中的循环步骤完全展开。这样会增加汇编代码的长度,并且攻击者需要隔离出每个循环,进行单独的修改,从而增大了攻击难度。

问题:在linux环境下编译可以完全展开整个循环逻辑,但是在苹果编译器中目前是不能完全展开,不知道新版xcode中的gcc是否可以。

int main( ) {

int i = 0;

for(i=0; i<1000; ++i) {

puts("This is my loop of secure session checks");

}

}

例子1:在mac os x上使用 –funroll-loops编译选项

$ gcc -o main main.c -funroll-loops -funroll-all-loops

$ otool -tV main

_main:

0000000100000ef0 pushq %rbp

0000000100000ef1 movq %rsp,%rbp

0000000100000ef4 subq $0x10,%rsp

0000000100000ef8 movl $0x00000000,0xf8(%rbp)

0000000100000eff xorb %al,%al

0000000100000f01 leaq 0x00000054(%rip),%rcx

0000000100000f08 movq %rcx,%rdi

0000000100000f0b callq 0x100000f30 ; symbol stub for: _puts

0000000100000f10 movl 0xf8(%rbp),%eax

0000000100000f13 addl $0x01,%eax

0000000100000f16 movl %eax,0xf8(%rbp)

0000000100000f19 movl 0xf8(%rbp),%eax

0000000100000f1c cmpl $0x09,%eax

0000000100000f1f jle 0x100000eff

0000000100000f21 movl 0xfc(%rbp),%eax

0000000100000f24 addq $0x10,%rsp

0000000100000f28 popq %rbp

0000000100000f29 ret

即使使用了–funroll-loops选项,循环也未

例子2:在linux 上使用 –funroll-loops编译选项

080483f0 <main>:

80483f0: 55 push %ebp

80483f1: 89 e5 mov %esp,%ebp

80483f3: 83 e4 f0 and $0xfffffff0,%esp

80483f6: 53 push %ebx

80483f7: 31 db xor %ebx,%ebx

80483f9: 83 ec 1c sub $0x1c,%esp

80483fc: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi

8048400: 83 c3 08 add $0x8,%ebx

8048403: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

804840a: e8 09 ff ff ff call 8048318 <puts@plt>

804840f: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

8048416: e8 fd fe ff ff call 8048318 <puts@plt>

804841b: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

8048422: e8 f1 fe ff ff call 8048318 <puts@plt>

8048427: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

804842e: e8 e5 fe ff ff call 8048318 <puts@plt>

8048433: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

804843a: e8 d9 fe ff ff call 8048318 <puts@plt>

804843f: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

8048446: e8 cd fe ff ff call 8048318 <puts@plt>

804844b: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

8048452: e8 c1 fe ff ff call 8048318 <puts@plt>

8048457: c7 04 24 40 85 04 08 movl $0x8048540,(%esp)

804845e: e8 b5 fe ff ff call 8048318 <puts@plt>

8048463: 81 fb e8 03 00 00 cmp $0x3e8,%ebx

8048469: 75 95 jne 8048400 <main+0x10>

804846b: 83 c4 1c add $0x1c,%esp

804846e: 5b pop %ebx

804846f: 89 ec mov %ebp,%esp

8048471: 5d pop %ebp

8048472: c3 ret

来源:碳基体

objective-c runtime安全措施之三:反汇编(strip)

《O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记反汇编:通过优化编译器选项、去除符号表来复杂化编译后生成的汇编代码(使用反汇编工具结合动态调试工具弄清并篡改程序逻辑)

方法3:使用strip命令除去目标文件中的指定符号

原理:使用strip命令去掉符号表中的指定符号

下面的代码是用来检查是否有debugger的存在

#include <unistd.h>

#include <sys/types.h>

#include <sys/sysctl.h>

#include <string.h>

#include <stdio.h>

int check_debugger( )

{

size_t size = sizeof(struct kinfo_proc);

struct kinfo_proc info;

int ret, name[4];

memset(&info, 0, sizeof(struct kinfo_proc));

name[0] = CTL_KERN;

name[1] = KERN_PROC;

name[2] = KERN_PROC_PID;

name[3] = getpid();

if (ret = (sysctl(name, 4, &info, &size, NULL, 0))) {

return ret; /* sysctl() failed for some reason */

}

return (info.kp_proc.p_flag & P_TRACED) ? 1 : 0;

}

int main( ) {

int i = 0, f;

do {

if (check_debugger())

puts("Eek! I'm being debugged!");

else

puts("I'm doing something really secure here!!");

++i;

sleep(5);

} while(i<10);

}

 

例子1:正常使用nm导出符号表信息

当符号表被导出,check_debugger和main函数的符号和地址对攻击者是清晰可见的

$ nm main

00003038 S _NXArgc

0000303c S _NXArgv

00003044 S ___progname

00002dd8 t __dyld_func_lookup

00001000 A __mh_execute_header

00002de4 T _check_debugger

00003040 S _environ

U _exit

U _getpid

00002ef4 T _main

U _memset

U _puts

U _sysctl

00003034 d dyld__mach_header

00002db8 t dyld_stub_binding_helper

00002d6c T start

这些符号在二进制反汇编代码中可以看到

_check_debugger:

00002de4 e92d4090 push {r4, r7, lr}

00002de8 e28d7004 add r7, sp, #4 @ 0x4

00002dec e24ddf8f sub sp, sp, #572 @ 0x23c

00002df0 e3cdd007 bic sp, sp, #7 @ 0x7

00002df4 e59f00e8 ldr r0, [pc, #232] @ 0x2ee4

00002df8 e28d1040 add r1, sp, #64 @ 0x40

...

_main:

00002ef4 e92d4080 push {r7, lr}

00002ef8 e1a0700d mov r7, sp

00002efc e24dd018 sub sp, sp, #24 @ 0x18

00002f00 e59f0070 ldr r0, [pc, #112] @ 0x2f78

00002f04 e5070008 str r0, [r7, #-8]

00002f08 e59f0068 ldr r0, [pc, #104] @ 0x2f78

00002f0c e58d0008 str r0, [sp, #8]

...

例子2:使用strip后导出符号表信息

$ strip main

$ nm main

00001000 A __mh_execute_header

U _exit

U _getpid

U _memset

U _puts

U _sysctl

攻击者不知道函数出现在地址空间的哪里,甚至完全不会知道check_debugger函数的存在。为了找出具体程序逻辑,攻击者不得不查看上千行汇编代码,如下所示:

00002d6c e59d0000 ldr r0, [sp]

00002d70 e28d1004 add r1, sp, #4 @ 0x4

00002d74 e2804001 add r4, r0, #1 @ 0x1

00002d78 e0812104 add r2, r1, r4, lsl #2

00002d7c e3cdd007 bic sp, sp, #7 @ 0x7

00002d80 e1a03002 mov r3, r2

00002d84 e4934004 ldr r4, [r3], #4

00002d88 e3540000 cmp r4, #0 @ 0x0

00002d8c 1afffffc bne 0x2d84

00002d90 e59fc018 ldr ip, [pc, #24] @ 0x2db0

00002d94 e08fc00c add ip, pc, ip

00002d98 e59cc000 ldr ip, [ip]

00002d9c e12fff3c blx ip

00002da0 e59fc00c ldr ip, [pc, #12] @ 0x2db4

00002da4 e08fc00c add ip, pc, ip

00002da8 e59cc000 ldr ip, [ip]

00002dac e12fff1c bx ip

00002db0 00000280 andeq r0, r0, r0, lsl #5

00002db4 00000274 andeq r0, r0, r4, ror r2

00002db8 e52dc004 push {ip} @ (str ip, [sp, #-4]!)

00002dbc e59fc00c ldr ip, [pc, #12] @ 0x2dd0

00002dc0 e79fc00c ldr ip, [pc, ip]

00002dc4 e52dc004 push {ip} @ (str ip, [sp, #-4]!)

00002dc8 e59fc004 ldr ip, [pc, #4] @ 0x2dd4

00002dcc e79ff00c ldr pc, [pc, ip]

00002dd0 0000026c andeq r0, r0, ip, ror #4

00002dd4 0000022c andeq r0, r0, ip, lsr #4

00002dd8 e59fc000 ldr ip, [pc, #0] @ 0x2de0

00002ddc e79ff00c ldr pc, [pc, ip]

00002de0 00000004 andeq r0, r0, r4

00002de4 e92d4090 push {r4, r7, lr}

00002de8 e28d7004 add r7, sp, #4 @ 0x4

00002dec e24ddf8f sub sp, sp, #572 @ 0x23c

00002df0 e3cdd007 bic sp, sp, #7 @ 0x7

00002df4 e59f00e8 ldr r0, [pc, #232] @ 0x2ee4

00002df8 e28d1040 add r1, sp, #64 @ 0x40

00002dfc e28d202c add r2, sp, #44 @ 0x2c

00002e00 e59f30e0 ldr r3, [pc, #224] @ 0x2ee8

00002e04 e59fc0e0 ldr ip, [pc, #224] @ 0x2eec

00002e08 e59fe0e0 ldr lr, [pc, #224] @ 0x2ef0

00002e0c e58de22c str lr, [sp, #556]

00002e10 e58d1028 str r1, [sp, #40]

00002e14 e58d1024 str r1, [sp, #36]

00002e18 e3a01000 mov r1, #0 @ 0x0

00002e1c e58d2020 str r2, [sp, #32]

00002e20 e3a02f7b mov r2, #492 @ 0x1ec

00002e24 e58d001c str r0, [sp, #28]

00002e28 e59d0024 ldr r0, [sp, #36]

00002e2c e58dc018 str ip, [sp, #24]

00002e30 e58d3014 str r3, [sp, #20]

00002e34 eb000057 bl 0x2f98 @ symbol stub for: _memset

00002e38 e59d0024 ldr r0, [sp, #36]

00002e3c e58d0230 str r0, [sp, #560]

00002e40 e59d0014 ldr r0, [sp, #20]

00002e44 e58d002c str r0, [sp, #44]

00002e48 e59d0018 ldr r0, [sp, #24]

00002e4c e58d0030 str r0, [sp, #48]

00002e50 e59d0014 ldr r0, [sp, #20]

00002e54 e58d0034 str r0, [sp, #52]

00002e58 eb00004b bl 0x2f8c @ symbol stub for: _getpid

00002e5c e58d0038 str r0, [sp, #56]

00002e60 e59d0020 ldr r0, [sp, #32]

00002e64 e59d1028 ldr r1, [sp, #40]

00002e68 e3a02000 mov r2, #0 @ 0x0

00002e6c e1a0300d mov r3, sp

00002e70 e5832004 str r2, [r3, #4]

00002e74 e5832000 str r2, [r3]

00002e78 e58d1010 str r1, [sp, #16]

00002e7c e3a01004 mov r1, #4 @ 0x4

00002e80 e28d3f8b add r3, sp, #556 @ 0x22c

00002e84 e59d2010 ldr r2, [sp, #16]

00002e88 eb000048 bl 0x2fb0 @ symbol stub for: _sysctl

00002e8c e58d003c str r0, [sp, #60]

00002e90 e59d003c ldr r0, [sp, #60]

00002e94 e59d101c ldr r1, [sp, #28]

00002e98 e1500001 cmp r0, r1

00002e9c 1a000000 bne 0x2ea4

00002ea0 ea000002 b 0x2eb0

00002ea4 e59d003c ldr r0, [sp, #60]

00002ea8 e58d0234 str r0, [sp, #564]

00002eac ea000006 b 0x2ecc

00002eb0 e5dd0051 ldrb r0, [sp, #81]

00002eb4 e2000008 and r0, r0, #8 @ 0x8

00002eb8 e1a001a0 lsr r0, r0, #3

00002ebc e58d000c str r0, [sp, #12]

00002ec0 e59d100c ldr r1, [sp, #12]

00002ec4 e58d1234 str r1, [sp, #564]

00002ec8 e58d0008 str r0, [sp, #8]

00002ecc e59d0234 ldr r0, [sp, #564]

00002ed0 e58d0238 str r0, [sp, #568]

00002ed4 e59d0238 ldr r0, [sp, #568]

00002ed8 e247d004 sub sp, r7, #4 @ 0x4

00002edc e8bd4090 pop {r4, r7, lr}

00002ee0 e12fff1e bx lr

00002ee4 00000000 andeq r0, r0, r0

00002ee8 00000001 andeq r0, r0, r1

00002eec 0000000e andeq r0, r0, lr

00002ef0 000001ec andeq r0, r0, ip, ror #3

00002ef4 e92d4080 push {r7, lr}

00002ef8 e1a0700d mov r7, sp

00002efc e24dd018 sub sp, sp, #24 @ 0x18

00002f00 e59f0070 ldr r0, [pc, #112] @ 0x2f78

00002f04 e5070008 str r0, [r7, #-8]

00002f08 e59f0068 ldr r0, [pc, #104] @ 0x2f78

00002f0c e58d0008 str r0, [sp, #8]

00002f10 ebffffb3 bl 0x2de4

00002f14 e59d1008 ldr r1, [sp, #8]

00002f18 e1500001 cmp r0, r1

00002f1c 1a000000 bne 0x2f24

00002f20 ea000004 b 0x2f38

00002f24 e59f0054 ldr r0, [pc, #84] @ 0x2f80

00002f28 e08f0000 add r0, pc, r0

00002f2c eb00001c bl 0x2fa4 @ symbol stub for: _puts

00002f30 e58d0004 str r0, [sp, #4]

00002f34 ea000003 b 0x2f48

00002f38 e59f003c ldr r0, [pc, #60] @ 0x2f7c

00002f3c e08f0000 add r0, pc, r0

00002f40 eb000017 bl 0x2fa4 @ symbol stub for: _puts

00002f44 e58d0000 str r0, [sp]

00002f48 e59f0034 ldr r0, [pc, #52] @ 0x2f84

00002f4c e59f1034 ldr r1, [pc, #52] @ 0x2f88

00002f50 e5172008 ldr r2, [r7, #-8]

00002f54 e0821001 add r1, r2, r1

00002f58 e5071008 str r1, [r7, #-8]

00002f5c e5171008 ldr r1, [r7, #-8]

00002f60 e1510000 cmp r1, r0

00002f64 daffffe7 ble 0x2f08

00002f68 e5170004 ldr r0, [r7, #-4]

00002f6c e1a0d007 mov sp, r7

00002f70 e8bd4080 pop {r7, lr}

00002f74 e12fff1e bx lr

00002f78 00000000 andeq r0, r0, r0

00002f7c 00000092 muleq r0, r2, r0

00002f80 0000008c andeq r0, r0, ip, lsl #1

00002f84 00000009 andeq r0, r0, r9

00002f88 00000001 andeq r0, r0, r1

跟踪这些代码是比较困难的。假如check_debugger函数是inline的,将更难弄清楚逻辑(原因见http://danqingdani.blog.163.com/blog/static/18609419520123111202352/ )。

来源:碳基体

objective-c runtime安全措施之三:反汇编(-03 编译选项)

《O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记反汇编:通过优化编译器选项、去除符号表来复杂化编译后生成的汇编代码(使用反汇编工具结合动态调试工具弄清并篡改程序逻辑)

方法2:使用编译器的 -03 选项 

原理:-03编译选项可以将具体的计算逻辑隐藏起来,直接输出计算结果

int main(int argc, char **argv)

{

int i;

int a = 0;

for(i=0;i<10;++i) {

a += i;

}

printf("%d\n", a);

return 0;

}

例子1:普通编译方式编译的汇编代码

_main:

0000000100000ec0 pushq %rbp

0000000100000ec1 movq %rsp,%rbp

0000000100000ec4 subq $0x20,%rsp

0000000100000ec8 movl %edi,0xfc(%rbp)

0000000100000ecb movq %rsi,0xf0(%rbp)

0000000100000ecf movl $0x00000000,0xe0(%rbp)

0000000100000ed6 movl $0x00000000,0xe4(%rbp)

0000000100000edd jmp 0x100000ef3

0000000100000edf movl 0xe0(%rbp),%eax

0000000100000ee2 movl 0xe4(%rbp),%ecx

0000000100000ee5 addl %ecx,%eax

0000000100000ee7 movl %eax,0xe0(%rbp)

0000000100000eea movl 0xe4(%rbp),%eax

0000000100000eed addl $0x01,%eax        ;加1

0000000100000ef0 movl %eax,0xe4(%rbp)

0000000100000ef3 movl 0xe4(%rbp),%eax

0000000100000ef6 cmpl $0x09,%eax         ;加9

0000000100000ef9 jle 0x100000edf

0000000100000efb movl 0xe0(%rbp),%eax

0000000100000efe xorb %cl,%cl

0000000100000f00 leaq 0x00000055(%rip),%rdx

0000000100000f07 movq %rdx,%rdi

0000000100000f0a movl %eax,%esi

0000000100000f0c movb %cl,%al

0000000100000f0e callq 0x100000f30 ; symbol stub for: _printf

0000000100000f13 movl $0x00000000,0xe8(%rbp)

0000000100000f1a movl 0xe8(%rbp),%eax

0000000100000f1d movl %eax,0xec(%rbp)

0000000100000f20 movl 0xec(%rbp),%eax

0000000100000f23 addq $0x20,%rsp

0000000100000f27 popq %rbp

0000000100000f28 ret

例子2:采用 -03 编译选项编译的汇编代码

  

_main:

0000000100000f10 pushq %rbp

0000000100000f11 movq %rsp,%rbp

0000000100000f14 movl $0x0000002d,%esi  ;最终结果45

0000000100000f19 xorb %al,%al

0000000100000f1b leaq 0x0000003a(%rip),%rdi

0000000100000f22 callq 0x100000f32 ; symbol stub for: _printf

0000000100000f27 xorl %eax,%eax

0000000100000f29 popq %rbp

0000000100000f2a ret

优化后的输出直接计算出结果0x2D(45,1+2+3+4+5+6+7+8+9的和),将其发送给printf函数,没有显示任何循环过程。这样依赖,攻击者也完全看不出计算逻辑了。下面的调试过程,显示了优化后,直接在寄存器中创建和存储了一个常量。

  

$ gdb -q ./testprog

Reading symbols for shared libraries .. done

(gdb) break printf

Function "printf" not defined.

Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 1 (printf) pending.

(gdb) r

Starting program: /Users/jonz/Downloads/a

Reading symbols for shared libraries +........................ done

Breakpoint 1 at 0x7fff8b69922e

Pending breakpoint 1 - "printf" resolved

(gdb) info reg

rax 0x0 0

rbx 0x0 0

rcx 0x0 0

rdx 0x100000f5c 4294971228

rsi 0x2d 45

  

rdi 0x100000f5c 4294971228

...

来源:碳基体

objective-c runtime安全措施之三:反汇编(inline编译方式)

《O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记

反汇编:通过优化编译器选项、去除符号表来复杂化编译后生成的汇编代码(使用反汇编工具结合动态调试工具弄清并篡改程序逻辑)

  

方法1:采用inline函数

原理:设置inline属性、static属性,可以使得编译后生成的目标代码在反汇编成汇编代码时,不容易阅读,弄清其中的逻辑,因为inline会导致汇编代码中是直接将inline函数的函数体拷贝到main中,而不是清晰的call调用;static属性,则会让编译生成的二进制代码中,没有清晰的符号表,同样使得攻击者很难通过逆向弄清楚程序逻辑。

例子1. non-inline函数和其反汇编代码

#include <stdlib.h>

int is_session_valid(int session_id) {//session_id为偶数返回1,为奇数返回0

if (session_id % 2 == 0) {

return 1;

} else {

return 0;

}

}

 

int main( ) {

int session = 3;

if (! is_session_valid(session))

return EXIT_FAILURE;

/*

* Do something else

*/

if (! is_session_valid(session))

return EXIT_FAILURE;

/*

* Do something else

*/

if (! is_session_valid(session))

return EXIT_FAILURE;

return EXIT_SUCCESS;

}

编译$ gcc -o securitycheck securitycheck.c

使用otool工具反汇编该程序,为了方便阅读start函数已经被移除了。

$ otool -tV securitycheck

_is_session_valid:

0000000100000e70 pushq %rbp

0000000100000e71 movq %rsp,%rbp

0000000100000e74 movl %edi,0xfc(%rbp)

0000000100000e77 movl 0xfc(%rbp),%eax

0000000100000e7a andl $0x01,%eax

0000000100000e7d cmpl $0x00,%eax

0000000100000e80 jne 0x100000e8b

0000000100000e82 movl $0x00000001,0xf4(%rbp)

0000000100000e89 jmp 0x100000e92

0000000100000e8b movl $0x00000000,0xf4(%rbp)

0000000100000e92 movl 0xf4(%rbp),%eax

0000000100000e95 movl %eax,0xf8(%rbp)

0000000100000e98 movl 0xf8(%rbp),%eax

0000000100000e9b popq %rbp

0000000100000e9c ret

0000000100000e9d nopl (%rax)

_main:

0000000100000ea0 pushq %rbp

0000000100000ea1 movq %rsp,%rbp

0000000100000ea4 subq $0x10,%rsp

0000000100000ea8 movl $0x00000003,0xf4(%rbp)

0000000100000eaf movl 0xf4(%rbp),%eax

0000000100000eb2 movl %eax,%edi

0000000100000eb4 callq _is_session_valid

0000000100000eb9 movl %eax,%ecx

0000000100000ebb cmpl $0x00,%ecx

0000000100000ebe jne 0x100000ec9

0000000100000ec0 movl $0x00000001,0xf8(%rbp)

0000000100000ec7 jmp 0x100000f04

0000000100000ec9 movl 0xf4(%rbp),%eax

0000000100000ecc movl %eax,%edi

0000000100000ece callq _is_session_valid

0000000100000ed3 movl %eax,%ecx

0000000100000ed5 cmpl $0x00,%ecx

0000000100000ed8 jne 0x100000ee3

0000000100000eda movl $0x00000001,0xf8(%rbp)

0000000100000ee1 jmp 0x100000f04

0000000100000ee3 movl 0xf4(%rbp),%eax

0000000100000ee6 movl %eax,%edi

0000000100000ee8 callq _is_session_valid

0000000100000eed movl %eax,%ecx

0000000100000eef cmpl $0x00,%ecx

0000000100000ef2 jne 0x100000efd

0000000100000ef4 movl $0x00000001,0xf8(%rbp)

0000000100000efb jmp 0x100000f04

0000000100000efd movl $0x00000000,0xf8(%rbp)

0000000100000f04 movl 0xf8(%rbp),%eax

0000000100000f07 movl %eax,0xfc(%rbp)

0000000100000f0a movl 0xfc(%rbp),%eax

0000000100000f0d addq $0x10,%rsp

0000000100000f11 popq %rbp

0000000100000f12 ret

 

如你所知,is_sesssion_valid函数和main函数的定义是非常清晰的。攻击者是非常容易通过动态调试设置断点的方法修改is_session_valid函数的返回值来绕过检查。

$ gdb -q ./securitycheck

Reading symbols for shared libraries .. done

(gdb) break is_session_valid

Breakpoint 1 at 0x100000e77

(gdb) commands

Type commands for when breakpoint 1 is hit, one per line.

End with a line saying just "end".

>return 1

>continue

>end

(gdb) r

Starting program: /Users/jonz/securitycheck

Reading symbols for shared libraries +........................ done

Breakpoint 1, 0x0000000100000e77 in is_session_valid ()

Breakpoint 1, 0x0000000100000e77 in is_session_valid ()

Breakpoint 1, 0x0000000100000e77 in is_session_valid ()

Program exited normally.

(gdb)

程序在第一次调用is_session_valid时不会退出,因为调试器将is_session_valid函数值改成了1.

 

例子2:inline函数和其反汇编代码

#include <stdlib.h>

inline int is_session_valid(int session_id) {

if (session_id % 2 == 0) {

return 1;

} else {

return 0;

}

}

int main( ) {

int session = 3;

if (! is_session_valid(session))

return EXIT_FAILURE;

/*

* Do something else

*/

if (! is_session_valid(session))

return EXIT_FAILURE;

/*

* Do something else

*/

if (! is_session_valid(session))

return EXIT_FAILURE;

return EXIT_SUCCESS;

}

编译, -finline-functions告诉编译器尽可能的采用inline编译方式;-Winline告诉编译器在不能使用inline编译方式编译时报错

$ gcc -o securitycheck securitycheck.c -finline-functions -Winline

使用otool工具反汇编该程序

$ otool -tV securitycheck

_is_session_valid:

0000000100000e20 pushq %rbp

0000000100000e21 movq %rsp,%rbp

0000000100000e24 movl %edi,0xfc(%rbp)

0000000100000e27 movl 0xfc(%rbp),%eax

0000000100000e2a andl $0x01,%eax

0000000100000e2d cmpl $0x00,%eax

0000000100000e30 jne 0x100000e3b

0000000100000e32 movl $0x00000001,0xf4(%rbp)

0000000100000e39 jmp 0x100000e42

0000000100000e3b movl $0x00000000,0xf4(%rbp)

0000000100000e42 movl 0xf4(%rbp),%eax

0000000100000e45 movl %eax,0xf8(%rbp)

0000000100000e48 movl 0xf8(%rbp),%eax

0000000100000e4b popq %rbp

0000000100000e4c ret

0000000100000e4d nopl (%rax)

_main:

0000000100000e50 pushq %rbp

0000000100000e51 movq %rsp,%rbp

0000000100000e54 movl $0x00000003,0xd0(%rbp)

0000000100000e5b movl 0xd0(%rbp),%eax

0000000100000e5e movl %eax,0xe4(%rbp)

0000000100000e61 movl 0xe4(%rbp),%eax

0000000100000e64 andl $0x01,%eax

0000000100000e67 cmpl $0x00,%eax

0000000100000e6a jne 0x100000e75

0000000100000e6c movl $0x00000001,0xdc(%rbp)

0000000100000e73 jmp 0x100000e7c

0000000100000e75 movl $0x00000000,0xdc(%rbp)

0000000100000e7c movl 0xdc(%rbp),%eax

0000000100000e7f movl %eax,0xe0(%rbp)

0000000100000e82 movl 0xe0(%rbp),%eax

0000000100000e85 cmpl $0x00,%eax

0000000100000e88 jne 0x100000e93

0000000100000e8a movl $0x00000001,0xd4(%rbp)

0000000100000e91 jmp 0x100000f0a

0000000100000e93 movl 0xd0(%rbp),%eax

0000000100000e96 movl %eax,0xfc(%rbp)

0000000100000e99 movl 0xfc(%rbp),%eax

0000000100000e9c andl $0x01,%eax

0000000100000e9f cmpl $0x00,%eax

0000000100000ea2 jne 0x100000ead

0000000100000ea4 movl $0x00000001,0xf4(%rbp)

0000000100000eab jmp 0x100000eb4

0000000100000ead movl $0x00000000,0xf4(%rbp)

0000000100000eb4 movl 0xf4(%rbp),%eax

0000000100000eb7 movl %eax,0xf8(%rbp)

0000000100000eba movl 0xf8(%rbp),%eax

0000000100000ebd cmpl $0x00,%eax

0000000100000ec0 jne 0x100000ecb

0000000100000ec2 movl $0x00000001,0xd4(%rbp)

0000000100000e91 jmp 0x100000f0a

0000000100000e93 movl 0xd0(%rbp),%eax

0000000100000e96 movl %eax,0xfc(%rbp)

0000000100000e99 movl 0xfc(%rbp),%eax

0000000100000e9c andl $0x01,%eax

0000000100000e9f cmpl $0x00,%eax

0000000100000ea2 jne 0x100000ead

0000000100000ea4 movl $0x00000001,0xf4(%rbp)

0000000100000eab jmp 0x100000eb4

0000000100000ead movl $0x00000000,0xf4(%rbp)

0000000100000eb4 movl 0xf4(%rbp),%eax

0000000100000eb7 movl %eax,0xf8(%rbp)

0000000100000eba movl 0xf8(%rbp),%eax

0000000100000ebd cmpl $0x00,%eax

0000000100000ec0 jne 0x100000ecb

0000000100000ec2 movl $0x00000001,0xd4(%rbp)

0000000100000ec9 jmp 0x100000f0a

0000000100000ecb movl 0xd0(%rbp),%eax

0000000100000ece movl %eax,0xf0(%rbp)

0000000100000ed1 movl 0xf0(%rbp),%eax

0000000100000ed4 andl $0x01,%eax

0000000100000ed7 cmpl $0x00,%eax

0000000100000eda jne 0x100000ee5

0000000100000edc movl $0x00000001,0xe8(%rbp)

0000000100000ee3 jmp 0x100000eec

0000000100000ee5 movl $0x00000000,0xe8(%rbp)

0000000100000eec movl 0xe8(%rbp),%eax

0000000100000eef movl %eax,0xec(%rbp)

0000000100000ef2 movl 0xec(%rbp),%eax

0000000100000ef5 cmpl $0x00,%eax

0000000100000ef8 jne 0x100000f03

0000000100000efa movl $0x00000001,0xd4(%rbp)

0000000100000f01 jmp 0x100000f0a

0000000100000f03 movl $0x00000000,0xd4(%rbp)

0000000100000f0a movl 0xd4(%rbp),%eax

0000000100000f0d movl %eax,0xd8(%rbp)

0000000100000f10 movl 0xd8(%rbp),%eax

0000000100000f13 popq %rbp

0000000100000f14 ret

新的反汇编代码有非常多的不同, is_session_valid函数不会在main函数中被调用了,而是在main函数中将is_session_valid的汇编代码拷贝了3次

例子3:static inline函数和其反汇编代码

  

#include <stdlib.h>

static int is_session_valid(int session_id) __attribute__((always_inline));

  

int is_session_valid(int session_id) {

if (session_id % 2 == 0) {

return 1;

} else {

return 0;

}

}

...

反汇编

  

$ otool -tV securitycheck

securitycheck:

(__TEXT,__text) section

start:

0000000100000e40 pushq $0x00

0000000100000e42 movq %rsp,%rbp

0000000100000e45 andq $0xf0,%rsp

0000000100000e49 movq 0x08(%rbp),%rdi

0000000100000e4d leaq 0x10(%rbp),%rsi

0000000100000e51 movl %edi,%edx

0000000100000e53 addl $0x01,%edx

0000000100000e56 shll $0x03,%edx

0000000100000e59 addq %rsi,%rdx

0000000100000e5c movq %rdx,%rcx

0000000100000e5f jmp 0x100000e65

0000000100000e61 addq $0x08,%rcx

0000000100000e65 cmpq $0x00,(%rcx)

0000000100000e69 jne 0x100000e61

0000000100000e6b addq $0x08,%rcx

0000000100000e6f callq _main

0000000100000e74 movl %eax,%edi

0000000100000e76 callq 0x100000f46 ; symbol stub for: _exit

0000000100000e7b hlt

0000000100000e7c nop

0000000100000e7d nop

0000000100000e7e nop

0000000100000e7f nop

_main:

0000000100000e80 pushq %rbp

0000000100000e81 movq %rsp,%rbp

0000000100000e84 movl $0x00000003,0xd0(%rbp)

0000000100000e8b movl 0xd0(%rbp),%eax

0000000100000e8e movl %eax,0xe4(%rbp)

0000000100000e91 movl 0xe4(%rbp),%eax

0000000100000e94 andl $0x01,%eax

0000000100000e97 cmpl $0x00,%eax

...

因为声明了static 属性,反汇编代码中没有了符号表说明,因此使得攻击者难以通过反汇编代码弄清楚程序的逻辑。方法3中将讲述另一种从二进制代码中隐藏符号表的方法,特别是在不能将函数声明为static时比较适用。

来源:碳基体

objective-c runtime安全措施之二:反注入

O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记

反注入:在类函数被调用前做完整性检测(预防应用自定义函数或apple标准库函数被修改或替换)

  

原理:调用dladdr()函数检查类方法的基本信息是否合法

  

例子1:检查Foundation框架类中NSMutableURLRequest基类(用于改变URL请求)的setHTTPBody方法的基本信息

  

#include <dlfcn.h>

#include <objc/objc.h>

#include <objc/runtime.h>

#include <stdio.h>

#include <string.h>

int main() {

Dl_info info;

  

IMP imp = class_getMethodImplementation(

objc_getClass("NSMutableURLRequest"),

sel_registerName("setHTTPBody:"));

printf("pointer %p\n", imp);

if (dladdr(imp, &info)) {

printf("dli_fname: %s\n", info.dli_fname);

printf("dli_sname: %s\n", info.dli_sname);

printf("dli_fbase: %p\n", info.dli_fbase);

printf("dli_saddr: %p\n", info.dli_saddr);

} else {

printf("error: can't find that symbol.\n");

}

}

在Mac OS上使用gcc编译

$ gcc -o main main.m -lobjc -framework Foundation

然后运行该程序和观察输出,这些信息(地址空间、文件名、符号名)可以确认该函数来源、是否合法

$ ./main

  

pointer 0x7fff8e7aba62

  

dli_fname: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation

  

dli_sname: -[NSMutableURLRequest(NSMutableHTTPURLRequest) setHTTPBody:]

  

dli_fbase: 0x7fff8e633000

  

dli_saddr: 0x7fff8e7aba62

  

例子2:使用dladdr函数检查类中的所有方法的通用代码

  

#include <dlfcn.h>

#include <stdio.h>

#include <objc/objc.h>

#include <objc/runtime.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

static inline BOOL validate_methods(const char *, const char *)

__attribute__((always_inline));

BOOL validate_methods(const char *cls, const char *fname) {

Class aClass = objc_getClass(cls);

Method *methods;

unsigned int nMethods;

Dl_info info;

IMP imp;

char buf[128];

Method m;

if (!aClass)

return NO;

methods = class_copyMethodList(aClass, &nMethods);

while(nMethods--) {

m = methods[nMethods];

printf("validating [ %s %s ]\n",

(const char *) class_getName(aClass),

(const char *) method_getName(m));

imp = method_getImplementation(m);

if (!imp) {

printf("error: method_getImplementation(%s) failed\n",

(const char *) method_getName(m));

free(methods);

return NO;

}

if (! dladdr(imp, &info)) {

printf("error: dladdr() failed for %s\n",

(const char *)method_getName(m));

free(methods);

return NO;

}

/* Validate image path */

  

if (strcmp(info.dli_fname, fname))

goto FAIL;

/* Validate class name in symbol */

  

snprintf(buf, sizeof(buf), "[%s ",

(const char *) class_getName(aClass));

if (strncmp(info.dli_sname+1, buf, strlen(buf)))

{

snprintf(buf, sizeof(buf), "[%s(",

(const char *) class_getName(aClass));

if (strncmp(info.dli_sname+1, buf, strlen(buf)))

goto FAIL;

}

/* Validate selector in symbol */

  

snprintf(buf, sizeof(buf), " %s]",

(const char *) method_getName(m));

if (strncmp(info.dli_sname + (strlen(info.dli_sname) - strlen(buf)),

buf, strlen(buf)))

{

goto FAIL;

}

}

return YES;

FAIL:

printf("method %s failed integrity test:\n",

(const char *)method_getName(m));

printf(" dli_fname: %s\n", info.dli_fname);

printf(" dli_sname: %s\n", info.dli_sname);

printf(" dli_fbase: %p\n", info.dli_fbase);

printf(" dli_saddr: %p\n", info.dli_saddr);

free(methods);

return NO;

}

【注意】

  

  1. 重命名检查函数(例如不要用validate_methods这样具有明显意义的名字)

  

  1. 在应用的多处加入检查函数,任何与敏感数据交互的方法在执行前都需要检查

  

  1. 例子中的logging和printf语句只是用来调试,代码正式发布前要移除

  

  1. 验证完整性只是提高了攻击的门槛,不能完全防御黑客,需要综合应用多种技巧,例如思路一中的反调试技巧,及马上要介绍的反汇编技巧。


来源:碳基体

objective-c runtime安全措施之一:反调试

<<O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记


反调试:检查是否有debugger在trace游戏进程 (预防动态调试进程)

方法1: 检查进程的状态是否为 P_TRACED 

原理:当进程被调试的时候,内核自动设置进程选项为P_TRACED。因此可以通过检查该标记来确认是否被调试

  

例子1:check_debugger()

  

#include <unistd.h>

#include <sys/types.h>

#include <sys/sysctl.h>

#include <string.h>

static int check_debugger( ) __attribute__((always_inline));

  

int check_debugger( )

{

size_t size = sizeof(struct kinfo_proc);

struct kinfo_proc info;

int ret, name[4];

memset(&info, 0, sizeof(struct kinfo_proc));

name[0] = CTL_KERN;

name[1] = KERN_PROC;

name[2] = KERN_PROC_PID;

name[3] = getpid();

if (ret = (sysctl(name, 4, &info, &size, NULL, 0))) {

return ret; /* sysctl() failed for some reason */

}

return (info.kp_proc.p_flag & P_TRACED) ? 1 : 0;

  

}

【注意】

1. 为了让程序以inline方式编译,需要设置编译器的优化选项,-0z(函数以inline方式编译),-fast(加快编译速度)

  

2. 为了避免sysctl被替换,需要在调用该函数前验证其完整性(在下面会介绍如何验证sysctl函数完整性)

  

--------------------------------------------------------------------------------------------------------------------------------------------------

方法2:调用ptrace请求来检查进程是否被调试

原理,调用ptrace请求的PT_DENY_ATTACH方法。使用该方法后,下面两种情况都会导致调试器崩溃,应用退出。

(1)如果应用使用调试器来运行,调试器会崩溃;(下面以调试iTunes为例)

$ gdb -q /Applications/iTunes.app/Contents/MacOS/iTunes

Reading symbols for shared libraries .................................... done

(gdb) r

Starting program: /Applications/iTunes.app/Contents/MacOS/iTunes

Reading symbols for shared libraries ++++++++++++++++++++++++++++++....++++

+....................................................................................

............................................................... done

Program exited with code 055.

(gdb)

(2)如果应用运行中,使用调试器,调试器也会崩溃。

$ gdb -q -p 3933

Attaching to process 3933.

Segmentation fault: 11

 

Mac OS X系统中

  

#include <sys/ptrace.h>

int main( ) {

ptrace(PT_DENY_ATTACH, 0, 0, 0);

  

...

}

iOS系统中

  

int main( ) {

ptrace(31, 0, 0, 0); //因为PT_DENY_ATTACH只存在于iOS模拟器头文件中,所以用31来代替

  

...

}

【注意】

1. ptrace方法可以通过打断点的方法绕过,如下所示:

  

# gdb ?1 ./main

  

Reading symbols for shared libraries . done

(gdb) b ptrace

  

Function "ptrace" not defined.

Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 1 (ptrace) pending.

(gdb) commands

  

Type commands for when breakpoint 1 is hit, one per line.

End with a line saying just "end".

>return

  

>continue

  

>end

  

(gdb) run

  

Starting program: /private/var/root/main

Reading symbols for shared libraries .............................. done

Breakpoint 1 at 0x342afa98

Pending breakpoint 1 - "ptrace" resolved

Breakpoint 1, 0x342afa98 in ptrace ()

I'm doing something really secure here!!

2.由于可能被攻击者绕过该方法的调用,在应用的多处增加ptrace函数会提高应用的安全性


来源:碳基体

iOS与Android的一些区别

前言

总结了在做iOS与Android安全研究时,需要了解的区别。包括系统架构的区别,安装包的区别,文件系统的区别,二进制文件的区别,安全机制的区别与版权保护的区别



一、系统架构的区别(左边iOS,右边Android)


1.iOS架构

分为4层,分别为

(1)cocoa Touch层:包括Foundation Framework,UIkit Framework,Address Book UI Framework

(2)媒体层:包括图像(Quartz,Core Animation,OpenGL ES),音频(Core Audio,OpenAL)和视频技术

(3)核心服务层:例如CoreFoundation.framework是基于C语言的接口集,提供应用的基本数据管理和服务功能;CFNetwork.framework是一组高性能的C语言接口集,提供网络协议的面向对象的抽象。开发者可以使用CFNetwork框架操作协议栈,并且可以访问底层的结构如BSD sockets等;Security.framework提供管理证书,公钥/私钥对和信任策略等的接口来确保应用数据的安全性

(4)核心OS层: 基于Mac操作系统


2.Android架构

分为4层,分别为

(1)应用程序:使用java编写

(2)应用程序框架:

  • 活动管理器:用来管理应用程序生命周期并提供常用的导航回退功能

  • 资源管理器:提供非代码资源的访问,如本地字符串、图形和布局文件

  • 内容提供器:用来存放和获取数据并使用这些数据可以被所有应用程序访问

  • XMPP服务器:基于XML的网络实时通讯协议

(3)系统运行库+Android运行时

系统运行库:android包括一些c/c++库,这些库能被android系统中的不同的组件使用,例如libc是一个从BSD继承来的标准c系统函数库;webkit为Web浏览器引擎,支持Android浏览器(苹果Safari的引擎也是webkit)。SQLite为功能强劲的轻量级关系数据库引擎(iOS也是采用的该数据库引擎)。

Android运行时:包括核心库(基本类库,例如data structure,network,file system等),很多实现代码都来自Apache Harmony项目,主要目的时保证虚拟机的类库能够与Java SE类库最大程度的兼容)与Dalvik虚拟机(用于运行dex:dalvik executable格式二进制可执行文件,该虚拟机较之java虚拟机的最大区别是Dalvik基于寄存器)

(4)linux内核:基于linux 2.6内核


总的来说,如果要深层次挖掘Android的漏洞就要明白linux内核安全,如果要挖身深层次挖掘iOS的漏洞就要了解Mac内核安全(BSD内核安全)。

二、安装包的区别(左边iOS,右边Android)

 总的来说,安装包由可执行文件,资源文件,签名文件,配置文件组成。


 三、文件系统的区别(左边iOS,右边Android)

注意: android的sdcard是不受文件访问控制约束的


四、二进制文件的区别

1. iOS二进制文件格式

mach-o , dylib

 

2.Android二进制文件的区别

dex, so(ELF shared object)


五、安全机制的区别

1. iOS安全机制

(1)安全沙箱

进程隔离,每个程序都有自己的虚拟地址空间。应用程序在安装之后,系统就通过计算得到一个标识,然后基于应用程序的根目录和这个标识构件一个指向应用程序目录的路径,其他应用程序都不能进行访问。iOS 的沙箱是基于TrustBSD策略框架的内核扩展模块,针对每个进程都可以制定特殊的沙箱配置文件,沙箱配置文件编译后以2进制的方式保存在KernelCache文件中(iOS下),需反汇编成可读的文本格式来查看内核中的沙盒规则


(2)代码签名

apple需要所有开发人员对自己的iPhone应用程序使用数字签名技术。这个签名用来标识应用程序的开发者以及保证应用程序在签名之后不被更改和损坏。开发者证书由apple提供(这是与android最大的区别,android是自签名),有以下两类证书:

Developer Certificate:用于本机测试

Distribution Certificate:Ad-hoc用于100台设备以内的测试和共享;app store用于发布应用程序

所有的可执行文件、库文件都需要Apple签名后才可以运行在iOS中,内核会在调用execve之前检测Mach-o文件中的LC_CODE_SIGNATURE段是否有效和可信任的,iOS启动的时候同样也会检测KernelCache的签名是否有效

代码签名的破坏可见《iOS平台游戏安全之IPA破解原理及防御

(3)ASLR(address space layout randomisation)/DEP


PIE: position independent executable


iOS 4.3后开始支持该功能,iOS上的预装应用都开启了该功能

 

ASLR的其他信息可见《ASLR


 

DEP(Data execution Prevention),内核不允许将页面保护标志设置为RWS,并在ARMv6引入XN(execute never)标志位,从而在硬件上支持执行保护。


(4)文件系统加密

 

Data protection APIs

NSFileProtectionNone

NSFileProtectionComplete

NSFileProtectionCompleteUnlessOpen

NSFileProtectionCompleteUntilUserAuthentication

KSecAttrAccessibleAlways

KSecAttrAccessibleWhenUnlocked

KSecAttrAccessibleAfterFirstUnlock

KSecAttrAccessibleAlwaysThisdeviceOnly

KSecAttrAccessibleWhenUnlockedThisDeviceOnly

KSecAttrAccessibleAfterFirstUnlockThisDeviceOnly


2.Android安全机制

(1)安全沙箱

每一个Android应用程序(apk文件)会在安装时分配一个独有的linux用户ID(即一个用户id识别一个应用程序),这就为它建立了一个沙箱,使其不能与其他应用程序进行接触。这个用户ID在安装时分配,并在该设备上一直保持同一个数值。所有存储在应用程序中的数据都会赋予该应用程序的用户ID,使其他应用程序无法访问这些数据(如需要访问,见(4)文件访问控制)。


(2)代码签名

采用自签名机制,不需要权威机构签名和审核,完全由用户自行判断是否信任该程序(与iOS区别很大)。签名是为了:

  • 识别代码的作者

  • 检测应用程序是否发生了变化

  • 在应用程序之间建立信任:使用相同数字签名签署的两个应用程序可以相互授予权限来反问基于签名的API,如果他们共享用户ID,那么也可以运行在同一进程中,从而允许访问对方的代码和数据(见(4)文件访问控制)。

代码签名的详细机制可见《Android签名与签名校验


(3)manifest权限管理

Android要求用户在使用API时进行申明,称为permission,对一些敏感API的使用在安装时就可以给用户风险提示,由用户确定是否安装,例如READ_CONTACTS为读取通讯录数据权限。权限在AndroidManifest.xml文件里进行设置,通过<manifest../>元素添加<uses-permission.../>子元素,如下图所示


 

permission分为4个保护等级:normal,dangerous,signature,signatureorsystem。不同的保护级别代表程序要使用此权限时的认证方式。

normal:只要申请就可以使用

dangerous:在安装时需要用户确认才可以使用,最经常使用的权限

signature:告诉android系统这个权限只能授予拥有同样数字签名并且定义了该权限的应用程序

signatureorsystem:需要开发者的应用和系统使用同一个数字证书,即需要系统或者平台签名,真实手机中的系统签名只有厂商知道


应用程序也可以定制权限以保护自己的资源,当前ita应用程序想要访问一个应用程序的受保护资源时,就必须通过它们自己的manifest文件请求适当的权限

 

(4)文件访问控制

因为安全沙箱的存在导致不同应用程序之间的数据(文件)是隔离的。在通过

getSharedPreferences(filename,operatingMode)

openFileOutput(filename,operatingMode)

openOrCreateDatabase(filename,operatingMode, SQLiteDatabase.CursorFactory)

等方法来创建一个新文件时,可以通过指定文件的存储方式operationMode来进行文件的访问控制,android文件存储有以下4种方式:

Context.MODE_PRIVATE:默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容

Context.MODE_APPEND:代表该文件是私有数据,只能被应用本身访问,在该模式下,会检查文件是否存在,存在就往文件追加内容,否则就创建新文件

Context.MODE_WORLD_READABLE:表示当前文件可以被其他应用读取

Context.MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。


除了使用Context.MODE_WORLD_READABLE/Context.MODE_WORLD_WRITEABLE标识位来使两个程序相互访问对方的资源。还可以通过设置AndroidManifest.xml文件的manifest标签中的sharedUserId属性,来使得不同的应用程序共用同一个用户ID,并且这些应用程序还使用同一个签名签署,在满足以上两个条件(共同的sharedUserID,共同的签名)的情况下就可以实现不同应用程序相互资源的访问了,如下图所示


 

(5)ASLR

android 4.1后才开始支持完整版功能


六、版权保护的区别

1. iOS

App store,采用FairPlay DRM保护商店下载应用

2. Android

(1)google play store,采用Android License Verification Library保护商店下载应用

(2)Amazon Appstore DRM

(3)其他


参考:

《移动互联网之智能终端安全揭秘》Android与iOS章

来源:碳基体