Misc
- Misc 50 -
공지에서 저기 확인을 누르면
이렇게 flag를 준다.
- Misc 100 -
수학 문제를 자동화 시켜야 한다. 이 CTF의 Misc에서는 거의 다 코딩 분야더라.
서버에 들어가서 보면
이렇게 나온다.
저기 나오는 ax + by = c 의 직선방정식 3개의 교점을 찾아서 그 찾아진 교점들의 좌표를 구해서 그 좌표로 삼각형의 넓이를 구해야한다.
물론 난 수학을 못하기 때문에(그래도 다행히 교점을 찾아야 되겠다는 생각은 했다..ㅋㅋ) 이걸 구하는 식을 모른다.
그래서 인터넷에 검색해보며 그 식을 구했고 그걸 이용하여 자동화 툴을 만들었다.
from pwn import *
r = remote("218.158.141.199", 24763)
def calc_x(a1,b1,c1,a2,b2,c2):
try:
return round(((c1*b2) - (b1*c2)) / ((a1*b2) - (b1*a2)), 1)
except:
return 0
def calc_y(a1,b1,c1,a2,b2,c2):
try:
return round(((a1*c2) - (c1*a2)) / ((a1*b2) - (b1*a2)), 1)
except:
return 0
def calc_S(x1,y1,x2,y2,x3,y3):
print ((x1*y2) + (x2*y3) + (x3*y1))
print ((x1*y3) + (x3*y2) + (x2*y1))
if ((x1*y3) + (x3*y2) + (x2*y1)) > 0:
if ((x1*y2) + (x2*y3) + (x3*y1)) > ((x1*y3) + (x3*y2) + (x2*y1)):
return round(((((x1*y2) + (x2*y3) + (x3*y1)) - ((x1*y3) + (x3*y2) + (x2*y1))) / 2), 1)
return round((((((x1*y2) + (x2*y3) + (x3*y1)) - ((x1*y3) + (x3*y2) + (x2*y1))) / 2) * -1), 1)
if ((x1*y2) + (x2*y3) + (x3*y1)) < ((x1*y3) + (x3*y2) + (x2*y1)):
return round((((((x1*y2) + (x2*y3) + (x3*y1)) - ((x1*y3) + (x3*y2) + (x2*y1))) / 2) * -1), 1)
return round(((((x1*y2) + (x2*y3) + (x3*y1)) - ((x1*y3) + (x3*y2) + (x2*y1))) / 2), 1)
r.recvuntil("<Quiz Start>")
r.recvline()
r.recvline()
while 1:
r.recvline()
r.recvline()
text = r.recvline()
text1 = r.recvline()
text2 = r.recvline()
x_value1, text = text.split("x")
x_value1 = int(x_value1)
x_value2, text1 = text1.split("x")
x_value2 = int(x_value2)
x_value3, text2 = text2.split("x")
x_value3 = int(x_value3)
y_value1,text = text.split("y")
y_value1 = y_value1[3:]
y_value1 = int(y_value1)
y_value2,text1 = text1.split("y")
y_value2 = y_value2[3:]
y_value2 = int(y_value2)
y_value3,text2 = text2.split("y")
y_value3 = y_value3[3:]
y_value3 = int(y_value3)
text,c_value1 = text.split("=")
c_value1 = c_value1[1:]
c_value1 = int(c_value1)
text1, c_value2 = text1.split("=")
c_value2 = c_value2[1:]
c_value2 = int(c_value2)
text2, c_value3 = text2.split("=")
c_value3 = c_value3[1:]
c_value3 = int(c_value3)
x1 = calc_x(x_value1,y_value1,c_value1,x_value2,y_value2,c_value2)
y1 = calc_y(x_value1,y_value1,c_value1,x_value2,y_value2,c_value2)
print "x1 = "+ str(x1)
print "y1 = "+ str(y1)
x2 = calc_x(x_value3,y_value3,c_value3,x_value2,y_value2,c_value2)
y2 = calc_y(x_value3,y_value3,c_value3,x_value2,y_value2,c_value2)
print "x2 = "+ str(x2)
print "y2 = "+ str(y2)
x3 = calc_x(x_value1,y_value1,c_value1,x_value3,y_value3,c_value3)
y3 = calc_y(x_value1,y_value1,c_value1,x_value3,y_value3,c_value3)
print "x3 = "+ str(x3)
print "y3 = "+ str(y3)
S = calc_S(x1,y1,x2,y2,x3,y3)
r.sendline(str(S))
print "S = " + str(S)
try :
on = r.recvuntil("Step : ", timeout = 1)
except :
# on = r.recvline()
# if "Wrong!" in on:
# r.close()
# r = remote("218.158.141.199", 24763)
# r.recvuntil("<Quiz Start>")
# r.recvline()
# r.recvline()
# else:
r.interactive()
실행시키면
쭉 진행되어 이렇게 마지막엔 답이 나온다.
근데 calc_S를 보면 이상한 if 문이 많은 이유가 있다.
이상하게도(내가 계산해봐도 맞는데) 어떤 특수한 경우에만 내가 구한 값은 -가 있는데 저기는 없고 나는 없는데 저기는 있고 이렇게 됐었다. - 빼면 값이 같다는 걸 보면 내 식이 틀린 건 아닌데 이상하게도 서버에서 정하는 값과 약간 달라서
어쩔수 없이 if문을 넣어줬다. 다행히도 특수한 경우에만 발생하기에 if문 만으로 고칠 수 있었다.
근데 서버 값을 어떻게 본 지 궁금할 수 있다. 그건 처음에 주는 예제로 테스트를 했었다.
- Misc 150 -
일단 처음 보면 뭔 말인지 모르겠다. 나도 사실 이거 처음에 보고 뭔소리인지 모르겠어서 안 풀었는데 결국에 보니까 복잡한게 아니었다.
서버에 들가면 이렇게 뜬다.
내가 헷갈린 이유는 conversion rule과 ex)가 뭔 소릴 하는 지 몰라서였는데 애초에 볼 필요가 없다.
그냥 table에 있는 저 딕셔너리와 height, 그리고 저 이진수 값만 보면 된다.
이게 뭐냐면 저기 table에 있는 숫자들을 주어진 이진수 값에 끼워 맞추면 된다.
간단하게 어찌 동작해야하는 지 생각할 수 있었고 바로 했다.
from pwn import *
r = remote("218.158.141.182", 52387)
while 1 :
try :
r.recvuntil("Step :")
except :
r.interactive()
r.recvline()
r.recvline()
text = r.recvuntil("\n")
r.recvuntil("t = ")
height = int(r.recvuntil("\n"))
table = r.recvline()
table = table[10:-2]
table = table.replace("'", "")
table = table.replace(",", ":")
table = table.split(": ")
print table
tab = {}
i = 0
while i < height*2:
tab[str(table[i+1])] = str(table[i])
i += 2
print tab
print text
print len(text)
key = ""
i = 0
j = 0
while i < len(text):
while j < len(text):
print str(text[i:j])
if str(text[i:j]) in tab:
if i == j:
j += 1
key += str(tab[str(text[i:j])])
else:
if i == len(text)-1:
i += 1
j += 1
j += 1
continue
i = j
print "i = " + str(i)
break
print key
r.recv(1024)
r.sendline(key)
계속 이렇게 연산을 하다보면 flag를 구할 수 있게된다.
딕셔너리를 활용하면 되게 쉬웠던 문제.
- Misc 200 -
이것또한 이렇게 보면 뭔 말인지 모르겠다.
서버에 들어가면 이렇게 뜨는데 간단히 설명하면 어느 곳에서 시작해서 그 지점에서 저기 써져있는 대로 올라가고 옆가고 뭐시기 하면 결국엔 다 돌아서 F에 오게된다.
그래서 나는 결국 F에 오니까 F에 올 수 있는 애 한명 집어서 또 그 놈한테 올 수 있는 애 찾고 또 찾고 찾고 해서 발견하기로 했다. (근데 지금 생각해보니까 더 쉬운 방법이 있다.)
from pwn import *
r = remote("218.158.141.142", 9238)
def chr_check(rows, x, y, i,row_num, column_num):
text = rows[y][x]
text1 = text[:1]
text1 = str(text1)
if text1 == "F":
return 99, 99
if i == 0:
return 99, 99
text2 = text[1:2]
text2 = int(text2)
if text1 == "D":
ret_x = x
if (column_num - (y+1)) < text2 & text2 < column_num:
minus = text2 - (column_num - (y+1))
ret_y = y - minus
ret_y = y + (text2 % column_num)
elif text1 == "U":
ret_x = x
if y < text2 & text2 < column_num:
add = column_num - text2
ret_y = y + add
ret_y = y - (text2 % column_num)
elif text1 == "R":
ret_x = x + (text2 % row_num)
ret_y = y
elif text1 == "L":
ret_x = x - (text2 % row_num)
ret_y = y
return ret_x, ret_y
def check_side(rows, x, y, row_num, column_num): #((x + i) % row_num) is target x.
for i in range(row_num):
ret_x, ret_y = chr_check(rows, ((x + i) % row_num), y, i,row_num,column_num)
# print "side x = " + str(ret_x)
# print "side y = " + str(ret_y)
if ret_x == x :
return ((x + i) % row_num)
return 999
def check_up(rows, x, y, row_num, column_num):
for i in range(column_num):
ret_x, ret_y = chr_check(rows, x, ((y + i) % column_num), i,row_num,column_num)
# print "up x = " + str(ret_x)
# print "up y = " + str(ret_y)
if ret_y == y :
return ((y + i) % column_num)
return 999
def check(rows, x, y, row_num, column_num):
ret_x = check_side(rows, x, y, row_num, column_num)
ret_y = check_up(rows, x, y, row_num, column_num)
if ret_x != 999:
return ret_x, y
elif ret_y != 999:
return x, ret_y
r.recvuntil("Input : 3 1")
r.recvline()
RR = 0
while 1:
print str(RR);
RR += 1
if RR == 101:
r.interactive()
r.recvline()
r.recvline()
r.recvline()
# column = y, row = x
text = ""
texts = []
for i in range(11):
text = r.recvline()
if not "\t" in text:
column_num = i
print "COLUMN_NUM = " + str(column_num)
break
text = text[0:-3]
texts.insert(i,text)
rows = []
for i in range(0, column_num):
row = str(texts[i])
row = row.split("\t")
rows.insert(i, row)
print rows[i]
row_num = len(rows[0])
for i in range(column_num):
for j in range(row_num):
if "F" in rows[i][j]:
Fin_x = j
Fin_y = i
print "Fin_x = " + str(Fin_x)
print "Fin_y = " + str(Fin_y)
ret_x, ret_y = check(rows, Fin_x, Fin_y, row_num, column_num)
# print "ret_x = " + str(ret_x)
# print "ret_y = " + str(ret_y)
for i in range((row_num * column_num) - 2):
ret_x, ret_y = check(rows, ret_x, ret_y, row_num, column_num)
# print "ret_x = " + str(ret_x)
# print "ret_y = " + str(ret_y)
r.recv(1024)
r.sendline(str(ret_x)+" "+str(ret_y))
코드는 좀 길다.
그러니까 이게 뭐냐면 chr_check로 내가 정한 좌표에 있는 애가 어느 좌표로 이동하는 지 구하는 함수다.
check_side는 내가 정한 좌표의 옆에 애들을 확인해서 어느 좌표에 있는 애가 내 자리로 오나 구한다.
check_up은 내가 정한 좌표의 위 아래 애들을 확인해서 어느 좌표에 있는 애가 내 자리로 오나 구한다.
check는 이걸 다 합쳐서 상하좌우에서 어느 애가 내 자리로 오나 구하는 것이다.
근데 chr_check에 if문이 많은 이유는 바로 줄은 7줄인데 D8 혹은 U9처럼 있는 줄보다 더 많이 올라가는 애들이 있다.
오마갓! 그럼 그 애들은 index out of bound가 될 수도 있으니 만약 있는 줄을 넘어간다고 하면 다시 그 뒤 혹은 앞부터 시작하게 해줘야 한다.
그래서 그렇게 해주느라 if문이 생겼다.(이거 만들때 머리 쥐어 짰음...ㅋㅋㅋㅋㅋㅋㅋ)
그렇게 각 버튼이 있는 개수를 구해서 그거의 - 1번 만큼 이걸 진행하면 마지막에는 첫번째 시작하는 애를 구할 수 있다.
그래서 실행하면 이렇게 결과를 얻을 수 있다.
근데 나 지금 완전 완전 쉬운 방법 알아냈다. 그러니까.. 이것보다 훨신 쉬운거.
여기서 첫번째 시작하는 애를 보면 그 애한테 올 수 있는 애는 없다.
그러니까 걔가 시작이다보니까 아무도 걔한테 가지 않는데
그러면 아까 내가 말했듯이 check로 내 상하좌우에 나한테 올 수 있는 애를 구한다고 했으니까
그 check를 모든 애들에게 해주면 그 중 한명이 나한테 올 수 있는 애가 한명도 없을 태고 그럼 걔가 첫번쨰 시작 아닐까?
... 안될 이유가 없어보인다.ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
아휴 나 뭐한거니 진짜..ㅋㅋ 그런 쉬운방법을 놔두고 좌표로 개고생했네...
뭐 그래도 머리 쓰는 재미가 있었으니 됐다.
미스크는 이렇게 끝이다. 코딩 연습 해본적 없는데 4문제나 풀려서 나도 신기했다.
Reversing
- Rev 50 -
쉬운 문제다. 바이너리를 준다.
main 함수에서 여러가지를 해줘야 flag를 출력하는 함수에 갈 수 있다.
해줘야 되는걸 안하고 바로 flag를 출력하는 함수에 간다면 flag 전체가 출력되지 않는다.
그래서 그 해줘야 되는 것들을 gdb에서 했다고 변경시켜주고 들어가면 된다.
원래는 jump 하는건데 내가 eax를 0으로 바꿔줌으로써 jump를 안하게 되었다.
이렇게 if문에 걸려서 점프하게 되는 것들을 다 안해주면 문제가 풀린다.
ID와 Password 입력하는 것도 있는데 아무거나 쓰고 이것도 jump 안하게 하면 된다.
이렇게 계속 가다보면 문제가 풀린다.
짜잔 이렇게 풀 수 있다.
- Rev 100 -
윈도우 리버싱이다. 근데 그리 많은 윈도우 리버싱 실력을 요구하지는 않는다. 그냥 소스코드 분석 향이 더 강하다.
처음 열어보면 뭘 어케 해야할 지 모르겠다. 함수명을 몰라서.. 이때 윈도우 리버싱을 하면 된다.
나는 immunity debugger을 사용했다.
화면 출력하는 함수 들어가서 보다가 위에 올려다 보면 여러 함수들이 있다.
그중에서 이 함수가 딱 flag를 출력하는 함수 같아 분석을 했다.
첨에는 그냥 rip를 여기로 바꿔서 이 함수를 실행해보니까 이상한 값이 나왔다.
그래서 미로를 탈출할 때 어느 곳으로 가야하나? 해서 분석을 해보니 뭔가 정해진 루트대로 가야 되게 해놨는데
애초에 불가능하다.
그래서 여기를 분석해야 되는게 아니구나 해서 위에있는 저 함수 자체를 그냥 분석해봤다.
이렇게 여러 함수들을 실행시킨다. 여기서 볼 함수는 flag가 출력되는 애가 write 되는 함수이다.
그리고 그게 첫번째 함수다. 이것만 보면 되니 한번 살펴보자.
405240 % 10 == 5라면 flag가 출력되는 애(404660)를 변조한다.
그리고 exit 안되는 if문에서 실행시키는 함수를 봐보면
아까 함수랑 구조가 비슷하다. 여기서는 405240이 % 100 / 5 == 9이면 404660이 변조되게 만든다.
또 저기 if문 안에 있는 함수로 들어가보자.
여기는 405240 / 100 = 1이면 값이 변조된다.
즉 200보다 작고 100으로 나눴을 때 나머지가 45이고 10으로 나눴을 때 나머지가 5여야 된다.
145밖에 없다.
하지만 이 값을 가지고 저기서 하는 연산을 내가 일일이 다 연산하는 건 너무 오래걸린다.
그러니 그냥 디버거에서 rip를 저 함수로 옮겨서 405240에 145를 넣어주자. 그럼 얘가 알아서 해줄것이다.
정상적으로 작동하면 무조건 점프하는 구문이다. 저기서 점프 되는 주소를 우리가 가야할 함수로 바꿔주자.
이렇게 가게 되었다. 이제 저기 c05240 안에 값을 0x91(145)로 바꿔주자.
바꿨다. 이제 그냥 쭉 실행되게 해보자.
앗 그러고보니 이게 끝이 아니라 아까 함수 볼 때 있었던 if문을 성립시켜줘야 한다.(아니면 exit한다)
각 함수마다 1번씩만 값을 바꿔주면 되니 총 3번만 조금 일하면 된다.
확인하는 e4524c 주소를 1로 바꿔주었다. 이렇게 3번 값 바꿔주면 된다.
이렇게 다 변경해주면 함수들이 다 끝나는 부분만 남는다.
애초에 이 첫번째 함수에서는 출력이 되지 않기 때문에 저기서 그냥 bp 없이 쭉 실행되게 해주면 되긴 하지만 나는 그당시 바로 보고싶어서 그냥 660 주소에 있는 문자열을 바로 확인했다.
저기 왜 Y여야할 부분이 ?로 되어있는 지는 모르겠지만(그당시 할때는 잘 됐다) 일단 flag를 구하긴 했다.
끝!
Web
- Web 50 -
꽤나 재밌었다. vim을 쓰던 사람이라면 풀 가능성이 꽤나 높았을 것이다.(내가 vim을 쓴다ㅋㅋ)
vim을 켜서 계속 쓰고 있는 상태에서 ls를 해보면 이상한 파일이 하나 생긴다. .swp로 끝나는 파일인데 딱 보고 이게 연상됐다. 그래서 index.php의 swp 파일 형태로 .index.php.swp를 적었다.
그랬더니 딱 나왔다. 나는 이 상태에서 거의 다 푼 줄 알았다. 근데 아니었다.
매직 해쉬를 쓰기에는 마지막에 S@L7이 붙어서 못쓴다. 결국 내가 S@L7이 마지막에 붙는 매직해쉬 문자열을 찾아야 된다는 것이다.
이걸 어케 할까 고민하다가 그냥 내가 찾는 프로그램을 만들었다.
그냥 무식하게 때려 넣었다.
몇분이 지나야 끝나는 지는 모른다.
그래도 한 2분정도 있다보면 작동하는 문자열이 하나 둘 씩 나온다.
그 중 하나를 사용해보자.
여기 하나가 나왔다. 이걸 사용하자.
이렇게 넣고 보내면
flag를 얻을 수 있다.
이렇게 7문제 풀이 끝!
'CTF' 카테고리의 다른 글
Hacking Championship Junior 문제 2개 풀이 (0) | 2019.10.21 |
---|---|
Layer7 CTF Write up (0) | 2019.10.07 |
디미CTF 풀이 (총 8문제 풀이) (0) | 2019.07.11 |
WSL에서 ssl, git, apt 등에서 인터넷 문제가 생길 때! (2) | 2019.06.30 |
Windows terminal에서 WSL 탭이 안 나올 때 (0) | 2019.06.30 |