드림핵 Forensic CTF

챠챠비둘기·2023년 7월 28일
0

방학 스터디(포렌식)

목록 보기
19/22
post-thumbnail

sleepingshark

와이어샤크를 이용한 네트워크 포렌식 문제이다.
압축파일을 다운받아서 해제하면 pcap 파일이 나오는데 pcap 파일을 열어서 패킷을 분석해 보자.

저 SELECT가 적혀 있는 패킷으로 가 보자.

flag라는 글자를 발견할 수 있다. 저 문자열을 복사해서 url decode를 해 보면

flag의 단서?랑 SLEEP 3초라는 명령문을 얻을 수 있다. 좀 더 자세한 정보를 위해 전체 url을 decode해 보자.

뭔가 비교해서 맞으면 3초동안 잠드는 걸로 보인다. 여기서 비교 대상은 flag 값이라고 추측할 수 있다. 즉, flag 값이 맞으면 3초동안 잠드므로, 3초 단위로 http 패킷을 분석하면 플래그 값이 나올 것이라고 생각해 볼 수 있다.

이렇게 SELECT 문이 적혀 있는 http 패킷들에서 flag정보를 합해서, 온전한 플래그 값을 얻을 수 있는 걸로 보인다.
다시말해 노가다 문제이다. 그냥 노가다하기에는 http 패킷이 너무 많아 파이썬의 도움을 얻어서 풀어보기로 하였다...☠️

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


def analyze_packets(pcap):
    
    flag = list()
    for i in range(39):
        flag.append('X')
    post_sent = False
    payload = ''
    request_time = 0
    response_time = 0
    
    for timestamp, buf in pcap:


        eth = dpkt.ethernet.Ethernet(buf)
        # ip 패킷을 포함해야 한다
        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:
            # 타임스탬프도 함께 출력한다
            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:
            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():
    
    with open('C:\\toyproject\\Python\\ctf\\dump.pcap', 'rb') as f:   #열어보려는 파일의 경로
        pcap = dpkt.pcap.Reader(f)
        print('flag : ' + analyze_packets(pcap))



if __name__ == '__main__':
    test()


수작업으로 했다가는 100년걸릴 뻔했다. 아무튼 플래그 찾아서 다행.....

profile
개발 + 보안

1개의 댓글

comment-user-thumbnail
2023년 7월 28일

공감하며 읽었습니다. 좋은 글 감사드립니다.

답글 달기