tcpdump 캡처 출력에서 ​​유니코드 텍스트를 볼 수 있습니까?

tcpdump 캡처 출력에서 ​​유니코드 텍스트를 볼 수 있습니까?

tcpdump불행하게도 캡처에서 유니코드로 인코딩된 텍스트(특히 UTF-8)를 감지하고 표시할 수 있는 방법은 없는 것 같습니다 . 유니코드 텍스트를 일반 이진 데이터로 처리하여 점으로 표시합니다. 애플리케이션을 디버깅하려면 이 기능이 필요합니다.

보다 구체적으로 말하면 tmuxGnome Terminal의 원격 SSH 세션에서 tcpdump 4.3.0을 실행하고 있습니다. 운영체제는 데비안 7 입니다.

tcpdump이것을 사용하거나 다른 Linux 명령과 결합하여 라이브 네트워크 캡처에서 유니코드 텍스트를 볼 수 있습니까 ?

답변1

다음 TXR Lisp 프로그램은 pcap.tl다음과 같이 호출됩니다.

$ tcpdump -s 1024 -w - | ~/txr/txr pcap.tl

pcap 형식 출력을 구문 분석 -w하고 다음 출력을 생성합니다.

192.168.1.102 --> 192.168.1.146
  ether hdr: #S(eth-header dst-mac #(8 0 39 249 113 4) src-mac #(0 30 79 164 102 184) eth-type ETH_IPV4)
  ipv4 hdr:  #S(ipv4-header ihl 5 ver 4 ecn 0 dscp 0 len 101 ident 7434 fragoffs-hi 0 flags 2
               fragoffs-lo 0 ttl 64 proto 6 hdr-sum 39232 src-ip 3232235878
               dst-ip 3232235922)
  ipv4 payload as text: P��.;;�.�+i�.6�...
KK-?9rrt2b
春が来た (Haru-ga Kita/Spring has Com

이 코드는 FFI 유형 선언을 사용하여 pcap 파일 및 패킷 형식, 이더넷 헤더 및 ipv4 헤더에 해당하는 구조 유형을 정의합니다. ipv4 헤더는 비트 필드에 의존하기 때문에 빅엔디안과 리틀엔디안 시스템에 대해 두 가지 다른 방식으로 정의됩니다.

전체 IPv4 페이로드를 UTF-8 데이터로 가져와서 디코딩하고 제어 문자를 점으로 교체한 후 인쇄합니다.

2022년 5월 24일 편집: 새로운 코드는 TXR 276의 엔디안 비트필드 지원을 활용합니다. 이제 비트 필드는 엔디안 유형을 기반으로 할 수 있으므로 be-uint16더 이상 엔디안을 기반으로 하는 두 가지 방법으로 IPv4 헤더 구조 소유자를 선언할 필요가 없습니다.

(typedef ll-t (enumed uint32 ll-t
                DLT_NULL DLT_EN10MB))

(typedef eth-t (enumed be-uint16 eth-t
                 (ETH_IPV4 #x0800)
                 (ETH_ARP  #x0806)
                 (ETH_IPV6 #x08DD)))

(typedef pcap-header (struct pcap-header
                       (magic uint32)
                       (majver uint16)
                       (minver uint16)
                       (tzoffs uint32)
                       (tzprec uint32)
                       (snaplen uint32)
                       (lltype ll-t)))

(typedef pkt-header (struct pkt-header
                      (tsec uint32)
                      (tfrac uint32)
                      (trunclen uint32)
                      (origlen uint32)))


(typedef eth-header (struct eth-header
                      (dst-mac (array 6 uint8))
                      (src-mac (array 6 uint8))
                      (eth-type eth-t)))

(typedef ipv4-header (struct ipv4-header
                       (ver (bit 4 be-uint16))
                       (ihl (bit 4 be-uint16))
                       (dscp (bit 6 be-uint16))
                       (ecn (bit 2 be-uint16))
                       (len be-uint16)
                       (ident be-uint16)
                       (flags (bit 3 be-uint16))
                       (fragoffs-hi (bit 5 be-uint16))
                       (fragoffs-lo uint8)
                       (ttl uint8)
                       (proto uint8)
                       (hdr-sum be-uint16)
                       (src-ip be-uint32)
                       (dst-ip be-uint32))))

;; Look for IPv4 packets and print headers
(defun decode-packet (phdr buf)
  (let ((eh (ffi-get buf (ffi eth-header))))
    (unless (eq eh.eth-type 'ETH_IPV4)
      (return-from decode-packet))
    (let* ((ih (ffi-get buf (ffi ipv4-header) (sizeof eth-header)))
           (hdrsz (+ (sizeof eth-header) (sizeof ipv4-header)))
           (len (- (length buf) hdrsz))
           (body (carray-buf buf (ffi char) hdrsz))
           (rawtext (carray-get body))
           (text (mapcar (iffi [andf chr-iscntrl [notf chr-isspace]] (ret #\.))
                         rawtext)))
      (put-line `@(str-inaddr ih.src-ip) --> @(str-inaddr ih.dst-ip)`)
      (put-line `  ether hdr: @eh`)
      (put-line `  ipv4 hdr:  @ih`)
      (put-line `  ipv4 payload as text: @text`))))

;; main program
(let ((*stdin* (open-fileno (fileno *stdin*) "rbu")) ;; binary, unbuffered
      (hdr (new pcap-header))
      (hdr-buf (make-buf (sizeof pcap-header)))
      (phdr (new pkt-header))
      (phdr-buf (make-buf (sizeof pkt-header)))
      (pay-buf (make-buf 65536)))

  ;; read pcap file header
  (when (< (fill-buf hdr-buf) (sizeof pcap-header))
    (return))

  ;; decode to structure
  (ffi-in hdr-buf hdr (ffi pcap-header) t)

  (unless (eq hdr.lltype 'DLT_EN10MB)
    (put-line "can only deal with Ethernet frames")
    (exit nil))

  ;; read and decode packets
  (while t
    (when (< (fill-buf phdr-buf) (sizeof pkt-header))
      (return))
    (ffi-in phdr-buf phdr (ffi pkt-header) t)
    (buf-set-length pay-buf phdr.trunclen)
    (when (< (fill-buf pay-buf) phdr.trunclen)
      (return))
    (decode-packet phdr pay-buf)))

body이더넷 및 IPV4 헤더를 전달하기 위해 변위가 carray중첩된 개체 에 바인딩됩니다 . 요소 유형은 헤더 뒤의 버퍼 전체를 차지합니다.bufhdrszchar

그러면 (carray-get body)전체 외부 값이 Lisp 문자열로 변환됩니다 . UTF-8 변환은 요소 유형이 다음과 같으므로 시작됩니다 char. 배열의 특수 동작 char. 유형이 이면 bchar바이트를 문자 1:1로 처리합니다. 유형이 인 경우 wchar배열은 wchar_t문자가 되며 이에 따라 문자열로 변환됩니다. 문자열 대신 숫자 바이트 벡터를 얻으려면 요소 유형을 uchar또는 으로 설정할 수 있습니다 uint8.

이 프로그램은 TCP, UDP, IPv6 등 필요한 모든 것을 처리하도록 쉽게 확장 가능합니다. 특정 헤더 필드에서 특정 일치 항목을 찾습니다.

관련 정보