와이어샤크를 이용한 네트워크 포렌식 문제이다.
압축파일을 다운받아서 해제하면 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년걸릴 뻔했다. 아무튼 플래그 찾아서 다행.....
공감하며 읽었습니다. 좋은 글 감사드립니다.