|
1 | 1 | #!/usr/bin/env python
|
2 | 2 |
|
3 | 3 | import sys
|
4 |
| -from scapy.all import * |
| 4 | +from scapy.all import PcapReader, re, Raw, TCP |
5 | 5 |
|
6 | 6 |
|
7 |
| -if len(sys.argv) != 2: |
8 |
| - print ("I need an input file. Usage ./pcap2curl.py inputfilename") |
9 |
| - exit() |
| 7 | +VALID_METHODS = [ |
| 8 | + "GET", |
| 9 | + "HEAD", |
| 10 | + "POST", |
| 11 | + "PUT", |
| 12 | + "DELETE", |
| 13 | + "CONNECT", |
| 14 | + "OPTIONS", |
| 15 | + "TRACE", |
| 16 | + "PATCH" |
| 17 | +] # see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods |
10 | 18 |
|
11 |
| -infile = sys.argv[1] |
12 |
| - |
13 |
| -packets=rdpcap(infile) |
14 | 19 |
|
15 | 20 | def payload2curl(p):
|
16 |
| - lines=re.compile("[\n\r]+").split(p) |
17 |
| - startline=re.search('^([A-Z]+) ([^ ]+) (HTTP\/[0-9\/]+)',lines[0]) |
18 |
| - curl='curl '; |
19 |
| - method=startline.group(1) |
20 |
| - url=startline.group(2) |
21 |
| - version=startline.group(3) |
22 |
| - |
23 |
| - del lines[0] |
24 |
| - headers=[] |
25 |
| - for line in lines: |
26 |
| - if ":" in line: |
27 |
| - headers.append("-H '"+line+"'") |
28 |
| - if "Host:" in line: |
29 |
| - hostheader=re.search("^Host: (.*)",line) |
30 |
| - hostname=hostheader.group(1) |
31 |
| - |
32 |
| - if hostname not in url: |
33 |
| - url='http://'+hostname+'/'+url |
34 |
| - curl=curl+' '+"'"+url+"' \\\n" |
35 |
| - curl=curl+'-X'+method+" \\\n" |
36 |
| - curl=curl+" \\\n".join(headers) |
37 |
| - return curl |
38 |
| - |
39 |
| -for p in packets: |
40 |
| - payload='' |
41 |
| - if p.haslayer(TCP) and p.haslayer(Raw) and p[TCP].dport == 80: |
42 |
| - payload=p[Raw].load |
43 |
| - print (payload2curl(payload)) |
| 21 | + lines = re.compile("[\n\r]+").split(p.decode()) |
| 22 | + start_line = re.search("^([A-Z]+) ([^ ]+) (HTTP\/[0-9\/]+)", lines[0]) |
| 23 | + method = start_line.group(1) |
| 24 | + url = start_line.group(2) |
| 25 | + version = start_line.group(3) # Never used |
| 26 | + |
| 27 | + if method not in VALID_METHODS: |
| 28 | + return |
| 29 | + |
| 30 | + del lines[0] |
| 31 | + headers = [] |
| 32 | + for line in lines: |
| 33 | + if ":" in line: |
| 34 | + headers.append("-H '{}'".format(line)) |
| 35 | + if "Host:" in line: |
| 36 | + host_header = re.search("^Host: (.*)", line) |
| 37 | + host_name = host_header.group(1) |
| 38 | + |
| 39 | + proto_host = 'http://{}/'.format(host_name) |
| 40 | + if not url.startswith(proto_host): |
| 41 | + url = "{}{}".format(proto_host, url[1:] if url[0] == "/" else url) |
| 42 | + curl = "curl '{}' \\\n -X {} \\\n ".format(url, method) |
| 43 | + curl += " \\\n ".join(headers) |
| 44 | + return curl |
| 45 | + |
| 46 | + |
| 47 | +def main(): |
| 48 | + if len(sys.argv) != 2: |
| 49 | + print ("I need an input file. Usage ./pcap2curl.py inputfilename") |
| 50 | + return |
| 51 | + |
| 52 | + infile = sys.argv[1] |
| 53 | + |
| 54 | + with PcapReader(infile) as packets: |
| 55 | + for p in packets: |
| 56 | + if p.haslayer(TCP) and p.haslayer(Raw) and p[TCP].dport == 80: |
| 57 | + payload = p[Raw].load |
| 58 | + cmd = payload2curl(payload) |
| 59 | + if cmd: |
| 60 | + print(cmd) |
| 61 | + |
| 62 | + |
| 63 | +if __name__ == "__main__": |
| 64 | + main() |
0 commit comments