2014-12-18 2 views
5

GET 메서드로만 HTTP 패킷을 인쇄하는 Scapy에서 간단한 스니퍼를 코딩하려고합니다. 여기Scapy의 HTTP GET 패킷 스니퍼

#!/usr/bin/python 
from scapy.all import * 

def http_header(packet): 
     http_packet=str(packet) 
     if http_packet.find('GET'): 
       print GET_print(packet) 
     print packet 
def GET_print(packet1): 
     print "***************************************GET PACKET****************************************************" 
     print packet1 

     print "*****************************************************************************************************" 


sniff(iface='eth0',prn=http_header) 

출력됩니다 :

***************************************************************************************************** 
None 
T��à 
    )�pEa��@@���h��#/��t 
          �}LGku���U 
oTE��I(��Ͻ�9qi���S��?�� 
          XuW�F=���-�k=X:� 
***************************************GET PACKET**************************************************** 
T��à 
    )�pE���@@���h��#/��t 
           ʪLGku���� 
oTE��I�K��AH�*�e��>�v1#D�(mG5T�o�?��8��喷╭���Ի�"�KT^�'�mB���]�����k> 
                       �_x�X�����8V?�Ǽw/�Z�=���N�À��\r�����)+}���l�c�9��j;���h��5�T�9Hۖ/O��)��P 
     މY�qf爂�%�_`��6x��5D�I3���O� 
t��tpI#�����$IC��E�� 
        �G� 
J��α���=�]��vһ���b5^|P��DK�)uq�2��ț�w� 
        tB������y=���n�i�r�.D6�kI�a���6iC���c'��0dPqED�4����[�[��hGh̃��~|Y/�>`\6yP Dq١?T��Mѵ���f�;���Җ��Ǵ gY���di�_x�8| 
