首页
社区
课程
招聘
[原创]2015第2届移动安全挑战赛 iOS writeup
发表于: 2015-10-18 20:58 2814

[原创]2015第2届移动安全挑战赛 iOS writeup

2015-10-18 20:58
2814
做了两道题出来,下面是两题的writeup。

第一题:
拖进IDA,F5,ViewController onClick方法中,忽略开始的解密部分,直接关注和用户输入进行比较的代码。
  v7 = objc_msgSend(v20, "textFeild");
  v8 = objc_msgSend(v7, "text");
  v9 = objc_msgSend(v8, "UTF8String");     v9 == user input
  v10 = objc_msgSend(v2, "UTF8String");    v10 == plain text,在lldb中此行代码上下断点,0xb7aa处

(lldb) bw b7aa                                                                                                           
br s -a '0xB7000+0xB7AA'                                                                                                
Breakpoint 1: where = level1`___lldb_unnamed_function36$$level1 + 266, address = 0x000c27aa                              
Process 3729 stopped                                                                                                     
* thread #1: tid = 0xaa458, 0x000c27aa level1`___lldb_unnamed_function36$$level1 + 266, queue = 'com.apple.main-thread, stop reason = breakpoint 1.1                                                                                             
    frame #0: 0x000c27aa level1`___lldb_unnamed_function36$$level1 + 266                                                
level1`___lldb_unnamed_function36$$level1 + 266:                                                                        
-> 0xc27aa:  blx    0xd2f18                   ; symbol stub for: objc_msgSend                                            
   0xc27ae:  mov    r5, r0                                                                                               
   0xc27b0:  ldrb   r0, [r5]                                                                                             
   0xc27b2:  cmp    r0, #0                                                                                               
(lldb) msgSend_analysis                                                                                                  
[Sp4rkDr0idKit UTF8String]  <---  Sp4rkDr0idKit 就是答案

第二题:
要得到kernelcache中对应的函数地址,还是先拖进IDA。对结构体cdevsw不太了解,但是可以从xnu的源码中搜到一些相关的代码,再根据源码去IDA中查找相关的结构体。

struct cdevsw {
        open_close_fcn_t        *d_open;
        open_close_fcn_t        *d_close;
        read_write_fcn_t        *d_read;   //这个
        read_write_fcn_t        *d_write;  //这个
        ioctl_fcn_t                *d_ioctl;      //这个
        stop_fcn_t                *d_stop;
        reset_fcn_t                *d_reset;
        struct        tty                 **d_ttys;
        select_fcn_t                *d_select;
        mmap_fcn_t                *d_mmap;
        strategy_fcn_t                *d_strategy;
        void                        *d_reserved_1;
        void                        *d_reserved_2;
        int                        d_type;
};

首先是random设备的random_cdevsw结构体。
从源码中可以看到,是通过cdevsw_add进行设置,那么就在IDA中查找其panic时输出的字符串。
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);
}

在kernelcache中定位到sub_800C0D88,说明off_803BDE74就是random_cdevsw。

    v0 = cdevsw_add(-1, off_803BDE74);

第三、第四、第五个值就是所需要查找的
__DATA:__data:803BDE74 19 0E 0C 80             off_803BDE74    DCD sub_800C0E18+1   
__DATA:__data:803BDE78 35 0E 0C 80                             DCD sub_800C0E34+1       
__DATA:__data:803BDE7C A1 0E 0C 80                             DCD sub_800C0EA0+1        ;d_read
__DATA:__data:803BDE80 39 0E 0C 80                             DCD sub_800C0E38+1   ;d_write
__DATA:__data:803BDE84 05 0E 0C 80                             DCD sub_800C0E04+1   ;d_ioctl
__DATA:__data:803BDE88 C9 73 28 80                             DCD _nulldev+1
__DATA:__data:803BDE8C C9 73 28 80                             DCD _nulldev+1

同理,pf设备
pfinit(void)中有 pool_init(&pf_rule_pl, sizeof (struct pf_rule), 0, 0, 0, "pfrulepl", NULL);
IDA中查找 "pfrulepl" 字符串,定位到sub_80246BB0,在里面可以看到下面的调用,
v452 = cdevsw_add(-1, off_803BDF1C);

maj = cdevsw_add(PF_CDEV_MAJOR, &pf_cdevsw);
        if (maj == -1) {
                printf("%s: failed to allocate major number!\n", __func__);
                return;
        }

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
};

因此off_803BDF1C就是pf_cdevsw的地址,
__DATA:__data:803BDF1C 65 2C 15 80             off_803BDF1C    DCD sub_80152C64+1
__DATA:__data:803BDF20 F5 2B 15 80                             DCD sub_80152BF4+1
__DATA:__data:803BDF24 AD 73 28 80                             DCD _enodev+1       ;d_read
__DATA:__data:803BDF28 AD 73 28 80                             DCD _enodev+1       ;d_write
__DATA:__data:803BDF2C 19 9D 14 80                             DCD sub_80149D18+1  ;d_ioctl

最后是ptmx的ptmx_cdev,xnu源码中
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);
        }
...
}

IDA中查找字符串ptmx,出现“Failed to set flags on ptmx cdevsw entry.”,定位到sub_80293330
v0 = cdevsw_add(-15, off_803BDF8C); //与源码一致
因此off_803BDF8C就是ptmx_cdev

__DATA:__data:803BDF8C 9D 1F 29 80             off_803BDF8C    DCD sub_80291F9C+1      ; DATA XREF: sub_80293330+50r
__DATA:__data:803BDF90 D5 20 29 80                             DCD sub_802920D4+1
__DATA:__data:803BDF94 51 22 29 80                             DCD sub_80292250+1      ; d_read
__DATA:__data:803BDF98 61 26 29 80                             DCD sub_80292660+1      ; d_write
__DATA:__data:803BDF9C 8D 29 29 80                             DCD sub_8029298C+1      ; d_ioctl
__DATA:__data:803BDFA0 59 26 29 80                             DCD sub_80292658+1
__DATA:__data:803BDFA4 5D 26 29 80                             DCD sub_8029265C+1

全部组合后,得到答案(最初提交的时候有大写字母,没通过。。改成小写就对了)
0x800c0ea1#0x800c0e39#0x800c0e05#0x802873ad#0x802873ad#0x80149d19#0x80292251#0x80292661#0x8029298d

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//