웹해킹/파이썬해킹

ICMP(Internet Control Message Protocol)

dongok218 2024. 9. 19. 21:10

3계층(네트워크 계층)에서 동작하며 네트워크 통신의 테스트 또는 오류 메시지 응답을 전송하는 데 주로 사용된다.

통신 상태를 확인할 때 사용하는 Ping, Tracert 또한 ICMP를 이용한다.

 

Type: ICMP패킷의 종류를 나타낸다.

Code: Type에 대한 상세한 항목이다.

Checksum: 오류를 검출하는 필드이다.

Other message specific information: ICMP 헤더의 추가 메시지 필드이다. ICMP헤더는 Type과 Code에 따라 헤더의 내용이 바뀐다.


ICMP 스니퍼(ICMP Sniffer)

sniff는 '킁킁거리다'라는 뜻이다. 네트워크 패킷을 훔쳐보는 프로그램을 스니퍼(Sniffer)라고 한다.

스니퍼 테스트를 위해 ICMP프로토콜을 수신하는 방화벽을 열어야 한다.

윈도우10을 기준으로 기본적으로 ICMP 프로토콜은 방화벽에서 막는다.

 

1. Win+R키를 눌러 Control을 입력 후 제어판을 연다.

2. 시스템 및 보안 클릭

3. Windows Defender방화벽 선택

4.'고급 설정' 클릭

5.'인바운드 규칙'에서 '파일 및 프린터 공유(에코 요청-ICMPv4-In)'의 개인과 공용프로필 항목을 확인.

 

[ICMP 스니퍼 코드]

from socket import *
import os
import struct


def parse_ip_header(ip_header):
    ip_headers = struct.unpack("!BBHHHBBH4s4s", ip_header[:20])
    ip_payloads = ip_header[20:]
    return ip_headers, ip_payloads


#ICMP 헤더와 메시지 내용의 튜플로 변환. ICMP헤더는 Type과 Code에 따라서 모양이 바뀔 수 있다. 자세한 내용은 RFC문서 링크를 참고
# icmp_payloads는 ping도구를 이용했을때 임의의 문자열을 담는다
def parse_icmp_header(icmp_data):
    icmp_headers = struct.unpack("!BBHHH", icmp_data[:8])
    icmp_payloads = icmp_data[8:]
    return icmp_headers, icmp_payloads


def parsing(host):
    if os.name == "nt":
        sock_protocol = IPPROTO_IP
    else:
        sock_protocol = IPPROTO_ICMP
    sock = socket(AF_INET, SOCK_RAW, sock_protocol)
    sock.bind((host, 0))

    sock.setsockopt(IPPROTO_IP, IP_HDRINCL, 1)

    if os.name == "nt":
        sock.ioctl(SIO_RCVALL, RCVALL_ON)

    try:
        #만약 수신하는 패킷이 ICMP 형태라면 그 내용을 출력
        while True:
            data = sock.recvfrom(65535)
            ip_headers, ip_payloads = parse_ip_header(data[0])
            #IP헤더의 6번째 튜플 요소는 프로토콜을 나타내며 1인 ICMP프로토콜만을 의미한다.
            #icmp_headers[0]은 ICMP헤더의 Type을 의미하며 Ping요청은 Echo Request를 출력하며 응답은 Echo Reply를 출력한다.
            #icmp_payloads는 임의의 문자열을 담는다.
            if ip_headers[6] == 1:
                ip_source_address = inet_ntoa(ip_headers[8])
                ip_destination_address = inet_ntoa(ip_headers[9])
                print(f"{ip_source_address}=>{ip_destination_address}")
                icmp_headers, icmp_payloads = parse_icmp_header(ip_payloads)
                if icmp_headers[0] == 0:
                    print("Echo Reply")
                elif icmp_headers[0] == 8:
                    print("Echo Request")
                print("icmp_headers=>", icmp_headers)
                print("icmp_payloads=>", icmp_payloads)
                print("===========================")
    except KeyboardInterrupt:
        if os.name == "nt":
            sock.ioctl(SIO_RCVALL, RCVALL_OFF)


if __name__ == "__main__":
    host = "192.168.50.56"
    print("START SNIFFING at [%s]" % host)
    parsing(host)

 

[출력화면(내 pc에서 ping쳤을때)]

Echo Request: ICMP 질의 메세지 요청

Echo Reply: ICMP 응답 메세지 요청

'웹해킹 > 파이썬해킹' 카테고리의 다른 글

TCP/UDP  (2) 2024.10.03
Ping Sweep 스캐너 구현  (0) 2024.10.03
은닉 채널을 이용한 파일 전송  (0) 2024.09.20
Raw소켓을 이용한 IP 헤더 분석  (0) 2024.09.19