PCスペック
備忘録。
マザーボード | ASUS PRIME Z390-A (Intel Z390 搭載 LGA1151 対応) | ¥ 21,999 |
CPU | Intel Core i5 9600 | ¥ 26,921 |
GPU | ASUS TURBO-RTX2070S-8G-EVO (ストレート排気モデル) | ¥ 68,147 |
メモリ | Crucial by Micron W4U2666CM-16G (PC4-21300(DDR4-2666) 16GB×2枚 288pin) | ¥ 13,442 |
SSD | Western Digital WD Blue WDS250G2B0A (SATA 3.0(SATA 6Gb/s)) * 2 | @¥ 4,867 |
Blu-ray | I-O DATA BRD-S16PX | ¥ 10,064 |
電源 | Corsair HX1000i 80PLUS PLATINUM 1000W | ¥ 18,118 |
OS | Windows10 Pro 64bit (DSP版) | ¥ 20,477 |
ケース | Fractal Design Define R6 Blackout | ¥ 13,606 |
合計 | ¥ 202,508 |
---|
2019/12-2020/1ごろにAmazonで調達。
WSL2でCUDAを使う
備忘録
参考:
qiita.com
やったこと
- TPMを有効化 (BIOSで、Discrete TPM -> Firmware TPMに変更)
- Windows 11 (Insider Preview)にアップグレード
- 最新のドライバインストール
- Ubuntu (20.04)にcuda-toolkit-11-4 のインストール
この時点で、こんな感じのエラーが出た。
$ ./deviceQuery ./deviceQuery Starting… CUDA Device Query (Runtime API) version (CUDART static linking) cudaGetDeviceCount returned 35 -> CUDA driver version is insufficient for CUDA runtime version Result = FAIL
調べてみてもよくわからなかったが、
- cudaのアップグレード
- (ホスト)Windowsの再起動
をしたら直った。
$ ./deviceQuery ./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "NVIDIA GeForce RTX 2070 SUPER" CUDA Driver Version / Runtime Version 11.4 / 11.4 CUDA Capability Major/Minor version number: 7.5 Total amount of global memory: 8192 MBytes (8589934592 bytes) (040) Multiprocessors, (064) CUDA Cores/MP: 2560 CUDA Cores GPU Max Clock rate: 1770 MHz (1.77 GHz) Memory Clock rate: 7001 Mhz Memory Bus Width: 256-bit L2 Cache Size: 4194304 bytes Maximum Texture Dimension Size (x,y,z) 1D=(131072), 2D=(131072, 65536), 3D=(16384, 16384, 16384) Maximum Layered 1D Texture Size, (num) layers 1D=(32768), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(32768, 32768), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total shared memory per multiprocessor: 65536 bytes Total number of registers available per block: 65536 Warp size: 32 Maximum number of threads per multiprocessor: 1024 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 2 copy engine(s) Run time limit on kernels: Yes Integrated GPU sharing Host Memory: No Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Disabled Device supports Unified Addressing (UVA): Yes Device supports Managed Memory: Yes Device supports Compute Preemption: Yes Supports Cooperative Kernel Launch: Yes Supports MultiDevice Co-op Kernel Launch: No Device PCI Domain ID / Bus ID / location ID: 0 / 2 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 11.4, CUDA Runtime Version = 11.4, NumDevs = 1 Result = PASS
picoCTF 2021 Crypto (5) Mini RSA
Mini RSA
| 70 points
Tags:
AUTHOR: SARA
Description
What happens if you have a small exponent? There is a twist though, we padded the plaintext so that (M ** e) is just barely larger than N. Let's decrypt this: ciphertext
# cat ciphertext N: 1615765684321463054078226051959887884233678317734892901740763321135213636796075462401950274602405095138589898087428337758445013281488966866073355710771864671726991918706558071231266976427184673800225254531695928541272546385146495736420261815693810544589811104967829354461491178200126099661909654163542661541699404839644035177445092988952614918424317082380174383819025585076206641993479326576180793544321194357018916215113009742654408597083724508169216182008449693917227497813165444372201517541788989925461711067825681947947471001390843774746442699739386923285801022685451221261010798837646928092277556198145662924691803032880040492762442561497760689933601781401617086600593482127465655390841361154025890679757514060456103104199255917164678161972735858939464790960448345988941481499050248673128656508055285037090026439683847266536283160142071643015434813473463469733112182328678706702116054036618277506997666534567846763938692335069955755244438415377933440029498378955355877502743215305768814857864433151287 e: 3 ciphertext (c): 1220012318588871886132524757898884422174534558055593713309088304910273991073554732659977133980685370899257850121970812405700793710546674062154237544840177616746805668666317481140872605653768484867292138139949076102907399831998827567645230986345455915692863094364797526497302082734955903755050638155202890599808154558034707767377524500302754459807923331810585173010977657982069888996945830789092526932364658459034145456505057469113036134559745659079236466119515004648189278227777550415021840140147319061470183840214034417917161940379351273394212022847037696265532968684592354941479799473941357715953204487236888712642494877545201005807776354854390358015733495331101077851132489983665939643188064986446883595239842621440918456201787168234988410659153219277329426230136499096098072681939491840913961290536851217677043565743644469862992310241563891464225935615676242084658617931225618537173689559419607688905143683603007487996422560430269750305079282818976557285786253025774883158125978164878245223052992502106
e=3なので、3乗根を取ればいいはず。
>>> from gmpy2 import * >>> c = 1220012318588871886132524757898884422174534558055593713309088304910273991073554732659977133980685370899257850121970812405700793710546674062154237544840177616746805668666317481140872605653768484867292138139949076102907399831998827567645230986345455915692863094364797526497302082734955903755050638155202890599808154558034707767377524500302754459807923331810585173010977657982069888996945830789092526932364658459034145456505057469113036134559745659079236466119515004648189278227777550415021840140147319061470183840214034417917161940379351273394212022847037696265532968684592354941479799473941357715953204487236888712642494877545201005807776354854390358015733495331101077851132489983665939643188064986446883595239842621440918456201787168234988410659153219277329426230136499096098072681939491840913961290536851217677043565743644469862992310241563891464225935615676242084658617931225618537173689559419607688905143683603007487996422560430269750305079282818976557285786253025774883158125978164878245223052992502106 >>> n = 1615765684321463054078226051959887884233678317734892901740763321135213636796075462401950274602405095138589898087428337758445013281488966866073355710771864671726991918706558071231266976427184673800225254531695928541272546385146495736420261815693810544589811104967829354461491178200126099661909654163542661541699404839644035177445092988952614918424317082380174383819025585076206641993479326576180793544321194357018916215113009742654408597083724508169216182008449693917227497813165444372201517541788989925461711067825681947947471001390843774746442699739386923285801022685451221261010798837646928092277556198145662924691803032880040492762442561497760689933601781401617086600593482127465655390841361154025890679757514060456103104199255917164678161972735858939464790960448345988941481499050248673128656508055285037090026439683847266536283160142071643015434813473463469733112182328678706702116054036618277506997666534567846763938692335069955755244438415377933440029498378955355877502743215305768814857864433151287 >>> cbrt(c) mpfr('1.0685333265243248e+335') >>> hex(int(cbrt(c))) '0x1ebab45fa208b60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' >>> get_context().precision = 10000 >>> hex(int(cbrt(c))) '0x1ebab45fa208b5e935ab142514c5ed26a3adfa2d78a734b1de5bf560ecd1e2164321f6a9ced9dd66e9607c02cd04f27c7c12b5a5ebf6c6e3980cd11999628f7d18bcbbf27d5f3c31b9a21bb9db47fdbdecf550feefd23486c3664e0e359c92c8b68d38e5a57be5190f9256fa51680bd79d1365836f0ce1efacfed4ede2ade5c5f0aa52741fbce11f4967b7d' >>> int(cbrt(c)) ** 3 == n False
単純に3乗根を取ってもダメ見たい。
なので、gmpy2.iroot()を使って、正しい値が取れるまでループさせる。
iroot(...)
iroot(x,n) returns a 2-element tuple (y, b) such that y is the integer n-th root of x and b is True if the root is exact. x must be >= 0 and n must be > 0.
Multiple-precision Integers — gmpy2 2.1.0a1 documentation
※iroot(x, n)は x >= 0じゃないといけないので、kの符号を反転させる。
>>> while True: ... m, b = iroot(c + k * n, 3) ... if b == True: ... break ... k += 1 ... >>> k 3533 >>> m mpz(1787330808968142828287809319332701517353332911736848279839502759158602467824780424488141955644417387373185756944952906538004355347478978500948630620749868180414755933760446136287315896825929319145984883756667607031853695069891380871892213007874933611243319812691520078269033745367443951846845107464675742664639073700704505958478225302653) >>> from Crypto.Util.number import long_to_bytes >>> long_to_bytes(m) b' picoCTF{e_sh0u1d_b3_lArg3r_aef7377d}' >>>
" should be larger"
picoCTF 2021 General Skills
Obedient Cat
Description
This file has a flag in plain sight (aka "in-the-clear"). Download flag.
# cat flag picoCTF{s4n1ty_v3r1f13d_f28ac910}
"sanity verified"
Python Wrangling
Description
Python scripts are invoked kind of like programs in the Terminal... Can you run this Python script using this password to get the flag?
# wget https://mercury.picoctf.net/static/0bf545252b5120845e3b568b9ad0277e/ende.py /// skipped /// # wget https://mercury.picoctf.net/static/0bf545252b5120845e3b568b9ad0277e/pw.txt /// skipped /// # wget https://mercury.picoctf.net/static/0bf545252b5120845e3b568b9ad0277e/flag.txt.en /// skipped /// # ls ende.py flag.txt.en pw.txt # python3 ende.py Usage: ende.py (-e/-d) [file] # python3 ende.py -d flag.txt.en Please enter the password: # cat pw.txt | python3 ende.py -d flag.txt.en Please enter the password:picoCTF{4p0110_1n_7h3_h0us3_6008014f}
"apollo in the house"(?)
Wave a flag
Description
Can you invoke help flags for a tool or binary? This program has extraordinarily helpful information...
# wget https://mercury.picoctf.net/static/b28b6021d6040b086c2226ebeb913bc2/warm /// skipped /// # file warm warm: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=b11c22752c901adc13ba1ce86eda9d5516f22763, with debug_info, not stripped # chmod +x warm # ./warm Hello user! Pass me a -h to learn what I can do! # ./warm -h Oh, help? I actually don't do much, but I do have this flag here: picoCTF{b1scu1ts_4nd_gr4vy_d6969390}
"biscuits and gravy"
Nice netcat
Description
There is a nice program that you can talk to by using this command in a shell: $ nc mercury.picoctf.net 22342, but it doesn't speak English...
# nc mercury.picoctf.net 22342 112 105 99 111 67 84 70 123 103 48 48 100 95 107 49 116 116 121 33 95 110 49 99 51 95 107 49 116 116 121 33 95 53 102 98 53 101 53 49 100 125 10
パッと見文字コードでしょう。
solver.py
from pwn import remote r = remote("mercury.picoctf.net", 22342) while True: try: c = chr(int(r.recvline().strip())) if c != "": print(c, end="") except EOFError as e: r.close() break
# python3 solver.py [+] Opening connection to mercury.picoctf.net on port 22342: Done picoCTF{g00d_k1tty!_n1c3_k1tty!_5fb5e51d} [*] Closed connection to mercury.picoctf.net port 22342
"good kitty! nice kitty!"
Static ain't always noise
Description
Can you look at the data in this binary: static? This BASH script might help!
# wget https://mercury.picoctf.net/static/ec4dbd8898ade34e1d60d5b70c1b8c8c/static /// skipped /// # wget https://mercury.picoctf.net/static/ec4dbd8898ade34e1d60d5b70c1b8c8c/ltdis.sh /// skipped /// # file static static: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=639391a8b15c579d69659462d3c935fa61693f17, not stripped # chmod +x static # ./static Oh hai! Wait what? A flag? Yes, it's around here somewhere! # cat ltdis.sh #!/bin/bash echo "Attempting disassembly of $1 ..." #This usage of "objdump" disassembles all (-D) of the first file given by #invoker, but only prints out the ".text" section (-j .text) (only section #that matters in almost any compiled program... objdump -Dj .text $1 > $1.ltdis.x86_64.txt #Check that $1.ltdis.x86_64.txt is non-empty #Continue if it is, otherwise print error and eject if [ -s "$1.ltdis.x86_64.txt" ] then echo "Disassembly successful! Available at: $1.ltdis.x86_64.txt" echo "Ripping strings from binary with file offsets..." strings -a -t x $1 > $1.ltdis.strings.txt echo "Any strings found in $1 have been written to $1.ltdis.strings.txt with file offset" else echo "Disassembly failed!" echo "Usage: ltdis.sh <program-file>" echo "Bye!" fi
シェルスクリプトはディスアセンブルしてるっぽい。
そうだとすれば、strings
でフラグ取れるのでは?(最初にテキストセクションがなんちゃらって書いてあるし)
# strings static /lib64/ld-linux-x86-64.so.2 libc.so.6 puts __cxa_finalize __libc_start_main GLIBC_2.2.5 _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable AWAVI AUATL []A\A]A^A_ Oh hai! Wait what? A flag? Yes, it's around here somewhere! ;*3$" picoCTF{d15a5m_t34s3r_98d35619} GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 crtstuff.c deregister_tm_clones __do_global_dtors_aux completed.7698 __do_global_dtors_aux_fini_array_entry frame_dummy __frame_dummy_init_array_entry static.c __FRAME_END__ __init_array_end _DYNAMIC __init_array_start __GNU_EH_FRAME_HDR _GLOBAL_OFFSET_TABLE_ __libc_csu_fini _ITM_deregisterTMCloneTable puts@@GLIBC_2.2.5 _edata __libc_start_main@@GLIBC_2.2.5 __data_start __gmon_start__ __dso_handle _IO_stdin_used __libc_csu_init __bss_start main __TMC_END__ _ITM_registerTMCloneTable flag __cxa_finalize@@GLIBC_2.2.5 .symtab .strtab .shstrtab .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame .init_array .fini_array .dynamic .data .bss .comment # strings static | grep pico picoCTF{d15a5m_t34s3r_98d35619}
"disasm teaser"
Tab, Tab, Attack
Description
Using tabcomplete in the Terminal will add years to your life, esp. when dealing with long rambling directory structures and filenames: Addadshashanammu.zip
# unzip Addadshashanammu.zip Archive: Addadshashanammu.zip creating: Addadshashanammu/ creating: Addadshashanammu/Almurbalarammi/ creating: Addadshashanammu/Almurbalarammi/Ashalmimilkala/ creating: Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/ creating: Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/Maelkashishi/ creating: Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/Maelkashishi/Onnissiralis/ creating: Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/Maelkashishi/Onnissiralis/Ularradallaku/ inflating: Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/Maelkashishi/Onnissiralis/Ularradallaku/fang-of-haynekhtnamet # file Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/Maelkashishi/Onnissiralis/Ularradallaku/fang-of-haynekhtnamet Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/Maelkashishi/Onnissiralis/Ularradallaku/fang-of-haynekhtnamet: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=55548d0314fdf7999b966728d19712cdf8a52e58, not stripped # strings Addadshashanammu/Almurbalarammi/Ashalmimilkala/Assurnabitashpi/Maelkashishi/Onnissiralis/Ularradallaku/fang-of-haynekhtnamet | grep pico *ZAP!* picoCTF{l3v3l_up!_t4k3_4_r35t!_f3553887}
"level up! take a rest!"
Magikarp Ground Mission
Description
Do you know how to move between directories and read files in the shell? Start the container, `ssh` to it, and then `ls` once connected to begin. Login via `ssh` as `ctf-player` with the password, `481e7b14`
インスタンスを起動させてから、指定されたサーバ・ポートにアクセス
# ssh ctf-player@venus.picoctf.net -p 54159 ctf-player@venus.picoctf.net's password: /// skipped /// ctf-player@pico-chall$ ls 1of3.flag.txt instructions-to-2of3.txt ctf-player@pico-chall$ cat 1of3.flag.txt picoCTF{xxsh_ ctf-player@pico-chall$ cat instructions-to-2of3.txt Next, go to the root of all things, more succinctly `/` ctf-player@pico-chall$ cd / ctf-player@pico-chall$ ls 2of3.flag.txt dev instructions-to-3of3.txt media proc sbin tmp bin etc lib mnt root srv usr boot home lib64 opt run sys var ctf-player@pico-chall$ cat 2of3.flag.txt 0ut_0f_\/\/4t3r_ ctf-player@pico-chall$ cat instructions-to-3of3.txt Lastly, ctf-player, go home... more succinctly `~` ctf-player@pico-chall$ cd ~ ctf-player@pico-chall$ ls 3of3.flag.txt drop-in ctf-player@pico-chall$ cat 3of3.flag.txt 1118a9a4}
picoCTF{xxsh_0ut_0f_\/\/4t3r_1118a9a4}
"xxsh out of water"
picoCTF 2021 Crypto (4) New Caesar
New Caesar
| 60 points
Tags:
AUTHOR: MADSTACKS
Description
We found a brand new type of encryption, can you break the secret code? (Wrap with picoCTF{}) lkmjkemjmkiekeijiiigljlhilihliikiliginliljimiklligljiflhiniiiniiihlhilimlhijil new_caesar.py
new_caesar.py
import string LOWERCASE_OFFSET = ord("a") ALPHABET = string.ascii_lowercase[:16] def b16_encode(plain): enc = "" for c in plain: binary = "{0:08b}".format(ord(c)) enc += ALPHABET[int(binary[:4], 2)] enc += ALPHABET[int(binary[4:], 2)] return enc def shift(c, k): t1 = ord(c) - LOWERCASE_OFFSET t2 = ord(k) - LOWERCASE_OFFSET return ALPHABET[(t1 + t2) % len(ALPHABET)] flag = "redacted" key = "redacted" assert all([k in ALPHABET for k in key]) assert len(key) == 1 b16 = b16_encode(flag) enc = "" for i, c in enumerate(b16): enc += shift(c, key[i % len(key)]) print(enc)
平文にb16_encodeした後、keyでシフトしている。
b16_encodeは、平文の文字コードを4ビットごとに分けて、それぞれを英小文字の[a-p]に割り当てているみたい。
keyは、assert文から、[a-p]のいずれか。
なので、keyを総当たりでデコードしてみる。
import string LOWERCASE_OFFSET = ord("a") ALPHABET = string.ascii_lowercase[:16] def deshift(c, k): t1 = ord(c) - LOWERCASE_OFFSET t2 = ord(k) - LOWERCASE_OFFSET return ALPHABET[(t1 - t2) % len(ALPHABET)] def b16_decode(enc): ### b16_encode # def b16_encode(plain): # enc = "" # for c in plain: # binary = "{0:08b}".format(ord(c)) # enc += ALPHABET[int(binary[:4], 2)] # enc += ALPHABET[int(binary[4:], 2)] # return enc plain = "" for i, c in enumerate(enc): if i % 2 == 0: upper_byte = ord(c) - LOWERCASE_OFFSET else: lower_byte = ord(c) - LOWERCASE_OFFSET plain += chr(upper_byte * 16 + lower_byte) return plain c = "lkmjkemjmkiekeijiiigljlhilihliikiliginliljimiklligljiflhiniiiniiihlhilimlhijil " for k in ALPHABET: _c = "" for _ in c: _c += deshift(_, k) #print(_c) plain = b16_decode(_c) print("key '{}': {}".format(k, plain))
# python3 exploit.py key 'a': ºÉ¤ÉÊ ¤¹·¸¸¹»¹ ··· key 'b': ©¸¸¹sxwu¨¦zv§yzu|§¨{yªu¨t¦|w|wv¦z{¦xz key 'c': §¨bgfdiehidkjhdckfkfeijgi key 'd': qQqVUS XT WXSZ YWSR ZUZUT XY VX key 'e': v ` @`EDBusGCtFGBItuHFwBuAsIDIDCsGHsEG key 'f': et_tu?_431db62c5618cd75f1d0b83832b67b46 key 'g': TcNcd.N#" SQ%!R$% 'RS&$U S/Q'"'"!Q%&Q#% key 'h': CR=RS=B@AABDB@@@ key 'i': 2A,AB ??? ,1?00131 key 'j': !01ûÿý .òþ/ñòýô/ óñ"ý ü.ôÿôÿþ.òó.ðò key 'k': / / ê ïîìáíàáìãâàìëãîãîíáâïá key 'l': ùÙùÞÝÛ ÑßÛÚ ÐÜ ÒÝÒÝÜ ÐÑ ÞÐ ÈèÍÌÊýûÏËüÎÏÊÁüýÀÎÿÊýÉûÁÌÁÌËûÏÀûÍÏ key 'n': íü×üý·×¼»¹ì꾺뽾¹°ë쿽î¹ì¸ê°»°»ºê¾¿ê¼¾ key 'o': ÜëÆëì¦Æ«ª¨ÛÙ©Ú¬¨¯ÚÛ®¬Ý¨Û§Ù¯ª¯ª©Ù®Ù« key 'p': ËÚµÚÛµÊÈÊÊÈ
よくわからないが、
key 'f': et_tu?_431db62c5618cd75f1d0b83832b67b46
が自然言語っぽい("et tu?"の部分がフランス語)ので、これを入れてみると通った。
picoCTF 2021 Crypto (3) Easy Peasy
Easy Peasy
| 40 points
Tags:
AUTHOR: MADSTACKS
Description
A one-time pad is unbreakable, but can you manage to recover the flag? (Wrap with picoCTF{}) nc mercury.picoctf.net 58913 otp.py
otp.py
#!/usr/bin/python3 -u import os.path KEY_FILE = "key" KEY_LEN = 50000 FLAG_FILE = "flag" def startup(key_location): flag = open(FLAG_FILE).read() kf = open(KEY_FILE, "rb").read() start = key_location stop = key_location + len(flag) key = kf[start:stop] key_location = stop result = list(map(lambda p, k: "{:02x}".format(ord(p) ^ k), flag, key)) print("This is the encrypted flag!\n{}\n".format("".join(result))) return key_location def encrypt(key_location): ui = input("What data would you like to encrypt? ").rstrip() if len(ui) == 0 or len(ui) > KEY_LEN: return -1 start = key_location stop = key_location + len(ui) kf = open(KEY_FILE, "rb").read() if stop >= KEY_LEN: stop = stop % KEY_LEN key = kf[start:] + kf[:stop] else: key = kf[start:stop] key_location = stop result = list(map(lambda p, k: "{:02x}".format(ord(p) ^ k), ui, key)) print("Here ya go!\n{}\n".format("".join(result))) return key_location print("******************Welcome to our OTP implementation!******************") c = startup(0) while c >= 0: c = encrypt(c)
入力文だけkeyをオフセットさせながら、好きな文字を暗号化させられる。
つまり、keyが50000字なので一周させればよさそう。
と思って以下のような感じでやたらうまくいかなかった。。
from pwn import remote r = remote("mercury.picoctf.net", 58913) r.recvuntil("This is the encrypted flag!\n") c = r.recvuntil("\n").strip() r.recvuntil("encrypt? ") r.sendline("\x00" * 50000) r.recvuntil("Here ya go!\n") k = r.recvuntil("\n").strip()[-len(c):] r.close() print(c) print(k) def otp(message, key): buf = "" b_message = int(message, 16).to_bytes(len(message)//2, byteorder="big") b_key = int(key, 16).to_bytes(len(b_message), byteorder="big") for m, k in zip(b_message, b_key): buf += chr(m ^ k) return buf print(otp(c, k))
# python3 exploit.py [+] Opening connection to mercury.picoctf.net on port 58913: Done [*] Closed connection to mercury.picoctf.net port 58913 b'51124f4d194969633e4b52026f4c07513a6f4d05516e1e50536c4954066a1c57' b'7830316a705c7865385c7838314176685c7839323f5c7864315c7861615c7838' )"~'i\x15\x06\x17:^q9f\x177n2f4b015g6do
そこで、とりあえず50000字に至るまで入力し、再度フラグ長分だけなげてみたらいけた。
from pwn import remote r = remote("mercury.picoctf.net", 58913) r.recvuntil("This is the encrypted flag!\n") c = r.recvuntil("\n").strip() r.recvuntil("encrypt? ") r.sendline("\x00" * (50000 - len(c)//2)) r.recvuntil("Here ya go!\n") #k = r.recvuntil("\n").strip()[-len(c):] r.recvuntil("encrypt? ") r.sendline("\x00" * (len(c)//2)) r.recvuntil("Here ya go!\n") k = r.recvuntil("\n").strip() r.close() print(c) print(k) def otp(message, key): # "".join(list(map(lambda p, k: "{}".format(chr(p ^ k)), int(c,16).to_bytes(len(c)//2, byteorder="big"), int(k,16).to_bytes(len(c)//2, byteorder="big")))) buf = "" b_message = int(message, 16).to_bytes(len(message)//2, byteorder="big") b_key = int(key, 16).to_bytes(len(b_message), byteorder="big") for m, k in zip(b_message, b_key): buf += chr(m ^ k) return buf print(otp(c, k))
# python3 exploit.py [+] Opening connection to mercury.picoctf.net on port 58913: Done [*] Closed connection to mercury.picoctf.net port 58913 b'51124f4d194969633e4b52026f4c07513a6f4d05516e1e50536c4954066a1c57' b'62272a2e7b7d5b505c7830365c783063595c7866325c7864625c7865655c7865' 35ecb423b3b43472c35cc2f41011c6d2
なぜだかしばらくよくわからなかったが、ふと、keyファイルが50000バイトより長い場合、一気に長いものを投げると50000字を超えた分までkeyとして使われてるってことなんだな、と思いつき、ローカルで試したらたぶんそうだった。
key = kf[start:] + kf[:stop]
のところで、kf[start:KEY_LEN]にしてないのが原因ですね・・・
picoCTF 2021 Crypto (2) Mind your Ps and Qs
Mind your Ps and Qs | 20 points Tags: AUTHOR: SARA Description In RSA, a small e value can be problematic, but what about N? Can you decrypt this? values
# cat values Decrypt my super sick RSA: c: 843044897663847841476319711639772861390329326681532977209935413827620909782846667 n: 1422450808944701344261903748621562998784243662042303391362692043823716783771691667 e: 65537
よくわからないが、問題文からnが分解できるということなんだろうから、とりあえずnを無理矢理素因数分解してみる。
これを利用。
Integer factorization calculator
1422 450808 944701 344261 903748 621562 998784 243662 042303 391362 692043 823716 783771 691667 (82 digits) = 2159 947535 959146 091116 171018 558446 546179 (40 digits) × 658558 036833 541874 645521 278345 168572 231473 (42 digits) Number of divisors: 4 Sum of divisors: 1422 450808 944701 344261 903748 621562 998784 904380 026672 892383 428681 273080 510790 469320 (82 digits) Euler's totient: 1422 450808 944701 344261 903748 621562 998783 582944 057933 890341 955406 374353 056752 914016 (82 digits) Möbius: 1 n = a² + b² + c² + d² a = 23153 753416 263562 304085 113679 610908 542901 (41 digits) b = 21879 576025 097055 792772 666607 707345 158969 (41 digits) c = 20108 191366 928777 506197 370908 995056 798757 (41 digits) d = 1816 398798 869307 932329 158302 569753 005684 (40 digits) Time elapsed: 0d 0h 6m 8.1s Modular multiplications: ECM: 78620336 Probable prime checking: 1389 SIQS: 128195 Sum of squares: 1124 SIQS: 780030 polynomials sieved 440269 sets of trial divisions 15206 smooth congruences found (1 out of every 4157971 values) 171081 partial congruences found (1 out of every 369568 values) 16049 useful partial congruences Size of binary matrix: 28814 × 28019 Timings: Probable prime test of 3 numbers: 0d 0h 0m 0.0s Factoring 1 number using ECM: 0d 0h 0m 12.5s Factoring 1 number using SIQS: 0d 0h 5m 55.6s Written by Dario Alpern. Last updated on 20 May 2021.
この2つの整数(40/42 digits)をp,qとしてdを求めてplaintextを求めればいいはず。
import gmpy from Crypto.Util.number import long_to_bytes qfile = "values" """ Decrypt my super sick RSA: c: 843044897663847841476319711639772861390329326681532977209935413827620909782846667 n: 1422450808944701344261903748621562998784243662042303391362692043823716783771691667 e: 65537 """ c, n, e = ([int(_[3:]) for _ in open(qfile).read().split("\n")[1:]]) p, q = [2159947535959146091116171018558446546179, 658558036833541874645521278345168572231473] phi = (p-1)*(q-1) d = gmpy.invert(e, phi) m = int(pow(c, d, n)) print("d: {}".format(d)) print("m: {}".format(m)) print("p: {}".format(long_to_bytes(m)))
# python3 exploit.py d: 975120122884150896343356420256053234758228648361853546720066993334766006694511009 m: 13016382529449106065927291425342535437996222135352905256639555294957886055592061 p: b'picoCTF{sma11_N_n0_g0od_00264570}'
Small N no good!
なお、RSA問題については以下のページが参考になる。
inaz2.hatenablog.com