iOS安全–阿里比赛iOS 1. 2 题解

第一题:
拿到ipa习惯性的拖到IDA看一看,找到-[ViewController onClick]函数:

2015-10-19_171246

额。。。如果只是这样,是不是有点简单了?
先不管了,既然你是调用AESCrypt来解密的,hook解密函数直接拿到结果即可。
hook代码如下:

代码:

1
2
3
%hook AESCrypt
+ (id)decrypt:(id)arg1 password:(id)arg2 { %log; id r = %orig; NSLog(@" = %@", r); return r; }
%end

然后打开题目,直接点击,看设备打印信息,得到如下信息:

代码:

1
2
3
4
5
6
7
8
9
10
iPad level1[2149] <Warning>: +[<AESCrypt: 0xa90e4> decrypt:inIVWxfpVkvZKCE9QaaD6c0eHDJjPJoBuvO0pUyw4N3GgwM0zktzZRqtV7DkmUKytBdcZeArzCGet95RFJAQL8nzkt4yi7CDRgxRyPFLinPpD7dkilS+tfPcCc2vMdo0pQCM8hYccar2OJkSywQKQQ== password:ZGlhb2RhX2ppYW5rYW5nCg==]
iPad level1[2149] <Warning>:  = hDmx1/d5KNhr1BBYQlRNVsZSEaOdw4MtKTpT3082x/x9lZucw0qEm+UhMaOVuoSLyqD1x0elXGXqM4nFSP3W8khfyg1ynDEwLhLt12m68U8=
iPad level1[2149] <Warning>: +[<AESCrypt: 0xa90e4> decrypt:eAju1/a5HKeo1YYVNiOKSpWPBxLat4JqHQmQ3082u/u9iWrzt0nBj+ReJxLSrlPIvnA1u0biUDUnJ4kCPM3T8hecvd1vkABtIeIq12j68R8= password:ZGlhb2RhX2ppYW5rYW5nCg==]
iPad level1[2149] <Warning>:  = e1s6fwEoaC3l/4VLi1DA4KKPJdGcGWK3elMxPqOuG7MNa9fcfWu6gpui+m3q1akL
iPad level1[2149] <Warning>: +[<AESCrypt: 0xa90e4> decrypt:c1q6duCmyA3j/4TJg1BY4IINHbEaEUI3cjKvNoMsE7KLy9dadUs6ensg+k3o1yiJ password:ZGlhb2RhX2ppYW5rYW5nCg==]
iPad level1[2149] <Warning>:  = 4p2eb81lORtnnduYgcAc3pxfqGh8Fybny9NFnTzYJ6B=
iPad level1[2149] <Warning>: +[<AESCrypt: 0xa90e4> decrypt:4o2da81kNQsmmctXfbZb3owepFg8Examx9MEmSyXI6A= password:ZGlhb2RhX2ppYW5rYW5nCg==]
iPad level1[2149] <Warning>:  = QNEcNAUUYKq5mMZJTh3J5w==
iPad level1[2149] <Warning>: +[<AESCrypt: 0xa90e4> decrypt:QNEcNAUUYKq5mMZJTh3J5w== password:ZGlhb2RhX2ppYW5rYW5nCg==]
iPad level1[2149] <Warning>:  = Sp4rkDr0idKit

可以看到5次解密之后的结果是:Sp4rkDr0idKit
好了,打开网站提交答案,成功!

第二题:
首先看到题目之后,好像和ios关系不大啊,还有这些cdevsw结构体没接触过啊。
没关系,先来搜索下这个结构体是啥,和设备/dev/random 又有什么关系。
搜索到cdevsw结构体如下:

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct cdevsw {
  int  (*d_open)  __P((dev_t dev, int oflags, int devtype,
             struct proc *p));
  int  (*d_close)  __P((dev_t dev, int fflag, int devtype,
             struct proc *));
  int  (*d_read)  __P((dev_t dev, struct uio *uio, int ioflag));
  int  (*d_write)  __P((dev_t dev, struct uio *uio, int ioflag));
  int  (*d_ioctl)  __P((dev_t dev, int cmd, caddr_t data,
             int fflag, struct proc *p));
  int  (*d_stop)  __P((struct tty *tp, int rw));
  int  (*d_reset)  __P((int uban));  /* XXX */
  struct  tty *d_ttys;
  int  (*d_select)  __P((dev_t dev, int which, struct proc *p));
  int  (*d_mmap)  __P(());
  int  (*d_strategy)  __P((struct buf *bp));
};

然后继续了解到,这个结构是通过cdevsw_add函数添加到设备,来定义设备的一些行为的,和Windows下的驱动自定义设备读写,以及控制应该是一样的。
那么有思路了,找到cdevsw_add函数,从而找到它被调用的地方:

2

找到了5个调用的地方,先来看第一个:

1

这不就是/dev/random cdevsw_add函数吗,所以第二个参数就是cdevsw结构,点进去:

3

d_read,d_write,d_ioctl对应的就是框住的地址!
继续在第三个调用的地方找到/dev/pf 的cdevsw结构。

4

5

然后第4.5个好像都和/dev/ptmx 有关。

6

没关系不要忽略我们的搜索能力,看源码吧!
/dev/random:

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Called to initialize our device,
 * and to register ourselves with devfs
 */

void
random_init(void)
{
  int ret;

  if (gRandomInstalled)
    return;

  /* install us in the file system */
  gRandomInstalled = 1;

  /* setup yarrow and the mutex */
  PreliminarySetup();

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

  devfs_make_node(makedev (ret, 0), 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, 1), DEVFS_CHAR,
    UID_ROOT, GID_WHEEL, 0666, "urandom", 0);
}

/dev/pf:

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
};
......
if (kernel_thread_start(pf_purge_thread_fn, NULL,
      &pf_purge_thread) != 0) {
    printf("%s: unable to start purge thread!", __func__);
    return;
  }

  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, 0), DEVFS_CHAR,
      UID_ROOT, GID_WHEEL, 0600, "pf", 0);
......

/dev/ptmx:

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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);
    return (0);
}

从上面可以看出,第一个cdevsw_add就是我们要找的/dev/ptmx的咯,第二个是ptsd的咯,自然不是咯。
所以得到地址:

7

好了把这几个地址组合得到:
0x800C0EA0#0x800C0E38#0x800C0E04#0x802873AC#0x802873AC#0x80149D18#0x80292250#0x80292660#0x8029298C
赶紧提交,wrong answer,,,这不是给我泼冷水吗?
后来注意到官方给出的例子,地址最后一位都是奇数,额,,我知道地址加1是为了从ARM 指令状态跳到Thumb 指令状态。那就加1吧,最后都转成小写,提交,通过!
所以answer is:
0x800c0ea1#0x800c0e39#0x800c0e05#0x802873ad#0x802873ad#0x80149d19#0x80292251#0x80292661#0x8029298d

本文链接:http://www.alonemonkey.com/ali-ios-game.html

4条评论


  1. 博主,我是个菜鸟,为什么第一题的ipa放到IDA中什么都没有,一行汇编代码都逆不出来。放到Hopper Disassembler中也出现类似的问题,但是class-dump完全可以查看,,也没有加密。。这是怎么回事

    1. AloneMonkey

      不会啊,可以直接拖到IDA的

Comments are closed.