eo�p�xW9��=���vŅYe�}�T�ۨɑy�^�C 
-�_(�<�{����}�������r 
$��J�k-�9����}�Ϡf�27��QKԛ�`�GY�8��Sh���[email protected]�E9�Rϔ�&a�/vkф��6�DF`�/9�I�d(��-��[A 
                        ��)pP��y\ռj]���8�_���vf�b����I7�������+�P<_` 
***************************************************************************************************** 

내가 기대하고하는 것은 다음은 코드는

GET/HTTP/1.1 
    Host: google.com 
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20140722 Firefox/24.0 Iceweasel/24.7.0 
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
    Accept-Language: en-US,en;q=0.5 
    Accept-Encoding: gzip, deflate 
    Cookie: PREF=ID=758a20b5fbd4eac9:U=2b2dedf6c84b001f:FF=0:TM=1412150291:LM=1415430021:S=Q-QemmrLqsSsEA9i; NID=67=mRdkPVhtImrOTLi5I1e5JM22J7g26jAcdiDEjj9C5q0H5jj0DWRX27hCM7gLJBeiowW-8omSv-1ycH595SW2InWX2n1JMMNh6b6ZrRsZ9zOCC2a-vstOQnBDSJu6K9LO 
    Connection: keep-alive 

내 예상 출력을 얻기 위해 무엇을 할 수 있는가?

답변

8

패킷 자체를 인쇄하는 대신 패킷의 sprintf function을 사용해야합니다. 당신은 또한 그렇지 않으면 한 줄에 출력을 모두 뱉어, 그것에서 반환 된 문자열을 분할하고 줄 바꿈 문자와 함께 다시 가입해야합니다

#!/usr/bin/python 
from scapy.all import * 

def http_header(packet): 
     http_packet=str(packet) 
     if http_packet.find('GET'): 
       return GET_print(packet) 

def GET_print(packet1): 
    ret = "***************************************GET PACKET****************************************************\n" 
    ret += "\n".join(packet1.sprintf("{Raw:%Raw.load%}\n").split(r"\r\n")) 
    ret += "*****************************************************************************************************\n" 
    return ret 

sniff(iface='eth0', prn=http_header, filter="tcp port 80") 

가 나는 또한 TCP 포트 80에 대한 필터를 추가,하지만이 될 수있다 필요한 경우 제거되었습니다.

예 출력 :

***************************************GET PACKET**************************************************** 
'GET /projects/scapy/doc/usage.html HTTP/1.1 
Host: www.secdev.org 
Connection: keep-alive 
Cache-Control: max-age=0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36 
Referer: https://www.google.co.uk/ 
Accept-Encoding: gzip, deflate, sdch 
Accept-Language: en-GB,en;q=0.8,en-US;q=0.6 
If-None-Match: "28c84-48498d5654df67640-gzip" 
If-Modified-Since: Mon, 19 Apr 2010 15:44:17 GMT 

' 
***************************************************************************************************** 

Pierre 당신이 완전히 sniff()lfilter 인수를 사용하여 멀리 http_header 기능을 할 수 있다고 지적한다.

#!/usr/bin/python 
from scapy.all import * 

stars = lambda n: "*" * n 

def GET_print(packet): 
    return "\n".join((
     stars(40) + "GET PACKET" + stars(40), 
     "\n".join(packet.sprintf("{Raw:%Raw.load%}").split(r"\r\n")), 
     stars(90))) 

sniff(
    iface='eth0', 
    prn=GET_print, 
    lfilter=lambda p: "GET" in str(p), 
    filter="tcp port 80") 
+2

감사! 매력처럼 작동합니다! –

+1

당신의 대답은 아주 좋습니다. 필터링 작업을 수행하고, http_header()를 제거하고,'sniff (iface = 'eth0', prn = GET_print, lfilter = lambda p : str (p)의 "GET", 필터 = "tcp port 80")'. – Pierre

+1

Thanks @Pierre 코드를 포함하도록 답변을 업데이트했습니다. –

2

당신이 pip install scapy-http를 실행하여 설치할 수 scapy의 HTTP 모듈이있다 : 나는 같은 시간에 코드를 좀 더 간결을 만들기의 자유를했다. 설치가 완료되면 import scapy_http.http을 실행하여 가져올 수 있습니다. 이것은 scapy 모듈과 별개이지만 scapy에 기능을 추가하므로 평소와 같이 scapy를 가져와야합니다.

일단 수입,

sniff(iface="eth0", 
prn=GET_print, 
lfilter= lambda x: x.haslayer(scapy_http.http.HTTPRequest)) 

에 필터 라인 변경은 내가 filter="tcp and port 80" 옵션을 제거 그것이 될 수없는 명백한 이유를 위해 SSL을 제외하고 상관없이 포트의 모든 HTTP 요청 쿼리를 반환합니다 HTTP의 lfilter을 사용하기 때문에 평소 상황에서 냄새가났다. 성능상의 이유로 filter 옵션을 유지해야 할 수 있습니다.

2

나는 그것을 향상시키는 한 가지 방법에 대해 의견을 말했지만, 나는 더 완벽한 해결책을 함께 채우기로 결정했다. 이것은 별표 (*)를 사용하지 않고 헤더를 예쁜 인쇄 사전으로 인쇄하므로 사용자에게 적합하거나 그렇지 않을 수도 있지만 사용자의 필요에 맞게 사용자 정의 할 수도 있습니다. 형식 지정과는 별도로, 이것은 지금까지이 질문에 가장 효율적인 수단으로 게시 된 것으로 보이며 형식을 추가하고 사전을 해체하는 함수에 위임 할 수 있습니다.

#!/usr/bin/env python2 

import argparse 
import pprint 
import sys 

# Suppress scapy warning if no default route for IPv6. This needs to be done before the import from scapy. 
import logging 
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) 


# Try to import sniff from scapy.all and show error w/ install instructions if it cannot be imported. 
try: 
    from scapy.all import sniff 
except ImportError: 
    sys.stderr.write("ERROR: You must have scapy installed.\n") 
    sys.stderr.write("You can install it by running: sudo pip install -U 'scapy>=2.3,<2.4'") 
    exit(1) 

# Try to import scapy_http.http and show error w/ install instructions if it cannot be imported. 
try: 
    import scapy_http.http 
except ImportError: 
    sys.stderr.write("ERROR: You must have scapy-http installed.\n") 
    sys.stderr.write("You can install it by running: sudo pip install -U 'scapy>=1.8'") 
    exit(1) 


if __name__ == "__main__": 
    # Parser command line arguments and make them available. 
    parser = argparse.ArgumentParser(
     formatter_class=argparse.ArgumentDefaultsHelpFormatter, 
     description="Print HTTP Request headers (must be run as root or with capabilities to sniff).", 
    ) 
    parser.add_argument("--interface", "-i", help="Which interface to sniff on.", default="eth0") 
    parser.add_argument("--filter", "-f", help='BPF formatted packet filter.', default="tcp and port 80") 
    parser.add_argument("--count", "-c", help="Number of packets to capture. 0 is unlimited.", type=int, default=0) 
    args = parser.parse_args() 

    # Sniff for the data and print it using lambda instead of writing a function to pretty print. 
    # There is no reason not to use a function you write for this but I just wanted to keep the example simply while 
    # demoing how to only match HTTP requests and to access the HTTP headers as pre-created dict's instead of 
    # parsing the data as a string. 
    sniff(iface=args.interface, 
      promisc=False, 
      filter=args.filter, 
      lfilter=lambda x: x.haslayer(scapy_http.http.HTTPRequest), 
      prn=lambda pkt: pprint.pprint(pkt.getlayer(scapy_http.http.HTTPRequest).fields, indent=4), 
      count=args.count 
    )