syn端口扫描的写法:
>>> ans, unans=sr(IP(src="172.31.100.222", dst="172.31.100.149")/TCP(sport=60000,dport=(1,1000),flags="S")) >>> ans.filter(lambda (s,r):r.sprintf("%TCP.flags%")=="SA").summary(lambda (s,r):r.sprintf("%TCP.sport% \tis open")) http is open 902 is open |
上面的脚本中的几个注意事项:
- flags="S"表示tcp的flags字段为SYN
- lambda (s,r)这里之所以两个变量是因为ans是一个由两个list组成的值,一个list是sent packets,一个是received packets,所以s和r分别遍历两个list
- sprintf字符串格式化方法,通过%TCP.flags%格式化得到flags的字符串值
也可以用summary或者nsummary加filter来输出结果:
>>> ans.summary(lfilter=lambda (s,r):r.sprintf("%TCP.flags%")=="SA") IP / TCP 172.31.100.222:60000 > 172.31.100.149:http S ==> IP / TCP 172.31.100.149:http > 172.31.100.222:60000 SA / Padding IP / TCP 172.31.100.222:60000 > 172.31.100.149:902 S ==> IP / TCP 172.31.100.149:902 > 172.31.100.222:60000 SA / Padding |
当然也可以使用make_table()方法来制一个表:
>>> filter(lambda (s,r):r.sprintf("%TCP.flags%")=="SA") Received 5272 packets, got 477 answers, remaining 1523 packets >>> ans.filter(lambda (s,r):r.sprintf("%TCP.flags%")=="SA").make_table(lambda (s,r):(s.dst,r.sport,"X")) 172.31.100.63 172.31.100.149 139 X - 445 X - 902 - X 912 - X >>> |
注:make_table的lambda表达式里面定义了一个row title(s.dst),一个col title(r.sport)和表格中的填充项“X”
此外,还有一个自带的方法report_ports()可以进行syn scan并反馈结果,结果的排版方式为LaTex格式:
>>> report_ports("139.219.196.160", (3300, 3400)) .........Begin emission: .......................****.*.******.*.*.*..*.*...*.*.*.*..*.*.*.**.*..**.*..*.**.*.**..**.***...*..****..**.**.*.*...**.**..*..**.**..*..*.**...**....*..*.***...*..***.*...***.*.*.....*.**.**Finished to send 101 packets. ..**..**.*..**....*...*..*..*..*.**.* Received 238 packets, got 101 answers, remaining 0 packets '\\begin{tabular}{|r|l|l|}\n\\hline\n3389 & open & SA \\\\\n\\hline\n3300 & closed & TCP RA \\\\\n3302 & closed & TCP RA \\\\\n3301 & closed & TCP RA \\\\\n3303 & closed & TCP RA \\\\\n3304 & closed & TCP RA \\\\\nmysql & closed & TCP RA \\\\\n3308 & closed & TCP RA \\\\\n3305 & closed & TCP RA \\\\\n3310 & closed & TCP RA \\\\\n3307 & closed & TCP RA \\\\\n3309 & closed & TCP RA \\\\\n3311 & closed & TCP RA \\\\\n3313 & closed & TCP RA \\\\\n3312 & closed & TCP RA \\\\\n3314 & closed & TCP RA \\\\\n3315 & closed & TCP RA \\\\\n3316 & closed & TCP RA \\\\\n3317 & closed & TCP RA \\\\\n3318 & closed & TCP RA \\\\\n3319 & closed & TCP RA \\\\\n3320 & closed & TCP RA \\\\\n3321 & closed & TCP RA \\\\\n3322 & closed & TCP RA \\\\\n3323 & closed & TCP RA \\\\\n3324 & closed & TCP RA \\\\\n3325 & closed & TCP RA \\\\\n3327 & closed & TCP RA \\\\\n3326 & closed & TCP RA \\\\\n3328 & closed & TCP RA \\\\\n3329 & closed & TCP RA \\\\\n3330 & closed & TCP RA \\\\\n3331 & closed & TCP RA \\\\\n3332 & closed & TCP RA…… |
对LaTex的结果再格式化一下:
>>> ans=report_ports("139.219.196.160", (3300, 3400)) >>> a = ans.split("\n") >>> for p in a: ... if ("open" in p): ... print "%s is open" % p[:p.find('&')-1] ... 3389 is open |
模拟TCP协议的traceroute(前4跳地址隐藏掉了):
>>> ans, unans=sr(IP(dst="139.219.196.160", ttl=(1,30), id=RandShort())/TCP(flags=0x02)) Begin emission: .*..*...*.*.**..*.*.....*.Finished to send 30 packets. ..........................................^C Received 68 packets, got 9 answers, remaining 21 packets >>> for s,r in ans: ... print s.ttl, r.src ... 1 ???.???.???.??? 2 ???.???.???.??? 3 ???.???.???.??? 4 ???.???.???.??? 5 59.43.77.1 6 172.30.1.17 7 180.149.129.158 8 180.149.129.158 9 139.219.196.160 |
补充一个TCP flags的定义:
#define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECNECHO 0x40 /* ECN Echo */ #define TH_CWR 0x80 /* ECN Cwnd Reduced */ |
使用wrpcap可以将报文写入cap文件中:
>>> ans, unans=sr(IP(dst="139.219.196.160", ttl=(1,30), id=RandShort())/TCP(flags=0x02)) wrpcap("/root/ans.cap", unans) |
几个转码的函数:
hexdump(pkt):用来将报文转码为16进制的转码
import_hexcap():用来将报文的16进制转码重新转为报文格式
>>> a <IP frag=0 proto=tcp dst=123.123.123.123 |<TCP sport=http |>> >>> hexdump(a) 0000 45 00 00 28 00 01 00 00 40 06 72 DB AC 1F 64 DE E..(....@.r...d. 0010 7B 7B 7B 7B 00 50 00 50 00 00 00 00 00 00 00 00 {{{{.P.P........ 0020 50 02 20 00 87 4E 00 00 P. ..N.. >>> b=Ether(import_hexcap()) 0000 45 00 00 28 00 01 00 00 40 06 72 DB AC 1F 64 DE E..(....@.r...d. 0010 7B 7B 7B 7B 00 50 00 50 00 00 00 00 00 00 00 00 {{{{.P.P........ 0020 50 02 20 00 87 4E 00 00 Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/lib/python2.7/dist-packages/scapy/utils.py", line 705, in import_hexcap l = raw_input().strip() KeyboardInterrupt >>> b <IP frag=0 proto=tcp dst=123.123.123.123 |<TCP sport=http |>> |
str():将报文转为16进制字符串
可以直接将转义后的字符串使用特定的layer转换回来
>>> a <IP frag=0 proto=tcp dst=123.123.123.123 |<TCP sport=http |>> >>> str(a) 'E\x00\x00(\x00\x01\x00\x00@\x06r\xdb\xac\x1fd\xde{{{{\x00P\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x87N\x00\x00' >>> IP(str(a)) <IP version=4L ihl=5L tos=0x0 len=40 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x72db src=172.31.100.222 dst=123.123.123.123 options=[] |<TCP sport=http dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x874e urgptr=0 |>> >>> Ether(str(a)) <Ether dst=45:00:00:28:00:01 src=00:00:40:06:72:db type=0xac1f |<Raw load='d\xde{{{{\x00P\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x87N\x00\x00' |>> -- Wrong format |
export_object():将报文转换为base64编码
import_object():将base64编码的报文内容转回普通报文格式