VMwareのゲストでマウスカーソルが表示されなくなった
この動画を参照して仮想マシンのアップデート(17.5 or later)したら直った
https://www.youtube.com/watch?v=Xn5qbMMgdxo
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]にしてないのが原因ですね・・・