화이트해커리그(CodeRed) - iOS Baby

[MOBILE]

Do you know storyboard?

iOS 앱 리버싱 문제다.
storyboard를 리버싱하는 의도로 출제를 했다.
이 문제의 풀이법은 정적 분석, 동적 분석 모두 존재한다.

Solution 1 (정적 분석)

먼저 ipa파일을 zip으로 확장자를 바꾼 뒤, 압축해제해준다.
그러면 ios_baby/Payload/ios_baby.app/Base.lproj/Main.storyboardc안에 두 개의 .nib파일이 있는것을 확인할 수 있을 것이다.

.nib파일들을 분석하기 위해서 https://github.com/davidquesada/ibtool을 사용하기로 한다.

1
python ibtool/ibtool.py ./BYZ-38-t0r-view-8bC-Xf-vdC.nib/objects-11.0+.nib

잘 살펴보면 UIViewUILabel이 보이는 것을 알 수 있다.
UIView는 한 개만 있는데 Storyboard에서 만든 ViewController안에 있는 기본적인 UIView일 것으로 별 볼일은 없다.
UILabel를 살펴보는것이 중요하다. UILabel은 총 18개가 존재하고 있었다.

일단 필요한 정보만 뽑아보면 이렇다.

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
3: UILabel
UICenter = (196.0, 97.5)
UIText = @9

9: NSLocalizableString
NS.bytes = 8

5: UILabel
UICenter = (74.0, 97.5)
UIText = @13

13: NSLocalizableString
NS.bytes = R

18: UILabel
UICenter = (154.0, 96.5)
UIText = @110

110: NSLocalizableString
NS.bytes = z

43: UILabel
UICenter = (249.0, 96.5)
UIText = @40

40: NSLocalizableString
NS.bytes = q

45: UILabel
UICenter = (132.0, 97.5)
UIText = @60

60: NSLocalizableString
NS.bytes = a

47: UILabel
UICenter = (93.0, 97.5)
UIText = @34

34: NSLocalizableString
NS.bytes = {

48: UILabel
UICenter = (117.0, 97.5)
UIText = @22

22: NSLocalizableString
NS.bytes = 3

51: UILabel
UICenter = (289.0, 97.5)
UIText = @103

103: NSLocalizableString
NS.bytes = a

58: UILabel
UICenter = (211.0, 97.5)
UIText = @44

44: NSLocalizableString
NS.bytes = 9

62: UILabel
UICenter = (54.0, 97.5)
UIText = @55

55: NSLocalizableString
NS.bytes = C

90: UILabel
UICenter = (187.0, 343.5)
UIText = @75

75: NSLocalizableString
NS.bytes = YOU CAN'T SEE THIS

91: UILabel
UICenter = (224.0, 97.5)
UIText = @29

29: NSLocalizableString
NS.bytes = _

92: UILabel
UICenter = (274.0, 97.5)
UIText = @74

74: NSLocalizableString
NS.bytes = r

96: UILabel
UICenter = (239.0, 96.5)
UIText = @67

67: NSLocalizableString
NS.bytes = b

98: UILabel
UICenter = (261.0, 96.5)
UIText = @17

17: NSLocalizableString
NS.bytes = _

100: UILabel
UICenter = (174.0, 96.5)
UIText = @89

89: NSLocalizableString
NS.bytes = 3

118: UILabel
UICenter = (104.0, 97.5)
UIText = @57

57: NSLocalizableString
NS.bytes = 5

120: UILabel
UICenter = (354.0, 97.5)
UIText = @94

94: NSLocalizableString
NS.bytes = }

UICenter에서 알려주는 x, y값의 좌표를 기반으로 해서NSLocalizableStringNS.bytes값으로 text를 잘 정리해주면 flag가 나오게 된다.

flag : CR{53az389_bq_ra}

Solution 2 (동적 분석)

현재 탈옥한 iPhone을 가진게 없어서 non-jailbreak된 기기로 분석하는 것을 기준으로 작성하겠다.
먼저 ipa파일에 Frida로 분석하기 위한 FridaGadget.dylib를 주입하고 ipa를 설치하기 위해서 appmonipa installer를 사용하기로 했다.

ipa installer로 앱을 잘 설치해준 다음 frida를 통해 분석을 시작한다.

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
~ ❯❯❯ frida-ps -U
PID Name
----- ------
12831 Gadget
~ ❯❯❯ frida -n Gadget -U
____
/ _ | Frida 10.1.4 - A world-class dynamic instrumentation framework
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/

[USB::iPhone::Gadget]-> console.log(ObjC.classes.UIWindow.keyWindow().rootViewController().view().subviews().toString())
(
"<UILabel: 0x103e10080; frame = (83 87; 42 21); text = '5'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408afa0>>",
"<UILabel: 0x103e10760; frame = (96 87; 42 21); text = '3'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408af00>>",
"<UILabel: 0x103e10c80; frame = (133 86; 42 21); text = 'z'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b130>>",
"<UILabel: 0x103e10f60; frame = (253 87; 42 21); text = 'r'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b1d0>>",
"<UILabel: 0x103e11240; frame = (190 87; 42 21); text = '9'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b270>>",
"<UILabel: 0x103e11520; frame = (240 86; 42 21); text = '_'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b310>>",
"<UILabel: 0x103e11800; frame = (268 87; 42 21); text = 'a'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b3b0>>",
"<UILabel: 0x103e11ae0; frame = (218 86; 42 21); text = 'b'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b450>>",
"<UILabel: 0x103e11dc0; frame = (228 86; 42 21); text = 'q'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b4f0>>",
"<UILabel: 0x103e120a0; frame = (53 87; 42 21); text = 'R'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b590>>",
"<UILabel: 0x103e127e0; frame = (333 87; 42 21); text = '}'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b630>>",
"<UILabel: 0x103e12ac0; frame = (111 87; 42 21); text = 'a'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b6d0>>",
"<UILabel: 0x103e12da0; frame = (72 87; 42 21); text = '{'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b770>>",
"<UILabel: 0x103e13080; frame = (175 87; 42 21); text = '8'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b810>>",
"<UILabel: 0x103e13360; frame = (153 86; 42 21); text = '3'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b8b0>>",
"<UILabel: 0x103e13840; frame = (33 87; 42 21); text = 'C'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b950>>",
"<UILabel: 0x103e13b20; frame = (203 87; 42 21); text = '_'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408b9f0>>",
"<UILabel: 0x103e13e00; frame = (0 5; 375 812); text = 'YOU CAN'T SEE THIS'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1c408ba90>>"
)

Frida를 통해 현재 보여지고 있는 viewsubview들을 모두 볼 수 있다. 하지만 아이폰 화면엔 YOU CAN'T SEE THIS만 보인다.

소스코드를 작성해서 해당 UILabel을 지워보기로 했다.

solve.js

1
2
3
4
5
6
7
8
9
10
11
12
var view = ObjC.classes.UIWindow.keyWindow().rootViewController().view();
var subviews = view.subviews();
var count = subviews.count();

for (var i = 0; i < count; i++) {
var x = subviews.objectAtIndex_(i);
console.log("<" + x.$className + ": " + x.handle + ":" + x.text() + ">");
if (x.text() == "YOU CAN'T SEE THIS") {
console.log(x)
x.removeFromSuperview()
}
}

성공적으로 flag가 보인다.

flag : CR{53az389_bq_ra}

Share