5. Scapy에 대해서

Peroro·2023년 4월 24일

캡스톤

목록 보기
5/10

길고 길었던 중간 발표가 끝이 났다.

일요일에 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)

우선 위의 함수에 대해서 하나하나 뜯어보도록 하자.

  • srp 함수는 'Send and receive packets at layer 2' OSI 7계층에서 데이터 링크층에 해당하는 layer 2에 해당 패킷을 보낸다는 뜻이다.
  • Ether 함수는 출발지 MAC Address와 목적지 MAC Address를 통해서 Ethernet 프레임을 생성하는 함수이다. 이는 OSI 2계층인 데이터 링크 계층에 해당한다. 위의 함수에서는 'ff:ff:ff:ff:ff:ff'로 두어 boradcast를 하고 있다.
  • ARP 함수는 출발지 IP와 도착지 IP, 출발지 MAC Address, 도착지 MAC Address를 포함한다.(여기서는 MAC Address가 생략) 이 함수 역시 ARP Spoofing을 시도하는데 큰 역할을 하는 함수이다. 아래는 ARP 함수의 인자이다. 필요할 때마다 인자를 불러 사용하면 된다.
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의 경우 응답이 오지 않았을 때로 나뉘어 저장된다.


  • sniffIP() 함수
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]

  • 뭔가 패킷을 sniffing 하는 것처럼 보이지만, 내 IP를 필터링하지 못한다. 이유를 찾아보니 libpcap을 설치하지 않아서 그런 것으로 보인다. MAC OS라 설치가 될지 잘 모르겠지만 Homebrew에 있는 것으로 보아 크게 문제 없을 것으로 보인다.
  • 틀린 내용이 있다면 알려주시길 부탁드립니다. 잘 모르는 초짜이다보니..
profile
오늘 공부한 것을 올리는 공간 / 일주일에 글 3개 / 블로그 이전 : https://perorochan321.tistory.com/

0개의 댓글