티스토리 뷰

최종 수정: 2015-11-08

hackability@TenDollar


안녕하세요. Hackability 입니다.


이번에 포스팅 할 내용은 2015 School CTF 의 Reverse 500 문제 입니다.


문제를 보면 c 파일과 h 파일 1개씩 제공합니다.


c 파일의 내용은 다음과 같습니다.

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "somelib.hxx"
#include <iostream>
#include <cstdlib>
 
void error()
{
    std::cout << "Wrong password" << std::endl;
    std::exit(-1);
}
 
int pow(int x, int n)
{
    int ret(1);
    for (int i = 1; i <= n; ++i)
        ret *= x;
    return ret;
}
 
void check_password(std::string& p)
{
    if (p.size() != 13)
    {
        std::cout << "Password must be 13 characters" << std::endl;
        std::exit(-1);
    }
 
    if (p[0]+p[1!= pow(I-----I,2* pow(I-----------I,2+ (I---I)) error();
 
    if (p[1]+p[2!= pow(I-------I,2* pow(I-----I,4- (I---I)) error();
 
    if (p[0]*p[2!= (pow(pow(I-------I,2* pow(I-----I,3- (I---I),2- (I-----I)*(I-------I))) error();
 
    if (p[3]+p[5!= pow((o-------o
                          |       !
                          !       !
                          !       !
                          o-------o).A,2* (I-----I)+(I---I)) error();
 
    if (p[3]+p[4!= pow((o-----------o
                          |           !
                          !           !
                          !           !
                          o-----------o).A,2)+(I---I)) error();
 
    if (p[4]*p[5!= (pow((o-------------o
                           |             !
                           !             !
                           !             !
                           o-------------o).A,2)-(I---I))*(I-----I)*pow(I-------I,2)) error();
 
    if (p[7]+p[8!= (o-----------o
                      |L           \
                      | L           \
                      |  L           \
                      |   o-----------o|!
                      o   |           !
                       L  |           !
                        L |           !
                         L|           !
                          o-----------o).V*pow(I-----I,2- pow((o-------o
                                                                      |       !
                                                                      !       !
                                                                      o-------o).A,2+ (I---I)) error();
 
    if (p[6]+p[8!= (o-----------o
                      |L           \
                      | L           \
                      |  L           \
                      |   L           \
                      |    L           \
                      |     o-----------o
                      |     !           !
                      o     |           !
                       L    |           !
                        L   |           !
                         L  |           !
                          L |           !
                           L|           !
                            o-----------o).V - (I-----I)) error();
 
    if (p[6]*p[7!= (o---------------------o
                      |L                     \
                      | L                     \
                      |  L                     \
                      |   L                     \
                      |    L                     \
                      |     L                     \
                      |      L                     \
                      |       L                     \
                      |        o---------------------o
                      |        !                     !
                      !        !                     !
                      o        |                     !
                       L       |                     !
                        L      |                     !
                         L     |                     !
                          L    |                     !
                           L   |                     !
                            L  |                     !
                             L |                     !
                              L|                     !
                               o---------------------o).V*(pow(I-------I,2+ (I-----I)) + pow(I-----I,6)) error();
 
    if (p[9]+p[10]*p[11!= (o---------o
                             |L         \
                             | L         \
                             |  L         \
                             |   L         \
                             |    o---------o
                             |    !         !
                             !    !         !
                             o    |         !
                              L   |         !
                               L  |         !
                                L |         !
                                 L|         !
                                  o---------o).V*(I-------I)*pow(I-----I,4)-(I---I)) error();
 
    if (p[10]+p[9]*p[11!= (o-----------o
                             |L           \
                             | L           \
                             |  L           \
                             |   L           \
                             |    L           \
                             |     o-----------o
                             |     !           !
                             o     |           !
                              L    |           !
                               L   |           !
                                L  |           !
                                 L |           !
                                  L|           !
                                   o-----------o).V*pow(I-------I,3- (I-----------I)*((I-----I)*(I-----------I)+(I---I))) error();
 
    if (p[9]+p[10!= (o-------------o
                       |L             \
                       | L             \
                       |  L             \
                       |   L             \
                       |    L             \
                       |     o-------------o
                       |     !             !
                       o     |             !
                        L    |             !
                         L   |             !
                          L  |             !
                           L |             !
                            L|             !
                             o-------------o).V-(I-----------I)) error();
 
    if (p[12!= 'w') error();
}
 
int main()
{
    std::cout << "Guess passwd" << std::endl;
    std::string password;
    std::cin >> password;
    check_password(password);
    std::cout << "Correct password! It's your flag, bruh" << std::endl;
}
cs

절대 무슨 ascii art 같은것이 아닙니다. 실제로 연산이 됩니다 =_=

사용자는 저 위의 괴랄한 조건을 만족시키는 12바이트 문자열을 찾아야 합니다.

먼저 저 이상한 문자들이 뭔지 출력을 해봅니다.

ex) printf(" %lf \n", pow(I-----I,2) * pow(I-----------I,2) + (I---I));

결과) 101.000000

?????! 잘 출력 됩니다. 해더 파일에 보면 연산자 오버로딩을 통해 구현한것 같은데 신기 합니다.

신기한 내용을 이제 알았으니 그 다음부터는 간단합니다. (우디르급 태세변환)

처음 조건문은 다음과 같이 변경될 수 있습니다.

p[0] + p[1] = 101

후후후... 그렇다면 나머지도 다 만들어 줍니다.

p[0] + p[1] = 101
p[1] + p[2] = 143
p[0] * p[2] = 5035

p[3] + p[5] = 163
p[3] + p[4] = 226
p[4] * p[5] = 5814

p[7] + p[8] = 205
p[6] + p[8] = 0
p[6] * p[7] = 9744

p[9] + p[10] * p[11] = 5375
p[10] + p[9] * p[11] = 4670
p[9] + p[10] = 0

저 빨갛게 칠한 부분이 제가 환경이 안맞아서 잘 연산이 안된 부분인것 같습니다. 0~5 까지는 미지수 3개 식 3개가 만족하기 때문에 미지수를 다 구할 수 있고, 6~8 까지는 미지수 3개 식 2개 (중간의 6 + 8 = 0 은 깨진 거라 못씀)이긴 하지만 

$7 = (1 ~ 205) 까지 범위
$8 = 205 - $7
$6 = 9744 / $7

이런식으로 만들 수 있기 때문에 구할 수 있습니다. 근데 마지막 미지수 3개 식 2개는.... -_-  fucked... 

다행히 범위가 크기 않기 때문에 brute forcing 으로 마지막은 답을 구합니다.

is_true 함수에서는 몇 가지 조건에 대해 문자열들을 제거 합니다.
  1. 계산 결과가 소수점이 나오는 경우, ascii 는 소수점이 없기 때문에 이런 계산이 나오는 경우는 제외 합니다.
  2. 계산 결과가 출력 가능한 ascii 범위 ( 0x20 <= X <= 0x7F ) 에 들지 않는 경우, 역시 제외 합니다.

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
def is_true(b):
    if b - int(b) > 0:
        return False
 
    if b >= 0x20 and b <= 0x7F:
        return True 
 
    return False
 
msg = ''
tmp = ''
for i in range(0x200x7F):
    n0 = i
    n1 = 101.0 - n0
    n2 = 5035.0 / n0
 
    if is_true(n0) and is_true(n1) and is_true(n2):
        tmp = chr(n0) + chr(int(n1)) + chr(int(n2))
 
msg += tmp
 
for i in range(0x200x7F):
    n3 = i
    n5 = 163.0 - n3
    n4 = 5814.0 / n5
 
    if is_true(n3) and is_true(n4) and is_true(n5):
        tmp = chr(n3) + chr(int(n4)) + chr(int(n5))
 
msg += tmp
 
for i in range(0x200x7F):
    n7 = i
    n8 = 205.0 - n7
    n6 = 9744.0 / n7
 
    if is_true(n6) and is_true(n7) and is_true(n8):
        tmp = chr(int(n6)) + chr(n7) + chr(int(n8))
 
msg += tmp
 
for i in range(0x200x7F): # v9
    for j in range(0x200x7F): # v10
        for k in range(0x200x7F): # v11
            if (5375 - i) != (j * k):
                continue
                #print i, j, k
 
            if (4670 - j) != (i * k):
                continue
 
            tmp = chr(i) + chr(j) + chr(k)
msg += tmp
msg += 'w'
 
print msg
cs

결과 : 50_pr3TtY_n0w


댓글