일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 워게임
- h4cking game
- 웹해킹
- System Hacking
- dreamhack
- Wargame
- 해킹
- crypto
- cryptography
- hack
- webhacking.kr
- WEB
- CTF
- ctf player
- got overwrite
- deayzl
- 2022 Fall GoN Open Qual CTF
- Buffer Overflow
- christmas ctf
- python
- Wreckctf
- hacking
- pwnable
- KAIST
- writeup
- hacking game
- TeamH4C
- reversing
- webhacking
- Gon
Archives
- Today
- Total
deayzl's blog
[2022 Fall GoN Open Qual CTF] Private Storage writeup 본문
CTF writeup/GoN Open Qual CTF
[2022 Fall GoN Open Qual CTF] Private Storage writeup
deayzl 2022. 8. 31. 21:00
#!/usr/bin/env python3
from Crypto.Cipher import ARC4
from base64 import b64encode
import zlib
from secret import flag, key
file = {"flag.txt" : flag, "key" : key}
def print_menu():
print("1. List file")
print("2. Download file")
print("3. Add file")
print("4. Copy file")
print("5. Remove File")
print("6. Logout")
def download_file():
filename = input("File name >> ").strip()
if filename not in file:
print("No such file")
pass
content = file[filename]
rc4 = ARC4.new(key.encode())
enc = rc4.encrypt(zlib.compress(file[filename].encode()))
print("Content :", b64encode(enc).decode())
def get_filename():
filename = input("File name >> ").strip()
if filename == "key":
print("No!")
exit(0)
return filename
def add_content(filename, content):
if filename not in file:
file[filename] = ""
file[filename] += content
def remove_file(filename):
if filename not in file:
print("No such file")
elif filename == "key":
print("No!")
exit(0)
else:
del file[filename]
print("Welcome to safe storage! Make sure to bring your key!")
while True:
print_menu()
ipt = input(">> ").strip()
if ipt == "1":
print(" ".join(file.keys()))
elif ipt == "2":
download_file()
elif ipt == "3":
filename = get_filename()
add_content(filename, input("Content >>").strip())
elif ipt == "4":
origin = input("Which file to copy >> ").strip()
filename = get_filename()
add_content(filename, file[origin])
elif ipt == "5":
filename = input("Which file to remove >> ").strip()
remove_file(filename)
elif ipt == "6":
break
제공된 server.py 파일의 소스코드다.
flag 를 rc4 방식으로 암호화하고 저장하는 프로그램으로 보인다.
Rc4 암호화 알고리듬을 모른다면 어떻게 풀어야하는 지 감이 안올거다.
RC4 security algorithm - YouTube
(문제를 풀 당시, 바로 위에 있는 세번째 영상이 크게 도움이 되었다)
문제 풀기 전, 휘갈겨놓은 노트를 보면
크게 2가지의 함수가 있는데, 이 함수 모두 Key 배열을 기반으로 KeyStream 을 만들어내는 과정의 일부이다.
중요한 것은 직접 plain text 와 xor 하는 KeyStream 은 K 와 S 배열에 종속적이고,
K 와 S 배열은 Key 만 같다면 항상 같을 수 밖에 없는 구조로 되어 있다는 점이다.
(암호화를 할 당시의 시간을 구해서 반영한다던가, 평문에 따라서 달라진다거나 하는 점이 아예 없다)
즉, KeyStream 이 항상 같으니 임의의 문자열을 암호화해서 암호화된 값과 평문을 xor 해주면
KeyStream 을 구할 수 있고 이 KeyStream 은 flag 문자열을 암호화했을 때 쓴 키이니
그대로 암호화된 flag 값에 구한 KeyStream 문자열을 xor 해주면 flag 를 구할 수 있다는 것이다.
(KeyStream 을 평문에 xor 할 때, 평문이 길다면 KeyStream 을 반복시킨 후 xor 하기에
암호화 된 값의 길이가 암호화된 flag 값의 길이가 같도록 해주고 KeyStream 을 구해줬다)
from pwn import *
import zlib
import base64
tmptext = b'asdfghjklqwertyuiopzxcv'
p = remote('host3.dreamhack.games', 23382)
def Download_file(filename):
p.recvuntil(b'>> ')
p.send_raw(b'2\n')
p.recvuntil(b'>> ')
p.send_raw(filename + b'\n')
p.recvuntil(b': ')
return p.recvline()[:-1]
def Add_file(filename, content):
p.recvuntil(b'>> ')
p.send_raw(b'3\n')
p.recvuntil(b'>> ')
p.send_raw(filename + b'\n')
p.recvuntil(b'>>')
p.send_raw(content + b'\n')
plain_text = zlib.compress(tmptext)
print(b'plain text : ' + plain_text + b'(' + str(len(plain_text)).encode() + b')')
Add_file(b'a.txt', tmptext)
cypher_text = base64.b64decode(Download_file(b'a.txt'))
print(b'cypher text : ' + cypher_text + b'(' + str(len(cypher_text)).encode() + b')')
keystream = list()
for i in range(len(plain_text)):
keystream.append(plain_text[i] ^ cypher_text[i])
keystream = bytes(keystream)
print(b'keystream : ' + keystream + b'(' + str(len(keystream)).encode() + b')')
flag_encrypted = base64.b64decode(Download_file(b'flag.txt'))
print(b'flag encrypted : ' + flag_encrypted + b'(' + str(len(flag_encrypted)).encode() + b')')
flag_compressed = list()
for i in range(len(keystream)):
flag_compressed.append(flag_encrypted[i] ^ keystream[i])
flag_compressed = bytes(flag_compressed)
print(b'flag compressed : ' + flag_compressed + b'(' + str(len(flag_compressed)).encode() + b')')
print(zlib.decompress(flag_compressed))
p.close()
'CTF writeup > GoN Open Qual CTF' 카테고리의 다른 글
[2022 Fall GoN Open Qual CTF] Bomblab - Hard writeup (0) | 2022.08.31 |
---|---|
[2022 Fall GoN Open Qual CTF] SleepingShark writeup (0) | 2022.08.31 |
[2022 Fall GoN Open Qual CTF] Zero Gravity writeup (0) | 2022.08.31 |
[2022 Fall GoN Open Qual CTF] Api Portal writeup (0) | 2022.08.31 |
[2022 Fall GoN Open Qual CTF] Checkers writeup (0) | 2022.08.31 |
Comments