-
-
[原创]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
第一题:
拖进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期)
赞赏
看原图
赞赏
雪币:
留言: