creantan 发表于 2015-11-3 16:20:02

2015第2届移动安全挑战赛iOS第二题分析

第二题题目如下
环境:iPhone5C(A1529) iOS 8.4 kernelcache ,解密后的kernelcache见附件

求得下列地址(减去kaslr):
(1)设备/dev/random,对应结构体cdevsw中d_read, d_write, d_ioctl在题目给出kernelcache中的地址。
(2)设备/dev/pf,对应结构体cdevsw中d_read, d_write, d_ioctl在题目给出kernelcache中的地址。
(3)设备/dev/ptmx,对应结构体cdevsw中d_read, d_write, d_ioctl在题目给出kernelcache中的地址。

假设上述地址的结果是:
/dev/random
d_read:0x80001231
d_write:0x80001253
d_ioctl:0x80001275
/dev/pf
d_read:0x80201297
d_write:0x802012b9
d_ioctl:0x801012db
/dev/ptmx
d_read:0x802012ed
d_write:0x802012ff
d_ioctl:0x80201211

那么答案的格式应该是:(用#号分隔)
0x80001231#0x80001253#0x80001275#0x80201297#0x802012b9#0x801012db#0x802012ed#0x802012ff#0x80201211


我们知道iOS内核是基于XNU内核改的,XNU for mac的代码可以从苹果官方下载到:
xnu-2782.40.9/bsd/dev/random/randomdev.c

static struct cdevsw random_cdevsw =
{
        random_open,                /* open */
        random_close,                /* close */
        random_read,                /* read */
        random_write,                /* write */
        random_ioctl,                /* ioctl */
        (stop_fcn_t *)nulldev, /* stop */
        (reset_fcn_t *)nulldev, /* reset */
        NULL,                                /* tty's */
        eno_select,                        /* select */
        eno_mmap,                        /* mmap */
        eno_strat,                        /* strategy */
        eno_getc,                        /* getc */
        eno_putc,                        /* putc */
        0                                        /* type */
};


/*
* Called to initialize our device,
* and to register ourselves with devfs
*/
void
random_init(void)
{
        int ret;

        ret = cdevsw_add(RANDOM_MAJOR, &random_cdevsw);
        if (ret < 0) {
                panic("random_init: failed to allocate a major number!");
        }

        devfs_make_node(makedev (ret, RANDOM_MINOR), DEVFS_CHAR,
                UID_ROOT, GID_WHEEL, 0666, "random", 0);

        /*
       * also make urandom
       * (which is exactly the same thing in our context)
       */
        devfs_make_node(makedev (ret, URANDOM_MINOR), DEVFS_CHAR,
                UID_ROOT, GID_WHEEL, 0666, "urandom", 0);

}

将kernercache拖到IDA或者hopper中分析,找到该代码段:

================ B E G I N N I N G   O F   P R O C E D U R E ================



             sub_800c0d88:
800c0d88         push       {r4, r5, r6, r7, lr}
800c0d8a         add      r7, sp, #0xc
800c0d8c         sub      sp, #0xc
800c0d8e         movw       r0, #0xc5c6
800c0d92         movt       r0, #0x2f
800c0d96         add      r0, pc                                              ; 0x803bd360 (_PE_poll_input + 0xaf4c)
800c0d98         addw       r1, r0, #0xb14
800c0d9c         mov.w      r0, #0xffffffff
800c0da0         bl         _cdevsw_add
800c0da4         mov      r4, r0
800c0da6         cmp.w      r4, #0xffffffff
800c0daa         bgt      0x800c0dba

800c0dac         movw       r0, #0x655f
800c0db0         movt       r0, #0x2b
800c0db4         add      r0, pc                                              ; "\\\\\\\\\\\\\\\\\\\\\\\\"random_init: failed to allocate a major number!\\\\\\\\\\\\\\\\\\\\\\\\"", argument #1 for method _panic
800c0db6         bl         _panic

800c0dba         movw       r0, #0x657b                                       ; XREF=sub_800c0d88+34
800c0dbe         mov.w      r6, #0x1b6
800c0dc2         movt       r0, #0x2b
800c0dc6         movs       r5, #0x0
800c0dc8         str      r6,                                           ; argument #5 for method _devfs_make_node
800c0dca         add      r0, pc                                              ; "random"
800c0dcc         movs       r1, #0x0                                          ; argument #2 for method _devfs_make_node
800c0dce         str      r0,                                     ; argument #6 for method _devfs_make_node
800c0dd0         lsl.w      r0, r4, #0x18                                       ; argument #1 for method _devfs_make_node
800c0dd4         movs       r2, #0x0                                          ; argument #3 for method _devfs_make_node
800c0dd6         movs       r3, #0x0                                          ; argument #4 for method _devfs_make_node
800c0dd8         str      r5,
800c0dda         bl         _devfs_make_node
800c0dde         movw       r0, #0x6560
800c0de2         movs       r1, #0x0                                          ; argument #2 for method _devfs_make_node
800c0de4         movt       r0, #0x2b
800c0de8         str      r6,                                           ; argument #5 for method _devfs_make_node
800c0dea         movs       r2, #0x0                                          ; argument #3 for method _devfs_make_node
800c0dec         add      r0, pc                                              ; "urandom"
800c0dee         movs       r3, #0x0                                          ; argument #4 for method _devfs_make_node
800c0df0         str      r0,                                     ; argument #6 for method _devfs_make_node
800c0df2         movs       r0, #0x1
800c0df4         orr.w      r0, r0, r4, lsl #24                                 ; argument #1 for method _devfs_make_node
800c0df8         str      r5,
800c0dfa         bl         _devfs_make_node
800c0dfe         add      sp, #0xc
800c0e00         pop      {r4, r5, r6, r7, pc}
                        ; endp
800c0e02         nop   

从源码中可以看出 cdevsw_add 函数第二个参数为cdevsw结构体地址
从汇编中算出random_cdevsw结构体地址为0x803bd360+0xb14 = 0x803BDE74
go到0x803BDE74random_cdevsw:

803bde74         db0x19 ; '.'
803bde75         db0x0e ; '.'
803bde76         db0x0c ; '.'
803bde77         db0x80 ; '.'
803bde78         db0x35 ; '5'
803bde79         db0x0e ; '.'
803bde7a         db0x0c ; '.'
803bde7b         db0x80 ; '.'
803bde7c         db0xa1 ; '.'
803bde7d         db0x0e ; '.'
803bde7e         db0x0c ; '.'
803bde7f         db0x80 ; '.'---->random_read 0x800c0ea1
803bde80         db0x39 ; '9'
803bde81         db0x0e ; '.'
803bde82         db0x0c ; '.'
803bde83         db0x80 ; '.'---->random_write 0x800c0e39
803bde84         db0x05 ; '.'
803bde85         db0x0e ; '.'
803bde86         db0x0c ; '.'
803bde87         db0x80 ; '.'---->random_ioctl 0x800c0e05
803bde88         db0xc9 ; '.'
803bde89         db0x73 ; 's'
803bde8a         db0x28 ; '('
803bde8b         db0x80 ; '.'
803bde8c         db0xc9 ; '.'
803bde8d         db0x73 ; 's'
803bde8e         db0x28 ; '('
803bde8f         db0x80 ; '.'
803bde90         db0x00 ; '.'
803bde91         db0x00 ; '.'
803bde92         db0x00 ; '.'
803bde93         db0x00 ; '.'
803bde94         db0xad ; '.'
803bde95         db0x73 ; 's'
803bde96         db0x28 ; '('
803bde97         db0x80 ; '.'
803bde98         db0xad ; '.'
803bde99         db0x73 ; 's'
803bde9a         db0x28 ; '('
803bde9b         db0x80 ; '.'
803bde9c         db0xb1 ; '.'
803bde9d         db0x73 ; 's'
803bde9e         db0x28 ; '('
803bde9f         db0x80 ; '.'
803bdea0         db0xad ; '.'
803bdea1         db0x73 ; 's'
803bdea2         db0x28 ; '('
803bdea3         db0x80 ; '.'
803bdea4         db0xad ; '.'
803bdea5         db0x73 ; 's'
803bdea6         db0x28 ; '('
803bdea7         db0x80 ; '.'
803bdea8         db0x00 ; '.'
803bdea9         db0x00 ; '.'
803bdeaa         db0x00 ; '.'
803bdeab         db0x00 ; '.'

得到 /dev/random 结果:0x800c0ea1#0x800c0e39#0x800c0e05


(2)设备/dev/pf,对应结构体cdevsw中d_read, d_write, d_ioctl在题目给出kernelcache中的地址。
xnu-2782.40.9/bsd/net/pf_ioctl.c:

static struct cdevsw pf_cdevsw = {
        /* open */        pfopen,
        /* close */        pfclose,
        /* read */        eno_rdwrt,
        /* write */        eno_rdwrt,
        /* ioctl */        pfioctl,
        /* stop */        eno_stop,
        /* reset */        eno_reset,
        /* tty */        NULL,
        /* select */        eno_select,
        /* mmap */        eno_mmap,
        /* strategy */        eno_strat,
        /* getc */        eno_getc,
        /* putc */        eno_putc,
        /* type */        0
};

void
pfinit(void)
{......
        maj = cdevsw_add(PF_CDEV_MAJOR, &pf_cdevsw);
        if (maj == -1) {
                printf("%s: failed to allocate major number!\\\\\\\\n", __func__);
                return;
        }
        (void) devfs_make_node(makedev(maj, PFDEV_PF), DEVFS_CHAR,
          UID_ROOT, GID_WHEEL, 0600, "pf", 0);

        (void) devfs_make_node(makedev(maj, PFDEV_PFM), DEVFS_CHAR,
          UID_ROOT, GID_WHEEL, 0600, "pfm", 0);
......
}


对应kernelcache汇编代码(节选):

8024b51a         movw       r0, #0x1e3a
8024b51e         movt       r0, #0x17
8024b522         add      r0, pc                                              ; 0x803bd360 (_PE_poll_input + 0xaf4c)
8024b524         addw       r1, r0, #0xbbc
8024b528         mov.w      r0, #0xffffffff
8024b52c         bl         _cdevsw_add      
8024b530         mov      r5, r0
8024b532         cmp.w      r5, #0xffffffff
8024b536         beq      0x8024b5ba

8024b538         movw       r0, #0x4532
8024b53c         mov.w      r4, #0x180
8024b540         movt       r0, #0x13
8024b544         mov.w      r11, #0x0
8024b548         str      r4,
8024b54a         add      r0, pc                                              ; "pf"
8024b54c         movs       r1, #0x0
8024b54e         str      r0,
8024b550         lsl.w      r0, r5, #0x18
8024b554         movs       r2, #0x0
8024b556         movs       r3, #0x0
8024b558         str.w      r11,
8024b55c         bl         _devfs_make_node
8024b560         movw       r0, #0x4555
8024b564         movs       r1, #0x0
8024b566         movt       r0, #0x13
8024b56a         str      r4,
8024b56c         movs       r2, #0x0
8024b56e         add      r0, pc                                              ; "pfm"
8024b570         movs       r3, #0x0
8024b572         str      r0,
8024b574         movs       r0, #0x1
8024b576         orr.w      r0, r0, r5, lsl #24
8024b57a         str.w      r11,
8024b57e         bl         _devfs_make_node

算出pf_cdevsw结构体地址为0x803bd360+0xbbc = 0x803BDF1C
go到0x803BDF1Cpf_cdevsw:

803bdf1c         db0x65 ; 'e'
803bdf1d         db0x2c ; ','
803bdf1e         db0x15 ; '.'
803bdf1f         db0x80 ; '.'
803bdf20         db0xf5 ; '.'
803bdf21         db0x2b ; '+'
803bdf22         db0x15 ; '.'
803bdf23         db0x80 ; '.'
803bdf24         db0xad ; '.'
803bdf25         db0x73 ; 's'
803bdf26         db0x28 ; '('
803bdf27         db0x80 ; '.'---->eno_rdwrt 0x802873ad
803bdf28         db0xad ; '.'
803bdf29         db0x73 ; 's'
803bdf2a         db0x28 ; '('
803bdf2b         db0x80 ; '.'---->eno_rdwrt 0x802873ad
803bdf2c         db0x19 ; '.'
803bdf2d         db0x9d ; '.'
803bdf2e         db0x14 ; '.'
803bdf2f         db0x80 ; '.'---->pfioctl 0x80149d19
803bdf30         db0xad ; '.'
803bdf31         db0x73 ; 's'
803bdf32         db0x28 ; '('
803bdf33         db0x80 ; '.'
803bdf34         db0xad ; '.'
803bdf35         db0x73 ; 's'
803bdf36         db0x28 ; '('
803bdf37         db0x80 ; '.'
803bdf38         db0x00 ; '.'
803bdf39         db0x00 ; '.'
803bdf3a         db0x00 ; '.'
803bdf3b         db0x00 ; '.'
803bdf3c         db0xad ; '.'
803bdf3d         db0x73 ; 's'
803bdf3e         db0x28 ; '('
803bdf3f         db0x80 ; '.'
803bdf40         db0xad ; '.'
803bdf41         db0x73 ; 's'
803bdf42         db0x28 ; '('
803bdf43         db0x80 ; '.'
803bdf44         db0xb1 ; '.'
803bdf45         db0x73 ; 's'
803bdf46         db0x28 ; '('
803bdf47         db0x80 ; '.'
803bdf48         db0xad ; '.'
803bdf49         db0x73 ; 's'
803bdf4a         db0x28 ; '('
803bdf4b         db0x80 ; '.'
803bdf4c         db0xad ; '.'
803bdf4d         db0x73 ; 's'
803bdf4e         db0x28 ; '('
803bdf4f         db0x80 ; '.'
803bdf50         db0x00 ; '.'
803bdf51         db0x00 ; '.'
803bdf52         db0x00 ; '.'
803bdf53         db0x00 ; '.'

得到 /dev/pf 的结果:0x802873ad#0x802873ad#0x80149d19

(3)设备/dev/ptmx,对应结构体cdevsw中d_read, d_write, d_ioctl在题目给出kernelcache中的地址。
/xnu-2782.40.9/bsd/kern/tty_ptmx.c:

static struct cdevsw ptmx_cdev = {
        ptcopen,        ptcclose,        ptcread,        ptcwrite,
        ptyioctl,        ptcstop,        ptcreset,        0,
        ptcselect,        eno_mmap,        eno_strat,        eno_getc,
        eno_putc,        D_TTY
};

int
ptmx_init( __unused int config_count)
{
        /*
       * We start looking at slot 10, since there are inits that will
       * stomp explicit slots (e.g. vndevice stomps 1) below that.
       */

        /* Get a major number for /dev/ptmx */
        if((ptmx_major = cdevsw_add(-15, &ptmx_cdev)) == -1) {
                printf("ptmx_init: failed to obtain /dev/ptmx major number\\\\\\\\n");
                return (ENOENT);
        }

        if (cdevsw_setkqueueok(ptmx_major, &ptmx_cdev, 0) == -1) {
                panic("Failed to set flags on ptmx cdevsw entry.");
        }

        /* Get a major number for /dev/pts/nnn */
        if ((ptsd_major = cdevsw_add(-15, &ptsd_cdev)) == -1) {
                (void)cdevsw_remove(ptmx_major, &ptmx_cdev);
                printf("ptmx_init: failed to obtain /dev/ptmx major number\\\\\\\\n");
                return (ENOENT);
        }
       
        if (cdevsw_setkqueueok(ptsd_major, &ptsd_cdev, 0) == -1) {
                panic("Failed to set flags on ptmx cdevsw entry.");
        }

        /*
       * Locks to guard against races between revoke and kevents
       */
        ptsd_kevent_lock_init();

        /* Create the /dev/ptmx device {<major>,0} */
        (void)devfs_make_node_clone(makedev(ptmx_major, 0),
                                DEVFS_CHAR, UID_ROOT, GID_TTY, 0666,
                                ptmx_clone, PTMX_TEMPLATE);

        _ptmx_driver.master = ptmx_major;
        _ptmx_driver.slave = ptsd_major;
        _ptmx_driver.fix_7828447 = 1;
        _ptmx_driver.fix_7070978 = 1;
#if CONFIG_MACF
        _ptmx_driver.mac_notify = 1;
#endif
        _ptmx_driver.open = &ptmx_get_ioctl;
        _ptmx_driver.free = &ptmx_free_ioctl;
        _ptmx_driver.name = &ptmx_get_name;
        _ptmx_driver.revoke = &ptsd_revoke_knotes;
        tty_dev_register(&_ptmx_driver);

        return (0);
}

对应kernelcache汇编代码(节选):


80293330         push       {r4, r5, r6, r7, lr}
80293332         add      r7, sp, #0xc
80293334         push.w   {r8, r10, r11}
80293338         sub      sp, #0xc
8029333a         movw       r4, #0xa016
8029333e         mvn      r0, #0xe
80293342         movt       r4, #0x12
80293346         add      r4, pc                                              ; 0x803bd360 (_PE_poll_input + 0xaf4c)
80293348         addw       r1, r4, #0xc2c
8029334c         bl         _cdevsw_add
80293350         movw       r8, #0x6b90
80293354         cmp.w      r0, #0xffffffff
80293358         movt       r8, #0x16
8029335c         add      r8, pc                                              ; 0x803f9ef0
8029335e         str.w      r0,                                     ; 0x803fab48
80293362         beq      0x80293412

80293364         cmp      r0, #0x2a
80293366         bhi      0x802933a8

80293368         movw       r1, #0xe0d0
8029336c         rsb      r2, r0, r0, lsl #3
80293370         movt       r1, #0x11
80293374         add      r1, pc                                              ; _cdevsw
80293376         add.w      r1, r1, r2, lsl #3
8029337a         movs       r2, #0x0

8029337c         adds       r6, r4, r2                                          ; XREF=sub_80293330+92
8029337e         ldrb       r3,
80293380         ldrb.w   r6,
80293384         cmp      r3, r6
80293386         bne      0x802933a8

80293388         adds       r2, #0x1
8029338a         cmp      r2, #0x38
8029338c         bne      0x8029337c

8029338e         movw       r1, #0x583c
80293392         movs       r2, #0x1
80293394         movt       r1, #0x16
80293398         add      r1, pc                                              ; 0x803f8bd8
8029339a         str.w      r2,
8029339e         add.w      r0, r1, r0, lsl #3
802933a2         movs       r1, #0x0
802933a4         str      r1,
802933a6         b          0x802933b6

802933a8         movw       r0, #0xeb91                                       ; XREF=sub_80293330+54, sub_80293330+86
802933ac         movt       r0, #0xc
802933b0         add      r0, pc                                              ; "\\\\\\\\\\\\\\\\\\\\\\\\"Failed to set flags on ptmx cdevsw entry.\\\\\\\\\\\\\\\\\\\\\\\\"", argument #1 for method _panic
802933b2         bl         _panic

802933b6         addw       r1, r4, #0xc64                                    ; XREF=sub_80293330+118
802933ba         mvn      r0, #0xe
802933be         bl         _cdevsw_add

算出ptmx_cdev结构体地址为0x803bd360+0xc2c = 0x803BDF8C
go到0x803BDF8Cptmx_cdev:

803bdf8c         db0x9d ; '.'
803bdf8d         db0x1f ; '.'
803bdf8e         db0x29 ; ')'
803bdf8f         db0x80 ; '.'
803bdf90         db0xd5 ; '.'
803bdf91         db0x20 ; ' '
803bdf92         db0x29 ; ')'
803bdf93         db0x80 ; '.'
803bdf94         db0x51 ; 'Q'
803bdf95         db0x22 ; '"'
803bdf96         db0x29 ; ')'
803bdf97         db0x80 ; '.' ---->ptcread 0x80292251
803bdf98         db0x61 ; 'a'
803bdf99         db0x26 ; '&'
803bdf9a         db0x29 ; ')'
803bdf9b         db0x80 ; '.' ---->ptcwrite 0x80292661
803bdf9c         db0x8d ; '.'
803bdf9d         db0x29 ; ')'
803bdf9e         db0x29 ; ')'
803bdf9f         db0x80 ; '.' ---->ptyioctl 0x8029298d
803bdfa0         db0x59 ; 'Y'
803bdfa1         db0x26 ; '&'
803bdfa2         db0x29 ; ')'
803bdfa3         db0x80 ; '.'
803bdfa4         db0x5d ; ']'
803bdfa5         db0x26 ; '&'
803bdfa6         db0x29 ; ')'
803bdfa7         db0x80 ; '.'
803bdfa8         db0x00 ; '.'
803bdfa9         db0x00 ; '.'
803bdfaa         db0x00 ; '.'
803bdfab         db0x00 ; '.'
803bdfac         db0x0d ; '.'
803bdfad         db0x25 ; '%'
803bdfae         db0x29 ; ')'
803bdfaf         db0x80 ; '.'
803bdfb0         db0xad ; '.'
803bdfb1         db0x73 ; 's'
803bdfb2         db0x28 ; '('
803bdfb3         db0x80 ; '.'
803bdfb4         db0xb1 ; '.'
803bdfb5         db0x73 ; 's'
803bdfb6         db0x28 ; '('
803bdfb7         db0x80 ; '.'
803bdfb8         db0xad ; '.'
803bdfb9         db0x73 ; 's'
803bdfba         db0x28 ; '('
803bdfbb         db0x80 ; '.'
803bdfbc         db0xad ; '.'
803bdfbd         db0x73 ; 's'
803bdfbe         db0x28 ; '('
803bdfbf         db0x80 ; '.'
803bdfc0         db0x03 ; '.'
803bdfc1         db0x00 ; '.'
803bdfc2         db0x00 ; '.'
803bdfc3         db0x00 ; '.'

得到 /dev/ptmx 的结果:0x80292251#0x80292661#0x8029298d

所以最终结果为:
0x800c0ea1#0x800c0e39#0x800c0e05#0x802873ad#0x802873ad#0x80149d19#0x80292251#0x80292661#0x8029298d

飘云 发表于 2015-11-3 16:23:42

学习,膜拜!!

[PYG]版务督察 发表于 2015-11-3 16:29:00

好厉害,前排学习~

tree_fly 发表于 2015-11-3 16:45:06

楼主,受我一拜,{:soso__27681679fe975de4-0a71ffedd0737876-83ba725f7dec7243c817e13bbb795d84.jpg_1:}

GeekCat 发表于 2015-11-3 17:23:21

膜拜C版大神~~~

yjf306 发表于 2015-11-3 20:00:16

没基础,看代码象天书,只能慢慢学习了。谢谢版主。

wgz001 发表于 2015-11-4 09:55:07

这个只能看看   无法模仿

Rooking 发表于 2015-11-4 10:22:07

完全不是一个层次的啊 膜拜一下

0xcb 发表于 2015-11-4 13:25:16

好强悍

熊猫正正 发表于 2015-11-5 09:58:06

过来顶一个吧,呵呵
页: [1] 2
查看完整版本: 2015第2届移动安全挑战赛iOS第二题分析