길고 길었던 중간 발표가 끝이 났다.
일요일에 ppt를 만든다고 팀원들과 고생을 했다. 나는 막차 때문에 먼저 갔지만, 팀원들은 ppt만든다고 새벽 1시에 해산했다고 한다. 그 이야기를 듣고 너무 미안했다. 교수님에게 피드백을 받긴 했지만, 팀원들 덕분에 무난하게 중간 발표도 끝났고 잠시 휴식시간이 생겼다. 그렇지만 이제는 내가 맡고 있는 소프트웨어 파트가 중요해져 쉴 틈이 없다.
이제, 기말 발표 전까지 Deauth, sniffIP, 그리고 실질적인 드론 조종 파트까지 남았다. 그러기 위해서는 이제 scapy 라이브러리가 정말로 중요해졌다.
막상 이때까지 scapy를 사용했지만, 여태껏 제대로 정리한 적은 없기에 오늘 이참에 정리하고자 한다.
내가 오늘 정리할 부분은 scapy에서 srp, ARP, Ether method에 관련되어 정리하고 내가 작성한 sniffIP 함수에 대해서 설명을 하고 문제점에 대해서 말할 예정이다.
참조: https://scapy.readthedocs.io/en/latest/usage.html#starting-scapy
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"), timeout=2)
우선 위의 함수에 대해서 하나하나 뜯어보도록 하자.
op: ARP 요청 유형 지정 // 1 = Request, 2 = reply
psrc: ARP 요청을 보낼 송신자 IP의 주소
pdst: ARP 요청을 받을 수신자 IP의 주소
hwsrc: ARP 요청을 보낼 송신자 MAC의 주소
hwdst: ARP 요청을 받을 수신자 MAC의 주소
psrc_hw: ARP 응답 패킷에서 송신자(IP, MAC) 주소를 지정
// reply일 때만 사용가능하고 psrc_hw = (192.168.0.1, "00:11:22:33:44:55")
pdst_hw: ARP 응답 패킷에서 수신자(IP, MAC) 주소를 지정
// 위와 마찬가지
arp_response = ARP(op=2, hwsrc = "00:11:22:33:44:55", psrc='192.168.0.1', pdst = '192.168.0.4')
//psrc와 hwsrc의 경우 어느 한개만 생략이 가능하다. 생략하는 경우 패킷을 보내는 컴퓨터, 즉 자신의 컴퓨터의 IP, MAC을 이용한다.
//hwsrc, hwdst의 경우 생략되어도 상관이 없다. ARP는 IP를 통해서 MAC주소를 매핑하기 때문이다. 대신, MAC 주소를 사용하지 않으면 그만큼 추가로 패킷을 요청하기 때문에 자원을 더 사용하게 된다.
근데 여기서 특이한 것은 Ether 함수와 ARP 함수 사이에 '/' 연산자가 있다는 점일 것이다. 처음에 나도 나누기로 생각했지만, 이는 Stacking layer operator로 layer를 stack하는데 사용한다. 즉, 두개의 층을 쌓아서 하나의 패킷으로 만들어주는 역할을 한다.
ans, unans로 나뉘는 이유는 ans의 경우 응답이 왔을 때, unans의 경우 응답이 오지 않았을 때로 나뉘어 저장된다.
def get_my_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
my_ip = s.getsockname()[0]
s.close()
return my_ip
//구글을 통해서 IP를 알아낸다. 하지만 드론에 접속한 경우 그러한 방식은 통하지 않기 때문에 테스트 단계에서만 이 방법을 사용한다.
def showPacket(packet)://sniff의 callback 함수.
src_ip = packet[0][1].src
dst_ip = packet[0][1].dst
prt = packet[0][1].proto
#if(proto == 17)# Code 17 is UDP
return src_ip, dst_ip
def sniffIP():#Get drone's IP and controller's IP!
my_ip = '192.168.0.4'
filter = f'ip and not host {my_ip}'//필터링
captured_packets = sniff(filter = filter, prn = showPacket, count = 1)
ips = [showPacket(packet) for packet in captured_packets]
return ips[0]
