CTF Writeup HamaCTF » 履歴 » バージョン 1
kanata, 2025/04/13 15:16
1 | 1 | kanata | # CTF Writeup HamaCTF |
---|---|---|---|
2 | |||
3 | 2017.12.2 [元祖 濱せっく #1](https://hamasec.connpass.com/event/70567/)で開催されたCTFの想定解です。 |
||
4 | |||
5 | {{toc}} |
||
6 | |||
7 | # 問題 |
||
8 | |||
9 | ## エクササイズ |
||
10 | |||
11 | ``` |
||
12 | 復号してね。シェル芸でできるよ。 |
||
13 | 2n,13,rev,64 |
||
14 | |||
15 | 01011000001100000011001101011010001100010101001001101101010011000110110001000001010100010111001001101101011001100110000101000101010010000100000101001000010011000110011101010011010101000100011000001010 |
||
16 | ``` |
||
17 | |||
18 | ## 全てがFになる |
||
19 | |||
20 | これから何かわかりますか? |
||
21 | |||
22 | attachment:f.zip |
||
23 | |||
24 | ## 難読化シェル芸1 |
||
25 | |||
26 | 解読してみましょう |
||
27 | |||
28 | attachment:NandokukaShellGeiSleeps.zip |
||
29 | |||
30 | 大サービス!フラグの一部を教えちゃう! |
||
31 | |||
32 | 38} |
||
33 | |||
34 | ## zlib |
||
35 | |||
36 | この中にzlibされたフラグが埋もれています。 |
||
37 | |||
38 | attachment:zlib.zip |
||
39 | |||
40 | ## sign |
||
41 | |||
42 | 以下のメッセージと attachment:sign.zip から何かわかりますか? |
||
43 | |||
44 | 9:14 PM 05 AUG 16 Edward Snowden |
||
45 | b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd |
||
46 | |||
47 | ## 難読化シェル芸2 |
||
48 | |||
49 | 解読してみましょう |
||
50 | |||
51 | attachment:NandokukaShellGeiInqAns.zip |
||
52 | |||
53 | 大サービス!フラグの一部を教えちゃう! |
||
54 | |||
55 | fi} |
||
56 | |||
57 | |||
58 | # 想定解 |
||
59 | |||
60 | 暇だったら想定解見る前にチャレンジしてみてクレメンス |
||
61 | |||
62 | {{collapse(想定解を表示...) |
||
63 | |||
64 | ## エクササイズ |
||
65 | |||
66 | 01の羅列と「2n,13,rev,64」という言葉があります。 |
||
67 | どうやら以下になりそうだと予想がつきます。 |
||
68 | |||
69 | * 2n → 2進数を文字に? |
||
70 | * 13 → ROT13(シーザー暗号) |
||
71 | * rev → 文字列をひっくり返す(revコマンドってありますね) |
||
72 | * 64 → base64からデコード |
||
73 | |||
74 | この通りに変換していけばよさそうです。 |
||
75 | 早速やってみましょう! |
||
76 | |||
77 | ### 2n(01から文字列に変換) |
||
78 | |||
79 | ```bash |
||
80 | $ echo "obase=16; ibase=2; 01011000001100000011001101011010001100010101001001101101010011000110110001000001010100010111001001101101011001100110000101000101010010000100000101001000010011000110011101010011010101000100011000001010" |bc|xxd -r -p |
||
81 | X03Z1RmLlAQrmfaEHAHLgSTF |
||
82 | ``` |
||
83 | |||
84 | ### 13(ROT13で復号) |
||
85 | |||
86 | ```bash |
||
87 | $ echo X03Z1RmLlAQrmfaEHAHLgSTF |tr A-Za-z N-ZA-Mn-za-m |
||
88 | K03M1EzYyNDezsnRUNUYtFGS |
||
89 | ``` |
||
90 | |||
91 | ### rev(文字列をひっくり返す) |
||
92 | |||
93 | ```bash |
||
94 | $ echo K03M1EzYyNDezsnRUNUYtFGS |rev |
||
95 | SGFtYUNURnszeDNyYzE1M30K |
||
96 | ``` |
||
97 | |||
98 | ### 64(base64からデコード) |
||
99 | |||
100 | ```bash |
||
101 | $ echo SGFtYUNURnszeDNyYzE1M30K|base64 -d |
||
102 | HamaCTF{3x3rc153} |
||
103 | ``` |
||
104 | |||
105 | フラグが手に入りました。 |
||
106 | |||
107 | ### まとめるとこんな感じ |
||
108 | |||
109 | この一連の変換をこんな感じでシェル芸にできます。 |
||
110 | |||
111 | ```bash |
||
112 | $ echo "01011000001100000011001101011010001100010101001001101101010011000110110001000001010100010111001001101101011001100110000101000101010010000100000101001000010011000110011101010011010101000100011000001010"|cat <((echo "obase=16; ibase=2; ")) -|tr -d '\n'|echo -e $(cat)|bc|xxd -r -p|tr A-Za-z N-ZA-Mn-za-m |rev |base64 -d |
||
113 | HamaCTF{3x3rc153} |
||
114 | ``` |
||
115 | |||
116 | ## 全てがFになる |
||
117 | |||
118 | とりあえず実行してみます |
||
119 | |||
120 | ```bash |
||
121 | $ bash f |
||
122 | ``` |
||
123 | |||
124 | 円状に画面がFで埋め尽くされたと思ったら、今度は埋められたFの一部が消されていきます。 |
||
125 | 何かを描くような処理に見えます。 |
||
126 | |||
127 | ``` |
||
128 | $Fbash f F FF |
||
129 | FF FF FF FF FFF F F FF F FF F F F F |
||
130 | F F F F FF FFF FFFF F FF F FFFF |
||
131 | FFF F FF F F FFFFF FFFF FF FFF F FFFF FF FFFF FF F F FF F |
||
132 | F FFF F FFF FFF F F F FFFFFFFFF FF F FFFFFFF F FF F F F F |
||
133 | F FF FFFFFFFFF FF FFFF FF FFFFFFFFFF FFFFFF FFFFFF FF FF FFF F FF |
||
134 | F FFF FFF FFFFF FFFF F FFFFFFF FFFFFF FFFF FFFFFFFF FF FF FFF F F |
||
135 | F FF F F F FFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF FF |
||
136 | FFF F F F F FFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF F F F F |
||
137 | F FFFFFF FF FFFF FFFFFFFFFFFFFFFFFFF FFFF FFFFFFFFFFFFFFFFFFFFFF FFFFF F F |
||
138 | F F F F FFFFFFFFF FF F FFFF F FFFF FFFFFFFFF FFFFFFFF F FF F FF FFF F |
||
139 | F F FFFF F FFF F FFF FFFFF F FFFFF FFFFFFFFFFF FFFFFF FF FFFFFFFF FFFF FFFF F F |
||
140 | FF F F FF F F FFFF FF FF F FFFFFFFF FFFFFFFFFF FFFF FFFFFF FF FFFFFFFF FF F |
||
141 | F FF F FF FFF FFFFFFF FFFFFFF FFFFFFFF FFFFFFFFFFFFFFFFF FFFFFFFFFF FF FF F F |
||
142 | F F FF FFFFFFFFFF FF FFF FFFFFFF FFFFFFFFF FF FF F FFFFF FFFF FFF F |
||
143 | FFFF FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF F F FF |
||
144 | F F F F FFFFFFFF FFFFFFF FFFFFFFFFFFFFFFFFFF FFF FFFFFFFFF FFFFFF FFFFFFFF F |
||
145 | FFFF FF FFFFFF FFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFF F FF F FF FF F |
||
146 | F F F F F F FF FFF FFFFF F FFFFFF FFF FFFF FFFFFF F F FFFFF F F |
||
147 | FF F F FFF F FF F FF FFFFF FF FF F FF FFF FF FF FFF F FF F |
||
148 | F F F F FFF FF FFF FFFFF FFFFFFFFF F F |
||
149 | F F F FF FF FF FFFFF FFFF |
||
150 | F F F F F F F F F |
||
151 | F FF F F F |
||
152 | F F |
||
153 | ``` |
||
154 | |||
155 | |||
156 | わかりやすく整形して中身を見てみましょう。 |
||
157 | ";"を改行に置換するのが見やすくするコツです(bashの文の区切りは改行か、;なので)。 |
||
158 | |||
159 | ```bash |
||
160 | D="MjJ...中略" |
||
161 | C=$(tput cols) |
||
162 | L=$(tput lines) |
||
163 | |||
164 | if [ $C -lt 80 ] || [ $L -lt 24 ] |
||
165 | then echo recommend : Terminal size over 80x24 |
||
166 | echo now "${C}x${L}" |
||
167 | read |
||
168 | fi |
||
169 | |||
170 | c="0" |
||
171 | while [ $c -lt 5000 ] |
||
172 | do x=$((($RANDOM%$C+$RANDOM%$C+$RANDOM%$C)/3)) |
||
173 | y=$((($RANDOM%$L+$RANDOM%$L+$RANDOM%$L)/3)) |
||
174 | printf "\033[${y};${x}fF" |
||
175 | c=$(($c+1)) |
||
176 | done |
||
177 | |||
178 | c="0" |
||
179 | LIST=$(echo $D|base64 -d) |
||
180 | while [ $c -lt 500 ] |
||
181 | do LINE=$(echo $LIST|tr ' ' '\n'|shuf|head -1) |
||
182 | x=$(echo $LINE|cut -d'_' -f2) |
||
183 | y=$(echo $LINE|cut -d'_' -f1) |
||
184 | printf "\033[${y};${x}f " |
||
185 | c=$(($c+1)) |
||
186 | done |
||
187 | ``` |
||
188 | |||
189 | 案外短いシェルスクリプトでした。1つ目のwhile文の中の処理でFを画面に表示し、2つ目のwhile文でそのFをスペースで上書きしている。。あたりまで読めたらゴールは近いです。 |
||
190 | whileで有限回数ループしていますが、どちらもループ回数が不十分のようです。 |
||
191 | |||
192 | * Fで画面を埋め尽くす |
||
193 | * そのFをスペースで消して、何かを表示しようとしている |
||
194 | |||
195 | とりあえずループ回数を増やしてみましょう。えいやっと10倍にしてみます。 |
||
196 | |||
197 | ``` |
||
198 | F F F F FFFFF FF F F FFFFF FFFFFF FF F FF F F FF F F |
||
199 | FFFFFFFFFFFFFFFF FFFF FFFFFFF FF FFFF FFFFF FFFF FFFFFF FFFFFF FFFFFFFFF F F |
||
200 | F FF FFF F FFF F F FFFFFFFFFF FFFF FFFFFFF FFFFFF FFFFFFFFF F F |
||
201 | F FFFFF F FFF FFF FF FFFF F FFFFF FFFF FFFF FFF FFFFFF FFFFFFFFF FFF FF |
||
202 | FFF FF F F F FFF FFF FF F F F FFFFFF FFFF FFFFFFF FFFFFF FFFFFFFFF FFF F |
||
203 | FF F FFFF F FFF FFF F FFFF F FFFF FFFF FFFF FFFFFFF FFFFFF FFFFFFFFFFFFF F |
||
204 | FFF FF F FFF FFF FF FF FF FF FFFF FFFFFFFF FFFF FFFFFFFFFFFFF FFF F |
||
205 | F F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFF |
||
206 | FFFF F FFFFF FFFF FFFFFFF F F FF FFF F F FFFFF FFFFFFF FFFFFFFFFFFFF FFF |
||
207 | FFFFFFFFFFFFFF F FFFF FFFFFFFFFF FFFFFFF FFFF FF FFFFF F FFFFFFFFFF FFFFFFFFFFFFFFFFF |
||
208 | FF FF FF FF FF FFFFFFFF FFF F FFFFFFFFFFFFFFF F |
||
209 | FFF F FFFF F FFFF F FFFF F FFFF F FFFFF FFFF F FFFFFFFFF FF FFFFFFFFFFFFFFF |
||
210 | FF F F F F FF F F FFFFFFF FFFFFFF F FFFFFFFFF FF FFFFFFFFFFFFFF |
||
211 | FFFF F FFFFFFF FFFFFFF FFFFFFF FFFFFFF FFFFFFF FFFFFFF FFFFFFFFF FF FFFFFFFFFF F F F |
||
212 | F FF F F F FFFFFF FFF F FFFFFFF FFFFFFFF FF FFFFF FFFFFFFFFF F F |
||
213 | FF FF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF F |
||
214 | FFFFFFF FFFFFFF FFF FFFFFFF FFFFFFF FFFF FFFF F FFFFFFFFFFFFFFFFFFFFFFFFFFF FFF |
||
215 | F F FF FFFF FF FFFFFFFFFFFFFFFF FF FFFFFFFFFFFFFFFF FFF FFFFFFFFFFFFFFFFFFFFFFFFFFFF FF |
||
216 | F FFF F FF FF FF FF FFF FFFFFFFFFFFFFFFFFFFFFFFFF F F |
||
217 | FF FFFF F FFFFF F F FFFF F FFFF F FFFF F FFF FFFFFFFFFFFFFFFFFFFFFFF FF F FF |
||
218 | F FFFF FF FF F F FF F FFFFFFF FFF FFFFFFFFFFFFFFFFFFFFFFF F FFF |
||
219 | F F F FFFFFFF F FFF FF FFFFFFF FFFFFFFFFFFFF FFFFFFFFFFFF F FFFFF FF F |
||
220 | F F FF F F F FFFFFFF F FFF FFFF FF FF FFFFF FF F |
||
221 | F F FFFFFFFFF F F FFF FFFF F FFFF FF FF F |
||
222 | F F |
||
223 | ``` |
||
224 | |||
225 | あ~、フラグっぽいのが見えます?ね。このままループ回数を調整してもフラグを得られそうですが、「Fで画面を埋める→スペースでフラグの文字を書く」から「Fで画面を埋める(コメントアウト)→Fでフラグの文字を書く」にソースコードを修正してみましょう。 |
||
226 | |||
227 | ```bash |
||
228 | D="MjJ...中略" |
||
229 | C=$(tput cols) |
||
230 | L=$(tput lines) |
||
231 | |||
232 | if [ $C -lt 80 ] || [ $L -lt 24 ] |
||
233 | then echo recommend : Terminal size over 80x24 |
||
234 | echo now "${C}x${L}" |
||
235 | read |
||
236 | fi |
||
237 | |||
238 | # c="0" |
||
239 | # while [ $c -lt 5000 ] |
||
240 | # do x=$((($RANDOM%$C+$RANDOM%$C+$RANDOM%$C)/3)) |
||
241 | # y=$((($RANDOM%$L+$RANDOM%$L+$RANDOM%$L)/3)) |
||
242 | # printf "\033[${y};${x}fF" |
||
243 | # c=$(($c+1)) |
||
244 | # done |
||
245 | |||
246 | c="0" |
||
247 | LIST=$(echo $D|base64 -d) |
||
248 | while [ $c -lt 500 ] |
||
249 | do LINE=$(echo $LIST|tr ' ' '\n'|shuf|head -1) |
||
250 | x=$(echo $LINE|cut -d'_' -f2) |
||
251 | y=$(echo $LINE|cut -d'_' -f1) |
||
252 | printf "\033[${y};${x}fF" # スペースからFに修正 |
||
253 | c=$(($c+1)) |
||
254 | done |
||
255 | ``` |
||
256 | |||
257 | 実行して、フラグが得られました。 |
||
258 | |||
259 | ``` |
||
260 | FF FF F FFFF FFF FF F FFFFFFFF FFF FFFFFFFF |
||
261 | FF FF FF FF FF FF FF FF |
||
262 | FF FF FFFFF FFFFFF FFFF FFFFF FF FF FF FF FF |
||
263 | FFFFFFFF FF FF FF FF FF FF FF FFFFF FFF FF |
||
264 | FF FF FFFFFFF FF FF FF FFFFFFF FF FF FF FF FF |
||
265 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF |
||
266 | FF FF FFFFFFF FF FF FF FF FFFF FFFFFF FF FF FFF FF |
||
267 | |||
268 | FF FFFFFFF FFF FF FF |
||
269 | FF FF FF FF FF FF |
||
270 | FFFFFFF FFFFF FF FF FFFFFF FFFFFF FF FFFFFF FFFFFFF FFFFFF |
||
271 | FF FF FF FF FF FF FF FF FF FF FFFF FF FF FF FF |
||
272 | FF FF FFFFFFFF FFFFFFF FFFFFFFF F FF FFFFFFFF F FF |
||
273 | FF FF FF FF FF FF FF FF FF FF FF |
||
274 | FF FF FFFFF FF FFFFFFF FF FF FFFFFF FFFFFFF FFFF |
||
275 | |||
276 | FFFFFF FF FF FF FFF |
||
277 | FF FF FF FF |
||
278 | FF FFFFFFF FFFFFFF FF FFFFFFF FFFFFF FFFFFF FF FF |
||
279 | FF FF FF FF FF FF FF FF FF F FF FF FFF |
||
280 | FF FF FF FFFFFF FF FF FF FFFFFFFF FF FF FF |
||
281 | FF FF FF FF FF FF FF FF FF FF |
||
282 | FFFFFF F FF FFFFFFF FF FFFFFF FFFFFFF FF FF FFF |
||
283 | ``` |
||
284 | |||
285 | HamaCTF{ThePerfectInsider!} |
||
286 | |||
287 | ## 難読化シェル芸1 |
||
288 | |||
289 | とりあえず実行してみます。 |
||
290 | |||
291 | ``` |
||
292 | $ bash NandokukaShellGeiSleeps |
||
293 | Let us decording!(≧∀≦*) |
||
294 | ``` |
||
295 | |||
296 | ここから、何も起きません。 |
||
297 | |||
298 | 中身のファイルを見ると難読化されたシェルスクリプトが見えます。 |
||
299 | うげっ、これをデコードするのかぁ、、という気持ちになるかもしれません、が、、 |
||
300 | |||
301 | ```bash |
||
302 | echo TGV0IHVzIGRlY29yZGluZyEo4omn4oiA4ommKikK|base64 -d;read;$($'\145\143\150\157' c2xlZXAK | $'\142\141\163\145\66\64' $'\55\144' ) $($'\x65\x63\x68\x6f' NDcK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) ;$($'\145\143\150\157' c2xlZXAK | $'\142\141\163\145\66\64' $'\55\144' ) $($'\145\143\150\157' OAo= | $'\142\141\163\145\66\64' $'\55\144' ) ;$'\u0073\u006c\u0065\u0065\u0070' $(echo =oQO |rev|base64 -d) ;$'\u0073\u006c\u0065\u0065\u0070' $($'\x65\x63\x68\x6f' NQo= | $'\x62\x61\x73\x65\x36\x34' -d) ;$'\164\162\141\160' '' $'\61' $'\62' $'\63' $'\x31\x35' $'\x31\x38' $'\u0031\u0039' $(echo MjAK |base64 -d);$($'\u0065\u0063\u0068\u006f' c2xlZXAK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) $'\u0034' ;$(echo pzIuMNb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) $($'\x65\x63\x68\x6f' MzcK | $'\x62\x61\x73\x65\x36\x34' -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo ZwHX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\72' echo good going)$'\x3A' $'\x70\x6f\x77\x65\x72\x6f\x66\x66';$'\x75\x6e\x73\x65\x74' $'\x65\x78\x69\x74' $'\x6b\x69\x6c\x6c' ;$(echo c2xlZXAK |base64 -d) $(echo XHQA |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\u0065\u0063\u0068\u006f' c2xlZXAK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) $(echo KATM |rev|base64 -d) ;$'\u0073\u006c\u0065\u0065\u0070' $'\x34\x39' ;$(echo KAXZlx2c |rev|base64 -d) $'\u0034\u0039' ;$(echo p2kyMKNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo MTEK |base64 -d) ;$(echo p2kyMKNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $'\u0032\u0035' ;$($'\145\143\150\157' cmVhZAo= | $'\142\141\163\145\66\64' $'\55\144' ) ;$'\72'|$'\x67\x72\x65\x70' $'\x2d\x71' $($'\x65\x63\x68\x6f' Ogo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' )||$'\u003a'|$(echo =bNpyW3M |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo XRKY |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo Ogo= |base64 -d)||$($'\u003A' poweroff)$(echo =owboNWZ |rev|base64 -d) JHZ1RSomfSYjP0UyKD1BZTY/QWV7OmNGezhsbAo=|base64 -d|tr '!-~' 'P-~!-O' |base64 -d;$'\u0073\u006c\u0065\u0065\u0070' $(echo NTYwCg== |base64 -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo NTk1Cg== |base64 -d) ;$'\x63\x61\x74' $0|$'\155\144\65\163\165\155'|$'\x63\x61\x74' - <((echo '}'))|tr -d '\n -';: $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $($'\145\143\150\157' NDAK | $'\142\141\163\145\66\64' $'\55\144' ) ;$'\x75\x6e\x73\x65\x74' $'\x65\x78\x69\x74' $'\x6b\x69\x6c\x6c' ;$(echo KAXZlx2c |rev|base64 -d) $($'\u0065\u0063\u0068\u006f' MTcK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) ;$'\u0075\u006e\u0073\u0065\u0074' $'\u0065\u0078\u0069\u0074' $'\u006b\u0069\u006c\u006c';$($'\u003A' killall sh)$'\u003A' $(echo cG93ZXJvZmYK |base64 -d);$($'\u003A' echo hello)$(: poweroff);$(echo KQXZz5Wd |rev|base64 -d) $(echo =oAdphXZ |rev|base64 -d) $(echo =oAbsl2a |rev|base64 -d);$($'\x3A' echo well)$'\u003A' $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $'\62\61' ;$(echo p2kyMKNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $'\62\65' ;$'\u003A' $($'\u0065\u0063\u0068\u006f' cG93ZXJvZmYK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo MjEK |base64 -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) $(echo XtQA |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$'\72' $(echo cG93ZXJvZmYK |base64 -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $($'\145\143\150\157' MjIK | $'\142\141\163\145\66\64' $'\55\144' ) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo XRwZ |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$'\162\145\141\144' ;$(echo XNKMyk2p |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo AGxX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\u003A' killall sh): pkill sh;$(echo =bNMuIzp |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$(echo KQXZz5Wd |rev|base64 -d) $(echo =oAdphXZ |rev|base64 -d) $(echo =oAbsl2a |rev|base64 -d);$(echo pzIuMNb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$'\u0073\u006c\u0065\u0065\u0070' $'\62\63' ;$(ls --help|grep ^G|cut -c9)$(ls --help|grep ^G|cut -c16)$(ls --help|grep ^G|cut -c13)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c10)$(xxd /bin/ls|head -1|cut -d: -f2|cut -c1)$(ls --help|grep ^G|cut -c8)$(printf "%b" $(printf '%s%x' '\x' $((0x77 ^ 0x2f)))|tr A-Z a-z)$(ls --help|grep ^G|cut -c11)$(ls --help|grep ^G|cut -c10)$(xxd /bin/ls|head -1|cut -d: -f2|cut -c1)$(printf "%b" $(printf '%s%x' '\x' $((0x77 ^ 0x1c))))$(ls --help|grep ^G|cut -c11)$(ls --help|grep ^G|cut -c12)$(ls --help|grep ^G|cut -c12);$($'\72' echo good going)$'\x3A' $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);$(echo KQXZz5Wd |rev|base64 -d) $(echo =oAdphXZ |rev|base64 -d) $(echo =oAbsl2a |rev|base64 -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $'\x39' ;$'\x73\x6c\x65\x65\x70' $($'\x65\x63\x68\x6f' NTQK | $'\x62\x61\x73\x65\x36\x34' -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo ZmNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\u0065\u0063\u0068\u006f' c2xlZXAK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) $($'\145\143\150\157' NjAK | $'\142\141\163\145\66\64' $'\55\144' ) ;$($'\x3A') $'\u003A' $($'\145\143\150\157' ZXhpdAo= | $'\142\141\163\145\66\64' $'\55\144' );$(echo KAXZlx2c |rev|base64 -d) $($'\u0065\u0063\u0068\u006f' MzUK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) ; |
||
303 | ``` |
||
304 | |||
305 | 次が大事なポイントで、この問題の核心です。 **「通常、シェルスクリプトをデバックするときにどうするか?」**です。 |
||
306 | (ご存知なければ、この機会に覚えていただければ!きっとこの先々役に立ちますよ!) |
||
307 | |||
308 | [bashのxオプションを使う](https://www.google.co.jp/search?q=%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%80%80%E3%83%87%E3%83%90%E3%83%83%E3%82%AF)んです。いくら難読化されていても最終的に評価されたコマンドがこれで見えてしまいます。 |
||
309 | |||
310 | やってみましょう! |
||
311 | |||
312 | ```bash |
||
313 | $ bash -x NandokukaShellGeiSleeps |
||
314 | + base64 -d |
||
315 | + echo TGV0IHVzIGRlY29yZGluZyEo4omn4oiA4ommKikK |
||
316 | Let us decording!(≧∀≦*) |
||
317 | + read |
||
318 | |||
319 | ++ echo c2xlZXAK |
||
320 | ++ base64 -d |
||
321 | ++ echo NDcK |
||
322 | ++ base64 -d |
||
323 | + sleep 47 |
||
324 | ++ base64 -d |
||
325 | ++ echo c2xlZXAK |
||
326 | ++ echo OAo= |
||
327 | ++ base64 -d |
||
328 | + sleep 8 |
||
329 | ++ rev |
||
330 | ++ base64 -d |
||
331 | ++ echo =oQO |
||
332 | + sleep 9 |
||
333 | ++ base64 -d |
||
334 | ++ echo NQo= |
||
335 | + sleep 5 |
||
336 | ++ base64 -d |
||
337 | ++ echo MjAK |
||
338 | + trap '' 1 2 3 15 18 19 20 |
||
339 | ++ base64 -d |
||
340 | ++ echo c2xlZXAK |
||
341 | + sleep 4 |
||
342 | ++ base64 -d |
||
343 | ++ tr A-Za-z N-ZA-Mn-za-m |
||
344 | ++ echo pzIuMNb= |
||
345 | + read |
||
346 | (続く..) |
||
347 | ``` |
||
348 | |||
349 | 見える...見えるぞ!!難読化が解かれる過程の処理が混じって見えますが、sleepと、たまにreadが実行されるだけのようです。 |
||
350 | このまま待っていればフラグが得られそうですが... |
||
351 | いったい何時間待てばいいか、わかりません。このsleepとreadを、なんとかスキップできないでしょうか? |
||
352 | |||
353 | readはビルトインコマンドなのでkillできません。ENTERして進めましょう。 |
||
354 | sleepはkillすればいいんです。 |
||
355 | >「処理中のsleepを待てないから早く進めたい」という時に使えます。シェルスクリプトを開発する際に、たまに使うちょっとしたテクニックなので、これも覚えておくと良いと思います。 |
||
356 | |||
357 | |||
358 | でも私は、trapで全てのシグナルを捨てるように作問しました。普通にkillしてもsleepは死なないようにしています。 |
||
359 | それでも、プロセスはkillできます。そう kill -9 ならね。 |
||
360 | |||
361 | と、いうわけでターミナルを二つ起動して、一方は問題を実行(readはENTERだけ押して処理を進める)。もう一方はsleepをひたすらkillすればゴールです。 |
||
362 | |||
363 | ``` |
||
364 | $ pkill -9 sleep |
||
365 | $ pkill -9 sleep |
||
366 | $ pkill -9 sleep |
||
367 | $ pkill -9 sleep |
||
368 | $ pkill -9 sleep |
||
369 | . |
||
370 | . |
||
371 | . |
||
372 | ``` |
||
373 | |||
374 | ``` |
||
375 | + echo JHZ1RSomfSYjP0UyKD1BZTY/QWV7OmNGezhsbAo= |
||
376 | HamaCTF{ZZZzzzz....++ echo NTYwCg== |
||
377 | ++ base64 -d |
||
378 | + sleep 560 |
||
379 | NandokukaShellGeiSleeps: 1 行: 24303 強制終了 'sleep' $(echo NTYwCg== |base64 -d)++ base64 -d |
||
380 | ++ echo c2xlZXAK |
||
381 | ++ base64 -d |
||
382 | ++ echo NTk1Cg== |
||
383 | + sleep 595 |
||
384 | NandokukaShellGeiSleeps: 1 行: 24636 強制終了 $('echo' c2xlZXAK | 'base64' -d) $(echo NTk1Cg== |base64 -d) |
||
385 | + md5sum |
||
386 | + cat - /dev/fd/63 |
||
387 | + tr -d '\n -' |
||
388 | + cat NandokukaShellGeiSleeps |
||
389 | ++ echo '}' |
||
390 | 3ebc92ee5adb8d0ee4490ede8ec4bb38}++ base64 -d |
||
391 | ++ echo c2h1dGRvd24K |
||
392 | + : shutdown |
||
393 | ++ echo c2xlZXAK |
||
394 | ++ base64 -d |
||
395 | ++ base64 -d |
||
396 | ++ echo NDAK |
||
397 | + sleep 40 |
||
398 | ``` |
||
399 | |||
400 | 実行結果からフラグが見えます |
||
401 | |||
402 | HamaCTF{ZZZzzzz....3ebc92ee5adb8d0ee4490ede8ec4bb38} |
||
403 | |||
404 | >このフラグですが、後半がこのファイル自身のMD5ハッシュ値になっています。つまり、フラグの出力処理だけ抜き出しても正しいフラグが得られないようになっています。 |
||
405 | |||
406 | |||
407 | ## zlib |
||
408 | |||
409 | 低レイヤちっくな問題ですが、これもシェル芸で扱うことができます。 |
||
410 | まずzlibですが、以下の仕様が重要でございます(たーなさんがwriteup書いてくれてました!)。 |
||
411 | zlibは、たまにForensic問題でも必要になったりします。 |
||
412 | |||
413 | >ちなみにzlib=zipではなく、zlibがzipを包含している関係です。zlibを利用した一つの圧縮方法としてzipやgzipが実装されています。 |
||
414 | |||
415 | {{rawhtml(<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">SHELLART 300<br>zlib<br>問題:<br>この中にzlibされたフラグが埋もれています。<br><br>解法:<br>Zlibの仕様書見る<a href="https://t.co/LFApZJ8M5a">https://t.co/LFApZJ8M5a</a><br><br>中に一文、これ大事!<br>Any data which may appear after ADLER32 are not part of the zlib stream. <br><br>(続く<a href="https://twitter.com/hashtag/HamaSec?src=hash&ref_src=twsrc%5Etfw">#HamaSec</a> <a href="https://twitter.com/hashtag/Writeup?src=hash&ref_src=twsrc%5Etfw">#Writeup</a></p>— たーな (@tanafuji_) <a href="https://twitter.com/tanafuji_/status/936989718272606208?ref_src=twsrc%5Etfw">2017年12月2日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>)}} |
||
416 | |||
417 | {{rawhtml(<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">SHELLART 300<br>(続き<br><br>つまりヘッダのシグネチャがあっていればフッタ以降無視<br><br>Pythonのzlib.decompressを問題ファイルの1byte目から順に当てていき、<br>zlib.errorが発生しない行が正しいzlibストリームなので、それをprintして正解<a href="https://twitter.com/hashtag/HamaSec?src=hash&ref_src=twsrc%5Etfw">#HamaSec</a> <a href="https://twitter.com/hashtag/Writeup?src=hash&ref_src=twsrc%5Etfw">#Writeup</a></p>— たーな (@tanafuji_) <a href="https://twitter.com/tanafuji_/status/936990119361331201?ref_src=twsrc%5Etfw">2017年12月2日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>)}} |
||
418 | |||
419 | つまり、zlibの先頭バイトさえ合っていればお尻にゴミがくっついていてもOKという事ですねっ! |
||
420 | ファイルの先頭を1バイトずつずらしながらデコードできるか試していけばよさそうです。 |
||
421 | |||
422 | 普通にプログラミングして実装してもいいです。ここではシェル芸でやってみます。zlibの展開にはopensslが使えます。 |
||
423 | |||
424 | ```bash |
||
425 | $ for I in `seq 790` ; do cat zlib | dd bs=1 skip=${I} | openssl zlib -d > out_file_${I} 2>/dev/null ; done ; strings out_file* |
||
426 | ``` |
||
427 | |||
428 | >シェル芸自体はもっとエレガントに書ける余地がありそう |
||
429 | |||
430 | ちょっと見やすくすると、こんな感じ。 |
||
431 | |||
432 | ```bash |
||
433 | #!/bin/bash |
||
434 | |||
435 | for I in `seq 790` |
||
436 | do |
||
437 | cat zlib | dd bs=1 skip=${I} | openssl zlib -d > out_file_${I} 2>/dev/null |
||
438 | done |
||
439 | strings out_file* |
||
440 | ``` |
||
441 | |||
442 | HamaCTF{HamanKarn} |
||
443 | |||
444 | ## sign |
||
445 | |||
446 | {{rawhtml(<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ちなsignって名付けた問題は、OSINTとWebと低レイヤの簡単な知識が必要でお気に入りなんだけど競技時間中には解かれなかったのです(´Д`。)グスン <a href="https://twitter.com/hashtag/HamaSec?src=hash&ref_src=twsrc%5Etfw">#HamaSec</a></p>— kanata (@kanata201612) <a href="https://twitter.com/kanata201612/status/937662342589923329?ref_src=twsrc%5Etfw">2017年12月4日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>)}} |
||
447 | |||
448 | やっていきましょう! |
||
449 | |||
450 | ### 9:14 PM 05 AUG 16 Edward Snowden |
||
451 | |||
452 | ``` |
||
453 | 9:14 PM 05 AUG 16 Edward Snowden |
||
454 | ``` |
||
455 | |||
456 | この時、エドワード・スノーデンさんは何をしていたのでしょう?みなさんのOSINTスキルを使って調べみましょう。 |
||
457 | |||
458 | |||
459 | {{rawhtml(<iframe width="560" height="315" src="https://www.youtube.com/embed/4kBnDIN6pTw" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe>)}} |
||
460 | |||
461 | |||
462 | さほど苦労せずに、 **ffdae96f8dd292374a966ec8b57d9cc680ce1d23cb7072c522efe32a1a7e34b0**という文字列を得ることが出来るはずです。 |
||
463 | エドワード・スノーデンさん自身もこの文字列は何なのか言及せず、該当のTwitterは削除済みになっています。 |
||
464 | |||
465 | ### sign.zip |
||
466 | |||
467 | 展開すると circuit というファイルがあって... |
||
468 | |||
469 | $ file circuit |
||
470 | circuit: SVG Scalable Vector Graphics image |
||
471 | |||
472 | SVGですね。ブラウザで表示できます。 |
||
473 | |||
474 |  |
||
475 | |||
476 | これが何かは、ちょっとした低レイヤの知識が必要です。XORの論理回路図ですね。 |
||
477 | |||
478 | ### b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd |
||
479 | |||
480 | 整理してみましょう。 |
||
481 | |||
482 | * スノーデンさんのTweet |
||
483 | |||
484 | ffdae96f8dd292374a966ec8b57d9cc680ce1d23cb7072c522efe32a1a7e34b0 |
||
485 | |||
486 | * sign.zip |
||
487 | |||
488 | XOR |
||
489 | |||
490 | * 問題文 |
||
491 | |||
492 | b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd |
||
493 | |||
494 | ### と、いうことは |
||
495 | |||
496 | こうですね! |
||
497 | |||
498 | ``` |
||
499 | ffdae96f8dd292374a966ec8b57d9cc680ce1d23cb7072c522efe32a1a7e34b0 |
||
500 | XOR b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd |
||
501 | -------------------------------------------------------------------- |
||
502 | 48616D614354467B452E536E6F7764656E7A446561646D616E5377697463687D |
||
503 | ``` |
||
504 | |||
505 | これをASCIIにすると |
||
506 | |||
507 | HamaCTF{E.SnowdenzDeadmanSwitch} |
||
508 | |||
509 | ちなみに、シェルスクリプトでソルバを書くとこんな感じになりました。 |
||
510 | |||
511 | ```bash |
||
512 | #!/bin/bash |
||
513 | |||
514 | S=`curl -s https://www.youtube.com/watch?v=4kBnDIN6pTw|grep '<title'|cut -c8-71` |
||
515 | F="b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd" |
||
516 | |||
517 | C=1 |
||
518 | while : |
||
519 | do |
||
520 | SW=`echo $S |cut -c$C-$(($C+1))` |
||
521 | FG=`echo $F |cut -c$C-$(($C+1))` |
||
522 | A1=`printf '%02X' $(( 0x$SW ^ 0x$FG ))` |
||
523 | echo $A1 |grep -q "00" && break |
||
524 | A2="$A2$A1" |
||
525 | C=$(($C+2)) |
||
526 | done |
||
527 | |||
528 | echo $A2|tr A-Z a-z|xxd -ps -r |
||
529 | ``` |
||
530 | |||
531 | ## 難読化シェル芸2 |
||
532 | |||
533 | まずは実行してみましょう。 |
||
534 | Hint通りに入力すると先に進めるようですが、No hintの時に何を入力すればいいかわかりません。 |
||
535 | 間違うと終了してしまいます。 |
||
536 | |||
537 | ``` |
||
538 | $ bash NandokukaShellGeiInqAns |
||
539 | Let us decording!(≧∀≦*) |
||
540 | |||
541 | Hint 85UEYPQuBL |
||
542 | 85UEYPQuBL |
||
543 | Hint Ogwu/VmCee |
||
544 | Ogwu/VmCee |
||
545 | No hint |
||
546 | |||
547 | ``` |
||
548 | |||
549 | 解き方は「難読化シェル芸1」と同じです。 |
||
550 | bashのxオプションを使います。 |
||
551 | |||
552 | No hintの処理の箇所を見てみましょう。 |
||
553 | |||
554 | ``` |
||
555 | + echo No hint |
||
556 | No hint |
||
557 | ++ base64 -d |
||
558 | ++ rev |
||
559 | ++ echo =oAZhVmc |
||
560 | + read r |
||
561 | |||
562 | ++ echo cmV2Cg== |
||
563 | ++ base64 -d |
||
564 | ++ echo Z3JlcAo= |
||
565 | ++ base64 -d |
||
566 | + rev |
||
567 | ++ echo YmFzZTY0Cg== |
||
568 | ++ base64 -d |
||
569 | + base64 |
||
570 | ++ echo =owboNWZ |
||
571 | ++ rev |
||
572 | ++ base64 -d |
||
573 | + echo |
||
574 | ++ tr A-Za-z N-ZA-Mn-za-m |
||
575 | ++ base64 -d |
||
576 | ++ rev |
||
577 | ++ echo XRKY |
||
578 | + grep -q =ogWXdTS3IkcGRXO |
||
579 | + exit |
||
580 | ``` |
||
581 | |||
582 | 注目するのは、「grep -q =ogWXdTS3IkcGRXO」です。これと一致しないとexitするようです。 |
||
583 | 「=ogWXdTS3IkcGRXO」はどうやって生成されているかも、このデバック内容と、ソースの該当箇所を眺めるとわかります。 |
||
584 | 入力内容をbase64した後にrevしています。つまり、=ogWXdTS3IkcGRXOをrevしてbase64デコードした内容を入力してあげればいいことになります。 |
||
585 | |||
586 | ``` |
||
587 | $ echo =ogWXdTS3IkcGRXO|rev|base64 -d |
||
588 | 9tFrB7I7WZ |
||
589 | ``` |
||
590 | |||
591 | 先に進みました。またNo hintなので、同じ方法で解きます。 |
||
592 | |||
593 | ``` |
||
594 | + echo |
||
595 | ++ echo ==gC2Vmc |
||
596 | ++ rev |
||
597 | ++ base64 -d |
||
598 | ++ echo XRKY |
||
599 | ++ rev |
||
600 | ++ tr A-Za-z N-ZA-Mn-za-m |
||
601 | ++ base64 -d |
||
602 | + rev |
||
603 | ++ echo LzSmMGL0Pt== |
||
604 | ++ tr A-Za-z N-ZA-Mn-za-m |
||
605 | ++ base64 -d |
||
606 | + grep -q =oQMjxkUHNlM4gXS |
||
607 | + base64 |
||
608 | ++ echo MKucqNb= |
||
609 | ++ tr A-Za-z N-ZA-Mn-za-m |
||
610 | ++ base64 -d |
||
611 | + exit |
||
612 | ``` |
||
613 | |||
614 | ``` |
||
615 | $ echo =oQMjxkUHNlM4gXS|rev|base64 -d |
||
616 | Ix82SGRLc1 |
||
617 | ``` |
||
618 | |||
619 | まとめると |
||
620 | |||
621 | 1. 85UEYPQuBL を入力 |
||
622 | 2. Ogwu/VmCee を入力 |
||
623 | 3. 13秒待つか、sleepをkillする |
||
624 | 4. 9tFrB7I7WZ を入力 |
||
625 | 5. Ix82SGRLc1 を入力 |
||
626 | 6. 33秒待つか、sleepをkillする |
||
627 | |||
628 | HamaCTF{Y0uD1dI78db6173ca3c49e83cdff6ccb0860cdf1} |
||
629 | |||
630 | }} |