티스토리 뷰

2016 CSAW CTF Quals



Crypto - Sleeping Guard



Exercise


진정한 해커는 PNG 속의 마술을 볼 수 있다...





Solution


nc 로 접속할 수 있는 주소가 있다. 접속해보면, 상당한 양의 문자열을 확인할 수 있다. .bin 파일로 리다이렉션 한 뒤, 해당 문자열 데이터를 확인해보면, 아래와 같이 특수 문자를 포함한 문자열임을 확인할 수 있다.





+, / 등의 문자열과 숫자, 알파벳으로 이루어진 것으로 보아 base64 문자열임을 추측해 볼 수 있다.  문제와 함께 주어진 sleeping_dist.py 라는 code 를 확인해 보면, 아래와 같다. 12 글자의 key 값을 확인한 뒤, encrypt 함수를 통해서 길이 만큼 암호화를 한 뒤, base64 로 encoding 을 하고, png 파일을 저장하는 것을 확인할 수 있다. 이를 통해서, nc로 접속할 때, 확인된 문자열이 png 파일이 암호화 된 것을 추측할 수 있다.



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

import base64

from twisted.internet import reactor, protocol

import os

PORT = 9013

import struct

def get_bytes_from_file(filename):  

   return open(filename, "rb").read()  

   

KEY = "[CENSORED]"

def length_encryption_key():

   return len(KEY)

def get_magic_png():

   image = get_bytes_from_file("./sleeping.png")

   encoded_string = base64.b64encode(image)

   key_len = length_encryption_key()

   print 'Sending magic....'

   if key_len != 12:

       return ''

   return encoded_string

   

class MyServer(protocol.Protocol):

   def connectionMade(self):

       resp = get_magic_png()

       self.transport.write(resp)

class MyServerFactory(protocol.Factory):

   protocol = MyServer

factory = MyServerFactory()

reactor.listenTCP(PORT, factory)

reactor.run()

Colored by Color Scripter

cs



KEY 가 12 글자로 제한되는 것을 확인할 수 있는데, magic 이란 단어가 언급된 점을 보아, Magic signature 를 의미하는 것으로 생각, PNG magic number 를 확인하여 signature 부터 12byte 만큼 고정 되는 값을 확인할 수 있었다.



읽어들인 base64 encode data 를 다시 decode 한 뒤, 앞 12 byte 를 본래 magic number 와 xor 연산을 해보니 아래와 같이 Key 를 확인할 수 있었다.





나온 Key 를 가지고 역연산을 수행 하였다. decode 한 data 전체를 KEY 로 xor 해주는 작업을 거쳤다.




1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

import base64

f = open('data.bin','rb').read()

data_ = base64.b64decode(f)

key = ""

png_ = [0x89,0x50, 0x4E, 0x47, 0x0D ,0x0A

,0x1A ,0x0A ,0x00 ,0x00 ,0x00 ,0x0D]

for i in  range (12):

   key+=chr(int(png_[i]) ^ ord (data_[i:i+1]))

print '[+]',key

key = list(key)

flag = ""

for i in range(len(data_)):

   flag += chr(ord(data_[i:i+1]) ^ ord(key[i%12]))

print '[+] write png...'

l = open("picture.png",'wb')

l.write(flag)

l.close()

Colored by Color Scripter

cs




png 를 암호화한 작업이었으므로, 정상적으로 복호화 되었다면 인식할 수 있는 PNG 파일일 것이므로, png 로 저장을 해주었고, 아래와 같이 정상적으로 이미지가 열리고 FLAG 를 확인할 수 있었다.


댓글
댓글쓰기 폼