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

creantan/P.Y.G 转载请注明出处

第二题题目如下

环境: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, [sp]                                            ; 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, [sp, #0x4]                                      ; 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, [sp, #0x8]
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, [sp]                                            ; 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, [sp, #0x4]                                      ; 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, [sp, #0x8]
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到0x803BDE74 random_cdevsw:

803bde74         db  0x19 ; '.'
803bde75         db  0x0e ; '.'
803bde76         db  0x0c ; '.'
803bde77         db  0x80 ; '.'
803bde78         db  0x35 ; '5'
803bde79         db  0x0e ; '.'
803bde7a         db  0x0c ; '.'
803bde7b         db  0x80 ; '.'
803bde7c         db  0xa1 ; '.'
803bde7d         db  0x0e ; '.'
803bde7e         db  0x0c ; '.'
803bde7f         db  0x80 ; '.'  ---->random_read 0x800c0ea1
803bde80         db  0x39 ; '9'
803bde81         db  0x0e ; '.'
803bde82         db  0x0c ; '.'
803bde83         db  0x80 ; '.'  ---->random_write 0x800c0e39
803bde84         db  0x05 ; '.'
803bde85         db  0x0e ; '.'
803bde86         db  0x0c ; '.'
803bde87         db  0x80 ; '.'  ---->random_ioctl 0x800c0e05
803bde88         db  0xc9 ; '.'
803bde89         db  0x73 ; 's'
803bde8a         db  0x28 ; '('
803bde8b         db  0x80 ; '.'
803bde8c         db  0xc9 ; '.'
803bde8d         db  0x73 ; 's'
803bde8e         db  0x28 ; '('
803bde8f         db  0x80 ; '.'
803bde90         db  0x00 ; '.'
803bde91         db  0x00 ; '.'
803bde92         db  0x00 ; '.'
803bde93         db  0x00 ; '.'
803bde94         db  0xad ; '.'
803bde95         db  0x73 ; 's'
803bde96         db  0x28 ; '('
803bde97         db  0x80 ; '.'
803bde98         db  0xad ; '.'
803bde99         db  0x73 ; 's'
803bde9a         db  0x28 ; '('
803bde9b         db  0x80 ; '.'
803bde9c         db  0xb1 ; '.'
803bde9d         db  0x73 ; 's'
803bde9e         db  0x28 ; '('
803bde9f         db  0x80 ; '.'
803bdea0         db  0xad ; '.'
803bdea1         db  0x73 ; 's'
803bdea2         db  0x28 ; '('
803bdea3         db  0x80 ; '.'
803bdea4         db  0xad ; '.'
803bdea5         db  0x73 ; 's'
803bdea6         db  0x28 ; '('
803bdea7         db  0x80 ; '.'
803bdea8         db  0x00 ; '.'
803bdea9         db  0x00 ; '.'
803bdeaa         db  0x00 ; '.'
803bdeab         db  0x00 ; '.'
得到 /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, [sp]
8024b54a         add        r0, pc                                              ; "pf"
8024b54c         movs       r1, #0x0
8024b54e         str        r0, [sp, #0x4]
8024b550         lsl.w      r0, r5, #0x18
8024b554         movs       r2, #0x0
8024b556         movs       r3, #0x0
8024b558         str.w      r11, [sp, #0x8]
8024b55c         bl         _devfs_make_node
8024b560         movw       r0, #0x4555
8024b564         movs       r1, #0x0
8024b566         movt       r0, #0x13
8024b56a         str        r4, [sp]
8024b56c         movs       r2, #0x0
8024b56e         add        r0, pc                                              ; "pfm"
8024b570         movs       r3, #0x0
8024b572         str        r0, [sp, #0x4]
8024b574         movs       r0, #0x1
8024b576         orr.w      r0, r0, r5, lsl #24
8024b57a         str.w      r11, [sp, #0x8]
8024b57e         bl         _devfs_make_node

算出pf_cdevsw结构体地址为0x803bd360+0xbbc = 0x803BDF1C
go到0x803BDF1C  pf_cdevsw:
803bdf1c         db  0x65 ; 'e'
803bdf1d         db  0x2c ; ','
803bdf1e         db  0x15 ; '.'
803bdf1f         db  0x80 ; '.'
803bdf20         db  0xf5 ; '.'
803bdf21         db  0x2b ; '+'
803bdf22         db  0x15 ; '.'
803bdf23         db  0x80 ; '.'
803bdf24         db  0xad ; '.'
803bdf25         db  0x73 ; 's'
803bdf26         db  0x28 ; '('
803bdf27         db  0x80 ; '.'  ---->eno_rdwrt 0x802873ad
803bdf28         db  0xad ; '.'
803bdf29         db  0x73 ; 's'
803bdf2a         db  0x28 ; '('
803bdf2b         db  0x80 ; '.'  ---->eno_rdwrt 0x802873ad
803bdf2c         db  0x19 ; '.'
803bdf2d         db  0x9d ; '.'
803bdf2e         db  0x14 ; '.'
803bdf2f         db  0x80 ; '.'  ---->pfioctl 0x80149d19
803bdf30         db  0xad ; '.'
803bdf31         db  0x73 ; 's'
803bdf32         db  0x28 ; '('
803bdf33         db  0x80 ; '.'
803bdf34         db  0xad ; '.'
803bdf35         db  0x73 ; 's'
803bdf36         db  0x28 ; '('
803bdf37         db  0x80 ; '.'
803bdf38         db  0x00 ; '.'
803bdf39         db  0x00 ; '.'
803bdf3a         db  0x00 ; '.'
803bdf3b         db  0x00 ; '.'
803bdf3c         db  0xad ; '.'
803bdf3d         db  0x73 ; 's'
803bdf3e         db  0x28 ; '('
803bdf3f         db  0x80 ; '.'
803bdf40         db  0xad ; '.'
803bdf41         db  0x73 ; 's'
803bdf42         db  0x28 ; '('
803bdf43         db  0x80 ; '.'
803bdf44         db  0xb1 ; '.'
803bdf45         db  0x73 ; 's'
803bdf46         db  0x28 ; '('
803bdf47         db  0x80 ; '.'
803bdf48         db  0xad ; '.'
803bdf49         db  0x73 ; 's'
803bdf4a         db  0x28 ; '('
803bdf4b         db  0x80 ; '.'
803bdf4c         db  0xad ; '.'
803bdf4d         db  0x73 ; 's'
803bdf4e         db  0x28 ; '('
803bdf4f         db  0x80 ; '.'
803bdf50         db  0x00 ; '.'
803bdf51         db  0x00 ; '.'
803bdf52         db  0x00 ; '.'
803bdf53         db  0x00 ; '.'
得到 /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 {,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, [r8, #0xc58]                                    ; 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, [r1, r2]
80293380         ldrb.w     r6, [r6, #0xc2c]
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, [r1, r0, lsl #3]
8029339e         add.w      r0, r1, r0, lsl #3
802933a2         movs       r1, #0x0
802933a4         str        r1, [r0, #0x4]
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到0x803BDF8C ptmx_cdev:

803bdf8c         db  0x9d ; '.'
803bdf8d         db  0x1f ; '.'
803bdf8e         db  0x29 ; ')'
803bdf8f         db  0x80 ; '.'
803bdf90         db  0xd5 ; '.'
803bdf91         db  0x20 ; ' '
803bdf92         db  0x29 ; ')'
803bdf93         db  0x80 ; '.'
803bdf94         db  0x51 ; 'Q'
803bdf95         db  0x22 ; '"'
803bdf96         db  0x29 ; ')'
803bdf97         db  0x80 ; '.' ---->ptcread 0x80292251
803bdf98         db  0x61 ; 'a'
803bdf99         db  0x26 ; '&'
803bdf9a         db  0x29 ; ')'
803bdf9b         db  0x80 ; '.' ---->ptcwrite 0x80292661
803bdf9c         db  0x8d ; '.'
803bdf9d         db  0x29 ; ')'
803bdf9e         db  0x29 ; ')'
803bdf9f         db  0x80 ; '.' ---->ptyioctl 0x8029298d
803bdfa0         db  0x59 ; 'Y'
803bdfa1         db  0x26 ; '&'
803bdfa2         db  0x29 ; ')'
803bdfa3         db  0x80 ; '.'
803bdfa4         db  0x5d ; ']'
803bdfa5         db  0x26 ; '&'
803bdfa6         db  0x29 ; ')'
803bdfa7         db  0x80 ; '.'
803bdfa8         db  0x00 ; '.'
803bdfa9         db  0x00 ; '.'
803bdfaa         db  0x00 ; '.'
803bdfab         db  0x00 ; '.'
803bdfac         db  0x0d ; '.'
803bdfad         db  0x25 ; '%'
803bdfae         db  0x29 ; ')'
803bdfaf         db  0x80 ; '.'
803bdfb0         db  0xad ; '.'
803bdfb1         db  0x73 ; 's'
803bdfb2         db  0x28 ; '('
803bdfb3         db  0x80 ; '.'
803bdfb4         db  0xb1 ; '.'
803bdfb5         db  0x73 ; 's'
803bdfb6         db  0x28 ; '('
803bdfb7         db  0x80 ; '.'
803bdfb8         db  0xad ; '.'
803bdfb9         db  0x73 ; 's'
803bdfba         db  0x28 ; '('
803bdfbb         db  0x80 ; '.'
803bdfbc         db  0xad ; '.'
803bdfbd         db  0x73 ; 's'
803bdfbe         db  0x28 ; '('
803bdfbf         db  0x80 ; '.'
803bdfc0         db  0x03 ; '.'
803bdfc1         db  0x00 ; '.'
803bdfc2         db  0x00 ; '.'
803bdfc3         db  0x00 ; '.'
得到 /dev/ptmx 的结果:  0x80292251#0x80292661#0x8029298d

所以最终结果为:

0x800c0ea1#0x800c0e39#0x800c0e05#0x802873ad#0x802873ad#0x80149d19#0x80292251#0x80292661#0x8029298d

你可能感兴趣的:(【原创】2015第2届移动安全挑战赛iOS第二题分析)