deayzl's blog

[2022 Fall GoN Open Qual CTF] SleepingShark writeup 본문

CTF writeup/GoN Open Qual CTF

[2022 Fall GoN Open Qual CTF] SleepingShark writeup

deayzl 2022. 8. 31. 21:00

dump.pcap

제공된 dump.pcap 의 모습이다.

 

wireshark 로 열어주면,

 

wireshark

http 프로토콜의 패킷을 보게 되는데 url decode 해주면

 

url decode

Time based Sql Injection 을 하는 payload 를 볼 수 있다.

 

http 프로토콜만 나오도록 해주고, timestamp 를 살펴봐서 3초 이상 차이나는 패킷을 확인하면 flag 문자열의 한글자 한글자씩의 아스키 코드를 알 수 있을 것이다.

 

 

(619번, 623번 패킷의 Time 섹션을 보면 4.7초에서 7.7 초로 넘어간 것을 볼 수 있다)

 

dump 파일을 모두 수작업으로 뒤질 수도 있지만, 그때 당시에 bomblab-hard 문제를 푸느라 바빠서 조금 하다가 포기했다.

그래서 pcap 파일을 직접 뒤져주는 파이썬 라이브러리 dpkt 이용해주었다. 

 

from pwn import *
import dpkt
import datetime
from dpkt.compat import compat_ord
import urllib

def analyze_packets(pcap):
    """Print out information about each packet in a pcap

       Args:
           pcap: dpkt pcap reader object (dpkt.pcap.Reader)
    """
    flag = list()
    for i in range(39):
        flag.append('X')
    post_sent = False
    payload = ''
    request_time = 0
    response_time = 0
    # For each packet in the pcap process the contents
    for timestamp, buf in pcap:


        eth = dpkt.ethernet.Ethernet(buf)
        # Make sure the Ethernet data contains an IP packet
        if not isinstance(eth.data, dpkt.ip.IP):
            print('Non IP Packet type not supported %s\n' % eth.data.__class__.__name__)
            continue
        ip = eth.data
        tcp = ip.data
        if not post_sent and tcp.dport == 80 and len(tcp.data) > 0:
            # Print out the timestamp in UTC
            time = datetime.datetime.utcfromtimestamp(timestamp)
            print('Timestamp: ', str(time), '(' + str(timestamp) + ')')
            request_time = timestamp
            
            http = dpkt.http.Request(tcp.data)
            payload = urllib.parse.unquote(http.uri)
            print('-- request --\n {0} {1}\n'.format(http.method, payload))
            if(http.method == 'POST'):
                post_sent = True
        elif post_sent and tcp.sport == 80 and len(tcp.data) > 0:
            # Print out the timestamp in UTC
            time = datetime.datetime.utcfromtimestamp(timestamp)
            print('Timestamp: ', str(time), '(' + str(timestamp) + ')')
            response_time = timestamp

            http = dpkt.http.Response(tcp.data)
            print('-- response --\n{0}'.format(http.status))

            if(response_time - request_time >= 2.8):
                payload = payload[payload.find('LIMIT 1),') + 9:]
                idx = int(payload[:payload.find(',')]) - 1
                ch = chr(int(payload[payload.find('))=') + 3:payload.find(', SLEEP(3)')]))
                flag[idx] = ch
                print('\n\nFound!!\n\n flag[{0}] : {1}\n\ncurrent flag : {2}'.format(idx, ch, ''.join(flag)))
                sleep(0.1)
            post_sent = False
    return ''.join(flag)


def test():
    """Open up a test pcap file and print out the packets"""
    with open('D:\\dreamhack\\dump.pcap', 'rb') as f:
        pcap = dpkt.pcap.Reader(f)
        print('flag : ' + analyze_packets(pcap))



if __name__ == '__main__':
    test()

 

Print HTTP Requests Example — dpkt 1.9.2 documentation

 

Print HTTP Requests Example — dpkt 1.9.2 documentation

© Copyright 2009-2019 Dug Song and lots of Contributors Revision 6291ed4f.

dpkt.readthedocs.io

(위 링크의 example 을 참고해서 스크립트를 작성했다)

Comments