PageRenderTime 132ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 1ms

/src/pentest/wifitap/scapy.py

https://github.com/sullivanmatt/Raspberry-Pwn
Python | 11715 lines | 9687 code | 258 blank | 1770 comment | 454 complexity | 1b2f061e41fe70968da8169cdb376e4a MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, MPL-2.0-no-copyleft-exception, GPL-2.0, GPL-3.0
  1. #! /usr/bin/env python
  2. #############################################################################
  3. ## ##
  4. ## scapy.py --- Interactive packet manipulation tool ##
  5. ## see http://www.secdev.org/projects/scapy/ ##
  6. ## for more informations ##
  7. ## ##
  8. ## Copyright (C) 2003 Philippe Biondi <phil@secdev.org> ##
  9. ## ##
  10. ## This program is free software; you can redistribute it and/or modify it ##
  11. ## under the terms of the GNU General Public License version 2 as ##
  12. ## published by the Free Software Foundation; version 2. ##
  13. ## ##
  14. ## This program is distributed in the hope that it will be useful, but ##
  15. ## WITHOUT ANY WARRANTY; without even the implied warranty of ##
  16. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
  17. ## General Public License for more details. ##
  18. ## ##
  19. #############################################################################
  20. #
  21. # $Log: scapy.py,v $
  22. # Revision 1.0.4.74 2006/08/27 17:36:08 pbi
  23. # - tweaked make_*_table() to add horizontal separation lines
  24. #
  25. # Revision 1.0.4.73 2006/08/27 16:11:06 pbi
  26. # - added multiplot to plot many series from the same packet list. The function must returns
  27. # a couple whose first element is the label of a serie and the second is the data to plot.
  28. #
  29. # Revision 1.0.4.72 2006/08/27 15:13:36 pbi
  30. # - WARNING: API change. crc32() is now the zlib function.
  31. # crc32(0xffffffffL, s) --> ~crc32(z)&0xffffffffL
  32. #
  33. # Revision 1.0.4.71 2006/08/27 14:16:47 pbi
  34. # - fixed possible failures in DNS.summary()
  35. #
  36. # Revision 1.0.4.70 2006/08/27 14:11:38 pbi
  37. # - improved L3PacketSocket to build the list of interfaces only when needed (promisc=1)
  38. #
  39. # Revision 1.0.4.69 2006/08/27 14:10:05 pbi
  40. # - added gz parameter to PcapWriter (and thus wrpcap()) to gzip captures
  41. # - added abilty to read gzipped pcap files in PcapReader (and thus rdpcap())
  42. #
  43. # Revision 1.0.4.68 2006/08/27 13:59:20 pbi
  44. # - changed Net representation for it to work with Packet.command()
  45. #
  46. # Revision 1.0.4.67 2006/08/27 13:58:48 pbi
  47. # - added diffplot() to PacketList to plot a function of couples (l[i],l[i+delay])
  48. #
  49. # Revision 1.0.4.66 2006/08/27 12:52:13 pbi
  50. # - added prototype to psdump() and pdfdump() docstring
  51. #
  52. # Revision 1.0.4.65 2006/08/27 12:47:32 pbi
  53. # - have srloop() and srploop() return results of all probes
  54. #
  55. # Revision 1.0.4.64 2006/08/11 12:24:31 pbi
  56. # - patched getmacbyip() to handle IP multicast and return the right MAC multicast
  57. #
  58. # Revision 1.0.4.63 2006/08/11 12:13:45 pbi
  59. # - fixed lambda filtering in PacketList.plot()
  60. #
  61. # Revision 1.0.4.62 2006/08/11 12:12:51 pbi
  62. # - fixed reinstantiation of a PacketList as parameter to another PacketList
  63. #
  64. # Revision 1.0.4.61 2006/08/11 12:11:10 pbi
  65. # - added docstring to route.delt()
  66. #
  67. # Revision 1.0.4.60 2006/08/11 12:10:41 pbi
  68. # - fixed /proc/net/route parsing to handle reject routes
  69. #
  70. # Revision 1.0.4.59 2006/08/05 15:38:50 pbi
  71. # - added ActionField(): a wrapper to put arround a field that will trigger the call of a method
  72. # each time a value is manually set into a field
  73. #
  74. # Revision 1.0.4.58 2006/08/05 15:37:31 pbi
  75. # - fix: moved call to superclass' constructor in EnumField's constructor
  76. #
  77. # Revision 1.0.4.57 2006/07/28 21:57:19 pbi
  78. # - fixed get_if_hwaddr() exception catching in SourceMACField and ARPSourceMACField
  79. #
  80. # Revision 1.0.4.56 2006/07/28 17:24:39 pbi
  81. # - fixed typo in inet_pton
  82. #
  83. # Revision 1.0.4.55 2006/07/19 17:23:30 pbi
  84. # - fix: ls() look for Packet subclasses in both globals() and __builtin__
  85. #
  86. # Revision 1.0.4.54 2006/07/19 17:13:25 pbi
  87. # - forced _ special variable initisalization to None in autorun_commands()
  88. #
  89. # Revision 1.0.4.53 2006/07/17 17:35:48 pbi
  90. # - replaced getattr() by Packet.getfieldval() in FieldLenField.i2m()
  91. #
  92. # Revision 1.0.4.52 2006/07/17 17:28:20 pbi
  93. # - improved MACField.i2m()
  94. #
  95. # Revision 1.0.4.51 2006/07/17 17:27:40 pbi
  96. # - changed Packet.__iter__() to clone unrolled packets without transforming fields values through i2h() and h2i()
  97. #
  98. # Revision 1.0.4.50 2006/07/17 15:18:06 pbi
  99. # - added Packet.getfieldval() and NoPayload.getfieldval() to return the internal value of a field
  100. # - changed Packet.__getattr__() to use Packet.getfieldval()
  101. # - changed do_build, do_build_ps, guess_payload_class, __eq__, haslayer, getlayer to use Packet.getfieldval()
  102. #
  103. # Revision 1.0.4.49 2006/07/17 14:00:53 pbi
  104. # - fixed little endian fields for big endian machines (replaced @ by <)
  105. #
  106. # Revision 1.0.4.48 2006/07/17 13:43:04 pbi
  107. # - simplified PacketListField.addfield()
  108. #
  109. # Revision 1.0.4.47 2006/07/17 13:42:09 pbi
  110. # - simplified Dot11SCField.is_applicable()
  111. #
  112. # Revision 1.0.4.46 2006/07/17 13:40:55 pbi
  113. # - added __nonzero__() methods to Packet and Payload for the first to be true and the second
  114. # to be false without assembling the packet
  115. #
  116. # Revision 1.0.4.45 2006/07/17 13:37:19 pbi
  117. # - fixed Ether_Dot3_Dispatcher() to make it work with no arguments
  118. #
  119. # Revision 1.0.4.44 2006/07/13 09:52:57 pbi
  120. # - Fixed 3BytesField assembling (N. Bareil, ticket #6)
  121. #
  122. # Revision 1.0.4.43 2006/07/12 16:07:11 pbi
  123. # - fixed docstring of Packet.post_dissection()
  124. #
  125. # Revision 1.0.4.42 2006/07/12 13:36:01 pbi
  126. # - added Packet.from_hexcap() class method
  127. #
  128. # Revision 1.0.4.41 2006/07/12 13:35:37 pbi
  129. # - added a Packet.pre_dissect() hook
  130. #
  131. # Revision 1.0.4.40 2006/07/12 13:23:19 pbi
  132. # - Added a Ether/802.3 dispatcher for "Ethernet" linktype
  133. # - 802.1q use LLC payload if type < 1500
  134. # - enhanced Dot3.mysummary()
  135. #
  136. # Revision 1.0.4.39 2006/07/11 22:40:37 pbi
  137. # - fixed Dot11.answers() behaviour for management frames (L. Butti, ticket #5)
  138. #
  139. # Revision 1.0.4.38 2006/07/11 22:37:36 pbi
  140. # - fixed endianness of some 802.11 fields (L. Butti, ticket #3)
  141. #
  142. # Revision 1.0.4.37 2006/07/11 22:36:06 pbi
  143. # - removed SC field from 802.11 control frames (L. Butti, ticket #4)
  144. #
  145. # Revision 1.0.4.36 2006/07/11 22:10:01 pbi
  146. # - fixed TCPOptionsField to support SAck option (P. Lindholm, ticket #3)
  147. # - strengthened TCPOptionsField against bad options
  148. #
  149. # Revision 1.0.4.35 2006/07/11 21:57:37 pbi
  150. # - fix typo
  151. #
  152. # Revision 1.0.4.34 2006/06/23 17:35:43 pbi
  153. # - improved error message details for get_if_hwaddr()
  154. #
  155. # Revision 1.0.4.33 2006/06/23 17:33:38 pbi
  156. # - arping() function can update ARP cache if parameter cache=1 (D. Schuster, ticket #2)
  157. #
  158. # Revision 1.0.4.32 2006/06/23 16:27:44 pbi
  159. # - fixed: overloaded volatile fields were not fixed for sending
  160. #
  161. # Revision 1.0.4.31 2006/05/27 23:04:41 pbi
  162. # - fixed possible loop in TCP options
  163. #
  164. # Revision 1.0.4.30 2006/05/25 18:00:40 pbi
  165. # - added split_layers(), split_top_down() and split_bottom_up() to undo the
  166. # effects of bind_layers(), bind_top_down() and bind_bottom_up()
  167. #
  168. # Revision 1.0.4.29 2006/05/25 10:25:32 pbi
  169. # - added missing SPI field for ISAKMP_payload_Proposal
  170. #
  171. # Revision 1.0.4.28 2006/05/25 09:23:16 pbi
  172. # - almost reversed Field.h2i() removal patch (1.0.4.25) (changed my mind :))
  173. # - had Field.any2i() use Field.h2i()
  174. #
  175. # Revision 1.0.4.27 2006/05/24 21:15:22 pbi
  176. # - enhanced Packet.__getattr__ prettiness
  177. #
  178. # Revision 1.0.4.26 2006/05/24 20:50:47 pbi
  179. # - enhanced prettiness of DNSRRCountField
  180. #
  181. # Revision 1.0.4.25 2006/05/24 20:49:44 pbi
  182. # - removed h2i() methods from Field API
  183. #
  184. # Revision 1.0.4.24 2006/04/29 13:52:35 pbi
  185. # - added next_payload value overloading for ISAKMP layers
  186. #
  187. # Revision 1.0.4.23 2006/04/29 13:31:18 pbi
  188. # - removed forgotten debug prints..
  189. #
  190. # Revision 1.0.4.22 2006/04/29 13:20:30 pbi
  191. # - fixed ISAKMPTransformSetField
  192. # - fixed ISAKMP_payload_Transform length calculation
  193. #
  194. # Revision 1.0.4.21 2006/04/29 12:48:13 pbi
  195. # - WARNING: Field API changed. parameter shift must be now provided to the
  196. # length-varying field and not to the length field.
  197. # - added Field.i2len() method to return the length of a field (the number of
  198. # bytes in the raw packet string)
  199. #
  200. # Revision 1.0.4.20 2006/04/28 21:53:24 pbi
  201. # - fixed some problems with Packet.haslayer()/getlayer() for empty and list fields
  202. # - reduced Packet.haslayer()/getlayer() speed overhead to the same level as older versions
  203. #
  204. # Revision 1.0.4.19 2006/04/26 14:55:18 pbi
  205. # - fixed (again) filter attaching on linux/amd64 (W. Robinet)
  206. #
  207. # Revision 1.0.4.18 2006/04/26 12:55:29 pbi
  208. # - fixed Dot11WEP default icv value
  209. #
  210. # Revision 1.0.4.17 2006/04/26 12:55:01 pbi
  211. # - ATTENTION: API change: Packet.post_build() now takes current
  212. # assembled layer and assembled payload separately. Thus the
  213. # new prototype: post_build(self, pkt payload) -> pkt. post_build()
  214. # is in charge to join current layer and payload.
  215. # Old API will work for a small transition time.
  216. #
  217. # Revision 1.0.4.16 2006/04/25 15:23:49 pbi
  218. # - added internal _iterpacket parameter to SetGen to prevent iteration over Packet instances
  219. # - bugfix: prevented iteration over Packet instances in Packet.getlayer/haslayer/show()
  220. #
  221. # Revision 1.0.4.15 2006/04/24 12:27:35 pbi
  222. # - added NetFlow v1 protocol layer (M. Geli)
  223. #
  224. # Revision 1.0.4.14 2006/04/24 11:08:53 pbi
  225. # - big ISAKMPAttributeTypes update (W. McVey)
  226. # - changed ISAKMPTransformSetField to dissectTLV attributes (W. McVey)
  227. # - changed ISAKMPTransformSetField to assemble TLV attributes
  228. # - fixed ISAKMPTransformSetField to handle broken packets
  229. #
  230. # Revision 1.0.4.13 2006/04/23 21:12:08 pbi
  231. # - big p0f update (P. Lalet)
  232. #
  233. # Revision 1.0.4.12 2006/04/20 13:10:13 pbi
  234. # - fixed a bug with alias_type in Packet.guess_payload_class() when a field exists only
  235. # in the alias class
  236. #
  237. # Revision 1.0.4.11 2006/04/20 13:07:15 pbi
  238. # - enhanced LaTeXTheme2: used \bfseries and added colors to styles fail, success and even
  239. #
  240. # Revision 1.0.4.10 2006/04/20 09:13:49 pbi
  241. # - fixed SetGen to better test int couples for intervals
  242. #
  243. # Revision 1.0.4.9 2006/04/10 05:31:11 pbi
  244. # - use None value to specify timeout must be calculated in __sr_loop()
  245. #
  246. # Revision 1.0.4.8 2006/04/09 05:40:19 pbi
  247. # - added PacketListField.do_copy()
  248. # - modified fuzz() to handle PacketListField
  249. #
  250. # Revision 1.0.4.7 2006/04/08 16:05:24 pbi
  251. # - added PacketListField whose length come from another fiekd
  252. # - changed Packet.haslayer(), Packet.getlayer() and Packet.show() to handle PacketListField
  253. #
  254. # Revision 1.0.4.6 2006/04/02 14:49:28 pbi
  255. # - modified getlayer() to accept "LAYER.field" parameters to enable format strings' %
  256. # operator to work : "dst=%(IP.dst)s dport=%(TCP.dport)04i" % pkt
  257. #
  258. # Revision 1.0.4.5 2006/04/02 13:12:10 pbi
  259. # - added __mul__() and __rmul__() operators to handle multiplication with an int
  260. #
  261. # Revision 1.0.4.4 2006/03/27 13:32:50 pbi
  262. # - added missing fileno() to PcapReader and PcapWriter
  263. #
  264. # Revision 1.0.4.3 2006/03/22 12:59:35 pbi
  265. # - use binary mode to open files (Windows needs that...)
  266. #
  267. # Revision 1.0.4.2 2006/03/22 12:42:46 pbi
  268. # - replicated packet creation time when unrolling an implicit packet
  269. #
  270. # Revision 1.0.4.1 2006/03/17 12:48:28 pbi
  271. # Release 1.0.4
  272. #
  273. # Revision 1.0.3.34 2006/03/17 12:48:02 pbi
  274. # - added docstring for TracerouteResult.trace3D()
  275. #
  276. # Revision 1.0.3.33 2006/03/14 19:05:05 pbi
  277. # - added equality tests between two packets.
  278. #
  279. # Revision 1.0.3.32 2006/03/14 18:35:41 pbi
  280. # - added a timeout parameter to sniff()
  281. #
  282. # Revision 1.0.3.31 2006/03/14 17:48:30 pbi
  283. # - removed deprecated Packet.send()
  284. #
  285. # Revision 1.0.3.30 2006/03/14 17:46:03 pbi
  286. # - fix indentation quirk
  287. #
  288. # Revision 1.0.3.29 2006/03/14 15:12:59 pbi
  289. # - removed forgotten print in Packet.trace3D()
  290. #
  291. # Revision 1.0.3.28 2006/03/12 18:00:42 pbi
  292. # - made Packet.getlayer() and Packet.haslayer() also work with class names
  293. # - got rid of Packet.haslayer_str()
  294. #
  295. # Revision 1.0.3.27 2006/03/12 17:56:14 pbi
  296. # - improved Packet.getlayer(), Packet.haslayer() and Packet.haslayer_str()
  297. # to look into PacketFields.
  298. #
  299. # Revision 1.0.3.26 2006/03/09 22:25:00 pbi
  300. # - removed bad loop in L3PacketSocket and L2Socket when discarding outgoing packets (W. McVey)
  301. #
  302. # Revision 1.0.3.25 2006/03/09 22:15:38 pbi
  303. # - added Ctrl-Click to TracerouteResult.trace3D() to scan an IP
  304. #
  305. # Revision 1.0.3.24 2006/02/28 18:33:32 pbi
  306. # - added a "trans" parameter to colgen to handle automatic specific conversions into color object
  307. # - used colgen() in Packet.canvas_dump()
  308. #
  309. # Revision 1.0.3.23 2006/02/28 18:24:27 pbi
  310. # - removed makecol() from TracerouteResult.graph()
  311. #
  312. # Revision 1.0.3.22 2006/02/28 18:23:46 pbi
  313. # - turned makecol() TracerouteResult.graph()' internal function into colgen() generator tool
  314. #
  315. # Revision 1.0.3.21 2006/02/28 18:04:10 pbi
  316. # - added TracerouteResult.trace3D() to have a 3D traceroute visualization with VPython
  317. #
  318. # Revision 1.0.3.20 2006/02/27 18:03:46 pbi
  319. # - added get_trace() method to TraceouteResult() to extract traceroute data
  320. #
  321. # Revision 1.0.3.19 2006/02/27 15:13:36 pbi
  322. # - Fixed Dot11Beacon's fields' endianness (G. Lukas)
  323. #
  324. # Revision 1.0.3.18 2006/02/27 15:08:25 pbi
  325. # - factorised tex_escape() function from ps/pdfdump()
  326. # - added LatexTheme2 for autorun_get_latex_interactive_session()
  327. # - escape stuff in autorun_get_latex_interactive_session()
  328. #
  329. # Revision 1.0.3.17 2006/02/22 11:33:34 pbi
  330. # - added config.prog to reference external program pathes
  331. #
  332. # Revision 1.0.3.16 2006/02/22 11:19:26 pbi
  333. # - added afterglow clone attempt (http://sourceforge.net/projects/afterglow)
  334. #
  335. # Revision 1.0.3.15 2006/02/22 11:14:39 pbi
  336. # - added prog parameter to do_graph()
  337. #
  338. # Revision 1.0.3.15 2006/02/21 12:45:00 pbi
  339. # - added prog paramter to do_graph()
  340. #
  341. # Revision 1.0.3.14 2006/02/21 12:21:44 pbi
  342. # - removed hard dependancy on libreadline. Now works even if no libreadline is installed
  343. #
  344. # Revision 1.0.3.13 2006/02/19 14:06:28 pbi
  345. # - fixed show()'s indentation
  346. #
  347. # Revision 1.0.3.12 2006/02/19 13:49:18 pbi
  348. # - many docstrings corrections
  349. #
  350. # Revision 1.0.3.11 2006/02/17 16:29:38 pbi
  351. # - improved show() to use an exploded view for fields which hold packets
  352. # - added show_indent flag to Packet() that can be overloaded to 0 for layers that are followed by peers
  353. # and for whom indentation in show() is not desired
  354. #
  355. # Revision 1.0.3.10 2006/02/17 11:14:16 pbi
  356. # - changed conversation parameter to group getsrc/getdst into getsrcdst
  357. #
  358. # Revision 1.0.3.9 2006/02/17 10:57:53 pbi
  359. # - added docstrings for PacketList
  360. #
  361. # Revision 1.0.3.8 2006/02/16 15:45:51 pbi
  362. # - added docstrings to sr*(), wrpcap(), rdpcap()
  363. #
  364. # Revision 1.0.3.7 2006/02/16 15:37:44 pbi
  365. # - fixed conf.BTsocket assignment BluetoothSocket BluetoothL2CAPSocket
  366. #
  367. # Revision 1.0.3.6 2006/02/16 15:11:13 pbi
  368. # - added docstrings to many methods of Packet
  369. #
  370. # Revision 1.0.3.5 2006/02/16 14:09:07 pbi
  371. # - added BluetoothHCIsocket
  372. # - added L2socket to sniff
  373. # - added HCI_Hdr, L2CAP_Hdr layers, moved L2CAP to L2CAP_HdrCmd
  374. #
  375. # Revision 1.0.3.4 2006/02/12 01:06:52 pbi
  376. # - initialize payload's underlayer before payload's dissection
  377. #
  378. # Revision 1.0.3.3 2006/01/29 00:06:48 pbi
  379. # - added shortcut to PacketList to extract a given protocol with []. ex : lst[ICMP]
  380. #
  381. # Revision 1.0.3.2 2006/01/28 23:52:21 pbi
  382. # - removed useless (and racy) __del__() methods from PcapReader and PcapWriter
  383. #
  384. # Revision 1.0.3.1 2006/01/28 14:32:55 pbi
  385. # Release 1.0.3
  386. #
  387. # Revision 1.0.2.37 2006/01/28 13:14:25 pbi
  388. # - tweaked ls() for add-on classes to appear in the listing
  389. #
  390. # Revision 1.0.2.36 2006/01/28 13:02:15 pbi
  391. # - replaced remaining occurences of use of display() [deprecated, use show()]
  392. # - removed URL from dummy IPv6 classes names
  393. #
  394. # Revision 1.0.2.35 2006/01/17 18:02:42 pbi
  395. # - finished Packet.canvas_dup() escape() function. Every char is correctly translated into TeX
  396. #
  397. # Revision 1.0.2.34 2006/01/15 13:15:57 pbi
  398. # -added information-request and information-response to ICMP types (J. Bowie)
  399. #
  400. # Revision 1.0.2.33 2006/01/15 13:15:16 pbi
  401. # - fixed NetBIOSNameField incorrect length calculation (J. Bowie)
  402. #
  403. # Revision 1.0.2.32 2006/01/14 16:54:29 pbi
  404. # - added missing _IPv6optionHearder dummy class
  405. # - removed useless IPv6_instace() function
  406. #
  407. # Revision 1.0.2.31 2006/01/12 11:02:51 pbi
  408. # - fixed 1.0.2.29 collision fix (s/mtu/mtu_present/)
  409. #
  410. # Revision 1.0.2.30 2006/01/11 17:45:45 pbi
  411. # - fixed endianness problems in PcapReader()
  412. # - fixed PcapReader.read_all()
  413. # - added missing try/except to PcapReader.read_packet()
  414. # - removed PcapReader.read_PacketList() (read_all() already returns a PacketList)
  415. # - removed debug "print" from PcapWriter()
  416. # - added endianness parameter in PcapWriter()
  417. #
  418. # Revision 1.0.2.29 2006/01/11 17:00:01 pbi
  419. # - added Solaris support (wit help from S. Despret)
  420. # - added Solaris missing IPPROTO_GRE
  421. # - changed read_routes() to work with Solaris netstat
  422. # - fixed read_route() local variable collision (mtu became mtu_present)
  423. # - changed variable fl to flg
  424. #
  425. # Revision 1.0.2.28 2006/01/05 17:49:17 pbi
  426. # - re-added indentation in Packet.show(). Can be tweaked with "indent" parameter
  427. #
  428. # Revision 1.0.2.27 2006/01/04 15:04:17 pbi
  429. # - added missing try/except arround dissection in rdpcap()
  430. #
  431. # Revision 1.0.2.26 2005/12/23 00:51:51 pbi
  432. # - strengthened DNS disassembly
  433. #
  434. # Revision 1.0.2.25 2005/12/23 00:11:09 pbi
  435. # - have scapy work if Python IPv6 support is not compiled in socketmodule
  436. #
  437. # Revision 1.0.2.24 2005/12/23 00:08:50 pbi
  438. # - aliased socket.inet_ntoa into local namespace for consistency with other ?to?
  439. #
  440. # Revision 1.0.2.23 2005/12/22 17:58:08 pbi
  441. # - fixed and enhanced autorun_commands()
  442. #
  443. # Revision 1.0.2.22 2005/12/21 23:00:16 pbi
  444. # - fixed bug introduced by fix 1.0.2.19 on _
  445. #
  446. # Revision 1.0.2.21 2005/12/21 22:58:45 pbi
  447. # - added Packet.get_field() to get a field instance from its name
  448. # - modified some fields to use Packet.get_field() instead of a complex operation
  449. #
  450. # Revision 1.0.2.20 2005/12/19 12:43:52 pbi
  451. # - added FieldListField to create arrays of fields whose number is given in a FieldLenField
  452. #
  453. # Revision 1.0.2.19 2005/12/18 22:46:35 pbi
  454. # - fixed uninitialized _ in autorun_commands()
  455. #
  456. # Revision 1.0.2.18 2005/12/17 11:27:05 pbi
  457. # - Changed ColorTheme class be usable
  458. # - Added NoTheme class
  459. # - added autorun_get_text_interactive_session()
  460. # - added autorun_get_ansi_interactive_session()
  461. # - added autorun_get_latex_interactive_session() (miss some special chars filtering)
  462. #
  463. # Revision 1.0.2.17 2005/12/15 15:13:58 pbi
  464. # - IPv6 migration step 1: integrate some IPv6 routing stuff for IPv6 fork to work
  465. # as an add-on
  466. #
  467. # Revision 1.0.2.16 2005/12/07 18:02:26 pbi
  468. # - added fallbacks if tcpdump can't be run and libpcap is not used
  469. #
  470. # Revision 1.0.2.15 2005/12/07 17:44:11 pbi
  471. # - fixed socket filter pushing for x86_64 arch. (W. Robinet)
  472. #
  473. # Revision 1.0.2.14 2005/12/06 16:41:30 pbi
  474. # - added conf.check_TCPerror_seqack (default 0) to relax ICMP error matching for TCP
  475. # packets (some broken PIX play with sequence numbers and forget to tidy them up)
  476. #
  477. # Revision 1.0.2.13 2005/11/27 00:09:30 pbi
  478. # - added code to run interactive sessions automatically
  479. #
  480. # Revision 1.0.2.12 2005/11/26 11:33:55 pbi
  481. # - catch exceptions in ColorPrompt from bad color theme to avoid
  482. # program termination
  483. #
  484. # Revision 1.0.2.11 2005/11/26 11:10:44 pbi
  485. # - added class HTMLTheme2 with trigram instead of '<' and '>' to easily convert others into &lt; and &gt;
  486. #
  487. # Revision 1.0.2.10 2005/11/20 16:23:01 pbi
  488. # - improved a bit error handling of import dnet/pcap
  489. # - made INFO messages for missing files a bit more clear
  490. #
  491. # Revision 1.0.2.9 2005/11/19 08:39:09 pbi
  492. # - handle API change between pylibpcap 0.4 and 0.5
  493. #
  494. # Revision 1.0.2.8 2005/11/17 11:05:56 pbi
  495. # - changed Packet.sprintf() format string specificator to accept only the
  496. # field name and take the currend layer
  497. #
  498. # Revision 1.0.2.7 2005/11/17 10:24:53 pbi
  499. # - added onlyasc parameter to linehexdump()
  500. # - added onlyasc parameter to fragleak() and fragleak2()
  501. #
  502. # Revision 1.0.2.6 2005/11/15 04:55:11 pbi
  503. # - added Packet.command() to go from a packet instance to the Scapy command to generate it
  504. #
  505. # Revision 1.0.2.5 2005/11/15 03:04:51 pbi
  506. # - write history in an atexit registered function
  507. #
  508. # Revision 1.0.2.4 2005/11/15 02:58:44 pbi
  509. # - fixed Enum fields for them to work with lists of values
  510. #
  511. # Revision 1.0.2.3 2005/11/09 19:56:42 pbi
  512. # - added a ColorTheme.__repr__() to fix objects that used it, like conf object!
  513. #
  514. # Revision 1.0.2.2 2005/11/09 18:26:57 pbi
  515. # - fixed itom() to return positive values even for big endian platforms
  516. # - fixed RandIP default __init__ parameter to be 0.0.0.0/0 instead of 0/0
  517. #
  518. # Revision 1.0.2.1 2005/11/07 14:04:39 pbi
  519. # release 1.0.2
  520. #
  521. # Revision 1.0.1.13 2005/11/07 14:00:54 pbi
  522. # - fixed Dot11Auth.seqnum to be little endian
  523. # - added Dot11Auth.answers()
  524. #
  525. # Revision 1.0.1.12 2005/11/07 13:39:31 pbi
  526. # - fixed some stuff in the LaTeX color theme
  527. #
  528. # Revision 1.0.1.11 2005/11/07 13:38:36 pbi
  529. # - added timeout parameter to fragleak()
  530. # - created fragleak2()
  531. #
  532. # Revision 1.0.1.10 2005/11/07 13:37:20 pbi
  533. # - fixed LLC/SNAP binding to overload LLC.ctrl with 3
  534. #
  535. # Revision 1.0.1.9 2005/11/07 13:35:12 pbi
  536. # - changed Dot11.summary() to show src > dst
  537. # - added Dot11.answers()
  538. #
  539. # Revision 1.0.1.8 2005/11/07 13:33:43 pbi
  540. # - added DNS.answsers()
  541. #
  542. # Revision 1.0.1.7 2005/11/07 13:33:19 pbi
  543. # - added SignedIntField() and LESignedIntField
  544. # - converted PrismHeader's "signal" field to signed
  545. #
  546. # Revision 1.0.1.6 2005/11/01 12:22:02 pbi
  547. # - added hint_iface parameter to sendp()
  548. # - used hint_iface in arpcachepoison()
  549. #
  550. # Revision 1.0.1.5 2005/10/31 12:29:09 pbi
  551. # - added ConditionalField to wrap a field and apply a condition to its presense
  552. # - added NewDefaultValues metaclass to create new Packet classes from old ones
  553. # with new default default values
  554. # - added GRE protocol from rfc2784. (need more work for rfc1701)
  555. #
  556. # Revision 1.0.1.4 2005/10/27 15:12:32 pbi
  557. # - created VolatileValue class to handle volatile values like RandomField
  558. # - redesigned inheritence of random fields arround VolatileValue
  559. # - added DelayedEval() volatile value
  560. #
  561. # Revision 1.0.1.3 2005/10/27 14:59:11 pbi
  562. # - Changed color themes handling. Now LatexTheme and HTMLTheme are not ugly hacks anymore.
  563. #
  564. # Revision 1.0.1.2 2005/10/26 16:15:06 pbi
  565. # - added CharEnumField()
  566. # - declared s2i and i2s in EnumField before calling superclass' contructor
  567. #
  568. # Revision 1.0.1.1 2005/10/25 07:49:35 pbi
  569. # Release 1.0.1
  570. #
  571. # Revision 1.0.0.61 2005/10/25 07:48:48 pbi
  572. # - added rebuild option to Packet.p{s|df}dump() to dump a packet as-is
  573. #
  574. # Revision 1.0.0.60 2005/10/23 18:20:30 pbi
  575. # - PacketList.sr() return ( (matched couples), (unmatched packets) ) from the packet list
  576. #
  577. # Revision 1.0.0.59 2005/10/23 17:15:34 pbi
  578. # - added layer_shift option to every p{s|df}dump() method to explode hexa dump by layers
  579. #
  580. # Revision 1.0.0.58 2005/10/23 17:09:29 pbi
  581. # - return a loopback route when no default route is present. XXX: linux specific!
  582. #
  583. # Revision 1.0.0.57 2005/10/23 17:07:59 pbi
  584. # - split bind_layers() into bind_top_down() and bind_bottom_up()
  585. #
  586. # Revision 1.0.0.56 2005/10/23 16:57:26 pbi
  587. # - fixed dissection errors exception management when conf.debug_dissector is true
  588. #
  589. # Revision 1.0.0.55 2005/10/23 16:56:00 pbi
  590. # - made MACField's default value to be "00:00:00:00:00:00"
  591. # - fixed DestMACField's default value to be "ff:ff:ff:ff:ff:ff"
  592. #
  593. # Revision 1.0.0.54 2005/10/23 16:54:00 pbi
  594. # - fixed Field.randval() to work with string formats and modifiers
  595. # - fixed fuzz() not to overload default value if field's proposed randval is None
  596. #
  597. # Revision 1.0.0.53 2005/10/17 16:03:36 pbi
  598. # - uniformized to "lfilter" the paramter name for lambda expressions used as filters
  599. # - removed a superfluous line in crc32()
  600. #
  601. # Revision 1.0.0.52 2005/10/15 13:17:18 pbi
  602. # - AutoTime() and IntAutoTime() classes that give a field a time dependant value
  603. # - PacketList.timeskew_graph() should work on SndRcvList()
  604. #
  605. # Revision 1.0.0.51 2005/10/08 20:52:45 pbi
  606. # - added StreamSocket supersocket to emulate a datagram socket on a stream
  607. # socket that supports MSG_PEEK and whose base layer class knows its own size
  608. # and put the remaining in Padding()
  609. #
  610. # Revision 1.0.0.50 2005/10/08 12:46:56 pbi
  611. # - remove useless routes in netstat -rn output (P. Lalet)
  612. #
  613. # Revision 1.0.0.49 2005/10/08 12:41:23 pbi
  614. # - fixed netmask calculations (P. Lalet)
  615. #
  616. # Revision 1.0.0.48 2005/10/08 11:21:28 pbi
  617. # - use color for packet numbering in nsummary() et al.
  618. #
  619. # Revision 1.0.0.47 2005/10/06 12:57:25 pbi
  620. # - fixed MAC addresses calculation when IP is a Gen() instance (G. Valadon)
  621. #
  622. # Revision 1.0.0.46 2005/10/06 12:44:51 pbi
  623. # - added route.get_if_bcast() to get interface's broadcast address (F. Raynal)
  624. # - added a check in getmacbyip() to give a broadcast MAC for a broadcast IP
  625. # - added sndrcv() (thus sr*() family) "multi" parameter to accept many answers
  626. # from one stimulus. (If stimulus uses a broadcast dst address, you'll need
  627. # to set conf.checkIPaddr=0)
  628. #
  629. # Revision 1.0.0.45 2005/10/06 12:03:46 pbi
  630. # - changed sys.exit() into os._exit() in sndrcv() to prevent children to flush files buffers
  631. # that would be written a second time by the parent (SJ Murdoch)
  632. #
  633. # Revision 1.0.0.44 2005/10/06 11:44:48 pbi
  634. # - worked arround (I hope) all FreeBSD/MacOS/pcap issues (look at pcap_get_selectable_fd() note of pcap8 manpage).
  635. # Thus no more active waits or unseen packets. Still problems to interrupt a capture with ^C on some FreeBSD kernels :(
  636. #
  637. # Revision 1.0.0.43 2005/10/05 11:51:33 pbi
  638. # - added nofilter option to supersockets to handle ethertype filtering for non-linux stuff
  639. # and for ARP resolution to bypass conf.except_filter
  640. #
  641. # Revision 1.0.0.42 2005/10/05 11:28:14 pbi
  642. # - added RandMAC()
  643. # - added early support for fuzzing
  644. # - added fuzz()
  645. #
  646. # Revision 1.0.0.41 2005/10/05 11:14:57 pbi
  647. # - modified Packet.__iter__ to also evaluate random defaults fields
  648. #
  649. # Revision 1.0.0.40 2005/10/05 11:11:56 pbi
  650. # - filtered more characters for LaTeX in ps/pdf dump
  651. # - removed character that has magically appeared in DHCP_am
  652. #
  653. # Revision 1.0.0.39 2005/10/05 11:08:32 pbi
  654. # - fixed StrFixedLenField.addfield()
  655. #
  656. # Revision 1.0.0.38 2005/10/05 11:06:51 pbi
  657. # - overloaded RandFields repr() to give the class name
  658. # - added RandLong()
  659. # - added RandBin() to be RandString() for all chars
  660. # - added RandTermString()
  661. # - added RandIP default template to be "0/0"
  662. #
  663. # Revision 1.0.0.37 2005/10/05 11:01:20 pbi
  664. # - more tests in DHCP_am.make_reply() to handle garbage in
  665. #
  666. # Revision 1.0.0.36 2005/09/24 14:37:51 pbi
  667. # - added a "padding" option to TracerouteResult.graph() to show routers that pad
  668. #
  669. # Revision 1.0.0.35 2005/09/24 14:32:40 pbi
  670. # - added Packet.psdump() and Packet.pdfdump()
  671. # - added PacketList.psdump() and PacketList.pdfdump()
  672. #
  673. # Revision 1.0.0.34 2005/09/24 14:30:15 pbi
  674. # - ability to change the BPF filter in traceroute()
  675. #
  676. # Revision 1.0.0.33 2005/09/24 14:29:30 pbi
  677. # - completed PrismHeader layer
  678. #
  679. # Revision 1.0.0.32 2005/09/24 14:27:27 pbi
  680. # - deprecated "packet.haslayer(l)" by "l in Packet"
  681. # - deprecated "Packet.getlayer(l)" by "Packet[l]"
  682. #
  683. # Revision 1.0.0.31 2005/09/24 14:25:01 pbi
  684. # - better error message if gnuplot wrapper is missing
  685. # - fixed subclass test in dissection error treatment
  686. # - fixed Dot11Elt summary
  687. # - fixed __sr_loop() to prevent stats calc if no packet have been received
  688. # - fixed sniff() to break loop at the end of reading a file (offline optoin)
  689. #
  690. # Revision 1.0.0.30 2005/09/13 16:03:47 pbi
  691. # - added Dot11Elt.mysummary() for SSID displaying
  692. # - fixed Enum*.i2repr()
  693. #
  694. # Revision 1.0.0.29 2005/09/13 16:02:35 pbi
  695. # - fix build of packets with more than one padding
  696. #
  697. # Revision 1.0.0.28 2005/09/12 16:14:41 pbi
  698. # - new hexdump() which displays offsets
  699. #
  700. # Revision 1.0.0.27 2005/09/12 14:56:31 pbi
  701. # - new summary() and mysummary() semantic (backward compatible!) to enable more than one class to be expanded.
  702. # The higher gives its dependances along with its own summary
  703. #
  704. # Revision 1.0.0.26 2005/09/12 14:03:10 pbi
  705. # - added ip.dst in ICMP summary()
  706. #
  707. # Revision 1.0.0.25 2005/09/12 13:25:22 pbi
  708. # - added post_dissection() method, called at the end of the dissection, when the packet is ready
  709. # - added default_payload_class() called when layer bonds are not sufficient
  710. # - improved/fixed conf.debug_dissector() which failed when guess_payload_class() returned None
  711. #
  712. # Revision 1.0.0.24 2005/09/08 14:13:36 pbi
  713. # - added RandIP()
  714. #
  715. # Revision 1.0.0.23 2005/09/08 05:29:23 pbi
  716. # - added conf.debug_dissecto checks where it was missing in SuperSockets
  717. # - Slice pcap object only once we know its not None ! (N. Peterson)
  718. #
  719. # Revision 1.0.0.22 2005/09/06 17:08:47 pbi
  720. # - made AnsweringMachine() callable instead of using the run() method
  721. #
  722. # Revision 1.0.0.21 2005/09/06 17:05:19 pbi
  723. # - new logging/warning facility using the logging module
  724. #
  725. # Revision 1.0.0.20 2005/08/28 18:01:12 pbi
  726. # - 802.11 tweaks
  727. #
  728. # Revision 1.0.0.19 2005/08/28 18:00:14 pbi
  729. # - added Packet.decode_payload_as()
  730. #
  731. # Revision 1.0.0.18 2005/08/28 17:51:05 pbi
  732. # - Added XShortEnumField()
  733. #
  734. # Revision 1.0.0.17 2005/08/17 18:11:13 pbi
  735. # - fixed crc32() computation for big endian systems
  736. #
  737. # Revision 1.0.0.16 2005/08/17 12:54:47 pbi
  738. # - fix regression introduced in 1.0.0.4 (netstat parsing)
  739. #
  740. # Revision 1.0.0.15 2005/08/16 17:00:35 pbi
  741. # - fixed socket creation/attach filter race condition for L2Socket and L3PacketSocket.
  742. # No more packets shoud go through the filter.
  743. #
  744. # Revision 1.0.0.14 2005/08/16 16:58:59 pbi
  745. # - don't return outgoing packets in L2Socket and L3PacketSocket
  746. # - L2Socket and L3PacketSocket don't catch the exception if conf.dissector=1
  747. #
  748. # Revision 1.0.0.13 2005/08/16 16:56:09 pbi
  749. # - enhanced Packet.summary() code
  750. #
  751. # Revision 1.0.0.12 2005/08/16 16:53:31 pbi
  752. # - keep tcp/udp ports numeric in traceroute result
  753. #
  754. # Revision 1.0.0.11 2005/08/15 09:27:45 pbi
  755. # - added NTP.mysummary()
  756. #
  757. # Revision 1.0.0.10 2005/08/15 09:18:56 pbi
  758. # - fixed Ether.summary() (P. Lalet)
  759. #
  760. # Revision 1.0.0.9 2005/08/10 22:18:25 pbi
  761. # - moved code to build answering machines' functions into a metaclass
  762. #
  763. # Revision 1.0.0.8 2005/08/10 20:05:45 pbi
  764. # - added MobileIP protocol (rfc3344 and friends) (B. Andersson)
  765. #
  766. # Revision 1.0.0.7 2005/08/10 20:01:56 pbi
  767. # - changed Ether.mysummary() (P. Lalet)
  768. # - Update of Sebek protocols (P. Lalet)
  769. #
  770. # Revision 1.0.0.6 2005/08/10 19:53:19 pbi
  771. # - fix problem in declaraion of answering machine functions
  772. #
  773. # Revision 1.0.0.5 2005/08/10 15:43:03 pbi
  774. # - added resolution of numbers from /etc/ethertypes, /etc/protocols and
  775. # /etc/services (P. Lalet)
  776. # - tweaked some mysummary() accordingly
  777. #
  778. # Revision 1.0.0.4 2005/08/10 14:48:06 pbi
  779. # - Better netstat parsing for OpenBSD (P. Lalet)
  780. #
  781. # Revision 1.0.0.3 2005/08/10 14:41:21 pbi
  782. # - fixed regression introduced by previous patch : Gen and Packet are not
  783. # classes anymore but types.
  784. #
  785. # Revision 1.0.0.2 2005/08/09 21:40:57 pbi
  786. # - added ChangeDefaultValues metaclass to easily make a variant of a protocol
  787. #
  788. # Revision 1.0.0.1 2005/08/09 18:30:10 pbi
  789. # Release 1.0.0
  790. #
  791. # Revision 1.0 2005/08/09 18:26:09 pbi
  792. # 1.0 release
  793. #
  794. # Revision 0.9.17.110 2005/08/09 18:19:17 pbi
  795. # - nothing
  796. #
  797. # Revision 0.9.17.109 2005/08/08 13:57:16 pbi
  798. # - replaced use of __builtins__ by globals()
  799. # - promiscuous mode is now default mode
  800. # - added HTML color theme
  801. #
  802. # Revision 0.9.17.108 2005/08/05 14:12:48 pbi
  803. # - fix: IP fragmentation offset needs to be 0 for payload to be decoded
  804. # (actually fixed in 0.9.17.106)
  805. #
  806. # Revision 0.9.17.107 2005/08/05 14:04:03 pbi
  807. # - added 'filter' parameter to PacketList.padding()
  808. # - added PacketList.nzpadding() method
  809. # - added 'lfilter' parameter to sniff()
  810. #
  811. # Revision 0.9.17.106 2005/08/05 14:02:19 pbi
  812. # - removed scapy module reloading to prepare interactive mode
  813. # - tweaked interact() function, now fully functionnal
  814. #
  815. # Revision 0.9.17.105 2005/07/20 16:24:06 pbi
  816. # - small fix nmap database class
  817. #
  818. # Revision 0.9.17.104 2005/07/20 16:22:51 pbi
  819. # - modified Packet.guess_payload_class() semantic : added the payload as parameter
  820. # - fixed TCP.answers() to take in account length of payload
  821. # - added timeout arg to arping()
  822. #
  823. # Revision 0.9.17.103 2005/06/07 10:18:27 pbi
  824. # - added a try/catch for get_if_hw_addr
  825. # - fixed the netstat parsing for OpenBSD
  826. # - changed Dot11WEP's key ID field from "key" to "keyid"
  827. #
  828. # Revision 0.9.17.102 2005/06/07 09:54:51 pbi
  829. # - added LEShortEnumField
  830. # - added L2CAP layer
  831. # - added Bluetooth supersocket
  832. # - added srbt() and srbt1()
  833. #
  834. # Revision 0.9.17.101 2005/05/30 17:21:48 pbi
  835. # - Fixes for 0.9.17.100
  836. #
  837. # Revision 0.9.17.100 2005/05/30 17:08:41 pbi
  838. # - added NetBIOS, SMB & Co support (Sebastien Chenevot & Sylvain Sarmejeanne)
  839. #
  840. # Revision 0.9.17.99 2005/05/28 14:28:40 pbi
  841. # - WEP support and ICV computation
  842. #
  843. # Revision 0.9.17.98 2005/05/27 23:05:35 pbi
  844. # -fixed a smlal bug in graphic traceroute
  845. #
  846. # Revision 0.9.17.97 2005/05/27 19:53:04 pbi
  847. # - added WEP ciphering to Dot11WEP
  848. #
  849. # Revision 0.9.17.96 2005/05/25 15:15:10 pbi
  850. # - ability to give a WEP key as an argument to unwep()
  851. #
  852. # Revision 0.9.17.95 2005/05/25 15:05:03 pbi
  853. # - fixed pcap supersockets warnings
  854. #
  855. # Revision 0.9.17.94 2005/05/25 15:01:24 pbi
  856. # - fixed/cleaned ISAKMP
  857. #
  858. # Revision 0.9.17.93 2005/05/25 15:00:34 pbi
  859. # - fixed Packet.remove_underlayer() args
  860. # - fixed FieldLenField
  861. # - added Atheros Prism Header linktype
  862. #
  863. # Revision 0.9.17.92 2005/05/18 16:59:32 pbi
  864. # - some voip_play() stuff
  865. #
  866. # Revision 0.9.17.91 2005/05/18 16:59:01 pbi
  867. # - added BIOCIMMEDIATE option to fix BSD's BPF/pcap/select() behaviour issues
  868. # - made PCAP/DNET the default mode, even for Linux (it seems quicker)
  869. #
  870. # Revision 0.9.17.90 2005/05/18 16:57:07 pbi
  871. # - purge ARP cache when changing IP address of an interface
  872. # - fixed loopback interface detection get_if_raw_hwaddr() for dnet
  873. # - changed a bit Dot11PacketList behaviour
  874. # - fixed build() overload by EAP class
  875. # - fixed close()/recv() mix up in L2pcapListenSocket
  876. #
  877. # Revision 0.9.17.89 2005/05/03 19:18:22 pbi
  878. # - DNET/PCAP stuff reordering
  879. #
  880. # Revision 0.9.17.88 2005/05/03 00:10:12 pbi
  881. # - made Padding not be seen as a payload
  882. #
  883. # Revision 0.9.17.87 2005/04/29 22:37:39 pbi
  884. # - added L2 recognition for L2pcapListenSocket
  885. # - workarround for a bug in libpcap/wrapper?. .next() sometimes returns None
  886. # - added consistant get_if_addr() and get_if_raw_addr()
  887. # - added ifadd(), ifdel() and ifchange() methods to Route class
  888. #
  889. # Revision 0.9.17.86 2005/04/27 21:14:24 pbi
  890. # - small code cleaning
  891. #
  892. # Revision 0.9.17.85 2005/04/27 13:53:32 pbi
  893. # - early BSD port with libdnet and libpcap wrappers
  894. #
  895. # Revision 0.9.17.84 2005/04/24 14:57:45 pbi
  896. # - added a usable geolocation database from GeoIP.
  897. #
  898. # Revision 0.9.17.83 2005/04/24 10:34:57 pbi
  899. # - fixed fragment() (Peter Hardy)
  900. #
  901. # Revision 0.9.17.82 2005/04/23 15:29:21 pbi
  902. # - fixed sndrcv() when given an empty set of packets
  903. #
  904. # Revision 0.9.17.81 2005/04/23 13:55:32 pbi
  905. # - Some Sebek layers fixes (Pierre Lalet)
  906. #
  907. # Revision 0.9.17.80 2005/04/23 13:43:16 pbi
  908. # - Early IrDA support (Pierre Lalet)
  909. #
  910. # Revision 0.9.17.79 2005/04/23 13:42:34 pbi
  911. # - fixed SebekV1 and SebekV2 (Pierre Lalet)
  912. #
  913. # Revision 0.9.17.78 2005/04/23 13:41:33 pbi
  914. # - fixed BitField (Pierre Lalet)
  915. #
  916. # Revision 0.9.17.77 2005/04/23 13:36:15 pbi
  917. # - added threshold for warnings
  918. #
  919. # Revision 0.9.17.76 2005/04/23 11:27:51 pbi
  920. # - Renamed SndRcvAns into SndRcvList
  921. #
  922. # Revision 0.9.17.75 2005/04/23 11:26:12 pbi
  923. # - added color display in srloop()
  924. #
  925. # Revision 0.9.17.74 2005/04/22 13:30:10 pbi
  926. # - fixed dhcp_request()
  927. # - changed make_table semantic : take one lambda instead of 3
  928. # - fixed import_hexcap()
  929. # - fixed StrLenField
  930. # - changed traceroute() and arping() to also return unanswered packets
  931. # - ls() now sorts its output alphabetically
  932. # - LaTeX color theme for straight copy/paste into your doc.
  933. #
  934. # Revision 0.9.17.73 2005/04/15 15:56:08 pbi
  935. # - fixed ARP.answers()' return value
  936. # - made TracerouteResult.graph() use both ASN information source
  937. #
  938. # Revision 0.9.17.72 2005/04/09 22:25:23 pbi
  939. # - fix route.route() to handle extended IP sets (ex. 192.168.*.1-5)
  940. # - generalised statistics in packet lists
  941. # - added Dot11PacketList()
  942. # - added some DHCP options
  943. # - fixes in DHCP options building
  944. # - modified unwep() to decrypt a WEP packet if it was not already done
  945. #
  946. # Revision 0.9.17.71 2005/04/06 10:49:11 pbi
  947. # - forgotten debug msg in Net()
  948. #
  949. # Revision 0.9.17.70 2005/04/04 17:58:15 pbi
  950. # - modified Net() to recognize things like 172.16.*.1-10
  951. #
  952. # Revision 0.9.17.69 2005/04/04 14:24:00 pbi
  953. # - fix DHCP
  954. # - added dhcp_request()
  955. #
  956. # Revision 0.9.17.68 2005/03/28 22:18:04 pbi
  957. # - first attempt with time skew graphing
  958. #
  959. # Revision 0.9.17.67 2005/03/28 22:17:44 pbi
  960. # - use gzip compression for load_object/save_object
  961. # - made RandNum() and Emph() pickable
  962. # - changed prompt color in default color theme
  963. #
  964. # Revision 0.9.17.66 2005/03/28 14:30:01 pbi
  965. # - more DHCP work
  966. #
  967. # Revision 0.9.17.65 2005/03/28 14:29:03 pbi
  968. # - first attempt to generate libnet C code from a packet
  969. #
  970. # Revision 0.9.17.64 2005/03/28 14:28:20 pbi
  971. # - forgot to delete temporary variables in scapy's global scope
  972. #
  973. # Revision 0.9.17.63 2005/03/28 14:22:38 pbi
  974. # - added colors, color themes, colored prompt
  975. #
  976. # Revision 0.9.17.62 2005/03/24 16:19:33 pbi
  977. # - made it possible to use a PacketList as a parameter for send* or sr*
  978. #
  979. # Revision 0.9.17.61 2005/03/23 18:27:06 pbi
  980. # - used init_cookie for ISAKMP.answers()
  981. # - raised an exception in route.make_route if parameters are incomplete
  982. #
  983. # Revision 0.9.17.60 2005/03/23 17:07:56 pbi
  984. # - fixed session loading with -s
  985. # - prevented save_session() to trash current session
  986. # - changed AnsweringMachine to make send_reply() a bit more generic
  987. #
  988. # Revision 0.9.17.59 2005/03/22 16:52:44 pbi
  989. # - added _elt2show() to PacketList
  990. # - changed PacketList.show() to use _elt2show()
  991. #
  992. # Revision 0.9.17.58 2005/03/22 16:21:39 pbi
  993. # - added conversation() to PacketList
  994. # - added padding() to PacketList
  995. # - fixed StrNullField
  996. # - added haslayer_str() to Packet
  997. # - changed Packet.sprintf() to use haslayer_str
  998. # - changed answers() to ask payload if same class as other
  999. # - add count parameter to rdpcap
  1000. #
  1001. # Revision 0.9.17.57 2005/03/16 14:18:28 pbi
  1002. # - added StrNullField
  1003. #
  1004. # Revision 0.9.17.56 2005/03/14 18:14:28 pbi
  1005. # - LLNumTypes fix
  1006. # - Added linktype recognition to PcapWriter class
  1007. #
  1008. # Revision 0.9.17.55 2005/03/14 17:59:23 pbi
  1009. # - indentation cosmetic fix
  1010. #
  1011. # Revision 0.9.17.54 2005/03/14 17:53:56 pbi
  1012. # - wrpcap() now writes the correct linktype in the pcap file
  1013. #
  1014. # Revision 0.9.17.53 2005/03/14 17:22:23 pbi
  1015. # - added ISAKMP transforms decoding
  1016. #
  1017. # Revision 0.9.17.52 2005/03/14 16:40:58 pbi
  1018. # - added ikescan()
  1019. # - added ISAKMPTransformField
  1020. # - fixed PacketList's private methods names do begin only with one "_"
  1021. #
  1022. # Revision 0.9.17.51 2005/03/14 13:03:11 pbi
  1023. # - added a prn parameter to PacketList's summary() and nsummary()
  1024. #
  1025. # Revision 0.9.17.50 2005/03/14 12:56:24 pbi
  1026. # - make internal methods of PacketResult begins with __
  1027. #
  1028. # Revision 0.9.17.49 2005/03/14 12:52:41 pbi
  1029. # - Deprecated display() method (for all objects). Use show() instead.
  1030. #
  1031. # Revision 0.9.17.48 2005/03/14 12:48:29 pbi
  1032. # - Modified PacketField to stop at Padding instead of Raw
  1033. # - Added PacketLenField
  1034. # - More ISAKMP rework. Almost working.
  1035. #
  1036. # Revision 0.9.17.47 2005/03/14 10:20:49 pbi
  1037. # - added unwep() method to Dot11 packets
  1038. # - fixed 4 missing bytes in Dot11WEP
  1039. #
  1040. # Revision 0.9.17.46 2005/03/08 17:56:49 pbi
  1041. # - added a possibility to give a hint for srp() to choose the intended interface
  1042. # - added is_promisc() to find boxes in promisc mode (will not always work) (Javier Merino)
  1043. #
  1044. # Revision 0.9.17.45 2005/03/08 17:21:14 pbi
  1045. # - added PacketField
  1046. # - ISAKMP work
  1047. #
  1048. # Revision 0.9.17.44 2005/03/06 17:50:06 pbi
  1049. # - changed PCAP and DNET defaults
  1050. #
  1051. # Revision 0.9.17.43 2005/03/03 17:15:26 pbi
  1052. # - ISAKMP work
  1053. #
  1054. # Revision 0.9.17.42 2005/03/02 18:09:00 pbi
  1055. # - added make_world_trace() method to TracerouteResult for a xtraceroute-like
  1056. #
  1057. # Revision 0.9.17.41 2005/02/20 22:33:55 pbi
  1058. # - Sebek protocol definitions enhancements (Pierre Lalet)
  1059. #
  1060. # Revision 0.9.17.40 2005/02/20 22:31:49 pbi
  1061. # - added ARP answering machine (farpd) (Pierre Lalet)
  1062. #
  1063. # Revision 0.9.17.39 2005/02/20 22:22:23 pbi
  1064. # - Graphic traceroute enhanced to cope with TCP, UDP, ICMP or other traceroutes
  1065. # - ASN clustering in graphic traceroute can be controlled with the "ASN" parameter
  1066. #
  1067. # Revision 0.9.17.38 2005/02/18 21:03:26 pbi
  1068. # - MGCP early support
  1069. # - RandString()
  1070. #
  1071. # Revision 0.9.17.37 2005/02/10 22:33:13 pbi
  1072. # - export_object()/import_object() to copy/paste base64 gzipped pickled objects
  1073. # - prevent save_session from deleting unpicklable objects
  1074. # - added hexdump() and hexraw() methods to PacketList object
  1075. # - Raw packet answers any Raw packet
  1076. # - added conf.checkIPaddr to recognize broadcast replies (BOOTP/DHCP)
  1077. #
  1078. # Revision 0.9.17.36 2005/02/02 22:39:48 pbi
  1079. # - added GPRS dummy packet class
  1080. #
  1081. # Revision 0.9.17.35 2005/01/29 00:29:25 pbi
  1082. # - added l4 parameter to traceroute() for UDP, ICMP and other layer 4 traceroutes
  1083. # - tweaked TracerouteResult display()
  1084. #
  1085. # Revision 0.9.17.34 2005/01/26 23:43:19 pbi
  1086. # - removed some outdated functions
  1087. #
  1088. # Revision 0.9.17.33 2005/01/26 23:41:58 pbi
  1089. # - small simplification of TracerouteResult display() thanks to new sprintf()
  1090. # conditionnal statement
  1091. #
  1092. # Revision 0.9.17.32 2005/01/26 23:12:59 pbi
  1093. # - added conditionnal statements in format strings
  1094. #
  1095. # Revision 0.9.17.31 2005/01/26 22:30:36 pbi
  1096. # - removed an uneeded "else" in sprintf()
  1097. #
  1098. # Revision 0.9.17.30 2005/01/22 22:25:24 pbi
  1099. # - re-added node coloring lost code line in traceroute graphing code
  1100. #
  1101. # Revision 0.9.17.29 2005/01/22 21:48:55 pbi
  1102. # - fixed need for warning() before it was declared
  1103. #
  1104. # Revision 0.9.17.28 2005/01/22 21:47:11 pbi
  1105. # - added ARPingResult to handle arping() results
  1106. # - moved ARPing displaying logic to ARPing object
  1107. #
  1108. # Revision 0.9.17.27 2005/01/22 21:42:59 pbi
  1109. # - added args todo_graph()
  1110. # - added TracerouteResults object to handle traceroute results
  1111. # - moved traceroute displaying logic to TracerouteResult object
  1112. # - moved traceroute graphing logic to TracerouteResult object
  1113. #
  1114. # Revision 0.9.17.26 2005/01/20 22:59:07 pbi
  1115. # - graph_traceroute : added AS clustering, colors, tweaks
  1116. #
  1117. # Revision 0.9.17.25 2005/01/17 22:10:58 pbi
  1118. # - added do_graph() to draw GraphViz graphs using SVG output, displayed with ImageMagick
  1119. # - added graph_traceroute() to make a graph from multiple traceroutes
  1120. # - added timeout parameter to traceroute()
  1121. #
  1122. # Revision 0.9.17.24 2005/01/13 14:25:00 pbi
  1123. # - added Sebek v1 and v2 protocols (Pierre Lalet)
  1124. #
  1125. # Revision 0.9.17.23 2005/01/10 21:55:14 pbi
  1126. # - addded promisc and iface parameters to L3RawSocket
  1127. #
  1128. # Revision 0.9.17.22 2004/12/26 18:07:43 pbi
  1129. # - Improved PacketList with stability by addition and slicing
  1130. # - Added plot() to PacketList using Gnuplot
  1131. # - Added StrStopField
  1132. # - Added conf.debug_disssector to prevent dissector's exception from being catched
  1133. # - Added CookedLinux packet type
  1134. # - Show linktype number when it is unknown
  1135. #
  1136. # Revision 0.9.17.21 2004/12/26 16:04:57 pbi
  1137. # - removed strace in soxmix command line
  1138. # - DHCP support (from Mattias Wadman)
  1139. # - added missing make_table to PacketList class
  1140. # - have UDP class asks its payload for answers()
  1141. #
  1142. # Revision 0.9.17.20 2004/12/01 17:13:28 pbi
  1143. # - Early WEP support
  1144. # - voip_play() tweaks
  1145. # - Added LEShortField for Dot11 SC field
  1146. #
  1147. # Revision 0.9.17.19 2004/10/18 13:42:50 pbi
  1148. # - HSRP early support
  1149. # - Cisco CSSP Skinny early support
  1150. # - added Little Endian IntEnumField
  1151. # - added filter() method to PacketList
  1152. # - some voip_play() work
  1153. # - loop parameter value in send*() is used as the time to sleep between 2 loops
  1154. #
  1155. # Revision 0.9.17.18 2004/09/21 21:45:20 pbi
  1156. # - added recv() method to PcapReader to emulate a SuperSocket
  1157. # - added "offline" parameter to sniff() to use sniff on pcap files
  1158. # - removed voip_play_offline() and renamed voip_play_sniff() to voip_play()
  1159. # which is now available to play offline
  1160. #
  1161. # Revision 0.9.17.17 2004/09/21 21:32:41 pbi
  1162. # - added early PPPoE support (Ralf Ertzinger)
  1163. # - fixed DNS summary() to handle empty queries or answers
  1164. #
  1165. # Revision 0.9.17.16 2004/09/21 14:58:15 pbi
  1166. # - added VOIP playing functions (not tested)
  1167. #
  1168. # Revision 0.9.17.15 2004/09/17 22:00:47 pbi
  1169. # - transfert traceroute() and arping() options to sndrcv() ("retry", etc.)
  1170. # - fixed retry option in sndrcv()
  1171. # - tweaked AnweringMachine class
  1172. # - rewrited airpwn to use AnsweringMachine
  1173. #
  1174. # Revision 0.9.17.14 2004/09/13 16:57:01 pbi
  1175. # - added loopback routing
  1176. #
  1177. # Revision 0.9.17.13 2004/09/12 21:44:45 pbi
  1178. # - AnsweringMachine working as I wanted!
  1179. #
  1180. # Revision 0.9.17.12 2004/09/10 16:54:46 pbi
  1181. # - AnsweringMachine twaking
  1182. # - added DNS spoofing answering machine
  1183. #
  1184. # Revision 0.9.17.11 2004/09/08 13:42:38 pbi
  1185. # - renamed ScapyPcapWriter class to PcapWriter
  1186. # - added linktype parameter to PcapWriter (William McVey)
  1187. # - added PcapReader class (William McVey)
  1188. #
  1189. # Revision 0.9.17.10 2004/09/08 13:06:01 pbi
  1190. # - added some text correspondances to Radius code field
  1191. #
  1192. # Revision 0.9.17.9 2004/09/06 14:28:02 pbi
  1193. # - early radius support
  1194. #
  1195. # Revision 0.9.17.8 2004/09/06 14:17:11 pbi
  1196. # - added "store" parameter to sniff()
  1197. # - added AnsweringMachine class to handle request/response protocols
  1198. # - replaced bootpd by a AnsweringMachine subclass
  1199. # - created DHCP answering machine draft
  1200. #
  1201. # Revision 0.9.17.7 2004/09/03 22:11:35 pbi
  1202. # - finished airpwn()
  1203. #
  1204. # Revision 0.9.17.6 2004/08/13 16:49:51 pbi
  1205. # - added first version of airpwn() clone
  1206. #
  1207. # Revision 0.9.17.5 2004/08/11 15:25:08 pbi
  1208. # - added RIP protocol
  1209. #
  1210. # Revision 0.9.17.4 2004/08/09 14:00:20 pbi
  1211. # - added gzip support to sessions saving
  1212. # - can force pickle protocol to inferior values for pickle backward compatility
  1213. #
  1214. # Revision 0.9.17.3 2004/08/07 10:59:34 pbi
  1215. # - fixed self reloading when launched from a different directory
  1216. # - fixed session reloading problems with PacketList() and SndRcvAns()
  1217. # - added load_session(), save_session(), update_session()
  1218. #
  1219. # Revision 0.9.17.2 2004/07/28 21:16:12 pbi
  1220. # - added nsummary() method to SndRcvList() class
  1221. #
  1222. # Revision 0.9.17.1 2004/07/26 19:52:55 pbi
  1223. # Release 0.9.17
  1224. #
  1225. # Revision 0.9.16.18 2004/07/26 19:50:16 pbi
  1226. # - added ScapyPcapWriter class (William McVey)
  1227. #
  1228. # Revision 0.9.16.17 2004/07/26 19:24:48 pbi
  1229. # - do not need to be named 'scapy.py' anymore
  1230. # - use of PacketList() for rdpcap() and sniff()
  1231. # - fixed a bug in StrFixedLenField
  1232. # - early IKE and ISAKMP support
  1233. #
  1234. # Revision 0.9.16.16 2004/07/16 15:39:37 pbi
  1235. # - small fix on bootpd
  1236. #
  1237. # Revision 0.9.16.15 2004/07/10 13:13:25 pbi
  1238. # - finished testing ethertype in supersockets to decide wether or not to apply BPF filters
  1239. #
  1240. # Revision 0.9.16.14 2004/07/10 13:06:38 pbi
  1241. # - do not apply any BPF filter if ethertype is given to a supersocket (so that ARP requests will work
  1242. # whatever the conf.except_filter value is)
  1243. #
  1244. # Revision 0.9.16.13 2004/07/09 09:11:15 pbi
  1245. # - changed the header and blocked the licence to GPLv2 only
  1246. #
  1247. # Revision 0.9.16.12 2004/07/09 09:07:41 pbi
  1248. # - added an independant routing table (conf.route) and methods to manipulate it
  1249. # - tweaked results stats
  1250. #
  1251. # Revision 0.9.16.11 2004/07/05 22:43:49 pbi
  1252. # - wrapper classes for results presentations and manipulation
  1253. # - sndrcv() retry auto adjustment when giving a negative value
  1254. #
  1255. # Revision 0.9.16.10 2004/07/05 08:53:41 pbi
  1256. # - added retry option to sndrcv()
  1257. # - improved debug class
  1258. # - added ottl() and hops() methods for IPTools class
  1259. # - improved UDP and ICMP summary()
  1260. #
  1261. # Revision 0.9.16.9 2004/06/07 16:09:21 pbi
  1262. # - fix again TCP.answers() and TCPerror.answers()
  1263. #
  1264. # Revision 0.9.16.8 2004/06/07 16:06:27 pbi
  1265. # - fixed conf.checkIPsrc behaviour of answers() and hashret() for TCP/UDP/TCPerror/UDPerror
  1266. # - added conf.debug_match to keep track of unanswered packets in debug.sent and debug.recv
  1267. #
  1268. # Revision 0.9.16.7 2004/06/07 09:20:43 pbi
  1269. # - added LEIntField and StrFixedLenField
  1270. # - added partial PrismHeader support
  1271. #
  1272. # Revision 0.9.16.6 2004/04/29 15:46:19 pbi
  1273. # - fixed fragment()
  1274. #
  1275. # Revision 0.9.16.5 2004/03/31 09:24:43 pbi
  1276. # - fix nmap fingerprint db parsing to handle the new format (Jochen Bartl)
  1277. #
  1278. # Revision 0.9.16.4 2004/03/23 08:45:10 pbi
  1279. # - Support for reading big endian pcap files (Pekka Pietikainen)
  1280. #
  1281. # Revision 0.9.16.3 2004/02/28 11:12:12 pbi
  1282. # - got rid of some future warnings (N. Bareil <nbareil@mouarf.org>)
  1283. # - improved BitField() for arbitrary length bit fields (N. Bareil <nbareil@mouarf.org>)
  1284. # - NTP protocol (N. Bareil <nbareil@mouarf.org>)
  1285. #
  1286. # Revision 0.9.16.2 2004/02/22 17:49:51 pbi
  1287. # added first sketch of a bootp daemon: bootpd()
  1288. #
  1289. # Revision 0.9.16.1 2004/01/26 18:01:00 pbi
  1290. # Release 0.9.16
  1291. #
  1292. # Revision 0.9.15.15 2004/01/26 18:00:08 pbi
  1293. # - added more text for DNS codes
  1294. #
  1295. # Revision 0.9.15.14 2004/01/15 13:24:48 pbi
  1296. # - fixed the case where IP field is a list of nets
  1297. # - randomize IPID in traceroute() to work better with conf.checkIPsrc=0
  1298. # - added make_tex_table() and make_lined_table()
  1299. # - added IPID_count() to identify machines with their IPID
  1300. # - added sport and dport args to fragleak()
  1301. #
  1302. # Revision 0.9.15.13 2004/01/11 11:47:07 pbi
  1303. # - srploop() and srloop() improvements
  1304. #
  1305. # Revision 0.9.15.12 2004/01/11 01:28:21 pbi
  1306. # - srloop() and srploop() improvements
  1307. #
  1308. # Revision 0.9.15.11 2004/01/11 01:07:05 pbi
  1309. # - srloop() and srploop() improvements
  1310. #
  1311. # Revision 0.9.15.10 2004/01/10 23:42:58 pbi
  1312. # - added srloop() and srploop() functions
  1313. #
  1314. # Revision 0.9.15.9 2004/01/10 23:40:51 pbi
  1315. # - added
  1316. #
  1317. # Revision 0.9.15.8 2004/01/09 16:42:42 pbi
  1318. # - improved send() and sendp() with parameters loop and verbose
  1319. #
  1320. # Revision 0.9.15.7 2004/01/09 16:04:07 pbi
  1321. # - fixed ARP opcodes values
  1322. #
  1323. # Revision 0.9.15.6 2004/01/09 15:53:46 pbi
  1324. # - added RARP and IARP req/resp description in ARP operation Enum field
  1325. #
  1326. # Revision 0.9.15.5 2003/12/19 15:54:30 pbi
  1327. # - added checkIPID and checkIPsrc options in conf to recognize IP in ICMP errors from broken IP stacks (see conf.__doc__)
  1328. # - changed default TCP source port to 20 (Muahahahah!)
  1329. # - tweaked TCP summary
  1330. # - changed default UDP source and destination ports to 53
  1331. # - created import_hexcap() to copy-paste an hexcap from tcpdump -xX, and get a string to feed IP() or ARP() or whatever
  1332. # - created make_table() to present results in a table from a list, and functions that map the list to x,y and z=f(x,y).
  1333. #
  1334. # Revision 0.9.15.4 2003/10/30 16:11:41 pbi
  1335. # - little enhancements to the DNS packets
  1336. # - added dyndns_add() and dyndns_del() (rfc2136)
  1337. # - fixed a format string error (3 times)
  1338. #
  1339. # Revision 0.9.15.3 2003/10/16 10:41:42 biondi
  1340. # - redesign summary() method
  1341. # - fixed Dot11 addresses fields
  1342. #
  1343. # Revision 0.9.15.2 2003/10/15 14:41:09 biondi
  1344. # - caching format size (calcsize()) in Field main class
  1345. # - allow first packet desassembly to fail in SuperSockets, falling back to Raw
  1346. #
  1347. # Revision 0.9.15.1 2003/10/02 15:24:29 pbi
  1348. # Release 0.9.15
  1349. #
  1350. # Revision 0.9.14.8 2003/10/02 15:16:26 pbi
  1351. # - small fix for p0f_base
  1352. # - lazy loading for p0f, queso and nmap knowledge databases
  1353. #
  1354. # Revision 0.9.14.7 2003/10/02 14:14:17 pbi
  1355. # - added a LongField
  1356. # - added classes and bonds for 802.11
  1357. # - added error handling and magic checks for rdpcap()
  1358. #
  1359. # Revision 0.9.14.6 2003/09/12 14:45:35 pbi
  1360. # - had Dot11 working
  1361. #
  1362. # Revision 0.9.14.5 2003/09/12 10:04:05 pbi
  1363. # - added summary() method to Packet objects
  1364. #
  1365. # Revision 0.9.14.4 2003/09/12 09:28:28 pbi
  1366. # - added SNAP protocol
  1367. # - catched broken pipe exception when shild die in sndrcv()
  1368. # - fixed default L2socket type in srp() and srp1() (ETH_P_ALL)
  1369. # - fixed format string in attach_filter()
  1370. #
  1371. # Revision 0.9.14.3 2003/09/10 08:47:41 pbi
  1372. # - fixed the fact that bpf filters were generated in cooked mode, and thus did
  1373. # not work
  1374. # - filter on socket type ETH_P_ARP instead of using a bpf filter for ARP replies
  1375. # - fixed the way of handling the SuperSocket close.
  1376. # - uniformised the naming for interface parameter : iface instead of iff
  1377. # - fixed the FutureWarning for long integers
  1378. # - fixed a typo in 3 format strings (%*i instead of %i)
  1379. #
  1380. # Revision 0.9.14.2 2003/07/20 00:12:04 pbi
  1381. # -added "-i any" for tcpdump to compile filters even if they don't work on main interface
  1382. # - put PPP special case before layer 2 general case in a super socket
  1383. # - added th filter parameter to L3RawSocket
  1384. # - added a special case in getmacbyip() when loopback interface is concernet
  1385. # - added value for RAWIP linktype in pcap capture files
  1386. #
  1387. # Revision 0.9.14.1 2003/06/25 13:18:23 pbi
  1388. # Release 0.9.14, from 0.9.13.4
  1389. #
  1390. # Revision 0.9.13.4 2003/06/25 12:35:57 pbi
  1391. # - fixed a regression in L3PacketSocket for ppp links
  1392. #
  1393. # Revision 0.9.13.3 2003/05/31 14:01:12 biondi
  1394. # - more tweaks on Packet.sprintf(). Added __doc__.
  1395. #
  1396. # Revision 0.9.13.2 2003/05/31 13:17:42 biondi
  1397. # - small tweaks in Packet.sprintf()
  1398. #
  1399. # Revision 0.9.13.1 2003/05/16 13:34:30 pbi
  1400. # Release 0.9.13
  1401. #
  1402. # Revision 0.9.12.9 2003/05/16 13:32:38 pbi
  1403. # - fixed verbose parameter in nmap_fp()
  1404. #
  1405. # Revision 0.9.12.8 2003/05/16 13:28:49 pbi
  1406. # - small enhancements in self-documentation
  1407. # - added early experiemental support for BOOTP and 802.11
  1408. #
  1409. # Revision 0.9.12.7 2003/05/16 11:25:48 pbi
  1410. # - added workarroung python bug 643005 (socket.inet_aton("255.255.255.255"))
  1411. # - use answers() method instead of operator
  1412. # - added hashret() method : returns a hash that is invariant for a packet and its reply
  1413. # - use hashret() in sndrcv() for dramatic improvements for matching replies on big set of packets
  1414. # - change report_ports() to return a string instead of printing
  1415. #
  1416. # Revision 0.9.12.6 2003/05/16 09:28:40 pbi
  1417. # - improved the __repr__() method of Packet class
  1418. #
  1419. # Revision 0.9.12.5 2003/05/12 15:15:02 pbi
  1420. # - added minttl parameter to traceroute()
  1421. #
  1422. # Revision 0.9.12.4 2003/05/06 13:39:21 pbi
  1423. # - Improved random number object (thanks to O. Poyen)
  1424. #
  1425. # Revision 0.9.12.3 2003/05/06 10:45:27 pbi
  1426. # - fixed a name overlap on "type" in L2ListenSocket and L3PacketSocket (thanks to E. M. Hopper)
  1427. #
  1428. # Revision 0.9.12.2 2003/05/06 10:41:58 pbi
  1429. # - externalized conversion from probes to signature with nmap_probes2sig() use probe results from, say, a pcap file
  1430. #
  1431. # Revision 0.9.12.1 2003/04/27 10:07:30 pbi
  1432. # Release 0.9.12
  1433. #
  1434. # Revision 0.9.11.5 2003/04/27 10:04:03 pbi
  1435. # - Fixed long int conversion in attach_filter()
  1436. #
  1437. # Revision 0.9.11.4 2003/04/27 10:00:57 pbi
  1438. # - rectification in SetGen to unroll Gen instances in lists
  1439. # - Completed DNS types and qtypes names
  1440. # - Small tuning in nmap_match_one_sig()
  1441. # - Parallelized nmap_sig()
  1442. #
  1443. # Revision 0.9.11.3 2003/04/24 12:47:49 pbi
  1444. # - removed 4 byte IP string autorecognition. Never used and broken for 4 byte names
  1445. # - added "islist" flag to fields to distinguish a list value from a list of values
  1446. # - changed TCP options from dict to list to preserve order and redundancy
  1447. # - added conf.except_filter, to have every command ignore your own traffic (BPF filter)
  1448. # - worked in progress for nmap OS fingerprint. Added PU test. Fixed other tests.
  1449. # - added nmap_sig2txt() to transform a signature to its text form, suitable for nmap base
  1450. #
  1451. # Revision 0.9.11.2 2003/04/23 21:23:30 pbi
  1452. # - small fixes in init_queso()
  1453. # - experimental support of nmap fingerprinting (not complete yet)
  1454. #
  1455. # Revision 0.9.11.1 2003/04/22 14:38:16 pbi
  1456. # Release 0.9.11
  1457. #
  1458. # Revision 0.9.10.8 2003/04/22 14:37:32 pbi
  1459. # - fixed bug in getmacbyip() using dnet module
  1460. # - deactivated getmacbyip() using dnet module because it did not resolve unknown IPs
  1461. # - added some commands listed by lsc()
  1462. #
  1463. # Revision 0.9.10.7 2003/04/22 13:55:01 pbi
  1464. # - some getattr/setattr/delattr enhancements
  1465. #
  1466. # Revision 0.9.10.6 2003/04/22 13:52:00 pbi
  1467. # - added experimental support for QueSO OS fingerprinting. Has someone a *recent* database ?
  1468. #
  1469. # Revision 0.9.10.5 2003/04/18 17:45:15 pbi
  1470. # - improved the completer to complete with protocol fields
  1471. # - small fix in get_working_if()
  1472. #
  1473. # Revision 0.9.10.4 2003/04/16 14:53:36 pbi
  1474. # - added option to include padding or not
  1475. #
  1476. # Revision 0.9.10.3 2003/04/16 14:35:32 pbi
  1477. # - added L2dnetSocket()
  1478. # - improved arping()
  1479. #
  1480. # Revision 0.9.10.2 2003/04/16 12:40:40 pbi
  1481. # - fixed the case when the history file does not exist
  1482. #
  1483. # Revision 0.9.10.1 2003/04/14 15:43:45 pbi
  1484. # Release 0.9.10
  1485. #
  1486. # Revision 0.9.9.15 2003/04/14 15:42:47 pbi
  1487. # - added L3pcapListenSocket
  1488. # - fixed L3ListenSocket to use ETH_P_ALL instead of ETH_P_IP by default
  1489. #
  1490. # Revision 0.9.9.14 2003/04/14 14:57:53 pbi
  1491. # - reworked L3dnetSocket
  1492. #
  1493. # Revision 0.9.9.13 2003/04/14 13:53:28 pbi
  1494. # - added completion (rlcompleter) and history support
  1495. #
  1496. # Revision 0.9.9.12 2003/04/14 10:05:42 pbi
  1497. # - bugfixed the close() method of some supersockets
  1498. #
  1499. # Revision 0.9.9.11 2003/04/13 21:41:01 biondi
  1500. # - added get_working_if()
  1501. # - use get_working_if() for default interface
  1502. #
  1503. # Revision 0.9.9.10 2003/04/12 23:33:42 biondi
  1504. # - add DNS layer (do not compress when assemble, answers() is missing)
  1505. #
  1506. # Revision 0.9.9.9 2003/04/12 22:15:40 biondi
  1507. # - added EnumField
  1508. # - used EnumField for ARP(), ICMP(), IP(), EAPOL(), EAP(),...
  1509. #
  1510. # Revision 0.9.9.8 2003/04/11 16:52:29 pbi
  1511. # - better integration of libpcap and libdnet, if available
  1512. #
  1513. # Revision 0.9.9.7 2003/04/11 15:49:31 pbi
  1514. # - some tweaks about supersockets close() and __del__() (not satisfied)
  1515. # - added L3dnetSocket, that use libdnet and libpcap if available
  1516. #
  1517. # Revision 0.9.9.6 2003/04/11 13:46:49 pbi
  1518. # - fixed a regression in bitfield dissection
  1519. # - tweaked and fixed a lot of small things arround supersockets
  1520. #
  1521. # Revision 0.9.9.5 2003/04/10 14:50:22 pbi
  1522. # - clean session only if it is to be saved
  1523. # - forgot to give its name to Padding class
  1524. # - fixed the NoPayload comparison tests so that they work on reloaded sessions
  1525. #
  1526. # Revision 0.9.9.4 2003/04/10 13:45:22 pbi
  1527. # - Prepared the configuration of L2/L3 supersockets
  1528. #
  1529. # Revision 0.9.9.3 2003/04/08 18:34:48 pbi
  1530. # - little fix in L2ListenSocket.__del__()
  1531. # - added doc and options in Conf class
  1532. # - added promisc support for L3PacketSocket, so that you can get answers to spoofed packets
  1533. #
  1534. # Revision 0.9.9.2 2003/04/08 17:42:19 pbi
  1535. # - added extract_padding() method to UDP
  1536. #
  1537. # Revision 0.9.9.1 2003/04/08 17:23:33 pbi
  1538. # Release 0.9.9
  1539. #
  1540. # Revision 0.9.8.9 2003/04/08 17:22:25 pbi
  1541. # - use cPickle instead of pickle (quicker and works with __getattr__() recursion)
  1542. # - small fixes on send() and sendp()
  1543. #
  1544. # Revision 0.9.8.8 2003/04/08 16:48:04 pbi
  1545. # - EAPOL overload Ether dst with PAE_GROUP_ADDR
  1546. # - tuning in ports_report()
  1547. # - tuning in fragleak
  1548. #
  1549. # Revision 0.9.8.7 2003/04/07 15:32:10 pbi
  1550. # - uses /usr/bin/env invocation
  1551. #
  1552. # Revision 0.9.8.6 2003/04/07 14:57:12 pbi
  1553. # - catch error during payload dissection and consider payload as raw data
  1554. #
  1555. # Revision 0.9.8.5 2003/04/07 14:43:13 pbi
  1556. # - srp() becomes srp1() and sr() equivalent for L2 is called srp()
  1557. # - hastype() Packet methods renamed to haslayer()
  1558. # - added getlayer() Packet method
  1559. # - added padding detection for layers that have a length field
  1560. # - added fragment() that fragment an IP packet
  1561. # - added report_ports() to scan a machine and output LaTeX report
  1562. #
  1563. # Revision 0.9.8.4 2003/04/01 11:19:06 pbi
  1564. # - added FlagsField(), used for TCP and IP
  1565. # - rfc3514 compliance
  1566. #
  1567. # Revision 0.9.8.3 2003/03/28 14:55:18 pbi
  1568. # Added pkt2uptime() : uses TCP timestamp to predict when the machine was booted
  1569. #
  1570. # Revision 0.9.8.2 2003/03/27 15:58:54 pbi
  1571. # - fixed sprintf() regression to use attributes from a packet that are not fields (eg: payload)
  1572. #
  1573. # Revision 0.9.8.1 2003/03/27 15:43:20 pbi
  1574. # Release 0.9.8
  1575. #
  1576. # Revision 0.9.7.9 2003/03/27 15:07:42 pbi
  1577. # - add filter support for sr(), sr1() and srp()
  1578. # - use filters for getmacbyip() and traceroute() for better reliability under heavy load
  1579. #
  1580. # Revision 0.9.7.8 2003/03/27 14:45:11 pbi
  1581. # - better timeout management in sndrcv
  1582. # - bugfixed sys.exit() imbrication issues
  1583. # - some self documentation
  1584. # - added lsc()command
  1585. #
  1586. # Revision 0.9.7.7 2003/03/26 17:51:33 pbi
  1587. # - Added IPTool class, to add commands like whois() to IP layer.
  1588. # - Have unknown class attributes be asked to payload before raising an exception.
  1589. #
  1590. # Revision 0.9.7.6 2003/03/26 17:35:36 pbi
  1591. # More powerful sprintf format string : %[fmt[r],][cls[:nb].]field% where fmt is a classic one, r can be
  1592. # appended for raw substitution (ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want
  1593. # (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer). Special case : "%.time" is the creation time.
  1594. # Ex : p.sprintf("%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% %03xr,IP.proto% %r,TCP.flags%")
  1595. #
  1596. # Revision 0.9.7.5 2003/03/26 14:47:39 pbi
  1597. # Added creation time packet. Supported by read/write pcap.
  1598. #
  1599. # Revision 0.9.7.4 2003/03/26 14:25:09 pbi
  1600. # Added the NoPayload terminal class
  1601. #
  1602. # Revision 0.9.7.3 2003/03/26 13:31:11 pbi
  1603. # Fixed RCS Id
  1604. #
  1605. # Revision 0.9.7.2 2003/03/26 13:30:05 pbi
  1606. # Adding RCS Id
  1607. #
  1608. #
  1609. from __future__ import generators
  1610. RCSID="$Id: scapy.py,v 1.0.4.74 2006/08/27 17:36:08 pbi Exp $"
  1611. VERSION = RCSID.split()[2]+"beta"
  1612. def usage():
  1613. print "Usage: scapy.py [-s sessionfile]"
  1614. sys.exit(0)
  1615. ##########[XXX]#=--
  1616. ##
  1617. # Next things to do :
  1618. #
  1619. # - fields to manage variable length hw addr (ARP, BOOTP, etc.)
  1620. # - improve pcap capture file support
  1621. # - better self-doc
  1622. #
  1623. ##
  1624. ##########[XXX]#=--
  1625. #############################
  1626. ##### Logging subsystem #####
  1627. #############################
  1628. import logging,traceback,time
  1629. class ScapyFreqFilter(logging.Filter):
  1630. def __init__(self):
  1631. logging.Filter.__init__(self)
  1632. self.warning_table = {}
  1633. def filter(self, record):
  1634. wt = conf.warning_threshold
  1635. if wt > 0:
  1636. stk = traceback.extract_stack(limit=1)
  1637. caller = stk[0][1]
  1638. tm,nb = self.warning_table.get(caller, (0,0))
  1639. ltm = time.time()
  1640. if ltm-tm > wt:
  1641. tm = ltm
  1642. nb = 0
  1643. else:
  1644. if nb < 2:
  1645. nb += 1
  1646. if nb == 2:
  1647. record.msg = "more "+record.msg
  1648. else:
  1649. return 0
  1650. self.warning_table[caller] = (tm,nb)
  1651. return 1
  1652. log_scapy = logging.getLogger("scapy")
  1653. console_handler = logging.StreamHandler()
  1654. console_handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
  1655. log_scapy.addHandler(console_handler)
  1656. log_runtime = logging.getLogger("scapy.runtime") # logs at runtime
  1657. log_runtime.addFilter(ScapyFreqFilter())
  1658. log_interactive = logging.getLogger("scapy.interactive") # logs in interactive functions
  1659. log_loading = logging.getLogger("scapy.loading") # logs when loading scapy
  1660. if __name__ == "__main__":
  1661. log_scapy.setLevel(1)
  1662. ##################
  1663. ##### Module #####
  1664. ##################
  1665. import socket, sys, getopt, string, struct, random, os, code
  1666. import cPickle, copy, types, gzip, base64, re, zlib
  1667. from select import select
  1668. from fcntl import ioctl
  1669. import fcntl
  1670. try:
  1671. import Gnuplot
  1672. GNUPLOT=1
  1673. except ImportError:
  1674. log_loading.info("did not find python gnuplot wrapper . Won't be able to plot")
  1675. GNUPLOT=0
  1676. try:
  1677. import pyx
  1678. PYX=1
  1679. except ImportError:
  1680. log_loading.info("Can't import PyX. Won't be able to use psdump() or pdfdump()")
  1681. PYX=0
  1682. LINUX=sys.platform.startswith("linux")
  1683. OPENBSD=sys.platform.startswith("openbsd")
  1684. FREEBSD=sys.platform.startswith("freebsd")
  1685. DARWIN=sys.platform.startswith("darwin")
  1686. BIG_ENDIAN= struct.pack("H",1) == "\x00\x01"
  1687. X86_64 = (os.uname()[4] == 'x86_64')
  1688. SOLARIS=sys.platform.startswith("sunos")
  1689. if LINUX:
  1690. DNET=PCAP=0
  1691. else:
  1692. DNET=PCAP=1
  1693. if PCAP:
  1694. try:
  1695. import pcap
  1696. PCAP = 1
  1697. except ImportError:
  1698. if LINUX:
  1699. log_loading.warning("did not find pcap module. Fallback to linux primitives")
  1700. PCAP = 0
  1701. else:
  1702. if __name__ == "__main__":
  1703. log_loading.error("did not find pcap module")
  1704. raise SystemExit
  1705. else:
  1706. raise
  1707. if DNET:
  1708. try:
  1709. import dnet
  1710. DNET = 1
  1711. except ImportError:
  1712. if LINUX:
  1713. log_loading.warning("did not find dnet module. Fallback to linux primitives")
  1714. DNET = 0
  1715. else:
  1716. if __name__ == "__main__":
  1717. log_loading.error("did not find dnet module")
  1718. raise SystemExit
  1719. else:
  1720. raise
  1721. if not PCAP:
  1722. f = os.popen("tcpdump -V 2> /dev/null")
  1723. if f.close() >> 8 == 0x7f:
  1724. log_loading.warning("Failed to execute tcpdump. Check it is installed and in the PATH")
  1725. TCPDUMP=0
  1726. else:
  1727. TCPDUMP=1
  1728. try:
  1729. from Crypto.Cipher import ARC4
  1730. except ImportError:
  1731. log_loading.info("Can't find Crypto python lib. Won't be able to decrypt WEP")
  1732. # Workarround bug 643005 : https://sourceforge.net/tracker/?func=detail&atid=105470&aid=643005&group_id=5470
  1733. try:
  1734. socket.inet_aton("255.255.255.255")
  1735. except socket.error:
  1736. def inet_aton(x):
  1737. if x == "255.255.255.255":
  1738. return "\xff"*4
  1739. else:
  1740. return socket.inet_aton(x)
  1741. else:
  1742. inet_aton = socket.inet_aton
  1743. inet_ntoa = socket.inet_ntoa
  1744. try:
  1745. inet_ntop = socket.inet_ntop
  1746. inet_pton = socket.inet_pton
  1747. except AttributeError:
  1748. log_loading.info("inet_ntop/pton functions not found. Python IPv6 support not present")
  1749. if SOLARIS:
  1750. # GRE is missing on Solaris
  1751. socket.IPPROTO_GRE = 47
  1752. ############
  1753. ## Consts ##
  1754. ############
  1755. ETHER_ANY = "\x00"*6
  1756. ETHER_BROADCAST = "\xff"*6
  1757. ETH_P_ALL = 3
  1758. ETH_P_IP = 0x800
  1759. ETH_P_ARP = 0x806
  1760. # From net/if_arp.h
  1761. ARPHDR_ETHER = 1
  1762. ARPHDR_METRICOM = 23
  1763. ARPHDR_PPP = 512
  1764. ARPHDR_LOOPBACK = 772
  1765. # From bits/ioctls.h
  1766. SIOCGIFHWADDR = 0x8927 # Get hardware address
  1767. SIOCGIFADDR = 0x8915 # get PA address
  1768. SIOCGIFNETMASK = 0x891b # get network PA mask
  1769. SIOCGIFNAME = 0x8910 # get iface name
  1770. SIOCSIFLINK = 0x8911 # set iface channel
  1771. SIOCGIFCONF = 0x8912 # get iface list
  1772. SIOCGIFFLAGS = 0x8913 # get flags
  1773. SIOCSIFFLAGS = 0x8914 # set flags
  1774. SIOCGIFINDEX = 0x8933 # name -> if_index mapping
  1775. SIOCGIFCOUNT = 0x8938 # get number of devices
  1776. # From if.h
  1777. IFF_UP = 0x1 # Interface is up.
  1778. IFF_BROADCAST = 0x2 # Broadcast address valid.
  1779. IFF_DEBUG = 0x4 # Turn on debugging.
  1780. IFF_LOOPBACK = 0x8 # Is a loopback net.
  1781. IFF_POINTOPOINT = 0x10 # Interface is point-to-point link.
  1782. IFF_NOTRAILERS = 0x20 # Avoid use of trailers.
  1783. IFF_RUNNING = 0x40 # Resources allocated.
  1784. IFF_NOARP = 0x80 # No address resolution protocol.
  1785. IFF_PROMISC = 0x100 # Receive all packets.
  1786. # From netpacket/packet.h
  1787. PACKET_ADD_MEMBERSHIP = 1
  1788. PACKET_DROP_MEMBERSHIP = 2
  1789. PACKET_RECV_OUTPUT = 3
  1790. PACKET_RX_RING = 5
  1791. PACKET_STATISTICS = 6
  1792. PACKET_MR_MULTICAST = 0
  1793. PACKET_MR_PROMISC = 1
  1794. PACKET_MR_ALLMULTI = 2
  1795. # From bits/socket.h
  1796. SOL_PACKET = 263
  1797. # From asm/socket.h
  1798. SO_ATTACH_FILTER = 26
  1799. SOL_SOCKET = 1
  1800. # From net/route.h
  1801. RTF_UP = 0x0001 # Route usable
  1802. RTF_REJECT = 0x0200
  1803. # From BSD net/bpf.h
  1804. #BIOCIMMEDIATE=0x80044270
  1805. BIOCIMMEDIATE=-2147204496
  1806. MTU = 1600
  1807. # file parsing to get some values :
  1808. spaces = re.compile("[ \t]+|\n")
  1809. IP_PROTOS={}
  1810. try:
  1811. f=open("/etc/protocols")
  1812. for l in f:
  1813. try:
  1814. if l[0] in ["#","\n"]:
  1815. continue
  1816. lt = tuple(re.split(spaces, l))
  1817. if len(lt) < 3:
  1818. continue
  1819. IP_PROTOS.update({lt[2]:int(lt[1])})
  1820. except:
  1821. log_loading.info("Couldn't parse one line from protocols file (" + l + ")")
  1822. f.close()
  1823. except IOError:
  1824. log_loading.info("Can't open /etc/protocols file")
  1825. ETHER_TYPES={}
  1826. try:
  1827. f=open("/etc/ethertypes")
  1828. for l in f:
  1829. try:
  1830. if l[0] in ["#","\n"]:
  1831. continue
  1832. lt = tuple(re.split(spaces, l))
  1833. if len(lt) < 2:
  1834. continue
  1835. ETHER_TYPES.update({lt[0]:int(lt[1], 16)})
  1836. except:
  1837. log_loading.info("Couldn't parse one line from ethertypes file (" + l + ")")
  1838. f.close()
  1839. except IOError,msg:
  1840. log_loading.info("Can't open /etc/ethertypes file")
  1841. TCP_SERVICES={}
  1842. UDP_SERVICES={}
  1843. try:
  1844. f=open("/etc/services")
  1845. for l in f:
  1846. try:
  1847. if l[0] in ["#","\n"]:
  1848. continue
  1849. lt = tuple(re.split(spaces, l))
  1850. if len(lt) < 2:
  1851. continue
  1852. if lt[1].endswith("/tcp"):
  1853. TCP_SERVICES.update({lt[0]:int(lt[1].split('/')[0])})
  1854. elif lt[1].endswith("/udp"):
  1855. UDP_SERVICES.update({lt[0]:int(lt[1].split('/')[0])})
  1856. except:
  1857. log_loading.warning("Couldn't parse one line from /etc/services file (" + l + ")")
  1858. f.close()
  1859. except IOError:
  1860. log_loading.info("Can't open /etc/services file")
  1861. ###########
  1862. ## Tools ##
  1863. ###########
  1864. def sane(x):
  1865. r=""
  1866. for i in x:
  1867. j = ord(i)
  1868. if (j < 32) or (j >= 127):
  1869. r=r+conf.color_theme.not_printable(".")
  1870. else:
  1871. r=r+i
  1872. return r
  1873. def hexdump(x):
  1874. x=str(x)
  1875. l = len(x)
  1876. i = 0
  1877. while i < l:
  1878. print "%04x " % i,
  1879. for j in range(16):
  1880. if i+j < l:
  1881. print "%02X" % ord(x[i+j]),
  1882. else:
  1883. print " ",
  1884. if j%16 == 7:
  1885. print "",
  1886. print " ",
  1887. print sane(x[i:i+16])
  1888. i += 16
  1889. def linehexdump(x, onlyasc=0):
  1890. x = str(x)
  1891. l = len(x)
  1892. if not onlyasc:
  1893. for i in range(l):
  1894. print "%02X" % ord(x[i]),
  1895. print "",
  1896. print sane(x)
  1897. if BIG_ENDIAN:
  1898. CRCPOLY=0x04c11db7L
  1899. else:
  1900. CRCPOLY=0xedb88320L
  1901. crc32 = zlib.crc32
  1902. def checksum(pkt):
  1903. pkt=str(pkt)
  1904. s=0
  1905. if len(pkt) % 2 == 1:
  1906. pkt += "\0"
  1907. for i in range(len(pkt)/2):
  1908. s = s + (struct.unpack("!H",pkt[2*i:2*i+2])[0])
  1909. s = (s >> 16) + (s & 0xffff)
  1910. s += s >> 16
  1911. return ~s & 0xffff
  1912. def warning(x):
  1913. log_runtime.warning(x)
  1914. def mac2str(mac):
  1915. return "".join(map(lambda x: chr(int(x,16)), mac.split(":")))
  1916. def str2mac(s):
  1917. return ("%02x:"*6)[:-1] % tuple(map(ord, s))
  1918. def strxor(x,y):
  1919. return "".join(map(lambda x,y:chr(ord(x)^ord(y)),x,y))
  1920. def atol(x):
  1921. try:
  1922. ip = inet_aton(x)
  1923. except socket.error:
  1924. ip = inet_aton(socket.gethostbyname(x))
  1925. return struct.unpack("I", ip)[0]
  1926. def ltoa(x):
  1927. return inet_ntoa(struct.pack("I", x))
  1928. def itom(x):
  1929. return socket.ntohl((0xffffffff00000000L>>x)&0xffffffffL)&0xffffffffL
  1930. def do_graph(graph,prog=None,type="svg",target=None):
  1931. """do_graph(graph, prog=conf.prog.dot, type="svg",target="| conf.prog.display"):
  1932. graph: GraphViz graph description
  1933. type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
  1934. target: filename or redirect. Defaults pipe to Imagemagick's display program
  1935. prog: which graphviz program to use"""
  1936. if prog is None:
  1937. prog = conf.prog.dot
  1938. if target is None:
  1939. target = "| %s" % conf.prog.display
  1940. w,r = os.popen2("%s -T %s %s" % (prog,type,target))
  1941. w.write(graph)
  1942. w.close()
  1943. _TEX_TR = {
  1944. "{":"{\\tt\\char123}",
  1945. "}":"{\\tt\\char125}",
  1946. "\\":"{\\tt\\char92}",
  1947. "^":"\\^{}",
  1948. "$":"\\$",
  1949. "#":"\\#",
  1950. "~":"\\~",
  1951. "_":"\\_",
  1952. "&":"\\&",
  1953. "%":"\\%",
  1954. "|":"{\\tt\\char124}",
  1955. "~":"{\\tt\\char126}",
  1956. "<":"{\\tt\\char60}",
  1957. ">":"{\\tt\\char62}",
  1958. }
  1959. def tex_escape(x):
  1960. s = ""
  1961. for c in x:
  1962. s += _TEX_TR.get(c,c)
  1963. return s
  1964. def colgen(*lstcol,**kargs):
  1965. """Returns a generator that mixes provided quantities forever
  1966. trans: a function to convert the three arguments into a color. lambda x,y,z:(x,y,z) by default"""
  1967. if len(lstcol) < 2:
  1968. lstcol *= 2
  1969. trans = kargs.get("trans", lambda x,y,z: (x,y,z))
  1970. while 1:
  1971. for i in range(len(lstcol)):
  1972. for j in range(len(lstcol)):
  1973. for k in range(len(lstcol)):
  1974. if i != j or j != k or k != i:
  1975. yield trans(lstcol[(i+j)%len(lstcol)],lstcol[(j+k)%len(lstcol)],lstcol[(k+i)%len(lstcol)])
  1976. ##############################
  1977. ## Session saving/restoring ##
  1978. ##############################
  1979. def save_session(fname, session=None, pickleProto=-1):
  1980. if session is None:
  1981. session = scapy_session
  1982. to_be_saved = session.copy()
  1983. if to_be_saved.has_key("__builtins__"):
  1984. del(to_be_saved["__builtins__"])
  1985. for k in to_be_saved.keys():
  1986. if type(to_be_saved[k]) in [types.TypeType, types.ClassType, types.ModuleType]:
  1987. log_interactive.error("[%s] (%s) can't be saved." % (k, type(to_be_saved[k])))
  1988. del(to_be_saved[k])
  1989. try:
  1990. os.rename(fname, fname+".bak")
  1991. except OSError:
  1992. pass
  1993. f=gzip.open(fname,"wb")
  1994. cPickle.dump(to_be_saved, f, pickleProto)
  1995. f.close()
  1996. def load_session(fname):
  1997. try:
  1998. s = cPickle.load(gzip.open(fname,"rb"))
  1999. except IOError:
  2000. s = cPickle.load(open(fname,"rb"))
  2001. scapy_session.clear()
  2002. scapy_session.update(s)
  2003. def update_session(fname):
  2004. try:
  2005. s = cPickle.load(gzip.open(fname,"rb"))
  2006. except IOError:
  2007. s = cPickle.load(open(fname,"rb"))
  2008. scapy_session.update(s)
  2009. def export_object(obj):
  2010. print base64.encodestring(gzip.zlib.compress(cPickle.dumps(obj,2),9))
  2011. def import_object(obj=None):
  2012. if obj is None:
  2013. obj = sys.stdin.read()
  2014. return cPickle.loads(gzip.zlib.decompress(base64.decodestring(obj.strip())))
  2015. def save_object(fname, obj):
  2016. cPickle.dump(obj,gzip.open(fname,"wb"))
  2017. def load_object(fname):
  2018. return cPickle.load(gzip.open(fname,"rb"))
  2019. #################
  2020. ## Debug class ##
  2021. #################
  2022. class debug:
  2023. recv=[]
  2024. sent=[]
  2025. match=[]
  2026. ####################
  2027. ## IP Tools class ##
  2028. ####################
  2029. class IPTools:
  2030. """Add more powers to a class that have a "src" attribute."""
  2031. def whois(self):
  2032. os.system("whois %s" % self.src)
  2033. def ottl(self):
  2034. t = [32,64,128,255]+[self.ttl]
  2035. t.sort()
  2036. return t[t.index(self.ttl)+1]
  2037. def hops(self):
  2038. return self.ottl()-self.ttl-1
  2039. ##############################
  2040. ## Routing/Interfaces stuff ##
  2041. ##############################
  2042. class Route:
  2043. def __init__(self):
  2044. self.resync()
  2045. self.s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  2046. def resync(self):
  2047. self.routes = read_routes()
  2048. def __repr__(self):
  2049. rt = "Network Netmask Gateway Iface Output IP\n"
  2050. for net,msk,gw,iface,addr in self.routes:
  2051. rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net),
  2052. ltoa(msk),
  2053. gw,
  2054. iface,
  2055. addr)
  2056. return rt
  2057. def make_route(self, host=None, net=None, gw=None, dev=None):
  2058. if host is not None:
  2059. thenet,msk = host,32
  2060. elif net is not None:
  2061. thenet,msk = net.split("/")
  2062. msk = int(msk)
  2063. else:
  2064. raise Exception("make_route: Incorrect parameters. You should specify a host or a net")
  2065. if gw is None:
  2066. gw="0.0.0.0"
  2067. if dev is None:
  2068. if gw:
  2069. nhop = gw
  2070. else:
  2071. nhop = thenet
  2072. dev,ifaddr,x = self.route(nhop)
  2073. else:
  2074. ifaddr = get_if_addr(dev)
  2075. return (atol(thenet), itom(msk), gw, dev, ifaddr)
  2076. def add(self, *args, **kargs):
  2077. """Ex:
  2078. add(net="192.168.1.0/24",gw="1.2.3.4")
  2079. """
  2080. self.routes.append(self.make_route(*args,**kargs))
  2081. def delt(self, *args, **kargs):
  2082. """delt(host|net, gw|dev)"""
  2083. route = self.make_route(*args,**kargs)
  2084. try:
  2085. i=self.routes.index(route)
  2086. del(self.routes[i])
  2087. except ValueError:
  2088. warning("no matching route found")
  2089. def ifchange(self, iff, addr):
  2090. the_addr,the_msk = (addr.split("/")+["32"])[:2]
  2091. the_msk = itom(int(the_msk))
  2092. the_rawaddr, = struct.unpack("I",inet_aton(the_addr))
  2093. the_net = the_rawaddr & the_msk
  2094. for i in range(len(self.routes)):
  2095. net,msk,gw,iface,addr = self.routes[i]
  2096. if iface != iff:
  2097. continue
  2098. if gw == '0.0.0.0':
  2099. self.routes[i] = (the_net,the_msk,gw,iface,the_addr)
  2100. else:
  2101. self.routes[i] = (net,msk,gw,iface,the_addr)
  2102. for i in arp_cache.keys():
  2103. del(arp_cache[i])
  2104. def ifdel(self, iff):
  2105. new_routes=[]
  2106. for rt in self.routes:
  2107. if rt[3] != iff:
  2108. new_routes.append(rt)
  2109. self.routes=new_routes
  2110. def ifadd(self, iff, addr):
  2111. the_addr,the_msk = (addr.split("/")+["32"])[:2]
  2112. the_msk = itom(int(the_msk))
  2113. the_rawaddr, = struct.unpack("I",inet_aton(the_addr))
  2114. the_net = the_rawaddr & the_msk
  2115. self.routes.append((the_net,the_msk,'0.0.0.0',iff,the_addr))
  2116. def route(self,dst):
  2117. # Transform "192.168.*.1-5" to one IP of the set
  2118. dst = dst.split("/")[0]
  2119. dst = dst.replace("*","0")
  2120. while 1:
  2121. l = dst.find("-")
  2122. if l < 0:
  2123. break
  2124. m = (dst[l:]+".").find(".")
  2125. dst = dst[:l]+dst[l+m:]
  2126. try:
  2127. dst=inet_aton(dst)
  2128. except socket.error:
  2129. dst=inet_aton(socket.gethostbyname(dst))
  2130. dst,=struct.unpack("I",dst)
  2131. pathes=[]
  2132. for d,m,gw,i,a in self.routes:
  2133. aa, = struct.unpack("I",inet_aton(a))
  2134. if aa == dst:
  2135. pathes.append((0xffffffffL,("lo",a,"0.0.0.0")))
  2136. if (dst & m) == (d & m):
  2137. pathes.append((m,(i,a,gw)))
  2138. if not pathes:
  2139. warning("No route found (no default route?)")
  2140. return "lo","0.0.0.0","0.0.0.0" #XXX linux specific!
  2141. # Choose the more specific route (greatest netmask).
  2142. # XXX: we don't care about metrics
  2143. pathes.sort()
  2144. return pathes[-1][1]
  2145. def get_if_bcast(self, iff):
  2146. for net, msk, gw, iface, addr in self.routes:
  2147. if (iff == iface and net != 0L):
  2148. bcast = atol(addr)|(~msk&0xffffffffL); # FIXME: check error in atol()
  2149. return ltoa(bcast);
  2150. warning("No broadcast address found for iface %s\n" % iff);
  2151. if DNET:
  2152. def get_if_raw_hwaddr(iff):
  2153. if iff[:2] == "lo":
  2154. return (772, '\x00'*6)
  2155. try:
  2156. l = dnet.intf().get(iff)
  2157. l = l["link_addr"]
  2158. except:
  2159. raise Exception("Error in attempting to get hw address for interface [%s]" % iff)
  2160. return l.type,l.data
  2161. def get_if_raw_addr(ifname):
  2162. i = dnet.intf()
  2163. return i.get(ifname)["addr"].data
  2164. else:
  2165. def get_if_raw_hwaddr(iff):
  2166. return struct.unpack("16xh6s8x",get_if(iff,SIOCGIFHWADDR))
  2167. def get_if_raw_addr(iff):
  2168. s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  2169. ifreq = ioctl(s, SIOCGIFADDR, struct.pack("16s16x",iff))
  2170. return ifreq[20:24]
  2171. if PCAP:
  2172. def get_if_list():
  2173. # remove 'any' interface
  2174. return map(lambda x:x[0],filter(lambda x:x[1] is None,pcap.findalldevs()))
  2175. def get_working_if():
  2176. try:
  2177. return pcap.lookupdev()
  2178. except pcap.pcapc.EXCEPTION:
  2179. return 'lo'
  2180. def attach_filter(s, filter):
  2181. warning("attach_filter() should not be called in PCAP mode")
  2182. def set_promisc(s,iff,val=1):
  2183. warning("set_promisc() should not be called in DNET/PCAP mode")
  2184. else:
  2185. def get_if_list():
  2186. f=open("/proc/net/dev","r")
  2187. lst = []
  2188. f.readline()
  2189. f.readline()
  2190. for l in f:
  2191. lst.append(l.split(":")[0].strip())
  2192. return lst
  2193. def get_working_if():
  2194. for i in get_if_list():
  2195. if i == 'lo':
  2196. continue
  2197. ifflags = struct.unpack("16xH14x",get_if(i,SIOCGIFFLAGS))[0]
  2198. if ifflags & IFF_UP:
  2199. return i
  2200. return "lo"
  2201. def attach_filter(s, filter):
  2202. # XXX We generate the filter on the interface conf.iface
  2203. # because tcpdump open the "any" interface and ppp interfaces
  2204. # in cooked mode. As we use them in raw mode, the filter will not
  2205. # work... one solution could be to use "any" interface and translate
  2206. # the filter from cooked mode to raw mode
  2207. # mode
  2208. if not TCPDUMP:
  2209. return
  2210. try:
  2211. f = os.popen("%s -i %s -ddd -s 1600 '%s'" % (conf.prog.tcpdump,conf.iface,filter))
  2212. except OSError,msg:
  2213. log_interactive.warning("Failed to execute tcpdump: (%s)")
  2214. return
  2215. lines = f.readlines()
  2216. if f.close():
  2217. raise Exception("Filter parse error")
  2218. nb = int(lines[0])
  2219. bpf = ""
  2220. for l in lines[1:]:
  2221. bpf += struct.pack("HBBI",*map(long,l.split()))
  2222. # XXX. Argl! We need to give the kernel a pointer on the BPF,
  2223. # python object header seems to be 20 bytes. 36 bytes for x86 64bits arch.
  2224. if X86_64:
  2225. bpfh = struct.pack("HL", nb, id(bpf)+36)
  2226. else:
  2227. bpfh = struct.pack("HI", nb, id(bpf)+20)
  2228. s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh)
  2229. def set_promisc(s,iff,val=1):
  2230. mreq = struct.pack("IHH8s", get_if_index(iff), PACKET_MR_PROMISC, 0, "")
  2231. if val:
  2232. cmd = PACKET_ADD_MEMBERSHIP
  2233. else:
  2234. cmd = PACKET_DROP_MEMBERSHIP
  2235. s.setsockopt(SOL_PACKET, cmd, mreq)
  2236. if not LINUX:
  2237. def new_read_routes():
  2238. rtlst = []
  2239. def addrt(rt,lst):
  2240. dst,gw = rt
  2241. lst.append(rt)
  2242. r = dnet.route()
  2243. print r.loop(addrt, rtlst)
  2244. return rtlst
  2245. def read_routes():
  2246. if SOLARIS:
  2247. f=os.popen("netstat -rvn") # -f inet
  2248. else:
  2249. f=os.popen("netstat -rn") # -f inet
  2250. ok = 0
  2251. mtu_present = False
  2252. routes = []
  2253. for l in f.readlines():
  2254. if not l:
  2255. break
  2256. l = l.strip()
  2257. if l.find("----") >= 0: # a separation line
  2258. continue
  2259. if l.find("Destination") >= 0:
  2260. ok = 1
  2261. if l.find("Mtu") >= 0:
  2262. mtu_present = True
  2263. continue
  2264. if ok == 0:
  2265. continue
  2266. if not l:
  2267. break
  2268. if SOLARIS:
  2269. dest,mask,gw,netif,mxfrg,rtt,ref,flg = l.split()[:8]
  2270. else:
  2271. if mtu_present:
  2272. dest,gw,flg,ref,use,mtu,netif = l.split()[:7]
  2273. else:
  2274. dest,gw,flg,ref,use,netif = l.split()[:6]
  2275. if flg.find("Lc") >= 0:
  2276. continue
  2277. if dest == "default":
  2278. dest = 0L
  2279. netmask = 0L
  2280. else:
  2281. if SOLARIS:
  2282. netmask, = struct.unpack("I",inet_aton(mask))
  2283. elif "/" in dest:
  2284. dest,netmask = dest.split("/")
  2285. netmask = itom(int(netmask))
  2286. else:
  2287. netmask = itom((dest.count(".") + 1) * 8)
  2288. dest += ".0"*(3-dest.count("."))
  2289. dest, = struct.unpack("I",inet_aton(dest))
  2290. if not "G" in flg:
  2291. gw = '0.0.0.0'
  2292. ifaddr = get_if_addr(netif)
  2293. routes.append((dest,netmask,gw,netif,ifaddr))
  2294. f.close()
  2295. return routes
  2296. def read_interfaces():
  2297. i = dnet.intf()
  2298. ifflist = {}
  2299. def addif(iff,lst):
  2300. if not iff.has_key("addr"):
  2301. return
  2302. if not iff.has_key("link_addr"):
  2303. return
  2304. rawip = iff["addr"].data
  2305. ip = inet_ntoa(rawip)
  2306. rawll = iff["link_addr"].data
  2307. ll = str2mac(rawll)
  2308. lst[iff["name"]] = (rawll,ll,rawip,ip)
  2309. i.loop(addif, ifflist)
  2310. return ifflist
  2311. else:
  2312. def read_routes():
  2313. f=open("/proc/net/route","r")
  2314. routes = []
  2315. s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  2316. ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x","lo"))
  2317. addrfamily = struct.unpack("h",ifreq[16:18])[0]
  2318. if addrfamily == socket.AF_INET:
  2319. ifreq2 = ioctl(s, SIOCGIFNETMASK,struct.pack("16s16x","lo"))
  2320. msk = struct.unpack("I",ifreq2[20:24])[0]
  2321. dst = struct.unpack("I",ifreq[20:24])[0] & msk
  2322. ifaddr = inet_ntoa(ifreq[20:24])
  2323. routes.append((dst, msk, "0.0.0.0", "lo", ifaddr))
  2324. else:
  2325. warning("Interface lo: unkownn address family (%i)"% addrfamily)
  2326. for l in f.readlines()[1:]:
  2327. iff,dst,gw,flags,x,x,x,msk,x,x,x = l.split()
  2328. flags = int(flags,16)
  2329. if flags & RTF_UP == 0:
  2330. continue
  2331. if flags & RTF_REJECT:
  2332. continue
  2333. ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x",iff))
  2334. addrfamily = struct.unpack("h",ifreq[16:18])[0]
  2335. if addrfamily == socket.AF_INET:
  2336. ifaddr = inet_ntoa(ifreq[20:24])
  2337. else:
  2338. warning("Interface %s: unkownn address family (%i)"%(iff, addrfamily))
  2339. continue
  2340. routes.append((long(dst,16),
  2341. long(msk,16),
  2342. inet_ntoa(struct.pack("I",long(gw,16))),
  2343. iff, ifaddr))
  2344. f.close()
  2345. return routes
  2346. def get_if(iff,cmd):
  2347. s=socket.socket()
  2348. ifreq = ioctl(s, cmd, struct.pack("16s16x",iff))
  2349. s.close()
  2350. return ifreq
  2351. def get_if_index(iff):
  2352. return int(struct.unpack("I",get_if(iff, SIOCGIFINDEX)[16:20])[0])
  2353. def get_if_addr(iff):
  2354. return inet_ntoa(get_if_raw_addr(iff))
  2355. def get_if_hwaddr(iff):
  2356. addrfamily, mac = get_if_raw_hwaddr(iff)
  2357. if addrfamily in [ARPHDR_ETHER,ARPHDR_LOOPBACK]:
  2358. return str2mac(mac)
  2359. else:
  2360. raise Exception("Unsupported address family (%i) for interface [%s]" % (addrfamily,iff))
  2361. #####################
  2362. ## ARP cache stuff ##
  2363. #####################
  2364. ARPTIMEOUT=120
  2365. # XXX Fill arp_cache with /etc/ether and arp cache
  2366. arp_cache={}
  2367. if 0 and DNET: ## XXX Can't use this because it does not resolve IPs not in cache
  2368. dnet_arp_object = dnet.arp()
  2369. def getmacbyip(ip):
  2370. tmp = map(ord, inet_aton(ip))
  2371. if (tmp[0] & 0xf0) == 0xe0: # mcast @
  2372. return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3])
  2373. iff,a,gw = conf.route.route(ip)
  2374. if iff == "lo":
  2375. return "ff:ff:ff:ff:ff:ff"
  2376. if gw != "0.0.0.0":
  2377. ip = gw
  2378. res = dnet_arp_object.get(dnet.addr(ip))
  2379. if res is None:
  2380. return None
  2381. else:
  2382. return res.ntoa()
  2383. else:
  2384. def getmacbyip(ip):
  2385. tmp = map(ord, inet_aton(ip))
  2386. if (tmp[0] & 0xf0) == 0xe0: # mcast @
  2387. return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3])
  2388. iff,a,gw = conf.route.route(ip)
  2389. if ( (iff == "lo") or (ip == conf.route.get_if_bcast(iff)) ):
  2390. return "ff:ff:ff:ff:ff:ff"
  2391. if gw != "0.0.0.0":
  2392. ip = gw
  2393. if arp_cache.has_key(ip):
  2394. mac, timeout = arp_cache[ip]
  2395. if timeout and (time.time()-timeout < ARPTIMEOUT):
  2396. return mac
  2397. res = srp1(Ether(dst=ETHER_BROADCAST)/ARP(op="who-has", pdst=ip),
  2398. type=ETH_P_ARP,
  2399. iface = iff,
  2400. timeout=2,
  2401. verbose=0,
  2402. nofilter=1)
  2403. if res is not None:
  2404. mac = res.payload.hwsrc
  2405. arp_cache[ip] = (mac,time.time())
  2406. return mac
  2407. return None
  2408. ####################
  2409. ## Random numbers ##
  2410. ####################
  2411. class VolatileValue:
  2412. def __repr__(self):
  2413. return "<%s>" % self.__class__.__name__
  2414. def __getattr__(self, attr):
  2415. return getattr(self._fix(),attr)
  2416. def _fix(self):
  2417. return None
  2418. class RandField(VolatileValue):
  2419. pass
  2420. class RandNum(RandField):
  2421. min = 0
  2422. max = 0
  2423. def __init__(self, min, max):
  2424. self.min = min
  2425. self.max = max
  2426. def _fix(self):
  2427. # XXX: replace with sth that guarantee unicity
  2428. return random.randint(self.min, self.max)
  2429. class RandByte(RandNum):
  2430. def __init__(self):
  2431. RandNum.__init__(self, 0, 255)
  2432. class RandShort(RandNum):
  2433. def __init__(self):
  2434. RandNum.__init__(self, 0, 65535)
  2435. class RandInt(RandNum):
  2436. def __init__(self):
  2437. # Well, 2147483647 won't be reached because max+1 must be int
  2438. # and 2147483647+1 is longint. (random module limitation)
  2439. RandNum.__init__(self, 0, 2147483646)
  2440. class RandLong(RandNum):
  2441. def __init__(self):
  2442. RandNum.__init__(self, 0, 2L**64-1)
  2443. class RandString(RandField):
  2444. def __init__(self, size, chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"):
  2445. self.chars = chars
  2446. self.size = size
  2447. def _fix(self):
  2448. s = ""
  2449. for i in range(self.size):
  2450. s += random.choice(self.chars)
  2451. return s
  2452. class RandBin(RandString):
  2453. def __init__(self, size):
  2454. RandString.__init__(self, size, "".join(map(chr,range(256))))
  2455. class RandTermString(RandString):
  2456. def __init__(self, size, term):
  2457. RandString.__init__(self, size, "".join(map(chr,range(1,256))))
  2458. self.term = term
  2459. def _fix(self):
  2460. return RandString._fix(self)+self.term
  2461. class RandIP(RandString):
  2462. def __init__(self, iptemplate="0.0.0.0/0"):
  2463. self.ip = Net(iptemplate)
  2464. def _fix(self):
  2465. return self.ip.choice()
  2466. class RandMAC(RandString):
  2467. def __init__(self, template="*"):
  2468. template += ":*:*:*:*:*"
  2469. template = template.split(":")
  2470. self.mac = ()
  2471. for i in range(6):
  2472. if template[i] == "*":
  2473. v = RandByte()
  2474. elif "-" in template[i]:
  2475. x,y = template[i].split("-")
  2476. v = RandNum(int(x,16), int(y,16))
  2477. else:
  2478. v = int(template[i],16)
  2479. self.mac += (v,)
  2480. def _fix(self):
  2481. return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac
  2482. # Automatic timestamp
  2483. class AutoTime(VolatileValue):
  2484. def __init__(self, base=None):
  2485. if base == None:
  2486. self.diff = 0
  2487. else:
  2488. self.diff = time.time()-base
  2489. def _fix(self):
  2490. return time.time()-self.diff
  2491. class IntAutoTime(AutoTime):
  2492. def _fix(self):
  2493. return int(AutoTime.current_val(self))
  2494. class DelayedEval(VolatileValue):
  2495. """ Exemple of usage: DelayedEval("time.time()") """
  2496. def __init__(self, expr):
  2497. self.expr = expr
  2498. def _fix(self):
  2499. return eval(self.expr)
  2500. ################
  2501. ## Generators ##
  2502. ################
  2503. class Gen(object):
  2504. def __iter__(self):
  2505. return iter([])
  2506. class SetGen(Gen):
  2507. def __init__(self, set, _iterpacket=1):
  2508. self._iterpacket=_iterpacket
  2509. if type(set) is list:
  2510. self.set = set
  2511. elif isinstance(set, PacketList):
  2512. self.set = list(set)
  2513. else:
  2514. self.set = [set]
  2515. def transf(self, element):
  2516. return element
  2517. def __iter__(self):
  2518. for i in self.set:
  2519. if (type(i) is tuple) and (len(i) == 2) and type(i[0]) is int and type(i[1]) is int:
  2520. if (i[0] <= i[1]):
  2521. j=i[0]
  2522. while j <= i[1]:
  2523. yield j
  2524. j += 1
  2525. elif isinstance(i, Gen) and (self._iterpacket or not isinstance(i,Packet)):
  2526. for j in i:
  2527. yield j
  2528. else:
  2529. yield i
  2530. def __repr__(self):
  2531. return "<SetGen %s>" % self.set.__repr__()
  2532. class Net(Gen):
  2533. """Generate a list of IPs from a network address or a name"""
  2534. name = "ip"
  2535. ipaddress = re.compile(r"^(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)(/[0-3]?[0-9])?$")
  2536. def __init__(self, net):
  2537. self.repr=net
  2538. tmp=net.split('/')+["32"]
  2539. if not self.ipaddress.match(net):
  2540. tmp[0]=socket.gethostbyname(tmp[0])
  2541. netmask = int(tmp[1])
  2542. def parse_digit(a,netmask):
  2543. netmask = min(8,max(netmask,0))
  2544. if a == "*":
  2545. a = (0,256)
  2546. elif a.find("-") >= 0:
  2547. x,y = map(int,a.split("-"))
  2548. if x > y:
  2549. y = x
  2550. a = (x & (0xffL<<netmask) , max(y, (x | (0xffL>>(8-netmask))))+1)
  2551. else:
  2552. a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1)
  2553. return a
  2554. self.parsed = map(lambda x,y: parse_digit(x,y), tmp[0].split("."), map(lambda x,nm=netmask: x-nm, (8,16,24,32)))
  2555. def __iter__(self):
  2556. for d in xrange(*self.parsed[3]):
  2557. for c in xrange(*self.parsed[2]):
  2558. for b in xrange(*self.parsed[1]):
  2559. for a in xrange(*self.parsed[0]):
  2560. yield "%i.%i.%i.%i" % (a,b,c,d)
  2561. def choice(self):
  2562. ip = []
  2563. for v in self.parsed:
  2564. ip.append(str(random.randint(v[0],v[1]-1)))
  2565. return ".".join(ip)
  2566. def __repr__(self):
  2567. return "Net(%r)" % self.repr
  2568. #############
  2569. ## Results ##
  2570. #############
  2571. class PacketList:
  2572. res = []
  2573. def __init__(self, res, name="PacketList", stats=None):
  2574. """create a packet list from a list of packets
  2575. res: the list of packets
  2576. stats: a list of classes that will appear in the stats (defaults to [TCP,UDP,ICMP])"""
  2577. if stats is None:
  2578. stats = [ TCP,UDP,ICMP ]
  2579. self.stats = stats
  2580. if isinstance(res, PacketList):
  2581. res = res.res
  2582. self.res = res
  2583. self.listname = name
  2584. def _elt2pkt(self, elt):
  2585. return elt
  2586. def _elt2sum(self, elt):
  2587. return elt.summary()
  2588. def _elt2show(self, elt):
  2589. return self._elt2sum(elt)
  2590. def __repr__(self):
  2591. # stats=dict.fromkeys(self.stats,0) ## needs python >= 2.3 :(
  2592. stats = dict(map(lambda x: (x,0), self.stats))
  2593. other = 0
  2594. for r in self.res:
  2595. f = 0
  2596. for p in stats:
  2597. if self._elt2pkt(r).haslayer(p):
  2598. stats[p] += 1
  2599. f = 1
  2600. break
  2601. if not f:
  2602. other += 1
  2603. s = ""
  2604. ct = conf.color_theme
  2605. for p in stats:
  2606. s += " %s%s%s" % (ct.packetlist_proto(p.name),
  2607. ct.punct(":"),
  2608. ct.packetlist_value(stats[p]))
  2609. s += " %s%s%s" % (ct.packetlist_proto("Other"),
  2610. ct.punct(":"),
  2611. ct.packetlist_value(other))
  2612. return "%s%s%s%s%s" % (ct.punct("<"),
  2613. ct.packetlist_name(self.listname),
  2614. ct.punct(":"),
  2615. s,
  2616. ct.punct(">"))
  2617. def __getattr__(self, attr):
  2618. return getattr(self.res, attr)
  2619. def __getitem__(self, item):
  2620. if type(item) is type and issubclass(item,Packet):
  2621. return self.__class__(filter(lambda x: item in self._elt2pkt(x),self.res),
  2622. name="%s from %s"%(item.__name__,self.listname))
  2623. if type(item) is slice:
  2624. return self.__class__(self.res.__getitem__(item),
  2625. name = "mod %s" % self.listname)
  2626. return self.res.__getitem__(item)
  2627. def __getslice__(self, *args, **kargs):
  2628. return self.__class__(self.res.__getslice__(*args, **kargs),
  2629. name="mod %s"%self.listname)
  2630. def __add__(self, other):
  2631. return self.__class__(self.res+other.res,
  2632. name="%s+%s"%(self.listname,other.listname))
  2633. def summary(self, prn=None, lfilter=None):
  2634. """prints a summary of each packet
  2635. prn: function to apply to each packet instead of lambda x:x.summary()
  2636. lfilter: truth function to apply to each packet to decide whether it will be displayed"""
  2637. for r in self.res:
  2638. if lfilter is not None:
  2639. if not lfilter(r):
  2640. continue
  2641. if prn is None:
  2642. print self._elt2sum(r)
  2643. else:
  2644. print prn(r)
  2645. def nsummary(self,prn=None, lfilter=None):
  2646. """prints a summary of each packet with the packet's number
  2647. prn: function to apply to each packet instead of lambda x:x.summary()
  2648. lfilter: truth function to apply to each packet to decide whether it will be displayed"""
  2649. for i in range(len(self.res)):
  2650. if lfilter is not None:
  2651. if not lfilter(self.res[i]):
  2652. continue
  2653. print conf.color_theme.id(i,"%04i"),
  2654. if prn is None:
  2655. print self._elt2sum(self.res[i])
  2656. else:
  2657. print prn(self.res[i])
  2658. def display(self): # Deprecated. Use show()
  2659. """deprecated. is show()"""
  2660. self.show()
  2661. def show(self, *args, **kargs):
  2662. """Best way to display the packet list. Defaults to nsummary() method"""
  2663. return self.nsummary(*args, **kargs)
  2664. def filter(self, func):
  2665. """Returns a packet list filtered by a truth function"""
  2666. return self.__class__(filter(func,self.res),
  2667. name="filtered %s"%self.listname)
  2668. def make_table(self, *args, **kargs):
  2669. """Prints a table using a function that returs for each packet its head column value, head row value and displayed value
  2670. ex: p.make_table(lambda x:(x[IP].dst, x[TCP].dport, x[TCP].sprintf("%flags%")) """
  2671. return make_table(self.res, *args, **kargs)
  2672. def make_lined_table(self, *args, **kargs):
  2673. """Same as make_table, but print a table with lines"""
  2674. return make_lined_table(self.res, *args, **kargs)
  2675. def make_tex_table(self, *args, **kargs):
  2676. """Same as make_table, but print a table with LaTeX syntax"""
  2677. return make_tex_table(self.res, *args, **kargs)
  2678. def plot(self, f, lfilter=None,**kargs):
  2679. """Applies a function to each packet to get a value that will be plotted with GnuPlot. A gnuplot object is returned
  2680. lfilter: a truth function that decides whether a packet must be ploted"""
  2681. g=Gnuplot.Gnuplot()
  2682. l = self.res
  2683. if lfilter is not None:
  2684. l = filter(lfilter, l)
  2685. l = map(f,l)
  2686. g.plot(Gnuplot.Data(l, **kargs))
  2687. return g
  2688. def diffplot(self, f, delay=1, lfilter=None, **kargs):
  2689. """diffplot(f, delay=1, lfilter=None)
  2690. Applies a function to couples (l[i],l[i+delay])"""
  2691. g = Gnuplot.Gnuplot()
  2692. l = self.res
  2693. if lfilter is not None:
  2694. l = filter(lfilter, l)
  2695. l = map(f,l[:-delay],l[delay:])
  2696. g.plot(Gnuplot.Data(l, **kargs))
  2697. return g
  2698. def multiplot(self, f, lfilter=None, **kargs):
  2699. """Uses a function that returns a label and a value for this label, then plots all the values label by label"""
  2700. g=Gnuplot.Gnuplot()
  2701. l = self.res
  2702. if lfilter is not None:
  2703. l = filter(lfilter, l)
  2704. d={}
  2705. for e in l:
  2706. k,v = f(e)
  2707. if k in d:
  2708. d[k].append(v)
  2709. else:
  2710. d[k] = [v]
  2711. data=[]
  2712. for k in d:
  2713. data.append(Gnuplot.Data(d[k], title=k, **kargs))
  2714. g.plot(*data)
  2715. return g
  2716. def hexdump(self):
  2717. """Prints an hexadecimal dump of each packet in the list"""
  2718. for p in self:
  2719. hexdump(self._elt2pkt(p))
  2720. def hexraw(self, lfilter=None):
  2721. """Same as nsummary(), except that if a packet has a Raw layer, it will be hexdumped
  2722. lfilter: a truth function that decides whether a packet must be displayed"""
  2723. for i in range(len(self.res)):
  2724. p = self._elt2pkt(self.res[i])
  2725. if lfilter is not None and not lfilter(p):
  2726. continue
  2727. print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2728. p.sprintf("%.time%"),
  2729. self._elt2sum(self.res[i]))
  2730. if p.haslayer(Raw):
  2731. hexdump(p.getlayer(Raw).load)
  2732. def padding(self, lfilter=None):
  2733. """Same as hexraw(), for Padding layer"""
  2734. for i in range(len(self.res)):
  2735. p = self._elt2pkt(self.res[i])
  2736. if p.haslayer(Padding):
  2737. if lfilter is None or lfilter(p):
  2738. print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2739. p.sprintf("%.time%"),
  2740. self._elt2sum(self.res[i]))
  2741. hexdump(p.getlayer(Padding).load)
  2742. def nzpadding(self, lfilter=None):
  2743. """Same as padding() but only non null padding"""
  2744. for i in range(len(self.res)):
  2745. p = self._elt2pkt(self.res[i])
  2746. if p.haslayer(Padding):
  2747. pad = p.getlayer(Padding).load
  2748. if pad == pad[0]*len(pad):
  2749. continue
  2750. if lfilter is None or lfilter(p):
  2751. print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2752. p.sprintf("%.time%"),
  2753. self._elt2sum(self.res[i]))
  2754. hexdump(p.getlayer(Padding).load)
  2755. def conversations(self, getsrcdst=None,**kargs):
  2756. """Graphes a conversations between sources and destinations and display it
  2757. (using graphviz and imagemagick)
  2758. getsrcdst: a function that takes an element of the list and return the source and dest
  2759. by defaults, return source and destination IP
  2760. type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
  2761. target: filename or redirect. Defaults pipe to Imagemagick's display program
  2762. prog: which graphviz program to use"""
  2763. if getsrcdst is None:
  2764. getsrcdst = lambda x:(x[IP].src, x[IP].dst)
  2765. conv = {}
  2766. for p in self.res:
  2767. p = self._elt2pkt(p)
  2768. try:
  2769. c = getsrcdst(p)
  2770. except:
  2771. #XXX warning()
  2772. continue
  2773. conv[c] = conv.get(c,0)+1
  2774. gr = 'digraph "conv" {\n'
  2775. for s,d in conv:
  2776. gr += '\t "%s" -> "%s"\n' % (s,d)
  2777. gr += "}\n"
  2778. do_graph(gr, **kargs)
  2779. def afterglow(self, src=None, event=None, dst=None, **kargs):
  2780. """Experimental clone attempt of http://sourceforge.net/projects/afterglow
  2781. each datum is reduced as src -> event -> dst and the data are graphed.
  2782. by default we have IP.src -> IP.dport -> IP.dst"""
  2783. if src is None:
  2784. src = lambda x: x[IP].src
  2785. if event is None:
  2786. event = lambda x: x[IP].dport
  2787. if dst is None:
  2788. dst = lambda x: x[IP].dst
  2789. sl = {}
  2790. el = {}
  2791. dl = {}
  2792. for i in self.res:
  2793. try:
  2794. s,e,d = src(i),event(i),dst(i)
  2795. if s in sl:
  2796. n,l = sl[s]
  2797. n += 1
  2798. if e not in l:
  2799. l.append(e)
  2800. sl[s] = (n,l)
  2801. else:
  2802. sl[s] = (1,[e])
  2803. if e in el:
  2804. n,l = el[e]
  2805. n+=1
  2806. if d not in l:
  2807. l.append(d)
  2808. el[e] = (n,l)
  2809. else:
  2810. el[e] = (1,[d])
  2811. dl[d] = dl.get(d,0)+1
  2812. except:
  2813. continue
  2814. import math
  2815. def normalize(n):
  2816. return 2+math.log(n)/4.0
  2817. def minmax(x):
  2818. m,M = min(x),max(x)
  2819. if m == M:
  2820. m = 0
  2821. if M == 0:
  2822. M = 1
  2823. return m,M
  2824. mins,maxs = minmax(map(lambda (x,y): x, sl.values()))
  2825. mine,maxe = minmax(map(lambda (x,y): x, el.values()))
  2826. mind,maxd = minmax(dl.values())
  2827. gr = 'digraph "afterglow" {\n\tedge [len=2.5];\n'
  2828. gr += "# src nodes\n"
  2829. for s in sl:
  2830. n,l = sl[s]; n = 1+float(n-mins)/(maxs-mins)
  2831. gr += '"src.%s" [label = "%s", shape=box, fillcolor="#FF0000", style=filled, fixedsize=1, height=%.2f,width=%.2f];\n' % (`s`,`s`,n,n)
  2832. gr += "# event nodes\n"
  2833. for e in el:
  2834. n,l = el[e]; n = n = 1+float(n-mine)/(maxe-mine)
  2835. gr += '"evt.%s" [label = "%s", shape=circle, fillcolor="#00FFFF", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (`e`,`e`,n,n)
  2836. for d in dl:
  2837. n = dl[d]; n = n = 1+float(n-mind)/(maxd-mind)
  2838. gr += '"dst.%s" [label = "%s", shape=triangle, fillcolor="#0000ff", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (`d`,`d`,n,n)
  2839. gr += "###\n"
  2840. for s in sl:
  2841. n,l = sl[s]
  2842. for e in l:
  2843. gr += ' "src.%s" -> "evt.%s";\n' % (`s`,`e`)
  2844. for e in el:
  2845. n,l = el[e]
  2846. for d in l:
  2847. gr += ' "evt.%s" -> "dst.%s";\n' % (`e`,`d`)
  2848. gr += "}"
  2849. open("/tmp/aze","w").write(gr)
  2850. do_graph(gr, **kargs)
  2851. def timeskew_graph(self, ip, **kargs):
  2852. """Tries to graph the timeskew between the timestamps and real time for a given ip"""
  2853. res = map(lambda x: self._elt2pkt(x), self.res)
  2854. b = filter(lambda x:x.haslayer(IP) and x.getlayer(IP).src == ip and x.haslayer(TCP), res)
  2855. c = []
  2856. for p in b:
  2857. opts = p.getlayer(TCP).options
  2858. for o in opts:
  2859. if o[0] == "Timestamp":
  2860. c.append((p.time,o[1][0]))
  2861. if not c:
  2862. warning("No timestamps found in packet list")
  2863. return
  2864. d = map(lambda (x,y): (x%2000,((x-c[0][0])-((y-c[0][1])/1000.0))),c)
  2865. g = Gnuplot.Gnuplot()
  2866. g.plot(Gnuplot.Data(d,**kargs))
  2867. return g
  2868. def _dump_document(self, **kargs):
  2869. d = pyx.document.document()
  2870. l = len(self.res)
  2871. for i in range(len(self.res)):
  2872. elt = self.res[i]
  2873. c = self._elt2pkt(elt).canvas_dump(**kargs)
  2874. cbb = c.bbox()
  2875. c.text(cbb.left(),cbb.top()+1,r"\font\cmssfont=cmss12\cmssfont{Frame %i/%i}" % (i,l),[pyx.text.size.LARGE])
  2876. if conf.verb >= 2:
  2877. os.write(1,".")
  2878. d.append(pyx.document.page(c, paperformat=pyx.document.paperformat.A4,
  2879. margin=1*pyx.unit.t_cm,
  2880. fittosize=1))
  2881. return d
  2882. def psdump(self, filename = None, **kargs):
  2883. """Creates a multipage poscript file with a psdump of every packet
  2884. filename: name of the file to write to. If empty, a temporary file is used and
  2885. conf.prog.psreader is called"""
  2886. d = self._dump_document(**kargs)
  2887. if filename is None:
  2888. filename = "/tmp/scapy.psd.%i" % os.getpid()
  2889. d.writePSfile(filename)
  2890. os.system("%s %s.ps &" % (conf.prog.psreader,filename))
  2891. else:
  2892. d.writePSfile(filename)
  2893. print
  2894. def pdfdump(self, filename = None, **kargs):
  2895. """Creates a PDF file with a psdump of every packet
  2896. filename: name of the file to write to. If empty, a temporary file is used and
  2897. conf.prog.pdfreader is called"""
  2898. d = self._dump_document(**kargs)
  2899. if filename is None:
  2900. filename = "/tmp/scapy.psd.%i" % os.getpid()
  2901. d.writePDFfile(filename)
  2902. os.system("%s %s.pdf &" % (conf.prog.pdfreader,filename))
  2903. else:
  2904. d.writePDFfile(filename)
  2905. print
  2906. def sr(self,multi=0):
  2907. """sr([multi=1]) -> (SndRcvList, PacketList)
  2908. Matches packets in the list and return ( (matched couples), (unmatched packets) )"""
  2909. remain = self.res[:]
  2910. sr = []
  2911. i = 0
  2912. while i < len(remain):
  2913. s = remain[i]
  2914. j = i
  2915. while j < len(remain)-1:
  2916. j += 1
  2917. r = remain[j]
  2918. if r.answers(s):
  2919. sr.append((s,r))
  2920. if multi:
  2921. remain[i]._answered=1
  2922. remain[j]._answered=2
  2923. continue
  2924. del(remain[j])
  2925. del(remain[i])
  2926. i -= 1
  2927. break
  2928. i += 1
  2929. print i, len(remain)
  2930. if multi:
  2931. remain = filter(lambda x:not hasattr(x,"_answered"), remain)
  2932. return SndRcvList(sr),PacketList(remain)
  2933. class Dot11PacketList(PacketList):
  2934. def __init__(self, res, name="Dot11List", stats=None):
  2935. if stats is None:
  2936. stats = [Dot11WEP, Dot11Beacon, UDP, ICMP, TCP]
  2937. PacketList.__init__(self, res, name, stats)
  2938. def toEthernet(self):
  2939. data = map(lambda x:x.getlayer(Dot11), filter(lambda x : x.haslayer(Dot11) and x.type == 2, self.res))
  2940. r2 = []
  2941. for p in data:
  2942. q = p.copy()
  2943. q.unwep()
  2944. r2.append(Ether()/q.payload.payload.payload) #Dot11/LLC/SNAP/IP
  2945. return PacketList(r2,name="Ether from %s"%self.listname)
  2946. class SndRcvList(PacketList):
  2947. def __init__(self, res, name="Results", stats=None):
  2948. PacketList.__init__(self, res, name, stats)
  2949. def _elt2pkt(self, elt):
  2950. return elt[1]
  2951. def _elt2sum(self, elt):
  2952. return "%s ==> %s" % (elt[0].summary(),elt[1].summary())
  2953. class ARPingResult(SndRcvList):
  2954. def __init__(self, res, name="ARPing", stats=None):
  2955. PacketList.__init__(self, res, name, stats)
  2956. def show(self):
  2957. for s,r in self.res:
  2958. print r.sprintf("%Ether.src% %ARP.psrc%")
  2959. class TracerouteResult(SndRcvList):
  2960. def __init__(self, res, name="Traceroute", stats=None):
  2961. PacketList.__init__(self, res, name, stats)
  2962. self.graphdef = None
  2963. self.graphASN = 0
  2964. self.padding = 0
  2965. self.hloc = None
  2966. self.nloc = None
  2967. def show(self):
  2968. return self.make_table(lambda (s,r): (s.sprintf("%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}"),
  2969. s.ttl,
  2970. r.sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}")))
  2971. def get_trace(self):
  2972. trace = {}
  2973. for s,r in self.res:
  2974. if IP not in s:
  2975. continue
  2976. d = s[IP].dst
  2977. if d not in trace:
  2978. trace[d] = {}
  2979. trace[d][s[IP].ttl] = r[IP].src, ICMP not in r
  2980. for k in trace.values():
  2981. m = filter(lambda x:k[x][1], k.keys())
  2982. if not m:
  2983. continue
  2984. m = min(m)
  2985. for l in k.keys():
  2986. if l > m:
  2987. del(k[l])
  2988. return trace
  2989. def trace3D(self):
  2990. """Give a 3D representation of the traceroute.
  2991. right button: rotate the scene
  2992. middle button: zoom
  2993. left button: move the scene
  2994. left button on a ball: toggle IP displaying
  2995. ctrl-left button on a ball: scan ports 21,22,23,25,80 and 443 and display the result"""
  2996. trace = self.get_trace()
  2997. import visual
  2998. class IPsphere(visual.sphere):
  2999. def __init__(self, ip, **kargs):
  3000. visual.sphere.__init__(self, **kargs)
  3001. self.ip=ip
  3002. self.label=None
  3003. self.setlabel(self.ip)
  3004. def setlabel(self, txt,visible=None):
  3005. if self.label is not None:
  3006. if visible is None:
  3007. visible = self.label.visible
  3008. self.label.visible = 0
  3009. elif visible is None:
  3010. visible=0
  3011. self.label=visual.label(text=txt, pos=self.pos, space=self.radius, xoffset=10, yoffset=20, visible=visible)
  3012. def action(self):
  3013. self.label.visible ^= 1
  3014. visual.scene = visual.display()
  3015. visual.scene.exit_on_close(0)
  3016. start = visual.box()
  3017. rings={}
  3018. tr3d = {}
  3019. for i in trace:
  3020. tr = trace[i]
  3021. tr3d[i] = []
  3022. ttl = tr.keys()
  3023. for t in range(1,max(ttl)+1):
  3024. if t not in rings:
  3025. rings[t] = []
  3026. if t in tr:
  3027. if tr[t] not in rings[t]:
  3028. rings[t].append(tr[t])
  3029. tr3d[i].append(rings[t].index(tr[t]))
  3030. else:
  3031. rings[t].append(("unk",-1))
  3032. tr3d[i].append(len(rings[t])-1)
  3033. for t in rings:
  3034. r = rings[t]
  3035. l = len(r)
  3036. for i in range(l):
  3037. if r[i][1] == -1:
  3038. col = (0.75,0.75,0.75)
  3039. elif r[i][1]:
  3040. col = visual.color.green
  3041. else:
  3042. col = visual.color.blue
  3043. s = IPsphere(pos=((l-1)*visual.cos(2*i*visual.pi/l),(l-1)*visual.sin(2*i*visual.pi/l),2*t),
  3044. ip = r[i][0],
  3045. color = col)
  3046. for trlst in tr3d.values():
  3047. if t <= len(trlst):
  3048. if trlst[t-1] == i:
  3049. trlst[t-1] = s
  3050. forecol = colgen(0.625, 0.4375, 0.25, 0.125)
  3051. for trlst in tr3d.values():
  3052. col = forecol.next()
  3053. start = (0,0,0)
  3054. for ip in trlst:
  3055. visual.cylinder(pos=start,axis=ip.pos-start,color=col,radius=0.2)
  3056. start = ip.pos
  3057. movcenter=None
  3058. while 1:
  3059. if visual.scene.kb.keys:
  3060. k = visual.scene.kb.getkey()
  3061. if k == "esc":
  3062. break
  3063. if visual.scene.mouse.events:
  3064. ev = visual.scene.mouse.getevent()
  3065. if ev.press == "left":
  3066. o = ev.pick
  3067. if o:
  3068. if ev.ctrl:
  3069. if o.ip == "unk":
  3070. continue
  3071. savcolor = o.color
  3072. o.color = (1,0,0)
  3073. a,b=sr(IP(dst=o.ip)/TCP(dport=[21,22,23,25,80,443]),timeout=2)
  3074. o.color = savcolor
  3075. if len(a) == 0:
  3076. txt = "%s:\nno results" % o.ip
  3077. else:
  3078. txt = "%s:\n" % o.ip
  3079. for s,r in a:
  3080. txt += r.sprintf("{TCP:%IP.src%:%TCP.sport% %TCP.flags%}{TCPerror:%IPerror.dst%:%TCPerror.dport% %IP.src% %ir,ICMP.type%}\n")
  3081. o.setlabel(txt, visible=1)
  3082. else:
  3083. if hasattr(o, "action"):
  3084. o.action()
  3085. elif ev.drag == "left":
  3086. movcenter = ev.pos
  3087. elif ev.drop == "left":
  3088. movcenter = None
  3089. if movcenter:
  3090. visual.scene.center -= visual.scene.mouse.pos-movcenter
  3091. movcenter = visual.scene.mouse.pos
  3092. def world_trace(self):
  3093. ips = {}
  3094. rt = {}
  3095. ports_done = {}
  3096. for s,r in self.res:
  3097. ips[r.src] = None
  3098. if s.haslayer(TCP) or s.haslayer(UDP):
  3099. trace_id = (s.src,s.dst,s.proto,s.dport)
  3100. elif s.haslayer(ICMP):
  3101. trace_id = (s.src,s.dst,s.proto,s.type)
  3102. else:
  3103. trace_id = (s.src,s.dst,s.proto,0)
  3104. trace = rt.get(trace_id,{})
  3105. if not r.haslayer(ICMP) or r.type != 11:
  3106. if ports_done.has_key(trace_id):
  3107. continue
  3108. ports_done[trace_id] = None
  3109. trace[s.ttl] = r.src
  3110. rt[trace_id] = trace
  3111. trt = {}
  3112. for trace_id in rt:
  3113. trace = rt[trace_id]
  3114. loctrace = []
  3115. for i in range(max(trace.keys())):
  3116. ip = trace.get(i,None)
  3117. if ip is None:
  3118. continue
  3119. loc = locate_ip(ip)
  3120. if loc is None:
  3121. continue
  3122. # loctrace.append((ip,loc)) # no labels yet
  3123. loctrace.append(loc)
  3124. if loctrace:
  3125. trt[trace_id] = loctrace
  3126. tr = map(lambda x: Gnuplot.Data(x,with_="lines"), trt.values())
  3127. g = Gnuplot.Gnuplot()
  3128. world = Gnuplot.File(conf.gnuplot_world,with_="lines")
  3129. g.plot(world,*tr)
  3130. return g
  3131. def make_graph(self,ASN,padding):
  3132. self.graphASN = ASN
  3133. self.graphpadding = padding
  3134. ips = {}
  3135. rt = {}
  3136. ports = {}
  3137. ports_done = {}
  3138. for s,r in self.res:
  3139. ips[r.src] = None
  3140. if s.haslayer(TCP) or s.haslayer(UDP):
  3141. trace_id = (s.src,s.dst,s.proto,s.dport)
  3142. elif s.haslayer(ICMP):
  3143. trace_id = (s.src,s.dst,s.proto,s.type)
  3144. else:
  3145. trace_id = (s.src,s.dst,s.proto,0)
  3146. trace = rt.get(trace_id,{})
  3147. if not r.haslayer(ICMP) or r.type != 11:
  3148. if ports_done.has_key(trace_id):
  3149. continue
  3150. ports_done[trace_id] = None
  3151. p = ports.get(r.src,[])
  3152. if r.haslayer(TCP):
  3153. p.append(r.sprintf("<T%ir,TCP.sport%> %TCP.sport%: %TCP.flags%"))
  3154. trace[s.ttl] = r.sprintf('"%IP.src%":T%ir,TCP.sport%')
  3155. elif r.haslayer(UDP):
  3156. p.append(r.sprintf("<U%ir,UDP.sport%> %UDP.sport%"))
  3157. trace[s.ttl] = r.sprintf('"%IP.src%":U%ir,UDP.sport%')
  3158. elif r.haslayer(ICMP):
  3159. p.append(r.sprintf("<I%ir,ICMP.type%> ICMP %ICMP.type%"))
  3160. trace[s.ttl] = r.sprintf('"%IP.src%":I%ir,ICMP.type%')
  3161. else:
  3162. p.append(r.sprintf("<P%ir,IP.proto> IP %IP.proto%"))
  3163. trace[s.ttl] = r.sprintf('"%IP.src%":P%ir,IP.proto%')
  3164. ports[r.src] = p
  3165. else:
  3166. trace[s.ttl] = r.sprintf('"%IP.src%"')
  3167. rt[trace_id] = trace
  3168. # Fill holes with unk%i nodes
  3169. unk = 0
  3170. blackholes = []
  3171. bhip = {}
  3172. for rtk in rt:
  3173. trace = rt[rtk]
  3174. k = trace.keys()
  3175. for n in range(min(k), max(k)):
  3176. if not trace.has_key(n):
  3177. trace[n] = "unk%i" % unk
  3178. unk += 1
  3179. if not ports_done.has_key(rtk):
  3180. if rtk[2] == 1: #ICMP
  3181. bh = "%s %i" % (rtk[1],rtk[3])
  3182. elif rtk[2] == 6: #TCP
  3183. bh = "%s:%i/tcp" % (rtk[1],rtk[3])
  3184. elif rtk[2] == 17: #UDP
  3185. bh = '%s:%i/udp' % (rtk[1],rtk[3])
  3186. else:
  3187. bh = '%s,proto %i' % (rtk[1],rtk[2])
  3188. ips[bh] = None
  3189. bhip[rtk[1]] = bh
  3190. bh = '"%s"' % bh
  3191. trace[max(k)+1] = bh
  3192. blackholes.append(bh)
  3193. # Find AS numbers
  3194. def getASNlist_radb(list):
  3195. def parseWhois(x):
  3196. asn,desc = None,""
  3197. for l in x.splitlines():
  3198. if not asn and l.startswith("origin:"):
  3199. asn = l[7:].strip()
  3200. if l.startswith("descr:"):
  3201. if desc:
  3202. desc += r"\n"
  3203. desc += l[6:].strip()
  3204. if asn is not None and desc:
  3205. break
  3206. return asn,desc.strip()
  3207. ASNlist = []
  3208. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  3209. s.connect(("whois.ra.net",43))
  3210. for ip in list:
  3211. s.send("-k %s\n" % ip)
  3212. asn,desc = parseWhois(s.recv(8192))
  3213. ASNlist.append((ip,asn,desc))
  3214. return ASNlist
  3215. def getASNlist_cymru(list):
  3216. ASNlist = []
  3217. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  3218. s.connect(("whois.cymru.com",43))
  3219. s.send("begin\r\n"+"\r\n".join(list)+"\r\nend\r\n")
  3220. r = ""
  3221. while 1:
  3222. l = s.recv(8192)
  3223. if l == "":
  3224. break
  3225. r += l
  3226. s.close()
  3227. for l in r.splitlines()[1:]:
  3228. asn,ip,desc = map(str.strip, l.split("|"))
  3229. if asn == "NA":
  3230. continue
  3231. asn = int(asn)
  3232. ASNlist.append((ip,asn,desc))
  3233. return ASNlist
  3234. ASN_query_list = dict.fromkeys(map(lambda x:x.split(":")[0],ips)).keys()
  3235. if ASN in [1,2]:
  3236. ASNlist = getASNlist_cymru(ASN_query_list)
  3237. elif ASN == 3:
  3238. ASNlist = getASNlist_radb(ASN_query_list)
  3239. else:
  3240. ASNlist = []
  3241. if ASN == 1:
  3242. ASN_ans_list = map(lambda x:x[0], ASNlist)
  3243. ASN_remain_list = filter(lambda x: x not in ASN_ans_list, ASN_query_list)
  3244. if ASN_remain_list:
  3245. ASNlist += getASNlist_radb(ASN_remain_list)
  3246. ASNs = {}
  3247. ASDs = {}
  3248. for ip,asn,desc, in ASNlist:
  3249. if asn is None:
  3250. continue
  3251. iplist = ASNs.get(asn,[])
  3252. if ip in bhip:
  3253. if ip in ports:
  3254. iplist.append(ip)
  3255. iplist.append(bhip[ip])
  3256. else:
  3257. iplist.append(ip)
  3258. ASNs[asn] = iplist
  3259. ASDs[asn] = desc
  3260. backcolorlist=colgen("60","86","ba","ff")
  3261. forecolorlist=colgen("a0","70","40","20")
  3262. s = "digraph trace {\n"
  3263. s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
  3264. s += "\n#ASN clustering\n"
  3265. for asn in ASNs:
  3266. s += '\tsubgraph cluster_%s {\n' % asn
  3267. col = backcolorlist.next()
  3268. s += '\t\tcolor="#%s%s%s";' % col
  3269. s += '\t\tnode [fillcolor="#%s%s%s",style=filled];' % col
  3270. s += '\t\tfontsize = 10;'
  3271. s += '\t\tlabel = "%s\\n[%s]"\n' % (asn,ASDs[asn])
  3272. for ip in ASNs[asn]:
  3273. s += '\t\t"%s";\n'%ip
  3274. s += "\t}\n"
  3275. s += "#endpoints\n"
  3276. for p in ports:
  3277. s += '\t"%s" [shape=record,color=black,fillcolor=green,style=filled,label="%s|%s"];\n' % (p,p,"|".join(ports[p]))
  3278. s += "\n#Blackholes\n"
  3279. for bh in blackholes:
  3280. s += '\t%s [shape=octagon,color=black,fillcolor=red,style=filled];\n' % bh
  3281. if padding:
  3282. s += "\n#Padding\n"
  3283. pad={}
  3284. for snd,rcv in self.res:
  3285. if rcv.src not in ports and rcv.haslayer(Padding):
  3286. p = rcv.getlayer(Padding).load
  3287. if p != "\x00"*len(p):
  3288. pad[rcv.src]=None
  3289. for rcv in pad:
  3290. s += '\t"%s" [shape=triangle,color=black,fillcolor=red,style=filled];\n' % rcv
  3291. s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
  3292. for rtk in rt:
  3293. s += "#---[%s\n" % `rtk`
  3294. s += '\t\tedge [color="#%s%s%s"];\n' % forecolorlist.next()
  3295. trace = rt[rtk]
  3296. k = trace.keys()
  3297. for n in range(min(k), max(k)):
  3298. s += '\t%s ->\n' % trace[n]
  3299. s += '\t%s;\n' % trace[max(k)]
  3300. s += "}\n";
  3301. self.graphdef = s
  3302. def graph(self, ASN=1, padding=0, **kargs):
  3303. """x.graph(ASN=1, other args):
  3304. ASN=0 : no clustering
  3305. ASN=1 : use whois.cymru.net AS clustering
  3306. ASN=2 : use whois.ra.net AS clustering
  3307. graph: GraphViz graph description
  3308. type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
  3309. target: filename or redirect. Defaults pipe to Imagemagick's display program
  3310. prog: which graphviz program to use"""
  3311. if (self.graphdef is None or
  3312. self.graphASN != ASN or
  3313. self.graphpadding != padding):
  3314. self.make_graph(ASN,padding)
  3315. do_graph(self.graphdef, **kargs)
  3316. ############
  3317. ## Fields ##
  3318. ############
  3319. class Field:
  3320. islist=0
  3321. holds_packets=0
  3322. def __init__(self, name, default, fmt="H"):
  3323. self.name = name
  3324. if fmt[0] in "@=<>!":
  3325. self.fmt = fmt
  3326. else:
  3327. self.fmt = "!"+fmt
  3328. self.default = self.any2i(None,default)
  3329. self.sz = struct.calcsize(self.fmt)
  3330. def i2len(self, pkt, x):
  3331. return self.sz
  3332. def h2i(self, pkt, x):
  3333. return x
  3334. def i2h(self, pkt, x):
  3335. return x
  3336. def m2i(self, pkt, x):
  3337. return x
  3338. def i2m(self, pkt, x):
  3339. if x is None:
  3340. x = 0
  3341. return x
  3342. def any2i(self, pkt, x):
  3343. return self.h2i(pkt, x)
  3344. def i2repr(self, pkt, x):
  3345. if x is None:
  3346. x = 0
  3347. return repr(self.i2h(pkt,x))
  3348. def addfield(self, pkt, s, val):
  3349. return s+struct.pack(self.fmt, self.i2m(pkt,val))
  3350. def getfield(self, pkt, s):
  3351. return s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0])
  3352. def do_copy(self, x):
  3353. if hasattr(x, "copy"):
  3354. return x.copy()
  3355. elif type(x) is list:
  3356. return x[:]
  3357. else:
  3358. return x
  3359. def __eq__(self, other):
  3360. return self.name == other
  3361. def __hash__(self):
  3362. return hash(self.name)
  3363. def __repr__(self):
  3364. return self.name
  3365. def copy(self):
  3366. return copy.deepcopy(self)
  3367. def randval(self):
  3368. fmtt = self.fmt[-1]
  3369. if fmtt in "BHIQ":
  3370. return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]()
  3371. elif fmtt == "s":
  3372. if self.fmt[0] in "0123456789":
  3373. l = int(self.fmt[:-1])
  3374. else:
  3375. l = int(self.fmt[1:-1])
  3376. return RandBin(l)
  3377. else:
  3378. warning("no random class for [%s] (fmt=%s)." % (self.name, self.fmt))
  3379. class Emph:
  3380. fld = ""
  3381. def __init__(self, fld):
  3382. self.fld = fld
  3383. def __getattr__(self, attr):
  3384. return getattr(self.fld,attr)
  3385. class ActionField:
  3386. def __init__(self, fld, action_method, **kargs):
  3387. self._fld = fld
  3388. self._action_method = action_method
  3389. self._privdata = kargs
  3390. def any2i(self, pkt, val):
  3391. getattr(pkt, self._action_method)(val, self._fld, **self._privdata)
  3392. return getattr(self._fld, "any2i")(pkt, val)
  3393. def __getattr__(self, attr):
  3394. return getattr(self._fld,attr)
  3395. class ConditionalField:
  3396. def __init__(self, fld, fldlst, cond):
  3397. self.fld = fld
  3398. self.fldlst = fldlst
  3399. self.cond = cond
  3400. def _evalcond(self,pkt):
  3401. if type(self.fldlst) is list or type(self.fldlst) is tuple:
  3402. res = map(lambda x,pkt=pkt:getattr(pkt,x), self.fldlst)
  3403. else:
  3404. res = getattr(pkt, self.fldlst)
  3405. return self.cond(res)
  3406. def getfield(self, pkt, s):
  3407. if self._evalcond(pkt):
  3408. return self.fld.getfield(pkt,s)
  3409. else:
  3410. return s,None
  3411. def addfield(self, pkt, s, val):
  3412. if self._evalcond(pkt):
  3413. return self.fld.addfield(pkt,s,val)
  3414. else:
  3415. return s
  3416. def __getattr__(self, attr):
  3417. return getattr(self.fld,attr)
  3418. class MACField(Field):
  3419. def __init__(self, name, default):
  3420. Field.__init__(self, name, default, "6s")
  3421. def i2m(self, pkt, x):
  3422. if x is None:
  3423. return "\0\0\0\0\0\0"
  3424. return mac2str(x)
  3425. def m2i(self, pkt, x):
  3426. return str2mac(x)
  3427. def any2i(self, pkt, x):
  3428. if type(x) is str and len(x) is 6:
  3429. x = self.m2i(pkt, x)
  3430. return x
  3431. def i2repr(self, pkt, x):
  3432. return self.i2h(pkt, x)
  3433. def randval(self):
  3434. return RandMAC()
  3435. class DestMACField(MACField):
  3436. def __init__(self, name):
  3437. MACField.__init__(self, name, None)
  3438. def i2h(self, pkt, x):
  3439. if x is None:
  3440. dstip = None
  3441. if isinstance(pkt.payload, IPv6):
  3442. dstip = pkt.payload.dst
  3443. elif isinstance(pkt.payload, IP):
  3444. dstip = pkt.payload.dst
  3445. elif isinstance(pkt.payload, ARP):
  3446. dstip = pkt.payload.pdst
  3447. if isinstance(dstip, Gen):
  3448. dstip = dstip.__iter__().next()
  3449. if dstip is not None:
  3450. if isinstance(pkt.payload, IPv6):
  3451. x = getmacbyip6(dstip)
  3452. else:
  3453. x = getmacbyip(dstip)
  3454. if x is None:
  3455. x = "ff:ff:ff:ff:ff:ff"
  3456. warning("Mac address to reach %s not found\n"%dstip)
  3457. return MACField.i2h(self, pkt, x)
  3458. def i2m(self, pkt, x):
  3459. return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3460. class SourceMACField(MACField):
  3461. def __init__(self, name):
  3462. MACField.__init__(self, name, None)
  3463. def i2h(self, pkt, x):
  3464. if x is None:
  3465. dstip = None
  3466. if isinstance(pkt.payload, IPv6):
  3467. dstip = pkt.payload.dst
  3468. elif isinstance(pkt.payload, IP):
  3469. dstip = pkt.payload.dst
  3470. elif isinstance(pkt.payload, ARP):
  3471. dstip = pkt.payload.pdst
  3472. if isinstance(dstip, Gen):
  3473. dstip = dstip.__iter__().next()
  3474. if dstip is not None:
  3475. if isinstance(pkt.payload, IPv6):
  3476. iff,a,nh = conf.route6.route(dstip)
  3477. else:
  3478. iff,a,gw = conf.route.route(dstip)
  3479. try:
  3480. x = get_if_hwaddr(iff)
  3481. except:
  3482. pass
  3483. if x is None:
  3484. x = "00:00:00:00:00:00"
  3485. return MACField.i2h(self, pkt, x)
  3486. def i2m(self, pkt, x):
  3487. return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3488. class ARPSourceMACField(MACField):
  3489. def __init__(self, name):
  3490. MACField.__init__(self, name, None)
  3491. def i2h(self, pkt, x):
  3492. if x is None:
  3493. dstip = pkt.pdst
  3494. if isinstance(dstip, Gen):
  3495. dstip = dstip.__iter__().next()
  3496. if dstip is not None:
  3497. iff,a,gw = conf.route.route(dstip)
  3498. try:
  3499. x = get_if_hwaddr(iff)
  3500. except:
  3501. pass
  3502. if x is None:
  3503. x = "00:00:00:00:00:00"
  3504. return MACField.i2h(self, pkt, x)
  3505. def i2m(self, pkt, x):
  3506. return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3507. class Dot11AddrMACField(MACField):
  3508. def is_applicable(self, pkt):
  3509. return 1
  3510. def addfield(self, pkt, s, val):
  3511. if self.is_applicable(pkt):
  3512. return MACField.addfield(self, pkt, s, val)
  3513. else:
  3514. return s
  3515. def getfield(self, pkt, s):
  3516. if self.is_applicable(pkt):
  3517. return MACField.getfield(self, pkt, s)
  3518. else:
  3519. return s,None
  3520. class Dot11Addr2MACField(Dot11AddrMACField):
  3521. def is_applicable(self, pkt):
  3522. if pkt.type == 1:
  3523. return pkt.subtype in [ 0xb, 0xa, 0xe, 0xf] # RTS, PS-Poll, CF-End, CF-End+CF-Ack
  3524. return 1
  3525. class Dot11Addr3MACField(Dot11AddrMACField):
  3526. def is_applicable(self, pkt):
  3527. if pkt.type in [0,2]:
  3528. return 1
  3529. return 0
  3530. class Dot11Addr4MACField(Dot11AddrMACField):
  3531. def is_applicable(self, pkt):
  3532. if pkt.type == 2:
  3533. if pkt.FCfield & 0x3 == 0x3: # To-DS and From-DS are set
  3534. return 1
  3535. return 0
  3536. class IPField(Field):
  3537. def __init__(self, name, default):
  3538. Field.__init__(self, name, default, "4s")
  3539. def h2i(self, pkt, x):
  3540. if type(x) is str:
  3541. try:
  3542. inet_aton(x)
  3543. except socket.error:
  3544. x = Net(x)
  3545. elif type(x) is list:
  3546. x = map(Net, x)
  3547. return x
  3548. def i2m(self, pkt, x):
  3549. return inet_aton(x)
  3550. def m2i(self, pkt, x):
  3551. return inet_ntoa(x)
  3552. def any2i(self, pkt, x):
  3553. return self.h2i(pkt,x)
  3554. def i2repr(self, pkt, x):
  3555. return self.i2h(pkt, x)
  3556. def randval(self):
  3557. return RandIP()
  3558. class SourceIPField(IPField):
  3559. def __init__(self, name, dstname):
  3560. IPField.__init__(self, name, None)
  3561. self.dstname = dstname
  3562. def i2m(self, pkt, x):
  3563. if x is None:
  3564. iff,x,gw = conf.route.route(getattr(pkt,self.dstname))
  3565. return IPField.i2m(self, pkt, x)
  3566. def i2h(self, pkt, x):
  3567. if x is None:
  3568. dst=getattr(pkt,self.dstname)
  3569. if isinstance(dst,Gen):
  3570. r = map(conf.route.route, dst)
  3571. r.sort()
  3572. if r[0] == r[-1]:
  3573. x=r[0][1]
  3574. else:
  3575. warning("More than one possible route for %s"%repr(dst))
  3576. return None
  3577. else:
  3578. iff,x,gw = conf.route.route(dst)
  3579. return IPField.i2h(self, pkt, x)
  3580. class ByteField(Field):
  3581. def __init__(self, name, default):
  3582. Field.__init__(self, name, default, "B")
  3583. class XByteField(ByteField):
  3584. def i2repr(self, pkt, x):
  3585. if x is None:
  3586. x = 0
  3587. return hex(self.i2h(pkt, x))
  3588. class X3BytesField(XByteField):
  3589. def __init__(self, name, default):
  3590. Field.__init__(self, name, default, "!I")
  3591. def addfield(self, pkt, s, val):
  3592. return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
  3593. def getfield(self, pkt, s):
  3594. return s[3:], self.m2i(pkt, struct.unpack(self.fmt, "\x00"+s[:3])[0])
  3595. class ShortField(Field):
  3596. def __init__(self, name, default):
  3597. Field.__init__(self, name, default, "H")
  3598. class LEShortField(Field):
  3599. def __init__(self, name, default):
  3600. Field.__init__(self, name, default, "<H")
  3601. class XShortField(ShortField):
  3602. def i2repr(self, pkt, x):
  3603. if x is None:
  3604. x = 0
  3605. return hex(self.i2h(pkt, x))
  3606. class IntField(Field):
  3607. def __init__(self, name, default):
  3608. Field.__init__(self, name, default, "I")
  3609. class SignedIntField(Field):
  3610. def __init__(self, name, default):
  3611. Field.__init__(self, name, default, "i")
  3612. class LEIntField(Field):
  3613. def __init__(self, name, default):
  3614. Field.__init__(self, name, default, "<I")
  3615. class LESignedIntField(Field):
  3616. def __init__(self, name, default):
  3617. Field.__init__(self, name, default, "<i")
  3618. class XIntField(IntField):
  3619. def i2repr(self, pkt, x):
  3620. if x is None:
  3621. x = 0
  3622. return hex(self.i2h(pkt, x))
  3623. class LongField(Field):
  3624. def __init__(self, name, default):
  3625. Field.__init__(self, name, default, "Q")
  3626. class XLongField(LongField):
  3627. def i2repr(self, pkt, x):
  3628. if x is None:
  3629. x = 0
  3630. return hex(self.i2h(pkt, x))
  3631. class StrField(Field):
  3632. def __init__(self, name, default, fmt="H", remain=0, shift=0):
  3633. Field.__init__(self,name,default,fmt)
  3634. self.remain = remain
  3635. self.shift = shift
  3636. def i2len(self, pkt, i):
  3637. return len(i)+self.shift
  3638. def i2m(self, pkt, x):
  3639. if x is None:
  3640. x = ""
  3641. return x
  3642. def addfield(self, pkt, s, val):
  3643. return s+self.i2m(pkt, val)
  3644. def getfield(self, pkt, s):
  3645. if self.remain == 0:
  3646. return "",self.m2i(pkt, s)
  3647. else:
  3648. return s[-self.remain:],self.m2i(pkt, s[:-self.remain])
  3649. def randval(self):
  3650. return RandBin(RandNum(0,1200))
  3651. class PacketField(StrField):
  3652. holds_packets=1
  3653. def __init__(self, name, default, cls, remain=0, shift=0):
  3654. StrField.__init__(self, name, default, remain=remain, shift=shift)
  3655. self.cls = cls
  3656. def i2m(self, pkt, i):
  3657. return str(i)
  3658. def m2i(self, pkt, m):
  3659. return self.cls(m)
  3660. def getfield(self, pkt, s):
  3661. i = self.m2i(pkt, s)
  3662. remain = ""
  3663. if i.haslayer(Padding):
  3664. r = i.getlayer(Padding)
  3665. del(r.underlayer.payload)
  3666. remain = r.load
  3667. return remain,i
  3668. class PacketLenField(PacketField):
  3669. holds_packets=1
  3670. def __init__(self, name, default, cls, fld, shift=0):
  3671. PacketField.__init__(self, name, default, cls, shift=shift)
  3672. self.fld = fld
  3673. def getfield(self, pkt, s):
  3674. l = getattr(pkt, self.fld)
  3675. l -= self.shift
  3676. i = self.m2i(pkt, s[:l])
  3677. return s[l:],i
  3678. class PacketListField(PacketLenField):
  3679. islist = 1
  3680. holds_packets=1
  3681. def do_copy(self, x):
  3682. return map(lambda p:p.copy(), x)
  3683. def getfield(self, pkt, s):
  3684. l = getattr(pkt, self.fld)
  3685. l -= self.shift
  3686. lst = []
  3687. remain = s
  3688. while l>0 and len(remain)>0:
  3689. l -= 1
  3690. p = self.m2i(pkt,remain)
  3691. if Padding in p:
  3692. pad = p[Padding]
  3693. remain = pad.load
  3694. del(pad.underlayer.payload)
  3695. else:
  3696. remain = ""
  3697. lst.append(p)
  3698. return remain,lst
  3699. def addfield(self, pkt, s, val):
  3700. return s+"".join(map(str, val))
  3701. class StrFixedLenField(StrField):
  3702. def __init__(self, name, default, length, shift=0):
  3703. StrField.__init__(self, name, default, shift=shift)
  3704. self.length = length
  3705. def i2len(self, pkt, s):
  3706. return self.length+self.shift
  3707. def getfield(self, pkt, s):
  3708. return s[self.length:], self.m2i(pkt,s[:self.length])
  3709. def addfield(self, pkt, s, val):
  3710. return s+struct.pack("%is"%self.length,self.i2m(pkt, val))
  3711. def randval(self):
  3712. return RandBin(self.length)
  3713. class NetBIOSNameField(StrFixedLenField):
  3714. def __init__(self, name, default, length=31, shift=0):
  3715. StrFixedLenField.__init__(self, name, default, length, shift=shift)
  3716. def i2m(self, pkt, x):
  3717. if x is None:
  3718. x = ""
  3719. x += " "*(self.length/2)
  3720. x = x[:(self.length/2)]
  3721. x = "".join(map(lambda x: chr(0x41+(ord(x)>>4))+chr(0x41+(ord(x)&0xf)), x))
  3722. x = " "+x
  3723. return x
  3724. def m2i(self, pkt, x):
  3725. x = x.strip("\x00").strip(" ")
  3726. return "".join(map(lambda x,y: chr((((ord(x)-1)&0xf)<<4)+((ord(y)-1)&0xf)), x[::2],x[1::2]))
  3727. class StrLenField(StrField):
  3728. def __init__(self, name, default, fld, shift=0):
  3729. StrField.__init__(self, name, default, shift=shift)
  3730. self.fld = fld
  3731. def getfield(self, pkt, s):
  3732. l = getattr(pkt, self.fld)
  3733. l -= self.shift
  3734. return s[l:], self.m2i(pkt,s[:l])
  3735. class FieldListField(Field):
  3736. islist=1
  3737. def __init__(self, name, default, cls, fld, shift=0):
  3738. self.name = name
  3739. self.default = default
  3740. self.cls = cls
  3741. self.fld = fld
  3742. self.shift=shift
  3743. def i2len(self, pkt, val):
  3744. if val is None:
  3745. return self.shift
  3746. else:
  3747. return len(val)+self.shift
  3748. def i2m(self, pkt, val):
  3749. if val is None:
  3750. val = []
  3751. return val
  3752. def addfield(self, pkt, s, val):
  3753. val = self.i2m(pkt, val)
  3754. for v in val:
  3755. s = self.cls.addfield(pkt, s, v)
  3756. return s
  3757. def getfield(self, pkt, s):
  3758. l = getattr(pkt, self.fld)
  3759. # add the shift from the length field
  3760. f = pkt.get_field(self.fld)
  3761. l -= self.shift
  3762. val = []
  3763. for i in range(l):
  3764. s,v = self.cls.getfield(pkt, s)
  3765. val.append(v)
  3766. return s, val
  3767. class FieldLenField(Field):
  3768. def __init__(self, name, default, fld, fmt = "H"):
  3769. Field.__init__(self, name, default, fmt)
  3770. self.fld = fld
  3771. def i2m(self, pkt, x):
  3772. if x is None:
  3773. f = pkt.get_field(self.fld)
  3774. x = f.i2len(pkt,pkt.getfieldval(self.fld))
  3775. return x
  3776. # see http://www.iana.org/assignments/ipsec-registry for details
  3777. ISAKMPAttributeTypes= { "Encryption": (1, { "DES-CBS" : 1,
  3778. "IDEA-CBC" : 2,
  3779. "Blowfish-CBC" : 3,
  3780. "RC5-R16-B64-CBC" : 4,
  3781. "3DES-CBC" : 5,
  3782. "CAST-CBC" : 6,
  3783. "AES-CBC" : 7,
  3784. "CAMELLIA-CBC" : 8, }, 0),
  3785. "Hash": (2, { "MD5": 1,
  3786. "SHA": 2,
  3787. "Tiger": 3,
  3788. "SHA2-256": 4,
  3789. "SHA2-384": 5,
  3790. "SHA2-512": 6,}, 0),
  3791. "Authentication":(3, { "PSK": 1,
  3792. "DSS": 2,
  3793. "RSA Sig": 3,
  3794. "RSA Encryption": 4,
  3795. "RSA Encryption Revised": 5,
  3796. "ElGamal Encryption": 6,
  3797. "ElGamal Encryption Revised": 7,
  3798. "ECDSA Sig": 8,
  3799. "HybridInitRSA": 64221,
  3800. "HybridRespRSA": 64222,
  3801. "HybridInitDSS": 64223,
  3802. "HybridRespDSS": 64224,
  3803. "XAUTHInitPreShared": 65001,
  3804. "XAUTHRespPreShared": 65002,
  3805. "XAUTHInitDSS": 65003,
  3806. "XAUTHRespDSS": 65004,
  3807. "XAUTHInitRSA": 65005,
  3808. "XAUTHRespRSA": 65006,
  3809. "XAUTHInitRSAEncryption": 65007,
  3810. "XAUTHRespRSAEncryption": 65008,
  3811. "XAUTHInitRSARevisedEncryption": 65009,
  3812. "XAUTHRespRSARevisedEncryptio": 65010, }, 0),
  3813. "GroupDesc": (4, { "768MODPgr" : 1,
  3814. "1024MODPgr" : 2,
  3815. "EC2Ngr155" : 3,
  3816. "EC2Ngr185" : 4,
  3817. "1536MODPgr" : 5,
  3818. "2048MODPgr" : 14,
  3819. "3072MODPgr" : 15,
  3820. "4096MODPgr" : 16,
  3821. "6144MODPgr" : 17,
  3822. "8192MODPgr" : 18, }, 0),
  3823. "GroupType": (5, {"MODP": 1,
  3824. "ECP": 2,
  3825. "EC2N": 3}, 0),
  3826. "GroupPrime": (6, {}, 1),
  3827. "GroupGenerator1":(7, {}, 1),
  3828. "GroupGenerator2":(8, {}, 1),
  3829. "GroupCurveA": (9, {}, 1),
  3830. "GroupCurveB": (10, {}, 1),
  3831. "LifeType": (11, {"Seconds": 1,
  3832. "Kilobytes": 2, }, 0),
  3833. "LifeDuration": (12, {}, 1),
  3834. "PRF": (13, {}, 0),
  3835. "KeyLength": (14, {}, 0),
  3836. "FieldSize": (15, {}, 0),
  3837. "GroupOrder": (16, {}, 1),
  3838. }
  3839. # the name 'ISAKMPTransformTypes' is actually a misnomer (since the table
  3840. # holds info for all ISAKMP Attribute types, not just transforms, but we'll
  3841. # keep it for backwards compatibility... for now at least
  3842. ISAKMPTransformTypes = ISAKMPAttributeTypes
  3843. ISAKMPTransformNum = {}
  3844. for n in ISAKMPTransformTypes:
  3845. val = ISAKMPTransformTypes[n]
  3846. tmp = {}
  3847. for e in val[1]:
  3848. tmp[val[1][e]] = e
  3849. ISAKMPTransformNum[val[0]] = (n,tmp, val[2])
  3850. del(n)
  3851. del(e)
  3852. del(tmp)
  3853. del(val)
  3854. class ISAKMPTransformSetField(StrLenField):
  3855. islist=1
  3856. def type2num(self, (typ,val)):
  3857. type_val,enc_dict,tlv = ISAKMPTransformTypes.get(typ, (typ,{},0))
  3858. val = enc_dict.get(val, val)
  3859. s = ""
  3860. if tlv and (val & ~0xffff):
  3861. n = 0
  3862. while val:
  3863. s = chr(val&0xff)+s
  3864. val >>= 8
  3865. n += 1
  3866. val = n
  3867. else:
  3868. type_val |= 0x8000
  3869. return struct.pack("!HH",type_val, val)+s
  3870. def num2type(self, typ, enc):
  3871. val = ISAKMPTransformNum.get(typ,(typ,{}))
  3872. enc = val[1].get(enc,enc)
  3873. return (val[0],enc)
  3874. def i2m(self, pkt, i):
  3875. if i is None:
  3876. return ""
  3877. i = map(self.type2num, i)
  3878. return "".join(i)
  3879. def m2i(self, pkt, m):
  3880. # I try to ensure that we don't read off the end of our packet based
  3881. # on bad length fields we're provided in the packet. There are still
  3882. # conditions where struct.unpack() may not get enough packet data, but
  3883. # worst case that should result in broken attributes (which would
  3884. # be expected). (wam)
  3885. lst = []
  3886. while len(m) >= 4:
  3887. trans_type, = struct.unpack("!H", m[:2])
  3888. is_tlv = not (trans_type & 0x8000)
  3889. if is_tlv:
  3890. # We should probably check to make sure the attribute type we
  3891. # are looking at is allowed to have a TLV format and issue a
  3892. # warning if we're given an TLV on a basic attribute.
  3893. value_len, = struct.unpack("!H", m[2:4])
  3894. if value_len+4 > len(m):
  3895. warning("Bad length for ISAKMP tranform type=%#6x" % trans_type)
  3896. value = m[4:4+value_len]
  3897. value = reduce(lambda x,y: (x<<8L)|y, struct.unpack("!%s" % ("B"*len(value),), value),0)
  3898. else:
  3899. trans_type &= 0x7fff
  3900. value_len=0
  3901. value, = struct.unpack("!H", m[2:4])
  3902. m=m[4+value_len:]
  3903. lst.append(self.num2type(trans_type, value))
  3904. if len(m) > 0:
  3905. warning("Extra bytes after ISAKMP transform dissection [%r]" % m)
  3906. return lst
  3907. def getfield(self, pkt, s):
  3908. l = getattr(pkt, self.fld)
  3909. l -= self.shift
  3910. i = self.m2i(pkt, s[:l])
  3911. return s[l:],i
  3912. class StrNullField(StrField):
  3913. def addfield(self, pkt, s, val):
  3914. return s+self.i2m(pkt, val)+"\x00"
  3915. def getfield(self, pkt, s):
  3916. l = s.find("\x00")
  3917. if l < 0:
  3918. #XXX \x00 not found
  3919. return "",s
  3920. return s[l+1:],self.m2i(pkt, s[:l])
  3921. def randval(self):
  3922. return RandTermString(RandNum(0,1200),"\x00")
  3923. class StrStopField(StrField):
  3924. def __init__(self, name, default, stop, additionnal=0):
  3925. Field.__init__(self, name, default)
  3926. self.stop=stop
  3927. self.additionnal=additionnal
  3928. def getfield(self, pkt, s):
  3929. l = s.find(self.stop)
  3930. if l < 0:
  3931. return "",s
  3932. # raise Exception,"StrStopField: stop value [%s] not found" %stop
  3933. l += len(self.stop)+self.additionnal
  3934. return s[l:],s[:l]
  3935. def randval(self):
  3936. return RandTermString(RandNum(0,1200),self.stop)
  3937. class LenField(Field):
  3938. def i2m(self, pkt, x):
  3939. if x is None:
  3940. x = len(pkt.payload)
  3941. return x
  3942. class BCDFloatField(Field):
  3943. def i2m(self, pkt, x):
  3944. return int(256*x)
  3945. def m2i(self, pkt, x):
  3946. return x/256.0
  3947. class BitField(Field):
  3948. def __init__(self, name, default, size):
  3949. Field.__init__(self, name, default)
  3950. self.size = size
  3951. def addfield(self, pkt, s, val):
  3952. if val is None:
  3953. val = 0
  3954. if type(s) is tuple:
  3955. s,bitsdone,v = s
  3956. else:
  3957. bitsdone = 0
  3958. v = 0
  3959. v <<= self.size
  3960. v |= val & ((1L<<self.size) - 1)
  3961. bitsdone += self.size
  3962. while bitsdone >= 8:
  3963. bitsdone -= 8
  3964. s = s+struct.pack("!B", v >> bitsdone)
  3965. v &= (1L<<bitsdone)-1
  3966. if bitsdone:
  3967. return s,bitsdone,v
  3968. else:
  3969. return s
  3970. def getfield(self, pkt, s):
  3971. if type(s) is tuple:
  3972. s,bn = s
  3973. else:
  3974. bn = 0
  3975. # we don't want to process all the string
  3976. nb_bytes = (self.size+bn-1)/8 + 1
  3977. w = s[:nb_bytes]
  3978. # split the substring byte by byte
  3979. bytes = struct.unpack('!%dB' % nb_bytes , w)
  3980. b = 0L
  3981. for c in range(nb_bytes):
  3982. b |= long(bytes[c]) << (nb_bytes-c-1)*8
  3983. # get rid of high order bits
  3984. b &= (1L << (nb_bytes*8-bn)) - 1
  3985. # remove low order bits
  3986. b = b >> (nb_bytes*8 - self.size - bn)
  3987. bn += self.size
  3988. s = s[bn/8:]
  3989. bn = bn%8
  3990. if bn:
  3991. return (s,bn),b
  3992. else:
  3993. return s,b
  3994. def randval(self):
  3995. return RandNum(0,2**self.size-1)
  3996. class XBitField(BitField):
  3997. def i2repr(self, pkt, x):
  3998. return hex(self.i2h(pkt,x))
  3999. class EnumField(Field):
  4000. def __init__(self, name, default, enum, fmt = "H"):
  4001. i2s = self.i2s = {}
  4002. s2i = self.s2i = {}
  4003. if type(enum) is list:
  4004. keys = xrange(len(enum))
  4005. else:
  4006. keys = enum.keys()
  4007. if filter(lambda x: type(x) is str, keys):
  4008. i2s,s2i = s2i,i2s
  4009. for k in keys:
  4010. i2s[k] = enum[k]
  4011. s2i[enum[k]] = k
  4012. Field.__init__(self, name, default, fmt)
  4013. def any2i_one(self, pkt, x):
  4014. if type(x) is str:
  4015. x = self.s2i[x]
  4016. return x
  4017. def i2repr_one(self, pkt, x):
  4018. return self.i2s.get(x, repr(x))
  4019. def any2i(self, pkt, x):
  4020. if type(x) is list:
  4021. return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
  4022. else:
  4023. return self.any2i_one(pkt,x)
  4024. def i2repr(self, pkt, x):
  4025. if type(x) is list:
  4026. return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
  4027. else:
  4028. return self.i2repr_one(pkt,x)
  4029. class CharEnumField(EnumField):
  4030. def __init__(self, name, default, enum, fmt = "1s"):
  4031. EnumField.__init__(self, name, default, enum, fmt)
  4032. k = self.i2s.keys()
  4033. if k and len(k[0]) != 1:
  4034. self.i2s,self.s2i = self.s2i,self.i2s
  4035. def any2i_one(self, pkt, x):
  4036. if len(x) != 1:
  4037. x = self.s2i[x]
  4038. return x
  4039. class BitEnumField(BitField,EnumField):
  4040. def __init__(self, name, default, size, enum):
  4041. EnumField.__init__(self, name, default, enum)
  4042. self.size = size
  4043. def any2i(self, pkt, x):
  4044. return EnumField.any2i(self, pkt, x)
  4045. def i2repr(self, pkt, x):
  4046. return EnumField.i2repr(self, pkt, x)
  4047. class ShortEnumField(EnumField):
  4048. def __init__(self, name, default, enum):
  4049. EnumField.__init__(self, name, default, enum, "H")
  4050. class LEShortEnumField(EnumField):
  4051. def __init__(self, name, default, enum):
  4052. EnumField.__init__(self, name, default, enum, "<H")
  4053. class ByteEnumField(EnumField):
  4054. def __init__(self, name, default, enum):
  4055. EnumField.__init__(self, name, default, enum, "B")
  4056. class IntEnumField(EnumField):
  4057. def __init__(self, name, default, enum):
  4058. EnumField.__init__(self, name, default, enum, "I")
  4059. class LEIntEnumField(EnumField):
  4060. def __init__(self, name, default, enum):
  4061. EnumField.__init__(self, name, default, enum, "<I")
  4062. class XShortEnumField(ShortEnumField):
  4063. def i2repr_one(self, pkt, x):
  4064. return self.i2s.get(x, hex(x))
  4065. # Little endian long field
  4066. class LELongField(Field):
  4067. def __init__(self, name, default):
  4068. Field.__init__(self, name, default, "<Q")
  4069. # Little endian fixed length field
  4070. class LEFieldLenField(FieldLenField):
  4071. def __init__(self, name, default, fld, fmt = "<H"):
  4072. FieldLenField.__init__(self, name, default, fld=fld, fmt=fmt)
  4073. class FlagsField(BitField):
  4074. def __init__(self, name, default, size, names):
  4075. BitField.__init__(self, name, default, size)
  4076. self.multi = type(names) is list
  4077. if self.multi:
  4078. self.names = map(lambda x:[x], names)
  4079. else:
  4080. self.names = names
  4081. def any2i(self, pkt, x):
  4082. if type(x) is str:
  4083. if self.multi:
  4084. x = map(lambda y:[y], x.split("+"))
  4085. y = 0
  4086. for i in x:
  4087. y |= 1 << self.names.index(i)
  4088. x = y
  4089. return x
  4090. def i2repr(self, pkt, x):
  4091. if self.multi:
  4092. r = []
  4093. else:
  4094. r = ""
  4095. i=0
  4096. while x:
  4097. if x & 1:
  4098. r += self.names[i]
  4099. i += 1
  4100. x >>= 1
  4101. if self.multi:
  4102. r = "+".join(r)
  4103. return r
  4104. class IPoptionsField(StrField):
  4105. def i2m(self, pkt, x):
  4106. return x+"\x00"*(3-((len(x)+3)%4))
  4107. def getfield(self, pkt, s):
  4108. opsz = (pkt.ihl-5)*4
  4109. if opsz < 0:
  4110. warning("bad ihl (%i). Assuming ihl=5"%pkt.ihl)
  4111. opsz = 0
  4112. return s[opsz:],s[:opsz]
  4113. def randval(self):
  4114. return RandBin(RandNum(0,39))
  4115. TCPOptions = (
  4116. { 0 : ("EOL",None),
  4117. 1 : ("NOP",None),
  4118. 2 : ("MSS","!H"),
  4119. 3 : ("WScale","!B"),
  4120. 4 : ("SAckOK",None),
  4121. 5 : ("SAck","!"),
  4122. 8 : ("Timestamp","!II"),
  4123. 14 : ("AltChkSum","!BH"),
  4124. 15 : ("AltChkSumOpt",None)
  4125. },
  4126. { "EOL":0,
  4127. "NOP":1,
  4128. "MSS":2,
  4129. "WScale":3,
  4130. "SAckOK":4,
  4131. "SAck":5,
  4132. "Timestamp":8,
  4133. "AltChkSum":14,
  4134. "AltChkSumOpt":15,
  4135. } )
  4136. class TCPOptionsField(StrField):
  4137. islist=1
  4138. def getfield(self, pkt, s):
  4139. opsz = (pkt.dataofs-5)*4
  4140. if opsz < 0:
  4141. warning("bad dataofs (%i). Assuming dataofs=5"%pkt.dataofs)
  4142. opsz = 0
  4143. return s[opsz:],self.m2i(pkt,s[:opsz])
  4144. def m2i(self, pkt, x):
  4145. opt = []
  4146. while x:
  4147. onum = ord(x[0])
  4148. if onum == 0:
  4149. opt.append(("EOL",None))
  4150. x=x[1:]
  4151. break
  4152. if onum == 1:
  4153. opt.append(("NOP",None))
  4154. x=x[1:]
  4155. continue
  4156. olen = ord(x[1])
  4157. if olen < 2:
  4158. warning("Malformed TCP option (announced length is %i)" % olen)
  4159. olen = 2
  4160. oval = x[2:olen]
  4161. if TCPOptions[0].has_key(onum):
  4162. oname, ofmt = TCPOptions[0][onum]
  4163. if onum == 5: #SAck
  4164. ofmt += "%iI" % (len(oval)/4)
  4165. if ofmt and struct.calcsize(ofmt) == len(oval):
  4166. oval = struct.unpack(ofmt, oval)
  4167. if len(oval) == 1:
  4168. oval = oval[0]
  4169. opt.append((oname, oval))
  4170. else:
  4171. opt.append((onum, oval))
  4172. x = x[olen:]
  4173. return opt
  4174. def i2m(self, pkt, x):
  4175. opt = ""
  4176. for oname,oval in x:
  4177. if type(oname) is str:
  4178. if oname == "NOP":
  4179. opt += "\x01"
  4180. continue
  4181. elif oname == "EOL":
  4182. opt += "\x00"
  4183. continue
  4184. elif TCPOptions[1].has_key(oname):
  4185. onum = TCPOptions[1][oname]
  4186. ofmt = TCPOptions[0][onum][1]
  4187. if onum == 5: #SAck
  4188. ofmt += "%iI" % len(oval)
  4189. if ofmt is not None:
  4190. if type(oval) is not tuple:
  4191. oval = (oval,)
  4192. oval = struct.pack(ofmt, *oval)
  4193. else:
  4194. warning("option [%s] unknown. Skipped."%oname)
  4195. continue
  4196. else:
  4197. onum = oname
  4198. if type(oval) is not str:
  4199. warning("option [%i] is not string."%onum)
  4200. continue
  4201. opt += chr(onum)+chr(2+len(oval))+oval
  4202. return opt+"\x00"*(3-((len(opt)+3)%4))
  4203. def randval(self):
  4204. return [] # XXX
  4205. class DNSStrField(StrField):
  4206. def i2m(self, pkt, x):
  4207. x = x.split(".")
  4208. x = map(lambda y: chr(len(y))+y, x)
  4209. x = "".join(x)
  4210. if x[-1] != "\x00":
  4211. x += "\x00"
  4212. return x
  4213. def getfield(self, pkt, s):
  4214. n = ""
  4215. while 1:
  4216. l = ord(s[0])
  4217. s = s[1:]
  4218. if not l:
  4219. break
  4220. if l & 0xc0:
  4221. raise Exception("DNS message can't be compressed at this point!")
  4222. else:
  4223. n += s[:l]+"."
  4224. s = s[l:]
  4225. return s, n
  4226. class DNSRRCountField(ShortField):
  4227. holds_packets=1
  4228. def __init__(self, name, default, rr):
  4229. ShortField.__init__(self, name, default)
  4230. self.rr = rr
  4231. def _countRR(self, pkt):
  4232. x = getattr(pkt,self.rr)
  4233. i = 0
  4234. while isinstance(x, DNSRR) or isinstance(x, DNSQR):
  4235. x = x.payload
  4236. i += 1
  4237. return i
  4238. def i2m(self, pkt, x):
  4239. if x is None:
  4240. x = self._countRR(pkt)
  4241. return x
  4242. def i2h(self, pkt, x):
  4243. if x is None:
  4244. x = self._countRR(pkt)
  4245. return x
  4246. def DNSgetstr(s,p):
  4247. name = ""
  4248. q = 0
  4249. jpath = [p]
  4250. while 1:
  4251. if p >= len(s):
  4252. warning("DNS RR prematured end (ofs=%i, len=%i)"%(p,len(s)))
  4253. break
  4254. l = ord(s[p])
  4255. p += 1
  4256. if l & 0xc0:
  4257. if not q:
  4258. q = p+1
  4259. if p >= len(s):
  4260. warning("DNS incomplete jump token at (ofs=%i)" % p)
  4261. break
  4262. p = ((l & 0x3f) << 8) + ord(s[p]) - 12
  4263. if p in jpath:
  4264. warning("DNS decompression loop detected")
  4265. break
  4266. jpath.append(p)
  4267. continue
  4268. elif l > 0:
  4269. name += s[p:p+l]+"."
  4270. p += l
  4271. continue
  4272. break
  4273. if q:
  4274. p = q
  4275. return name,p
  4276. class DNSRRField(StrField):
  4277. holds_packets=1
  4278. def __init__(self, name, countfld, passon=1):
  4279. StrField.__init__(self, name, None)
  4280. self.countfld = countfld
  4281. self.passon = passon
  4282. def i2m(self, pkt, x):
  4283. if x is None:
  4284. return ""
  4285. return str(x)
  4286. def decodeRR(self, name, s, p):
  4287. ret = s[p:p+10]
  4288. type,cls,ttl,rdlen = struct.unpack("!HHIH", ret)
  4289. p += 10
  4290. rr = DNSRR("\x00"+ret+s[p:p+rdlen])
  4291. if rr.type in [2, 3, 4, 5]:
  4292. rr.rdata = DNSgetstr(s,p)[0]
  4293. del(rr.rdlen)
  4294. p += rdlen
  4295. rr.rrname = name
  4296. return rr,p
  4297. def getfield(self, pkt, s):
  4298. if type(s) is tuple :
  4299. s,p = s
  4300. else:
  4301. p = 0
  4302. ret = None
  4303. c = getattr(pkt, self.countfld)
  4304. if c > len(s):
  4305. warning("wrong value: DNS.%s=%i" % (self.countfld,c))
  4306. return s,""
  4307. while c:
  4308. c -= 1
  4309. name,p = DNSgetstr(s,p)
  4310. rr,p = self.decodeRR(name, s, p)
  4311. if ret is None:
  4312. ret = rr
  4313. else:
  4314. ret.add_payload(rr)
  4315. if self.passon:
  4316. return (s,p),ret
  4317. else:
  4318. return s[p:],ret
  4319. class DNSQRField(DNSRRField):
  4320. holds_packets=1
  4321. def decodeRR(self, name, s, p):
  4322. ret = s[p:p+4]
  4323. p += 4
  4324. rr = DNSQR("\x00"+ret)
  4325. rr.qname = name
  4326. return rr,p
  4327. class RDataField(StrLenField):
  4328. def m2i(self, pkt, s):
  4329. family = None
  4330. if pkt.type == 1:
  4331. family = socket.AF_INET
  4332. elif pkt.type == 28:
  4333. family = socket.AF_INET6
  4334. elif pkt.type == 12:
  4335. s = DNSgetstr(s, 0)[0]
  4336. if family is not None:
  4337. s = inet_ntop(family, s)
  4338. return s
  4339. def i2m(self, pkt, s):
  4340. if pkt.type == 1:
  4341. if s:
  4342. s = inet_aton(s)
  4343. elif pkt.type == 28:
  4344. if s:
  4345. s = inet_pton(socket.AF_INET6, s)
  4346. elif pkt.type in [2,3,4,5]:
  4347. s = "".join(map(lambda x: chr(len(x))+x, s.split(".")))
  4348. if ord(s[-1]):
  4349. s += "\x00"
  4350. return s
  4351. class RDLenField(Field):
  4352. def __init__(self, name):
  4353. Field.__init__(self, name, None, "H")
  4354. def i2m(self, pkt, x):
  4355. if x is None:
  4356. rdataf = pkt.fieldtype["rdata"]
  4357. x = len(rdataf.i2m(pkt, pkt.rdata))
  4358. return x
  4359. def i2h(self, pkt, x):
  4360. if x is None:
  4361. rdataf = pkt.fieldtype["rdata"]
  4362. x = len(rdataf.i2m(pkt, pkt.rdata))
  4363. return x
  4364. # seconds between 01-01-1900 and 01-01-1970
  4365. ntp_basetime = 2208988800
  4366. class TimeStampField(BitField):
  4367. def __init__(self, name, default, size):
  4368. BitField.__init__(self, name, default, size)
  4369. self.size = size
  4370. def getfield(self, pkt, s):
  4371. s,timestamp = BitField.getfield(self, pkt, s)
  4372. if timestamp:
  4373. # timestamp is a 64 bits field :
  4374. # + first 32 bits : number of seconds since 1900
  4375. # + last 32 bits : fraction part
  4376. timestamp >>= 32
  4377. timestamp -= ntp_basetime
  4378. from time import gmtime, strftime
  4379. b = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime(timestamp))
  4380. else:
  4381. b = 'None'
  4382. return s, b
  4383. def addfield(self, pkt, s, val):
  4384. t = -1
  4385. if type(val) is str:
  4386. from time import strptime, mktime
  4387. t = int(mktime(strptime(val))) + ntp_basetime + 3600
  4388. else:
  4389. if val == -1:
  4390. from time import time
  4391. t = int(time()) + ntp_basetime
  4392. else:
  4393. t = val
  4394. t <<= 32
  4395. return BitField.addfield(self,pkt,s, t)
  4396. class FloatField(BitField):
  4397. def getfield(self, pkt, s):
  4398. s,b = BitField.getfield(self, pkt, s)
  4399. # fraction point between bits 15 and 16.
  4400. sec = b >> 16
  4401. frac = b & (1L << (32+1)) - 1
  4402. frac /= 65536.0
  4403. b = sec+frac
  4404. return s,b
  4405. class Dot11SCField(LEShortField):
  4406. def is_applicable(self, pkt):
  4407. return pkt.type != 1 # control frame
  4408. def addfield(self, pkt, s, val):
  4409. if self.is_applicable(pkt):
  4410. return LEShortField.addfield(self, pkt, s, val)
  4411. else:
  4412. return s
  4413. def getfield(self, pkt, s):
  4414. if self.is_applicable(pkt):
  4415. return LEShortField.getfield(self, pkt, s)
  4416. else:
  4417. return s,None
  4418. ###########################
  4419. ## Packet abstract class ##
  4420. ###########################
  4421. class Packet(Gen):
  4422. name="abstract packet"
  4423. fields_desc = []
  4424. aliastypes = []
  4425. overload_fields = {}
  4426. underlayer = None
  4427. payload_guess = []
  4428. initialized = 0
  4429. show_indent=1
  4430. def from_hexcap(cls):
  4431. return cls(import_hexcap())
  4432. from_hexcap = classmethod(from_hexcap)
  4433. def __init__(self, _pkt="", _internal=0, _underlayer=None, **fields):
  4434. self.time = time.time()
  4435. self.aliastypes = [ self.__class__ ] + self.aliastypes
  4436. self.default_fields = {}
  4437. self.overloaded_fields = {}
  4438. self.fields={}
  4439. self.fieldtype={}
  4440. self.packetfields=[]
  4441. self.__dict__["payload"] = NoPayload()
  4442. for f in self.fields_desc:
  4443. self.default_fields[f] = f.default
  4444. self.fieldtype[f] = f
  4445. if f.holds_packets:
  4446. self.packetfields.append(f)
  4447. self.underlayer = _underlayer
  4448. self.initialized = 1
  4449. if _pkt:
  4450. self.dissect(_pkt)
  4451. if not _internal:
  4452. self.dissection_done(self)
  4453. for f in fields.keys():
  4454. self.fields[f] = self.fieldtype[f].any2i(self,fields[f])
  4455. def dissection_done(self,pkt):
  4456. """DEV: will be called after a dissection is completed"""
  4457. self.post_dissection(pkt)
  4458. self.payload.dissection_done(pkt)
  4459. def post_dissection(self, pkt):
  4460. """DEV: is called after the dissection of the whole packet"""
  4461. pass
  4462. def get_field(self, fld):
  4463. """DEV: returns the field instance from the name of the field"""
  4464. return self.fields_desc[self.fields_desc.index(fld)]
  4465. def add_payload(self, payload):
  4466. if payload is None:
  4467. return
  4468. elif not isinstance(self.payload, NoPayload):
  4469. self.payload.add_payload(payload)
  4470. else:
  4471. if isinstance(payload, Packet):
  4472. self.__dict__["payload"] = payload
  4473. payload.add_underlayer(self)
  4474. for t in self.aliastypes:
  4475. if payload.overload_fields.has_key(t):
  4476. self.overloaded_fields = payload.overload_fields[t]
  4477. break
  4478. elif type(payload) is str:
  4479. self.__dict__["payload"] = Raw(load=payload)
  4480. else:
  4481. raise TypeError("payload must be either 'Packet' or 'str', not [%s]" % repr(payload))
  4482. def remove_payload(self):
  4483. self.payload.remove_underlayer(self)
  4484. self.__dict__["payload"] = NoPayload()
  4485. self.overloaded_fields = {}
  4486. def add_underlayer(self, underlayer):
  4487. self.underlayer = underlayer
  4488. def remove_underlayer(self,other):
  4489. self.underlayer = None
  4490. def copy(self):
  4491. """Returns a deep copy of the instance."""
  4492. clone = self.__class__()
  4493. clone.fields = self.fields.copy()
  4494. for k in clone.fields:
  4495. clone.fields[k]=self.fieldtype[k].do_copy(clone.fields[k])
  4496. clone.default_fields = self.default_fields.copy()
  4497. clone.overloaded_fields = self.overloaded_fields.copy()
  4498. clone.overload_fields = self.overload_fields.copy()
  4499. clone.underlayer=self.underlayer
  4500. clone.__dict__["payload"] = self.payload.copy()
  4501. clone.payload.add_underlayer(clone)
  4502. return clone
  4503. def getfieldval(self, attr):
  4504. for f in self.fields, self.overloaded_fields, self.default_fields:
  4505. if f.has_key(attr):
  4506. return f[attr]
  4507. return self.payload.getfieldval(attr)
  4508. def __getattr__(self, attr):
  4509. if self.initialized:
  4510. v = self.getfieldval(attr)
  4511. fld = self.fieldtype.get(attr,None)
  4512. if fld is not None:
  4513. return fld.i2h(self, v)
  4514. return v
  4515. raise AttributeError(attr)
  4516. def __setattr__(self, attr, val):
  4517. if self.initialized:
  4518. if self.default_fields.has_key(attr):
  4519. fld = self.fieldtype.get(attr)
  4520. if fld is None:
  4521. any2i = lambda x,y: y
  4522. else:
  4523. any2i = fld.any2i
  4524. self.fields[attr] = any2i(self, val)
  4525. elif attr == "payload":
  4526. self.remove_payload()
  4527. self.add_payload(val)
  4528. else:
  4529. self.__dict__[attr] = val
  4530. else:
  4531. self.__dict__[attr] = val
  4532. def __delattr__(self, attr):
  4533. if self.initialized:
  4534. if self.fields.has_key(attr):
  4535. del(self.fields[attr])
  4536. return
  4537. elif self.default_fields.has_key(attr):
  4538. return
  4539. elif attr == "payload":
  4540. self.remove_payload()
  4541. return
  4542. if self.__dict__.has_key(attr):
  4543. del(self.__dict__[attr])
  4544. else:
  4545. raise AttributeError(attr)
  4546. def __repr__(self):
  4547. s = ""
  4548. ct = conf.color_theme
  4549. for f in self.fields_desc:
  4550. if f in self.fields:
  4551. val = f.i2repr(self, self.fields[f])
  4552. elif f in self.overloaded_fields:
  4553. val = f.i2repr(self, self.overloaded_fields[f])
  4554. else:
  4555. continue
  4556. if isinstance(f, Emph):
  4557. ncol = ct.emph_field_name
  4558. vcol = ct.emph_field_value
  4559. else:
  4560. ncol = ct.field_name
  4561. vcol = ct.field_value
  4562. s += " %s%s%s" % (ncol(f.name),
  4563. ct.punct("="),
  4564. vcol(val))
  4565. return "%s%s %s %s%s%s"% (ct.punct("<"),
  4566. ct.layer_name(self.__class__.__name__),
  4567. s,
  4568. ct.punct("|"),
  4569. repr(self.payload),
  4570. ct.punct(">"))
  4571. def __str__(self):
  4572. return self.__iter__().next().build()
  4573. def __div__(self, other):
  4574. if isinstance(other, Packet):
  4575. cloneA = self.copy()
  4576. cloneB = other.copy()
  4577. cloneA.add_payload(cloneB)
  4578. return cloneA
  4579. elif type(other) is str:
  4580. return self/Raw(load=other)
  4581. else:
  4582. return other.__rdiv__(self)
  4583. def __rdiv__(self, other):
  4584. if type(other) is str:
  4585. return Raw(load=other)/self
  4586. else:
  4587. raise TypeError
  4588. def __mul__(self, other):
  4589. if type(other) is int:
  4590. return [self]*other
  4591. else:
  4592. raise TypeError
  4593. def __rmul__(self,other):
  4594. return self.__mul__(other)
  4595. def __nonzero__(self):
  4596. return True
  4597. def __len__(self):
  4598. return len(self.__str__())
  4599. def do_build(self):
  4600. p=""
  4601. for f in self.fields_desc:
  4602. p = f.addfield(self, p, self.getfieldval(f))
  4603. return p, self.payload.build(internal=1)
  4604. def post_build(self, pkt, pay):
  4605. """DEV: called right after the current layer is build."""
  4606. return pkt+pay
  4607. def build(self,internal=0):
  4608. pkt,pay=self.do_build()
  4609. try:
  4610. p = self.post_build(pkt,pay)
  4611. except TypeError:
  4612. log_runtime.error("API changed! post_build() now takes 2 arguments. Compatibility is only assured for a short transition time")
  4613. p = self.post_build(pkt+pay)
  4614. if not internal:
  4615. pkt = self
  4616. while pkt.haslayer(Padding):
  4617. pkt = pkt.getlayer(Padding)
  4618. p += pkt.load
  4619. pkt = pkt.payload
  4620. return p
  4621. def do_build_ps(self):
  4622. p=""
  4623. pl = []
  4624. q=""
  4625. for f in self.fields_desc:
  4626. p = f.addfield(self, p, self.getfieldval(f) )
  4627. if type(p) is str:
  4628. r = p[len(q):]
  4629. q = p
  4630. else:
  4631. r = ""
  4632. pl.append( (f, f.i2repr(self,self.getfieldval(f)), r) )
  4633. pkt,lst = self.payload.build_ps(internal=1)
  4634. p += pkt
  4635. lst.append( (self, pl) )
  4636. return p,lst
  4637. def build_ps(self,internal=0):
  4638. p,lst = self.do_build_ps()
  4639. # if not internal:
  4640. # pkt = self
  4641. # while pkt.haslayer(Padding):
  4642. # pkt = pkt.getlayer(Padding)
  4643. # lst.append( (pkt, [ ("loakjkjd", pkt.load, pkt.load) ] ) )
  4644. # p += pkt.load
  4645. # pkt = pkt.payload
  4646. return p,lst
  4647. def psdump(self, filename=None, **kargs):
  4648. """psdump(filename=None, layer_shift=0, rebuild=1)
  4649. Creates an EPS file describing a packet. If filename is not provided a temporary file is created and gs is called."""
  4650. canvas = self.canvas_dump(**kargs)
  4651. if filename is None:
  4652. fname = "/tmp/scapy.%i"%os.getpid()
  4653. canvas.writeEPSfile(fname)
  4654. os.system("%s '%s.eps' &" % (conf.prog.psreader,fname))
  4655. else:
  4656. canvas.writeEPSfile(filename)
  4657. def pdfdump(self, filename=None, **kargs):
  4658. """pdfdump(filename=None, layer_shift=0, rebuild=1)
  4659. Creates a PDF file describing a packet. If filename is not provided a temporary file is created and xpdf is called."""
  4660. canvas = self.canvas_dump(**kargs)
  4661. if filename is None:
  4662. fname = "/tmp/scapy.%i"%os.getpid()
  4663. canvas.writePDFfile(fname)
  4664. os.system("%s '%s.pdf' &" % (conf.prog.pdfreader,fname))
  4665. else:
  4666. canvas.writePDFfile(filename)
  4667. def canvas_dump(self, layer_shift=0, rebuild=1):
  4668. canvas = pyx.canvas.canvas()
  4669. if rebuild:
  4670. p,t = self.__class__(str(self)).build_ps()
  4671. else:
  4672. p,t = self.build_ps()
  4673. YTXT=len(t)
  4674. for n,l in t:
  4675. YTXT += len(l)
  4676. YTXT = float(YTXT)
  4677. YDUMP=YTXT
  4678. XSTART = 1
  4679. XDSTART = 10
  4680. y = 0.0
  4681. yd = 0.0
  4682. xd = 0
  4683. XMUL= 0.55
  4684. YMUL = 0.4
  4685. backcolor=colgen(0.6, 0.8, 1.0, trans=pyx.color.rgb)
  4686. forecolor=colgen(0.2, 0.5, 0.8, trans=pyx.color.rgb)
  4687. # backcolor=makecol(0.376, 0.729, 0.525, 1.0)
  4688. def hexstr(x):
  4689. s = []
  4690. for c in x:
  4691. s.append("%02x" % ord(c))
  4692. return " ".join(s)
  4693. def make_dump_txt(x,y,txt):
  4694. return pyx.text.text(XDSTART+x*XMUL, (YDUMP-y)*YMUL, r"\tt{%s}"%hexstr(txt), [pyx.text.size.Large])
  4695. def make_box(o):
  4696. return pyx.box.rect(o.left(), o.bottom(), o.width(), o.height(), relcenter=(0.5,0.5))
  4697. def make_frame(lst):
  4698. if len(lst) == 1:
  4699. b = lst[0].bbox()
  4700. b.enlarge(pyx.unit.u_pt)
  4701. return b.path()
  4702. else:
  4703. fb = lst[0].bbox()
  4704. fb.enlarge(pyx.unit.u_pt)
  4705. lb = lst[-1].bbox()
  4706. lb.enlarge(pyx.unit.u_pt)
  4707. if len(lst) == 2 and fb.left() > lb.right():
  4708. return pyx.path.path(pyx.path.moveto(fb.right(), fb.top()),
  4709. pyx.path.lineto(fb.left(), fb.top()),
  4710. pyx.path.lineto(fb.left(), fb.bottom()),
  4711. pyx.path.lineto(fb.right(), fb.bottom()),
  4712. pyx.path.moveto(lb.left(), lb.top()),
  4713. pyx.path.lineto(lb.right(), lb.top()),
  4714. pyx.path.lineto(lb.right(), lb.bottom()),
  4715. pyx.path.lineto(lb.left(), lb.bottom()))
  4716. else:
  4717. # XXX
  4718. gb = lst[1].bbox()
  4719. if gb != lb:
  4720. gb.enlarge(pyx.unit.u_pt)
  4721. kb = lst[-2].bbox()
  4722. if kb != gb and kb != lb:
  4723. kb.enlarge(pyx.unit.u_pt)
  4724. return pyx.path.path(pyx.path.moveto(fb.left(), fb.top()),
  4725. pyx.path.lineto(fb.right(), fb.top()),
  4726. pyx.path.lineto(fb.right(), kb.bottom()),
  4727. pyx.path.lineto(lb.right(), kb.bottom()),
  4728. pyx.path.lineto(lb.right(), lb.bottom()),
  4729. pyx.path.lineto(lb.left(), lb.bottom()),
  4730. pyx.path.lineto(lb.left(), gb.top()),
  4731. pyx.path.lineto(fb.left(), gb.top()),
  4732. pyx.path.closepath(),)
  4733. def make_dump(s, shift=0, y=0, col=None, bkcol=None, larg=16):
  4734. c = pyx.canvas.canvas()
  4735. tlist = []
  4736. while s:
  4737. dmp,s = s[:larg-shift],s[larg-shift:]
  4738. txt = make_dump_txt(shift, y, dmp)
  4739. tlist.append(txt)
  4740. shift += len(dmp)
  4741. if shift >= 16:
  4742. shift = 0
  4743. y += 1
  4744. if col is None:
  4745. col = pyx.color.rgb.red
  4746. if bkcol is None:
  4747. col = pyx.color.rgb.white
  4748. c.stroke(make_frame(tlist),[col,pyx.deco.filled([bkcol]),pyx.style.linewidth.Thick])
  4749. for txt in tlist:
  4750. c.insert(txt)
  4751. return c, tlist[-1].bbox(), shift, y
  4752. last_shift,last_y=0,0.0
  4753. while t:
  4754. bkcol = backcolor.next()
  4755. proto,fields = t.pop()
  4756. y += 0.5
  4757. pt = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % proto.name, [ pyx.text.size.Large])
  4758. y += 1
  4759. ptbb=pt.bbox()
  4760. ptbb.enlarge(pyx.unit.u_pt*2)
  4761. canvas.stroke(ptbb.path(),[pyx.color.rgb.black, pyx.deco.filled([bkcol])])
  4762. canvas.insert(pt)
  4763. for fname, fval, fdump in fields:
  4764. col = forecolor.next()
  4765. ft = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fname.name))
  4766. if fval is not None:
  4767. if len(fval) > 18:
  4768. fval = fval[:18]+"[...]"
  4769. else:
  4770. fval=""
  4771. vt = pyx.text.text(XSTART+3, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fval))
  4772. y += 1.0
  4773. if fdump:
  4774. dt,target,last_shift,last_y = make_dump(fdump, last_shift, last_y, col, bkcol)
  4775. dtb = dt.bbox()
  4776. dtb=target
  4777. vtb = vt.bbox()
  4778. bxvt = make_box(vtb)
  4779. bxdt = make_box(dtb)
  4780. dtb.enlarge(pyx.unit.u_pt)
  4781. try:
  4782. if yd < 0:
  4783. cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=-90)
  4784. else:
  4785. cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=90)
  4786. except:
  4787. pass
  4788. else:
  4789. canvas.stroke(cnx,[pyx.style.linewidth.thin,pyx.deco.earrow.small,col])
  4790. canvas.insert(dt)
  4791. canvas.insert(ft)
  4792. canvas.insert(vt)
  4793. last_y += layer_shift
  4794. return canvas
  4795. def extract_padding(self, s):
  4796. """DEV: to be overloaded to extract current layer's padding. Return a couple of strings (actual layer, padding)"""
  4797. return s,None
  4798. def post_dissect(self, s):
  4799. """DEV: is called right after the current layer has been dissected"""
  4800. return s
  4801. def pre_dissect(self, s):
  4802. """DEV: is called right before the current layer is dissected"""
  4803. return s
  4804. def do_dissect(self, s):
  4805. s = self.pre_dissect(s)
  4806. flist = self.fields_desc[:]
  4807. flist.reverse()
  4808. while s and flist:
  4809. f = flist.pop()
  4810. s,fval = f.getfield(self, s)
  4811. self.fields[f] = fval
  4812. s = self.post_dissect(s)
  4813. payl,pad = self.extract_padding(s)
  4814. self.do_dissect_payload(payl)
  4815. if pad and conf.padding:
  4816. self.add_payload(Padding(pad))
  4817. def do_dissect_payload(self, s):
  4818. if s:
  4819. cls = self.guess_payload_class(s)
  4820. try:
  4821. p = cls(s, _internal=1, _underlayer=self)
  4822. except:
  4823. if conf.debug_dissector:
  4824. if type(cls) is type and issubclass(cls,Packet):
  4825. log_runtime.error("%s dissector failed" % cls.name)
  4826. else:
  4827. log_runtime.error("%s.guess_payload_class() returned [%s]" % (self.__class__.__name__,repr(cls)))
  4828. if cls is not None:
  4829. raise
  4830. p = Raw(s, _internal=1, _underlayer=self)
  4831. self.add_payload(p)
  4832. def dissect(self, s):
  4833. return self.do_dissect(s)
  4834. def guess_payload_class(self, payload):
  4835. """DEV: Guesses the next payload class from layer bonds. Can be overloaded to use a different mechanism."""
  4836. for t in self.aliastypes:
  4837. for fval, cls in t.payload_guess:
  4838. ok = 1
  4839. for k in fval.keys():
  4840. if not hasattr(self, k) or fval[k] != self.getfieldval(k):
  4841. ok = 0
  4842. break
  4843. if ok:
  4844. return cls
  4845. return self.default_payload_class(payload)
  4846. def default_payload_class(self, payload):
  4847. """DEV: Returns the default payload class if nothing has been found by the guess_payload_class() method."""
  4848. return Raw
  4849. def hide_defaults(self):
  4850. """Removes fields' values that are the same as default values."""
  4851. for k in self.fields.keys():
  4852. if self.default_fields.has_key(k):
  4853. if self.default_fields[k] == self.fields[k]:
  4854. del(self.fields[k])
  4855. self.payload.hide_defaults()
  4856. def __iter__(self):
  4857. def loop(todo, done, self=self):
  4858. if todo:
  4859. eltname = todo.pop()
  4860. elt = self.getfieldval(eltname)
  4861. if not isinstance(elt, Gen):
  4862. if self.fieldtype[eltname].islist:
  4863. elt = SetGen([elt])
  4864. else:
  4865. elt = SetGen(elt)
  4866. for e in elt:
  4867. done[eltname]=e
  4868. for x in loop(todo[:], done):
  4869. yield x
  4870. else:
  4871. if isinstance(self.payload,NoPayload):
  4872. payloads = [None]
  4873. else:
  4874. payloads = self.payload
  4875. for payl in payloads:
  4876. done2=done.copy()
  4877. for k in done2:
  4878. if isinstance(done2[k], VolatileValue):
  4879. done2[k] = done2[k]._fix()
  4880. pkt = self.__class__()
  4881. pkt.fields = done2
  4882. pkt.time = self.time
  4883. pkt.underlayer = self.underlayer
  4884. pkt.overload_fields = self.overload_fields.copy()
  4885. if payl is None:
  4886. yield pkt
  4887. else:
  4888. yield pkt/payl
  4889. todo = map(lambda (x,y):x, filter(lambda (x,y):isinstance(y,VolatileValue), self.default_fields.items()))
  4890. todo += map(lambda (x,y):x, filter(lambda (x,y):isinstance(y,VolatileValue), self.overloaded_fields.items()))
  4891. todo += self.fields.keys()
  4892. return loop(map(lambda x:str(x), todo), {})
  4893. def __gt__(self, other):
  4894. """True if other is an answer from self (self ==> other)."""
  4895. if isinstance(other, Packet):
  4896. return other < self
  4897. elif type(other) is str:
  4898. return 1
  4899. else:
  4900. raise TypeError((self, other))
  4901. def __lt__(self, other):
  4902. """True if self is an answer from other (other ==> self)."""
  4903. if isinstance(other, Packet):
  4904. return self.answers(other)
  4905. elif type(other) is str:
  4906. return 1
  4907. else:
  4908. raise TypeError((self, other))
  4909. def __eq__(self, other):
  4910. if not isinstance(other, self.__class__):
  4911. return False
  4912. for f in self.fields_desc:
  4913. if f not in other.fields_desc:
  4914. return False
  4915. if self.getfieldval(f.name) != other.getfieldval(f.name):
  4916. return False
  4917. return self.payload == other.payload
  4918. def __ne__(self, other):
  4919. return not self.__eq__(other)
  4920. def hashret(self):
  4921. """DEV: returns a string that has the same value for a request and its answer."""
  4922. return self.payload.hashret()
  4923. def answers(self, other):
  4924. """DEV: true if self is an answer from other"""
  4925. if other.__class__ == self.__class__:
  4926. return self.payload.answers(other.payload)
  4927. return 0
  4928. def haslayer(self, cls):
  4929. """true if self has a layer that is an instance of cls. Superseded by "cls in self" syntax."""
  4930. if self.__class__ == cls or self.__class__.__name__ == cls:
  4931. return 1
  4932. for f in self.packetfields:
  4933. fvalue_gen = self.getfieldval(f)
  4934. if fvalue_gen is None:
  4935. continue
  4936. if not f.islist:
  4937. fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
  4938. for fvalue in fvalue_gen:
  4939. if isinstance(fvalue, Packet):
  4940. ret = fvalue.haslayer(cls)
  4941. if ret:
  4942. return ret
  4943. return self.payload.haslayer(cls)
  4944. def getlayer(self, cls, nb=1, _track=None):
  4945. """Return the nb^th layer that is an instance of cls."""
  4946. if type(cls) is str and "." in cls:
  4947. ccls,fld = cls.split(".",1)
  4948. else:
  4949. ccls,fld = cls,None
  4950. if self.__class__ == cls or self.__class__.name == ccls:
  4951. if nb == 1:
  4952. if fld is None:
  4953. return self
  4954. else:
  4955. return self.getfieldval(fld)
  4956. else:
  4957. nb -=1
  4958. for f in self.packetfields:
  4959. fvalue_gen = self.getfieldval(f)
  4960. if fvalue_gen is None:
  4961. continue
  4962. if not f.islist:
  4963. fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
  4964. for fvalue in fvalue_gen:
  4965. if isinstance(fvalue, Packet):
  4966. track=[]
  4967. ret = fvalue.getlayer(cls, nb, _track=track)
  4968. if ret is not None:
  4969. return ret
  4970. nb = track[0]
  4971. return self.payload.getlayer(cls,nb,_track=_track)
  4972. def __getitem__(self, cls):
  4973. if type(cls) is slice:
  4974. if cls.stop:
  4975. ret = self.getlayer(cls.start, cls.stop)
  4976. else:
  4977. ret = self.getlayer(cls.start)
  4978. if ret is None and cls.step is not None:
  4979. ret = cls.step
  4980. return ret
  4981. else:
  4982. return self.getlayer(cls)
  4983. def __contains__(self, cls):
  4984. """"cls in self" returns true if self has a layer which is an instance of cls."""
  4985. return self.haslayer(cls)
  4986. def display(self,*args,**kargs): # Deprecated. Use show()
  4987. """Deprecated. Use show() method."""
  4988. self.show(*args,**kargs)
  4989. def show(self, indent=3, lvl="", label_lvl=""):
  4990. """Prints a hierarchical view of the packet. "indent" gives the size of indentation for each layer."""
  4991. ct = conf.color_theme
  4992. print "%s%s %s %s" % (label_lvl,
  4993. ct.punct("###["),
  4994. ct.layer_name(self.name),
  4995. ct.punct("]###"))
  4996. for f in self.fields_desc:
  4997. if isinstance(f, Emph):
  4998. ncol = ct.emph_field_name
  4999. vcol = ct.emph_field_value
  5000. else:
  5001. ncol = ct.field_name
  5002. vcol = ct.field_value
  5003. fvalue = self.__getattr__(f)
  5004. if isinstance(fvalue, Packet) or isinstance(f, PacketListField):
  5005. print "%s \\%-10s\\" % (label_lvl+lvl, ncol(f.name))
  5006. fvalue_gen = SetGen(self.__getattr__(f),_iterpacket=0)
  5007. for fvalue in fvalue_gen:
  5008. fvalue.show(indent=indent, label_lvl=label_lvl+lvl+" |")
  5009. else:
  5010. print "%s %-10s%s %s" % (label_lvl+lvl,
  5011. ncol(f.name),
  5012. ct.punct("="),
  5013. vcol(f.i2repr(self,fvalue)))
  5014. self.payload.show(indent=indent, lvl=lvl+(" "*indent*self.show_indent), label_lvl=label_lvl)
  5015. def show2(self):
  5016. """Prints a hierarchical view of an assembled version of the packet, so that automatic fields are calculated (checksums, etc.)"""
  5017. self.__class__(str(self)).show()
  5018. def sprintf(self, fmt, relax=1):
  5019. """sprintf(format, [relax=1]) -> str
  5020. where format is a string that can include directives. A directive begins and
  5021. ends by % and has the following format %[fmt[r],][cls[:nb].]field%.
  5022. fmt is a classic printf directive, "r" can be appended for raw substitution
  5023. (ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want
  5024. (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer).
  5025. Special case : "%.time%" is the creation time.
  5026. Ex : p.sprintf("%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% "
  5027. "%03xr,IP.proto% %r,TCP.flags%")
  5028. Moreover, the format string can include conditionnal statements. A conditionnal
  5029. statement looks like : {layer:string} where layer is a layer name, and string
  5030. is the string to insert in place of the condition if it is true, i.e. if layer
  5031. is present. If layer is preceded by a "!", the result si inverted. Conditions
  5032. can be imbricated. A valid statement can be :
  5033. p.sprintf("This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet")
  5034. p.sprintf("{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}")
  5035. A side effect is that, to obtain "{" and "}" characters, you must use
  5036. "%(" and "%)".
  5037. """
  5038. escape = { "%": "%",
  5039. "(": "{",
  5040. ")": "}" }
  5041. # Evaluate conditions
  5042. while "{" in fmt:
  5043. i = fmt.rindex("{")
  5044. j = fmt[i+1:].index("}")
  5045. cond = fmt[i+1:i+j+1]
  5046. k = cond.find(":")
  5047. if k < 0:
  5048. raise Exception("Bad condition in format string: [%s] (read sprintf doc!)"%cond)
  5049. cond,format = cond[:k],cond[k+1:]
  5050. res = False
  5051. if cond[0] == "!":
  5052. res = True
  5053. cond = cond[1:]
  5054. if self.haslayer(cond):
  5055. res = not res
  5056. if not res:
  5057. format = ""
  5058. fmt = fmt[:i]+format+fmt[i+j+2:]
  5059. # Evaluate directives
  5060. s = ""
  5061. while "%" in fmt:
  5062. i = fmt.index("%")
  5063. s += fmt[:i]
  5064. fmt = fmt[i+1:]
  5065. if fmt[0] in escape:
  5066. s += escape[fmt[0]]
  5067. fmt = fmt[1:]
  5068. continue
  5069. try:
  5070. i = fmt.index("%")
  5071. sfclsfld = fmt[:i]
  5072. fclsfld = sfclsfld.split(",")
  5073. if len(fclsfld) == 1:
  5074. f = "s"
  5075. clsfld = fclsfld[0]
  5076. elif len(fclsfld) == 2:
  5077. f,clsfld = fclsfld
  5078. else:
  5079. raise Exception
  5080. if "." in clsfld:
  5081. cls,fld = clsfld.split(".")
  5082. else:
  5083. cls = self.__class__.__name__
  5084. fld = clsfld
  5085. num = 1
  5086. if ":" in cls:
  5087. cls,num = cls.split(":")
  5088. num = int(num)
  5089. fmt = fmt[i+1:]
  5090. except:
  5091. raise Exception("Bad format string [%%%s%s]" % (fmt[:25], fmt[25:] and "..."))
  5092. else:
  5093. if fld == "time":
  5094. val = time.strftime("%H:%M:%S.%%06i", time.localtime(self.time)) % int((self.time-int(self.time))*1000000)
  5095. elif cls == self.__class__.__name__ and hasattr(self, fld):
  5096. if num > 1:
  5097. val = self.payload.sprintf("%%%s,%s:%s.%s%%" % (f,cls,num-1,fld), relax)
  5098. f = "s"
  5099. elif f[-1] == "r": # Raw field value
  5100. val = getattr(self,fld)
  5101. f = f[:-1]
  5102. if not f:
  5103. f = "s"
  5104. else:
  5105. val = getattr(self,fld)
  5106. if fld in self.fieldtype:
  5107. val = self.fieldtype[fld].i2repr(self,val)
  5108. else:
  5109. val = self.payload.sprintf("%%%s%%" % sfclsfld, relax)
  5110. f = "s"
  5111. s += ("%"+f) % val
  5112. s += fmt
  5113. return s
  5114. def mysummary(self):
  5115. """DEV: can be overloaded to return a string that summarizes the layer.
  5116. Only one mysummary() is used in a whole packet summary: the one of the upper layer,
  5117. except if a mysummary() also returns (as a couple) a list of layers whose
  5118. mysummary() must be called if they are present."""
  5119. return ""
  5120. def summary(self, intern=0):
  5121. """Prints a one line summary of a packet."""
  5122. found,s,needed = self.payload.summary(intern=1)
  5123. if s:
  5124. s = " / "+s
  5125. ret = ""
  5126. if not found or self.__class__ in needed:
  5127. ret = self.mysummary()
  5128. if type(ret) is tuple:
  5129. ret,n = ret
  5130. needed += n
  5131. if ret or needed:
  5132. found = 1
  5133. if not ret:
  5134. ret = self.__class__.__name__
  5135. ret = "%s%s" % (ret,s)
  5136. if intern:
  5137. return found,ret,needed
  5138. else:
  5139. return ret
  5140. def lastlayer(self,layer=None):
  5141. """Returns the uppest layer of the packet"""
  5142. return self.payload.lastlayer(self)
  5143. def decode_payload_as(self,cls):
  5144. """Reassembles the payload and decode it using another packet class"""
  5145. s = str(self.payload)
  5146. self.payload = cls(s)
  5147. def libnet(self):
  5148. """Not ready yet. Should give the necessary C code that interfaces with libnet to recreate the packet"""
  5149. print "libnet_build_%s(" % self.__class__.name.lower()
  5150. det = self.__class__(str(self))
  5151. for f in self.fields_desc:
  5152. val = getattr(det, f.name)
  5153. if val is None:
  5154. val = 0
  5155. elif type(val) is int:
  5156. val = str(val)
  5157. else:
  5158. val = '"%s"' % str(val)
  5159. print "\t%s, \t\t/* %s */" % (val,f.name)
  5160. print ");"
  5161. def command(self):
  5162. """Returns a string representing the command you have to type to obtain the same packet"""
  5163. f = []
  5164. for fn,fv in self.fields.items():
  5165. if isinstance(fv, Packet):
  5166. fv = fv.command()
  5167. else:
  5168. fv = repr(fv)
  5169. f.append("%s=%s" % (fn, fv))
  5170. c = "%s(%s)" % (self.__class__.__name__, ", ".join(f))
  5171. pc = self.payload.command()
  5172. if pc:
  5173. c += "/"+pc
  5174. return c
  5175. class NoPayload(Packet,object):
  5176. def __new__(cls, *args, **kargs):
  5177. singl = cls.__dict__.get("__singl__")
  5178. if singl is None:
  5179. cls.__singl__ = singl = object.__new__(cls)
  5180. Packet.__init__(singl, *args, **kargs)
  5181. return singl
  5182. def __init__(self, *args, **kargs):
  5183. pass
  5184. def dissection_done(self,pkt):
  5185. return
  5186. def add_payload(self, payload):
  5187. raise Exception("Can't add payload to NoPayload instance")
  5188. def remove_payload(self):
  5189. pass
  5190. def add_underlayer(self,underlayer):
  5191. pass
  5192. def remove_underlayer(self,other):
  5193. pass
  5194. def copy(self):
  5195. return self
  5196. def __repr__(self):
  5197. return ""
  5198. def __str__(self):
  5199. return ""
  5200. def __nonzero__(self):
  5201. return False
  5202. def build(self, internal=0):
  5203. return ""
  5204. def build_ps(self, internal=0):
  5205. return "",[]
  5206. def getfieldval(self, attr):
  5207. raise AttributeError(attr)
  5208. def __getattr__(self, attr):
  5209. if attr in self.__dict__:
  5210. return self.__dict__[attr]
  5211. elif attr in self.__class__.__dict__:
  5212. return self.__class__.__dict__[attr]
  5213. else:
  5214. raise AttributeError, attr
  5215. def hide_defaults(self):
  5216. pass
  5217. def __iter__(self):
  5218. return iter([])
  5219. def __eq__(self, other):
  5220. if isinstance(other, NoPayload):
  5221. return True
  5222. return False
  5223. def hashret(self):
  5224. return ""
  5225. def answers(self, other):
  5226. return isinstance(other, NoPayload) or isinstance(other, Padding)
  5227. def haslayer(self, cls):
  5228. return 0
  5229. def getlayer(self, cls, nb=1, _track=None):
  5230. if _track is not None:
  5231. _track.append(nb)
  5232. return None
  5233. def show(self, indent=3, lvl="", label_lvl=""):
  5234. pass
  5235. def sprintf(self, fmt, relax):
  5236. if relax:
  5237. return "??"
  5238. else:
  5239. raise Exception("Format not found [%s]"%fmt)
  5240. def summary(self, intern=0):
  5241. return 0,"",[]
  5242. def lastlayer(self,layer):
  5243. return layer
  5244. def command(self):
  5245. return ""
  5246. ####################
  5247. ## packet classes ##
  5248. ####################
  5249. class ChangeDefaultValues(type):
  5250. def __new__(cls, name, bases, dct):
  5251. default = dct["new_default_values"]
  5252. fields = None
  5253. for b in bases:
  5254. if hasattr(b,"fields_desc"):
  5255. fields = b.fields_desc[:]
  5256. break
  5257. if fields is None:
  5258. raise Exception("No fields_desc in superclasses")
  5259. del(dct["new_default_values"])
  5260. new_fields = []
  5261. for f in fields:
  5262. if f in default:
  5263. f = f.copy()
  5264. f.default = default[f]
  5265. new_fields.append(f)
  5266. dct["fields_desc"] = new_fields
  5267. return super(ChangeDefaultValues, cls).__new__(cls, name, bases, dct)
  5268. # Metaclass
  5269. class NewDefaultValues(type):
  5270. def __new__(cls, name, bases, dct):
  5271. fields = None
  5272. for b in bases:
  5273. if hasattr(b,"fields_desc"):
  5274. fields = b.fields_desc[:]
  5275. break
  5276. if fields is None:
  5277. raise Exception("No fields_desc in superclasses")
  5278. new_fields = []
  5279. for f in fields:
  5280. if f in dct:
  5281. f = f.copy()
  5282. f.default = dct[f]
  5283. del(dct[f])
  5284. new_fields.append(f)
  5285. dct["fields_desc"] = new_fields
  5286. return super(NewDefaultValues, cls).__new__(cls, name, bases, dct)
  5287. class Raw(Packet):
  5288. name = "Raw"
  5289. fields_desc = [ StrField("load", "") ]
  5290. def answers(self, other):
  5291. return 1
  5292. # s = str(other)
  5293. # t = self.load
  5294. # l = min(len(s), len(t))
  5295. # return s[:l] == t[:l]
  5296. class Padding(Raw):
  5297. name = "Padding"
  5298. def build(self, internal=0):
  5299. if internal:
  5300. return ""
  5301. else:
  5302. return Raw.build(self)
  5303. class Ether(Packet):
  5304. name = "Ethernet"
  5305. fields_desc = [ DestMACField("dst"),
  5306. SourceMACField("src"),
  5307. XShortEnumField("type", 0x0000, ETHER_TYPES) ]
  5308. def hashret(self):
  5309. return struct.pack("H",self.type)+self.payload.hashret()
  5310. def answers(self, other):
  5311. if isinstance(other,Ether):
  5312. if self.type == other.type:
  5313. return self.payload.answers(other.payload)
  5314. return 0
  5315. def mysummary(self):
  5316. return self.sprintf("%Ether.src% > %Ether.dst% (%Ether.type%)")
  5317. class PPPoE(Packet):
  5318. name = "PPP over Ethernet"
  5319. fields_desc = [ BitField("version", 1, 4),
  5320. BitField("type", 1, 4),
  5321. ByteEnumField("code", 0, {0:"Session"}),
  5322. XShortField("sessionid", 0x0),
  5323. ShortField("len", None) ]
  5324. def post_build(self, p, pay):
  5325. p += pay
  5326. if self.len is None:
  5327. l = len(p)-6
  5328. p = p[:4]+struct.pack("!H", l)+p[6:]
  5329. return p
  5330. class PPPoED(PPPoE):
  5331. name = "PPP over Ethernet Discovery"
  5332. fields_desc = [ BitField("version", 1, 4),
  5333. BitField("type", 1, 4),
  5334. ByteEnumField("code", 0x09, {0x09:"PADI",0x07:"PADO",0x19:"PADR",0x65:"PADS",0xa7:"PADT"}),
  5335. XShortField("sessionid", 0x0),
  5336. ShortField("len", None) ]
  5337. class Dot3(Packet):
  5338. name = "802.3"
  5339. fields_desc = [ MACField("dst", ETHER_BROADCAST),
  5340. MACField("src", ETHER_ANY),
  5341. LenField("len", None, "H") ]
  5342. def extract_padding(self,s):
  5343. l = self.len
  5344. return s[:l],s[l:]
  5345. def answers(self, other):
  5346. if isinstance(other,Dot3):
  5347. return self.payload.answers(other.payload)
  5348. return 0
  5349. def mysummary(self):
  5350. return "802.3 %s > %s" % (self.src, self.dst)
  5351. class LLC(Packet):
  5352. name = "LLC"
  5353. fields_desc = [ XByteField("dsap", 0x00),
  5354. XByteField("ssap", 0x00),
  5355. ByteField("ctrl", 0) ]
  5356. class CookedLinux(Packet):
  5357. name = "cooked linux"
  5358. fields_desc = [ ShortEnumField("pkttype",0, {0: "unicast",
  5359. 4:"sent-by-us"}), #XXX incomplete
  5360. XShortField("lladdrtype",512),
  5361. ShortField("lladdrlen",0),
  5362. StrFixedLenField("src","",8),
  5363. XShortEnumField("proto",0x800,ETHER_TYPES) ]
  5364. class SNAP(Packet):
  5365. name = "SNAP"
  5366. fields_desc = [ X3BytesField("OUI",0x000000),
  5367. XShortEnumField("code", 0x000, ETHER_TYPES) ]
  5368. class Dot1Q(Packet):
  5369. name = "802.1Q"
  5370. aliastypes = [ Ether ]
  5371. fields_desc = [ BitField("prio", 0, 3),
  5372. BitField("id", 0, 1),
  5373. BitField("vlan", 1, 12),
  5374. XShortEnumField("type", 0x0000, ETHER_TYPES) ]
  5375. def answers(self, other):
  5376. if isinstance(other,Dot1Q):
  5377. if ( (self.type == other.type) and
  5378. (self.vlan == other.vlan) ):
  5379. return self.payload.answers(other.payload)
  5380. else:
  5381. return self.payload.answers(other)
  5382. return 0
  5383. def default_payload_class(self, pay):
  5384. if self.type < 1500:
  5385. return LLC
  5386. return Raw
  5387. def extract_padding(self,s):
  5388. if self.type < 1500:
  5389. return s[:self.type],s[self.type:]
  5390. return s,None
  5391. def mysummary(self):
  5392. if isinstance(self.underlayer, Ether):
  5393. return self.underlayer.sprintf("802.1q %Ether.src% > %Ether.dst% (%Dot1Q.type%) vlan %Dot1Q.vlan%")
  5394. else:
  5395. return self.sprintf("802.1q (%Dot1Q.type%) vlan %Dot1Q.vlan%")
  5396. class STP(Packet):
  5397. name = "Spanning Tree Protocol"
  5398. fields_desc = [ ShortField("proto", 0),
  5399. ByteField("version", 0),
  5400. ByteField("bpdutype", 0),
  5401. ByteField("bpduflags", 0),
  5402. ShortField("rootid", 0),
  5403. MACField("rootmac", ETHER_ANY),
  5404. IntField("pathcost", 0),
  5405. ShortField("bridgeid", 0),
  5406. MACField("bridgemac", ETHER_ANY),
  5407. ShortField("portid", 0),
  5408. ShortField("age", 1),
  5409. BCDFloatField("maxage", 20),
  5410. BCDFloatField("hellotime", 2),
  5411. BCDFloatField("fwddelay", 15) ]
  5412. class EAPOL(Packet):
  5413. name = "EAPOL"
  5414. fields_desc = [ ByteField("version", 1),
  5415. ByteEnumField("type", 0, ["EAP_PACKET", "START", "LOGOFF", "KEY", "ASF"]),
  5416. LenField("len", None, "H") ]
  5417. EAP_PACKET= 0
  5418. START = 1
  5419. LOGOFF = 2
  5420. KEY = 3
  5421. ASF = 4
  5422. def extract_padding(self, s):
  5423. l = self.len
  5424. return s[:l],s[l:]
  5425. def hashret(self):
  5426. return chr(self.type)+self.payload.hashret()
  5427. def answers(self, other):
  5428. if isinstance(other,EAPOL):
  5429. if ( (self.type == self.EAP_PACKET) and
  5430. (other.type == self.EAP_PACKET) ):
  5431. return self.payload.answers(other.payload)
  5432. return 0
  5433. def mysummary(self):
  5434. return self.sprintf("EAPOL %EAPOL.type%")
  5435. class EAP(Packet):
  5436. name = "EAP"
  5437. fields_desc = [ ByteEnumField("code", 4, {1:"REQUEST",2:"RESPONSE",3:"SUCCESS",4:"FAILURE"}),
  5438. ByteField("id", 0),
  5439. ByteEnumField("type",0, {1:"ID",4:"MD5"}),
  5440. ByteField("len",None)]
  5441. REQUEST = 1
  5442. RESPONSE = 2
  5443. SUCCESS = 3
  5444. FAILURE = 4
  5445. TYPE_ID = 1
  5446. TYPE_MD5 = 4
  5447. def answers(self, other):
  5448. if isinstance(other,EAP):
  5449. if self.code == self.REQUEST:
  5450. return 0
  5451. elif self.code == self.RESPONSE:
  5452. if ( (other.code == self.REQUEST) and
  5453. (other.type == self.type) ):
  5454. return 1
  5455. elif other.code == self.RESPONSE:
  5456. return 1
  5457. return 0
  5458. def build(self,internal=0):
  5459. l = self.len
  5460. if self.code in [EAP.SUCCESS, EAP.FAILURE]:
  5461. if l is None:
  5462. l = 4
  5463. return struct.pack("!BBH",
  5464. self.code,
  5465. self.id,
  5466. l)+str(self.payload)
  5467. else:
  5468. payl = str(self.payload)
  5469. if l is None:
  5470. l = 5+len(payl)
  5471. return struct.pack("!BBHB",
  5472. self.code,
  5473. self.id,
  5474. l,
  5475. self.type)+payl
  5476. class ARP(Packet):
  5477. name = "ARP"
  5478. fields_desc = [ XShortField("hwtype", 0x0001),
  5479. XShortEnumField("ptype", 0x0800, ETHER_TYPES),
  5480. ByteField("hwlen", 6),
  5481. ByteField("plen", 4),
  5482. ShortEnumField("op", 1, {"who-has":1, "is-at":2, "RARP-req":3, "RARP-rep":4, "Dyn-RARP-req":5, "Dyn-RAR-rep":6, "Dyn-RARP-err":7, "InARP-req":8, "InARP-rep":9}),
  5483. ARPSourceMACField("hwsrc"),
  5484. SourceIPField("psrc","pdst"),
  5485. MACField("hwdst", ETHER_ANY),
  5486. IPField("pdst", "0.0.0.0") ]
  5487. who_has = 1
  5488. is_at = 2
  5489. def answers(self, other):
  5490. if isinstance(other,ARP):
  5491. if ( (self.op == self.is_at) and
  5492. (other.op == self.who_has) and
  5493. (self.psrc == other.pdst) ):
  5494. return 1
  5495. return 0
  5496. def extract_padding(self, s):
  5497. return "",s
  5498. def mysummary(self):
  5499. if self.op == self.is_at:
  5500. return "ARP is at %s says %s" % (self.hwsrc, self.psrc)
  5501. elif self.op == self.who_has:
  5502. return "ARP who has %s says %s" % (self.pdst, self.psrc)
  5503. else:
  5504. return "ARP %ARP.op% %ARP.psrc% > %ARP.pdst%"
  5505. class IP(Packet, IPTools):
  5506. name = "IP"
  5507. fields_desc = [ BitField("version" , 4 , 4),
  5508. BitField("ihl", None, 4),
  5509. XByteField("tos", 0),
  5510. ShortField("len", None),
  5511. ShortField("id", 1),
  5512. FlagsField("flags", 0, 3, ["MF","DF","evil"]),
  5513. BitField("frag", 0, 13),
  5514. ByteField("ttl", 64),
  5515. ByteEnumField("proto", 0, IP_PROTOS),
  5516. XShortField("chksum", None),
  5517. #IPField("src", "127.0.0.1"),
  5518. Emph(SourceIPField("src","dst")),
  5519. Emph(IPField("dst", "127.0.0.1")),
  5520. IPoptionsField("options", "") ]
  5521. def post_build(self, p, pay):
  5522. ihl = self.ihl
  5523. if ihl is None:
  5524. ihl = len(p)/4
  5525. p = chr((self.version<<4) | ihl&0x0f)+p[1:]
  5526. if self.len is None:
  5527. l = len(p)+len(pay)
  5528. p = p[:2]+struct.pack("!H", l)+p[4:]
  5529. if self.chksum is None:
  5530. ck = checksum(p)
  5531. p = p[:10]+chr(ck>>8)+chr(ck&0xff)+p[12:]
  5532. return p+pay
  5533. def extract_padding(self, s):
  5534. l = self.len - (self.ihl << 2)
  5535. return s[:l],s[l:]
  5536. def send(self, s, slp=0):
  5537. for p in self:
  5538. try:
  5539. s.sendto(str(p), (p.dst,0))
  5540. except socket.error, msg:
  5541. log_runtime.error(msg)
  5542. if slp:
  5543. time.sleep(slp)
  5544. def hashret(self):
  5545. if ( (self.proto == socket.IPPROTO_ICMP)
  5546. and (isinstance(self.payload, ICMP))
  5547. and (self.payload.type in [3,4,5,11,12]) ):
  5548. return self.payload.payload.hashret()
  5549. else:
  5550. if conf.checkIPsrc and conf.checkIPaddr:
  5551. return strxor(inet_aton(self.src),inet_aton(self.dst))+struct.pack("B",self.proto)+self.payload.hashret()
  5552. else:
  5553. return struct.pack("B", self.proto)+self.payload.hashret()
  5554. def answers(self, other):
  5555. if not isinstance(other,IP):
  5556. return 0
  5557. if conf.checkIPaddr and (self.dst != other.src):
  5558. return 0
  5559. if ( (self.proto == socket.IPPROTO_ICMP) and
  5560. (isinstance(self.payload, ICMP)) and
  5561. (self.payload.type in [3,4,5,11,12]) ):
  5562. # ICMP error message
  5563. return self.payload.payload.answers(other)
  5564. else:
  5565. if ( (conf.checkIPaddr and (self.src != other.dst)) or
  5566. (self.proto != other.proto) ):
  5567. return 0
  5568. return self.payload.answers(other.payload)
  5569. def mysummary(self):
  5570. return self.sprintf("%IP.src% > %IP.dst% %IP.proto%")
  5571. class TCP(Packet):
  5572. name = "TCP"
  5573. fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES),
  5574. ShortEnumField("dport", 80, TCP_SERVICES),
  5575. IntField("seq", 0),
  5576. IntField("ack", 0),
  5577. BitField("dataofs", None, 4),
  5578. BitField("reserved", 0, 4),
  5579. FlagsField("flags", 0x2, 8, "FSRPAUEC"),
  5580. ShortField("window", 8192),
  5581. XShortField("chksum", None),
  5582. ShortField("urgptr", 0),
  5583. TCPOptionsField("options", {}) ]
  5584. def post_build(self, p, pay):
  5585. p += pay
  5586. dataofs = self.dataofs
  5587. if dataofs is None:
  5588. dataofs = 5+((len(self.fieldtype["options"].i2m(self,self.options))+3)/4)
  5589. p = p[:12]+chr((dataofs << 4) | ord(p[12])&0x0f)+p[13:]
  5590. if self.chksum is None:
  5591. if isinstance(self.underlayer, IP):
  5592. psdhdr = struct.pack("!4s4sHH",
  5593. inet_aton(self.underlayer.src),
  5594. inet_aton(self.underlayer.dst),
  5595. self.underlayer.proto,
  5596. len(p))
  5597. ck=checksum(psdhdr+p)
  5598. p = p[:16]+struct.pack("!H", ck)+p[18:]
  5599. elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
  5600. ck = in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)
  5601. p = p[:16]+struct.pack("!H", ck)+p[18:]
  5602. else:
  5603. warning("No IP underlayer to compute checksum. Leaving null.")
  5604. return p
  5605. def hashret(self):
  5606. if conf.checkIPsrc:
  5607. return struct.pack("H",self.sport ^ self.dport)+self.payload.hashret()
  5608. else:
  5609. return self.payload.hashret()
  5610. def answers(self, other):
  5611. if not isinstance(other, TCP):
  5612. return 0
  5613. if conf.checkIPsrc:
  5614. if not ((self.sport == other.dport) and
  5615. (self.dport == other.sport)):
  5616. return 0
  5617. if (abs(other.seq-self.ack) > 2+len(other.payload)):
  5618. return 0
  5619. return 1
  5620. def mysummary(self):
  5621. if isinstance(self.underlayer, IP):
  5622. return self.underlayer.sprintf("TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%")
  5623. elif isinstance(self.underlayer, IPv6):
  5624. return self.underlayer.sprintf("TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%")
  5625. else:
  5626. return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%")
  5627. class UDP(Packet):
  5628. name = "UDP"
  5629. fields_desc = [ ShortEnumField("sport", 53, UDP_SERVICES),
  5630. ShortEnumField("dport", 53, UDP_SERVICES),
  5631. ShortField("len", None),
  5632. XShortField("chksum", None), ]
  5633. def post_build(self, p, pay):
  5634. p += pay
  5635. l = self.len
  5636. if l is None:
  5637. l = len(p)
  5638. p = p[:4]+struct.pack("!H",l)+p[6:]
  5639. if self.chksum is None:
  5640. if isinstance(self.underlayer, IP):
  5641. psdhdr = struct.pack("!4s4sHH",
  5642. inet_aton(self.underlayer.src),
  5643. inet_aton(self.underlayer.dst),
  5644. self.underlayer.proto,
  5645. len(p))
  5646. ck=checksum(psdhdr+p)
  5647. p = p[:6]+struct.pack("!H", ck)+p[8:]
  5648. elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
  5649. ck = in6_chksum(socket.IPPROTO_UDP, self.underlayer, p)
  5650. p = p[:6]+struct.pack("!H", ck)+p[8:]
  5651. else:
  5652. warning("No IP underlayer to compute checksum. Leaving null.")
  5653. return p
  5654. def extract_padding(self, s):
  5655. l = self.len - 8
  5656. return s[:l],s[l:]
  5657. def hashret(self):
  5658. if conf.checkIPsrc:
  5659. return struct.pack("H",self.sport ^ self.dport)+self.payload.hashret()
  5660. else:
  5661. return self.payload.hashret()
  5662. def answers(self, other):
  5663. if not isinstance(other, UDP):
  5664. return 0
  5665. if conf.checkIPsrc:
  5666. if not ((self.sport == other.dport) and
  5667. (self.dport == other.sport)):
  5668. return 0
  5669. return self.payload.answers(other.payload)
  5670. def mysummary(self):
  5671. if isinstance(self.underlayer, IP):
  5672. return self.underlayer.sprintf("UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%")
  5673. elif isinstance(self.underlayer, IPv6):
  5674. return self.underlayer.sprintf("UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%")
  5675. else:
  5676. return self.sprintf("UDP %UDP.sport% > %UDP.dport%")
  5677. icmptypes = { 0 : "echo-reply",
  5678. 3 : "dest-unreach",
  5679. 4 : "source-quench",
  5680. 5 : "redirect",
  5681. 8 : "echo-request",
  5682. 9 : "router-advertisement",
  5683. 10 : "router-solicitation",
  5684. 11 : "time-exceeded",
  5685. 12 : "parameter-problem",
  5686. 13 : "timestamp-request",
  5687. 14 : "timestamp-reply",
  5688. 15 : "information-request",
  5689. 16 : "information-response",
  5690. 17 : "address-mask-request",
  5691. 18 : "address-mask-reply" }
  5692. class ICMP(Packet):
  5693. name = "ICMP"
  5694. fields_desc = [ ByteEnumField("type",8, icmptypes),
  5695. ByteField("code",0),
  5696. XShortField("chksum", None),
  5697. XShortField("id",0),
  5698. XShortField("seq",0) ]
  5699. def post_build(self, p, pay):
  5700. p += pay
  5701. if self.chksum is None:
  5702. ck = checksum(p)
  5703. p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
  5704. return p
  5705. def hashret(self):
  5706. return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
  5707. def answers(self, other):
  5708. if not isinstance(other,ICMP):
  5709. return 0
  5710. if ( (other.type,self.type) in [(8,0),(13,14),(15,16),(17,18)] and
  5711. self.id == other.id and
  5712. self.seq == other.seq ):
  5713. return 1
  5714. return 0
  5715. def guess_payload_class(self, payload):
  5716. if self.type in [3,4,5,11,12]:
  5717. return IPerror
  5718. else:
  5719. return None
  5720. def mysummary(self):
  5721. if isinstance(self.underlayer, IP):
  5722. return self.underlayer.sprintf("ICMP %IP.src% > %IP.dst% %ICMP.type% %ICMP.code%")
  5723. else:
  5724. return self.sprintf("ICMP %ICMP.type% %ICMP.code%")
  5725. class IPerror(IP):
  5726. name = "IP in ICMP"
  5727. def answers(self, other):
  5728. if not isinstance(other, IP):
  5729. return 0
  5730. if not ( ((conf.checkIPsrc == 0) or (self.dst == other.dst)) and
  5731. (self.src == other.src) and
  5732. ( ((conf.checkIPID == 0)
  5733. or (self.id == other.id)
  5734. or (conf.checkIPID == 1 and self.id == socket.htons(other.id)))) and
  5735. (self.proto == other.proto) ):
  5736. return 0
  5737. return self.payload.answers(other.payload)
  5738. def mysummary(self):
  5739. return Packet.mysummary(self)
  5740. class TCPerror(TCP):
  5741. name = "TCP in ICMP"
  5742. def answers(self, other):
  5743. if not isinstance(other, TCP):
  5744. return 0
  5745. if conf.checkIPsrc:
  5746. if not ((self.sport == other.sport) and
  5747. (self.dport == other.dport)):
  5748. return 0
  5749. if conf.check_TCPerror_seqack:
  5750. if self.seq is not None:
  5751. if self.seq != other.seq:
  5752. return 0
  5753. if self.ack is not None:
  5754. if self.ack != other.ack:
  5755. return 0
  5756. return 1
  5757. def mysummary(self):
  5758. return Packet.mysummary(self)
  5759. class UDPerror(UDP):
  5760. name = "UDP in ICMP"
  5761. def answers(self, other):
  5762. if not isinstance(other, UDP):
  5763. return 0
  5764. if conf.checkIPsrc:
  5765. if not ((self.sport == other.sport) and
  5766. (self.dport == other.dport)):
  5767. return 0
  5768. return 1
  5769. def mysummary(self):
  5770. return Packet.mysummary(self)
  5771. class ICMPerror(ICMP):
  5772. name = "ICMP in ICMP"
  5773. def answers(self, other):
  5774. if not isinstance(other,ICMP):
  5775. return 0
  5776. if not ((self.type == other.type) and
  5777. (self.code == other.code)):
  5778. return 0
  5779. if self.code in [0,8,13,14,17,18]:
  5780. if (self.id == other.id and
  5781. self.seq == other.seq):
  5782. return 1
  5783. else:
  5784. return 0
  5785. else:
  5786. return 1
  5787. def mysummary(self):
  5788. return Packet.mysummary(self)
  5789. class IPv6(Packet):
  5790. """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
  5791. name = "IPv6 not implemented here."
  5792. def __init__(self, *args, **kargs):
  5793. log_interactive.error(self.name)
  5794. def __repr__(self):
  5795. return "<IPv6: ERROR not implemented>"
  5796. class _IPv6OptionHeader(Packet):
  5797. """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
  5798. name = "IPv6 not implemented here."
  5799. def __init__(self, *args, **kargs):
  5800. log_interactive.error(self.name)
  5801. def __repr__(self):
  5802. return "<IPv6: ERROR not implemented>"
  5803. class PPP(Packet):
  5804. name = "PPP Link Layer"
  5805. fields_desc = [ ShortEnumField("proto", 0x0021, {0x0021: "IP",
  5806. 0xc021: "LCP"} ) ]
  5807. class DNS(Packet):
  5808. name = "DNS"
  5809. fields_desc = [ ShortField("id",0),
  5810. BitField("qr",0, 1),
  5811. BitEnumField("opcode", 0, 4, {0:"QUERY",1:"IQUERY",2:"STATUS"}),
  5812. BitField("aa", 0, 1),
  5813. BitField("tc", 0, 1),
  5814. BitField("rd", 0, 1),
  5815. BitField("ra", 0 ,1),
  5816. BitField("z", 0, 3),
  5817. BitEnumField("rcode", 0, 4, {0:"ok", 1:"format-error", 2:"server-failure", 3:"name-error", 4:"not-implemented", 5:"refused"}),
  5818. DNSRRCountField("qdcount", None, "qd"),
  5819. DNSRRCountField("ancount", None, "an"),
  5820. DNSRRCountField("nscount", None, "ns"),
  5821. DNSRRCountField("arcount", None, "ar"),
  5822. DNSQRField("qd", "qdcount"),
  5823. DNSRRField("an", "ancount"),
  5824. DNSRRField("ns", "nscount"),
  5825. DNSRRField("ar", "arcount",0) ]
  5826. def answers(self, other):
  5827. return (isinstance(other, DNS)
  5828. and self.id == other.id
  5829. and self.qr == 1
  5830. and other.qr == 0)
  5831. def mysummary(self):
  5832. type = ["Qry","Ans"][self.qr]
  5833. name = ""
  5834. if self.qr:
  5835. type = "Ans"
  5836. if self.ancount > 0 and isinstance(self.an, DNSRR):
  5837. name = ' "%s"' % self.an.rdata
  5838. else:
  5839. type = "Qry"
  5840. if self.qdcount > 0 and isinstance(self.qd, DNSQR):
  5841. name = ' "%s"' % self.qd.qname
  5842. return 'DNS %s%s ' % (type, name)
  5843. dnstypes = { 0:"ANY", 255:"ALL",
  5844. 1:"A", 2:"NS", 3:"MD", 4:"MD", 5:"CNAME", 6:"SOA", 7: "MB", 8:"MG",
  5845. 9:"MR",10:"NULL",11:"WKS",12:"PTR",13:"HINFO",14:"MINFO",15:"MX",16:"TXT",
  5846. 17:"RP",18:"AFSDB",28:"AAAA", 33:"SRV",38:"A6",39:"DNAME"}
  5847. dnsqtypes = {251:"IXFR",252:"AXFR",253:"MAILB",254:"MAILA",255:"ALL"}
  5848. dnsqtypes.update(dnstypes)
  5849. dnsclasses = {1: 'IN', 2: 'CS', 3: 'CH', 4: 'HS', 255: 'ANY'}
  5850. class DNSQR(Packet):
  5851. name = "DNS Question Record"
  5852. show_indent=0
  5853. fields_desc = [ DNSStrField("qname",""),
  5854. ShortEnumField("qtype", 1, dnsqtypes),
  5855. ShortEnumField("qclass", 1, dnsclasses) ]
  5856. class DNSRR(Packet):
  5857. name = "DNS Resource Record"
  5858. show_indent=0
  5859. fields_desc = [ DNSStrField("rrname",""),
  5860. ShortEnumField("type", 1, dnstypes),
  5861. ShortEnumField("rclass", 1, dnsclasses),
  5862. IntField("ttl", 0),
  5863. RDLenField("rdlen"),
  5864. RDataField("rdata", "", "rdlen") ]
  5865. dhcpmagic="c\x82Sc"
  5866. class BOOTP(Packet):
  5867. name = "BOOTP"
  5868. fields_desc = [ ByteEnumField("op",1, {1:"BOOTREQUEST", 2:"BOOTREPLY"}),
  5869. ByteField("htype",1),
  5870. ByteField("hlen",6),
  5871. ByteField("hops",0),
  5872. IntField("xid",0),
  5873. ShortField("secs",0),
  5874. FlagsField("flags", 0, 16, "???????????????B"),
  5875. IPField("ciaddr","0.0.0.0"),
  5876. IPField("yiaddr","0.0.0.0"),
  5877. IPField("siaddr","0.0.0.0"),
  5878. IPField("giaddr","0.0.0.0"),
  5879. Field("chaddr","", "16s"),
  5880. Field("sname","","64s"),
  5881. Field("file","","128s"),
  5882. StrField("options","") ]
  5883. def guess_payload_class(self, payload):
  5884. if self.options[:len(dhcpmagic)] == dhcpmagic:
  5885. return DHCP
  5886. else:
  5887. return Packet.guess_payload_class(self, payload)
  5888. def extract_padding(self,s):
  5889. if self.options[:len(dhcpmagic)] == dhcpmagic:
  5890. # set BOOTP options to DHCP magic cookie and make rest a payload of DHCP options
  5891. payload = self.options[len(dhcpmagic):]
  5892. self.options = self.options[:len(dhcpmagic)]
  5893. return payload, None
  5894. else:
  5895. return "", None
  5896. def hashret(self):
  5897. return struct.pack("L", self.xid)
  5898. def answers(self, other):
  5899. if not isinstance(other, BOOTP):
  5900. return 0
  5901. return self.xid == other.xid
  5902. #DHCP_UNKNOWN, DHCP_IP, DHCP_IPLIST, DHCP_TYPE \
  5903. #= range(4)
  5904. #
  5905. DHCPTypes = {
  5906. 1: "discover",
  5907. 2: "offer",
  5908. 3: "decline",
  5909. 4: "ack",
  5910. 5: "nak",
  5911. 6: "release",
  5912. 7: "inform"
  5913. }
  5914. #
  5915. #DHCPOptions = (
  5916. # {
  5917. # 1: ("subnet-mask", DHCP_IP),
  5918. # 3: ("routers", DHCP_IPLIST),
  5919. # 53: ("message-type", DHCP_MESSAGE_TYPE),
  5920. # 55: ("request-list", DHCP_REQUEST_LIST
  5921. # },
  5922. # {
  5923. # "subnet-mask": (1, DHCP_IP)
  5924. # "routers": (3, DHCP_IPLIST)
  5925. # "message-type": (53, DHCP_TYPE)
  5926. # } )
  5927. DHCPOptions = {
  5928. 0: "pad",
  5929. 1: IPField("subnet_mask", "0.0.0.0"),
  5930. 2: "time_zone",
  5931. 3: IPField("router","0.0.0.0"),
  5932. 4: IPField("time_server","0.0.0.0"),
  5933. 5: IPField("IEN_name_server","0.0.0.0"),
  5934. 6: IPField("name_server","0.0.0.0"),
  5935. 7: IPField("log_server","0.0.0.0"),
  5936. 8: IPField("cookie_server","0.0.0.0"),
  5937. 9: IPField("lpr_server","0.0.0.0"),
  5938. 12: "hostname",
  5939. 14: "dump_path",
  5940. 15: "domain",
  5941. 17: "root_disk_path",
  5942. 22: "max_dgram_reass_size",
  5943. 23: "default_ttl",
  5944. 24: "pmtu_timeout",
  5945. 28: IPField("broadcast_address","0.0.0.0"),
  5946. 35: "arp_cache_timeout",
  5947. 36: "ether_or_dot3",
  5948. 37: "tcp_ttl",
  5949. 38: "tcp_keepalive_interval",
  5950. 39: "tcp_keepalive_garbage",
  5951. 40: "NIS_domain",
  5952. 41: IPField("NIS_server","0.0.0.0"),
  5953. 42: IPField("NTP_server","0.0.0.0"),
  5954. 43: "vendor_specific",
  5955. 44: IPField("NetBIOS_server","0.0.0.0"),
  5956. 45: IPField("NetBIOS_dist_server","0.0.0.0"),
  5957. 51: IntField("lease_time", 43200),
  5958. 54: IPField("server_id","0.0.0.0"),
  5959. 55: "param_req_list",
  5960. 57: ShortField("max_dhcp_size", 1500),
  5961. 58: IntField("renewal_time", 21600),
  5962. 59: IntField("rebinding_time", 37800),
  5963. 60: "vendor_class_id",
  5964. 64: "NISplus_domain",
  5965. 65: IPField("NISplus_server","0.0.0.0"),
  5966. 69: IPField("SMTP_server","0.0.0.0"),
  5967. 70: IPField("POP3_server","0.0.0.0"),
  5968. 71: IPField("NNTP_server","0.0.0.0"),
  5969. 72: IPField("WWW_server","0.0.0.0"),
  5970. 73: IPField("Finger_server","0.0.0.0"),
  5971. 74: IPField("IRC_server","0.0.0.0"),
  5972. 75: IPField("StreetTalk_server","0.0.0.0"),
  5973. 76: "StreetTalk_Dir_Assistance",
  5974. 53: ByteEnumField("message-type", 1, DHCPTypes),
  5975. # 55: DHCPRequestListField("request-list"),
  5976. 255: "end"
  5977. }
  5978. DHCPRevOptions = {}
  5979. for k,v in DHCPOptions.iteritems():
  5980. if type(v) is str:
  5981. n = v
  5982. v = None
  5983. else:
  5984. n = str(v)
  5985. DHCPRevOptions[n] = (k,v)
  5986. del(n)
  5987. del(v)
  5988. del(k)
  5989. #
  5990. #{
  5991. # "pad": (0, None),
  5992. # "subnet-mask": (1, IPField("subnet-mask", "0.0.0.0")),
  5993. ## "routers": (3, IPListField("routers")),
  5994. # "message-type": (53, ByteEnumField("message-type", 1, DHCPTypes)),
  5995. # "end": (255, None)
  5996. # } )
  5997. class DHCPOptionsField(StrField):
  5998. islist=1
  5999. def i2repr(self,pkt,x):
  6000. s = []
  6001. for v in x:
  6002. if type(v) is tuple and len(v) == 2:
  6003. if DHCPRevOptions.has_key(v[0]) and isinstance(DHCPRevOptions[v[0]][1],Field):
  6004. f = DHCPRevOptions[v[0]][1]
  6005. vv = f.i2repr(pkt,v[1])
  6006. else:
  6007. vv = repr(v[1])
  6008. s.append("%s=%s" % (v[0],vv))
  6009. else:
  6010. s.append(str(v))
  6011. return "[%s]" % (" ".join(s))
  6012. def getfield(self, pkt, s):
  6013. #print "getfield s=%s %d" % (s, len(s))
  6014. return "", self.m2i(pkt, s)
  6015. def m2i(self, pkt, x):
  6016. #print "m2i x=%s len=%d" % (x, len(x))
  6017. opt = []
  6018. while x:
  6019. o = ord(x[0])
  6020. #print "o=%d x=%s len=%d" % (o, x, len(x))
  6021. if o == 255:
  6022. opt.append("end")
  6023. x = x[1:]
  6024. continue
  6025. if o == 0:
  6026. opt.append("pad")
  6027. x = x[1:]
  6028. continue
  6029. if DHCPOptions.has_key(o):
  6030. f = DHCPOptions[o]
  6031. if isinstance(f, str):
  6032. olen = ord(x[1])
  6033. opt.append( (f,x[2:olen+2]) )
  6034. x = x[olen+2:]
  6035. else:
  6036. olen = ord(x[1])
  6037. left, val = f.getfield(pkt,x[2:olen+2])
  6038. # val = f.m2i(pkt,val)
  6039. # if left:
  6040. # print "m2i data left left=%s" % left
  6041. opt.append((f.name, val))
  6042. x = x[olen+2:]
  6043. else:
  6044. olen = ord(x[1])
  6045. opt.append((o, x[2:olen+2]))
  6046. x = x[olen+2:]
  6047. return opt
  6048. def i2m(self, pkt, x):
  6049. #print "i2m x=%s" % x
  6050. s = ""
  6051. for o in x:
  6052. if type(o) is tuple and len(o) == 2:
  6053. name, val = o
  6054. if isinstance(name, int):
  6055. onum, oval = name, val
  6056. elif DHCPRevOptions.has_key(name):
  6057. onum, f = DHCPRevOptions[name]
  6058. if f is None:
  6059. oval = val
  6060. else:
  6061. # oval = f.addfield(pkt,"",f.i2m(pkt,f.any2i(pkt,val)))
  6062. oval = f.addfield(pkt,"",f.any2i(pkt,val))
  6063. else:
  6064. warning("Unknown field option %s" % name)
  6065. continue
  6066. s += chr(onum)
  6067. s += chr(len(oval))
  6068. s += oval
  6069. elif (type(o) is str and DHCPRevOptions.has_key(o) and
  6070. DHCPRevOptions[o][1] == None):
  6071. s += chr(DHCPRevOptions[o][0])
  6072. elif type(o) is int:
  6073. s += chr(o)
  6074. else:
  6075. warning("Malformed option %s" % o)
  6076. return s
  6077. class DHCP(Packet):
  6078. name = "DHCP options"
  6079. fields_desc = [ DHCPOptionsField("options","") ]
  6080. class Dot11(Packet):
  6081. name = "802.11"
  6082. fields_desc = [
  6083. BitField("subtype", 0, 4),
  6084. BitEnumField("type", 0, 2, ["Management", "Control", "Data", "Reserved"]),
  6085. BitField("proto", 0, 2),
  6086. FlagsField("FCfield", 0, 8, ["to-DS", "from-DS", "MF", "retry", "pw-mgt", "MD", "wep", "order"]),
  6087. ShortField("ID",0),
  6088. MACField("addr1", ETHER_ANY),
  6089. Dot11Addr2MACField("addr2", ETHER_ANY),
  6090. Dot11Addr3MACField("addr3", ETHER_ANY),
  6091. Dot11SCField("SC", 0),
  6092. Dot11Addr4MACField("addr4", ETHER_ANY)
  6093. ]
  6094. def mysummary(self):
  6095. return self.sprintf("802.11 %Dot11.type% %Dot11.subtype% %Dot11.addr2% > %Dot11.addr1%")
  6096. def guess_payload_class(self, payload):
  6097. if self.FCfield & 0x40:
  6098. return Dot11WEP
  6099. else:
  6100. return Packet.guess_payload_class(self, payload)
  6101. def answers(self, other):
  6102. if isinstance(other,Dot11):
  6103. if self.type == 0: # management
  6104. if self.addr1 != other.addr2: # check resp DA w/ req SA
  6105. return 0
  6106. if (other.subtype,self.subtype) in [(0,1),(2,3),(4,5)]:
  6107. return 1
  6108. if self.subtype == other.subtype == 11: # auth
  6109. return self.payload.answers(other.payload)
  6110. elif self.type == 1: # control
  6111. return 0
  6112. elif self.type == 2: # data
  6113. return self.payload.answers(other.payload)
  6114. elif self.type == 3: # reserved
  6115. return 0
  6116. return 0
  6117. def unwep(self, key=None, warn=1):
  6118. if self.FCfield & 0x40 == 0:
  6119. if warn:
  6120. warning("No WEP to remove")
  6121. return
  6122. if isinstance(self.payload.payload, NoPayload):
  6123. if key or conf.wepkey:
  6124. self.payload.decrypt(key)
  6125. if isinstance(self.payload.payload, NoPayload):
  6126. if warn:
  6127. warning("Dot11 can't be decrypted. Check conf.wepkey.")
  6128. return
  6129. self.FCfield &= ~0x40
  6130. self.payload=self.payload.payload
  6131. capability_list = [ "res8", "res9", "short-slot", "res11",
  6132. "res12", "DSSS-OFDM", "res14", "res15",
  6133. "ESS", "IBSS", "CFP", "CFP-req",
  6134. "privacy", "short-preamble", "PBCC", "agility"]
  6135. reason_code = {0:"reserved",1:"unspec", 2:"auth-expired",
  6136. 3:"deauth-ST-leaving",
  6137. 4:"inactivity", 5:"AP-full", 6:"class2-from-nonauth",
  6138. 7:"class3-from-nonass", 8:"disas-ST-leaving",
  6139. 9:"ST-not-auth"}
  6140. status_code = {0:"success", 1:"failure", 10:"cannot-support-all-cap",
  6141. 11:"inexist-asso", 12:"asso-denied", 13:"algo-unsupported",
  6142. 14:"bad-seq-num", 15:"challenge-failure",
  6143. 16:"timeout", 17:"AP-full",18:"rate-unsupported" }
  6144. class Dot11Beacon(Packet):
  6145. name = "802.11 Beacon"
  6146. fields_desc = [ LELongField("timestamp", 0),
  6147. LEShortField("beacon_interval", 0x0064),
  6148. FlagsField("cap", 0, 16, capability_list) ]
  6149. class Dot11Elt(Packet):
  6150. name = "802.11 Information Element"
  6151. fields_desc = [ ByteEnumField("ID", 0, {0:"SSID", 1:"Rates", 2: "FHset", 3:"DSset", 4:"CFset", 5:"TIM", 6:"IBSSset", 16:"challenge",
  6152. 42:"ERPinfo", 47:"ERPinfo",50:"ESRates",221:"vendor",68:"reserved"}),
  6153. FieldLenField("len", None, "info", "B"),
  6154. StrLenField("info", "", "len") ]
  6155. def mysummary(self):
  6156. if self.ID == 0:
  6157. return "SSID=%s"%repr(self.info),[Dot11]
  6158. else:
  6159. return ""
  6160. class Dot11ATIM(Packet):
  6161. name = "802.11 ATIM"
  6162. class Dot11Disas(Packet):
  6163. name = "802.11 Disassociation"
  6164. fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
  6165. class Dot11AssoReq(Packet):
  6166. name = "802.11 Association Request"
  6167. fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  6168. LEShortField("listen_interval", 0x00c8) ]
  6169. class Dot11AssoResp(Packet):
  6170. name = "802.11 Association Response"
  6171. fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  6172. LEShortField("status", 0),
  6173. LEShortField("AID", 0) ]
  6174. class Dot11ReassoReq(Packet):
  6175. name = "802.11 Reassociation Request"
  6176. fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  6177. MACField("current_AP", ETHER_ANY),
  6178. LEShortField("listen_interval", 0x00c8) ]
  6179. class Dot11ReassoResp(Dot11AssoResp):
  6180. name = "802.11 Reassociation Response"
  6181. class Dot11ProbeReq(Packet):
  6182. name = "802.11 Probe Request"
  6183. class Dot11ProbeResp(Packet):
  6184. name = "802.11 Probe Response"
  6185. fields_desc = [ LELongField("timestamp", 0),
  6186. LEShortField("beacon_interval", 0x0064),
  6187. FlagsField("cap", 0, 16, capability_list) ]
  6188. class Dot11Auth(Packet):
  6189. name = "802.11 Authentication"
  6190. fields_desc = [ LEShortEnumField("algo", 0, ["open", "sharedkey"]),
  6191. LEShortField("seqnum", 0),
  6192. LEShortEnumField("status", 0, status_code) ]
  6193. def answers(self, other):
  6194. if self.seqnum == other.seqnum+1:
  6195. return 1
  6196. return 0
  6197. class Dot11Deauth(Packet):
  6198. name = "802.11 Deauthentication"
  6199. fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
  6200. class Dot11WEP(Packet):
  6201. name = "802.11 WEP packet"
  6202. fields_desc = [ StrFixedLenField("iv", "\0\0\0", 3),
  6203. ByteField("keyid", 0),
  6204. StrField("wepdata",None,remain=4),
  6205. IntField("icv",None) ]
  6206. def post_dissect(self, s):
  6207. # self.icv, = struct.unpack("!I",self.wepdata[-4:])
  6208. # self.wepdata = self.wepdata[:-4]
  6209. self.decrypt()
  6210. def do_build(self):
  6211. p=""
  6212. for f in self.fields_desc:
  6213. p = f.addfield(self, p, self.__getattr__(f))
  6214. pay = None
  6215. if self.wepdata is None:
  6216. pay = self.payload.build(internal=1)
  6217. return p,pay
  6218. def post_build(self, p, pay):
  6219. if self.wepdata is None:
  6220. key = conf.wepkey
  6221. if key:
  6222. if self.icv is None:
  6223. pay += struct.pack("<I",crc32(pay))
  6224. icv = ""
  6225. else:
  6226. icv = p[4:8]
  6227. c = ARC4.new(self.iv+key)
  6228. p = p[:4]+c.encrypt(pay)+icv
  6229. else:
  6230. warning("No WEP key set (conf.wepkey).. strange results expected..")
  6231. return p
  6232. def decrypt(self,key=None):
  6233. if key is None:
  6234. key = conf.wepkey
  6235. if key:
  6236. c = ARC4.new(self.iv+key)
  6237. self.add_payload(LLC(c.decrypt(self.wepdata)))
  6238. class PrismHeader(Packet):
  6239. """ iwpriv wlan0 monitor 3 """
  6240. name = "Prism header"
  6241. fields_desc = [ LEIntField("msgcode",68),
  6242. LEIntField("len",144),
  6243. StrFixedLenField("dev","",16),
  6244. LEIntField("hosttime_did",0),
  6245. LEShortField("hosttime_status",0),
  6246. LEShortField("hosttime_len",0),
  6247. LEIntField("hosttime",0),
  6248. LEIntField("mactime_did",0),
  6249. LEShortField("mactime_status",0),
  6250. LEShortField("mactime_len",0),
  6251. LEIntField("mactime",0),
  6252. LEIntField("channel_did",0),
  6253. LEShortField("channel_status",0),
  6254. LEShortField("channel_len",0),
  6255. LEIntField("channel",0),
  6256. LEIntField("rssi_did",0),
  6257. LEShortField("rssi_status",0),
  6258. LEShortField("rssi_len",0),
  6259. LEIntField("rssi",0),
  6260. LEIntField("sq_did",0),
  6261. LEShortField("sq_status",0),
  6262. LEShortField("sq_len",0),
  6263. LEIntField("sq",0),
  6264. LEIntField("signal_did",0),
  6265. LEShortField("signal_status",0),
  6266. LEShortField("signal_len",0),
  6267. LESignedIntField("signal",0),
  6268. LEIntField("noise_did",0),
  6269. LEShortField("noise_status",0),
  6270. LEShortField("noise_len",0),
  6271. LEIntField("noise",0),
  6272. LEIntField("rate_did",0),
  6273. LEShortField("rate_status",0),
  6274. LEShortField("rate_len",0),
  6275. LEIntField("rate",0),
  6276. LEIntField("istx_did",0),
  6277. LEShortField("istx_status",0),
  6278. LEShortField("istx_len",0),
  6279. LEIntField("istx",0),
  6280. LEIntField("frmlen_did",0),
  6281. LEShortField("frmlen_status",0),
  6282. LEShortField("frmlen_len",0),
  6283. LEIntField("frmlen",0),
  6284. ]
  6285. class HSRP(Packet):
  6286. name = "HSRP"
  6287. fields_desc = [
  6288. ByteField("version", 0),
  6289. ByteEnumField("opcode", 0, { 0:"Hello"}),
  6290. ByteEnumField("state", 16, { 16:"Active"}),
  6291. ByteField("hellotime", 3),
  6292. ByteField("holdtime", 10),
  6293. ByteField("priority", 120),
  6294. ByteField("group", 1),
  6295. ByteField("reserved", 0),
  6296. StrFixedLenField("auth","cisco",8),
  6297. IPField("virtualIP","192.168.1.1") ]
  6298. class NTP(Packet):
  6299. # RFC 1769
  6300. name = "NTP"
  6301. fields_desc = [
  6302. BitEnumField('leap', 0, 2,
  6303. { 0: 'nowarning',
  6304. 1: 'longminute',
  6305. 2: 'shortminute',
  6306. 3: 'notsync'}),
  6307. BitField('version', 3, 3),
  6308. BitEnumField('mode', 3, 3,
  6309. { 0: 'reserved',
  6310. 1: 'sym_active',
  6311. 2: 'sym_passive',
  6312. 3: 'client',
  6313. 4: 'server',
  6314. 5: 'broadcast',
  6315. 6: 'control',
  6316. 7: 'private'}),
  6317. BitField('stratum', 2, 8),
  6318. BitField('poll', 0xa, 8), ### XXX : it's a signed int
  6319. BitField('precision', 0, 8), ### XXX : it's a signed int
  6320. FloatField('delay', 0, 32),
  6321. FloatField('dispersion', 0, 32),
  6322. IPField('id', "127.0.0.1"),
  6323. TimeStampField('ref', 0, 64),
  6324. TimeStampField('orig', -1, 64), # -1 means current time
  6325. TimeStampField('recv', 0, 64),
  6326. TimeStampField('sent', -1, 64)
  6327. ]
  6328. def mysummary(self):
  6329. return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%")
  6330. class GRE(Packet):
  6331. name = "GRE"
  6332. fields_desc = [ BitField("chksumpresent",0,1),
  6333. BitField("reserved0",0,12),
  6334. BitField("version",0,3),
  6335. XShortEnumField("proto", 0x0000, ETHER_TYPES),
  6336. ConditionalField(XShortField("chksum",None),"chksumpresent",lambda x:x==1),
  6337. ConditionalField(XShortField("reserved1",None),"chksumpresent",lambda x:x==1),
  6338. ]
  6339. def post_build(self, p, pay):
  6340. p += pay
  6341. if self.chksumpresent and self.chksum is None:
  6342. c = checksum(p)
  6343. p = p[:4]+chr((c>>8)&0xff)+chr(c&0xff)+p[6:]
  6344. return p
  6345. class Radius(Packet):
  6346. name = "Radius"
  6347. fields_desc = [ ByteEnumField("code", 1, {1: "Access-Request",
  6348. 2: "Access-Accept",
  6349. 3: "Access-Reject",
  6350. 4: "Accounting-Request",
  6351. 5: "Accounting-Accept",
  6352. 6: "Accounting-Status",
  6353. 7: "Password-Request",
  6354. 8: "Password-Ack",
  6355. 9: "Password-Reject",
  6356. 10: "Accounting-Message",
  6357. 11: "Access-Challenge",
  6358. 12: "Status-Server",
  6359. 13: "Status-Client",
  6360. 21: "Resource-Free-Request",
  6361. 22: "Resource-Free-Response",
  6362. 23: "Resource-Query-Request",
  6363. 24: "Resource-Query-Response",
  6364. 25: "Alternate-Resource-Reclaim-Request",
  6365. 26: "NAS-Reboot-Request",
  6366. 27: "NAS-Reboot-Response",
  6367. 29: "Next-Passcode",
  6368. 30: "New-Pin",
  6369. 31: "Terminate-Session",
  6370. 32: "Password-Expired",
  6371. 33: "Event-Request",
  6372. 34: "Event-Response",
  6373. 40: "Disconnect-Request",
  6374. 41: "Disconnect-ACK",
  6375. 42: "Disconnect-NAK",
  6376. 43: "CoA-Request",
  6377. 44: "CoA-ACK",
  6378. 45: "CoA-NAK",
  6379. 50: "IP-Address-Allocate",
  6380. 51: "IP-Address-Release",
  6381. 253: "Experimental-use",
  6382. 254: "Reserved",
  6383. 255: "Reserved"} ),
  6384. ByteField("id", 0),
  6385. ShortField("len", None),
  6386. StrFixedLenField("authenticator","",16) ]
  6387. def post_build(self, p, pay):
  6388. p += pay
  6389. l = self.len
  6390. if l is None:
  6391. l = len(p)
  6392. p = p[:2]+struct.pack("!H",l)+p[4:]
  6393. return p
  6394. class RIP(Packet):
  6395. name = "RIP header"
  6396. fields_desc = [
  6397. ByteEnumField("command",1,{1:"req",2:"resp",3:"traceOn",4:"traceOff",5:"sun",
  6398. 6:"trigReq",7:"trigResp",8:"trigAck",9:"updateReq",
  6399. 10:"updateResp",11:"updateAck"}),
  6400. ByteField("version",1),
  6401. ShortField("null",0),
  6402. ]
  6403. class RIPEntry(Packet):
  6404. name = "RIP entry"
  6405. fields_desc = [
  6406. ShortEnumField("AF",2,{2:"IP"}),
  6407. ShortField("RouteTag",0),
  6408. IPField("addr","0.0.0.0"),
  6409. IPField("mask","0.0.0.0"),
  6410. IPField("nextHop","0.0.0.0"),
  6411. IntEnumField("metric",1,{16:"Unreach"}),
  6412. ]
  6413. ISAKMP_payload_type = ["None","SA","Proposal","Transform","KE","ID","CERT","CR","Hash",
  6414. "SIG","Nonce","N","D","VendorID"]
  6415. ISAKMP_exchange_type = ["None","base","identity prot.",
  6416. "auth only", "aggressive", "info"]
  6417. class ISAKMP_class(Packet):
  6418. def guess_payload_class(self, payload):
  6419. np = self.next_payload
  6420. if np == 0:
  6421. return Raw
  6422. elif np < len(ISAKMP_payload_type):
  6423. pt = ISAKMP_payload_type[np]
  6424. return globals().get("ISAKMP_payload_%s" % pt, ISAKMP_payload)
  6425. else:
  6426. return ISAKMP_payload
  6427. class ISAKMP(ISAKMP_class): # rfc2408
  6428. name = "ISAKMP"
  6429. fields_desc = [
  6430. StrFixedLenField("init_cookie","",8),
  6431. StrFixedLenField("resp_cookie","",8),
  6432. ByteEnumField("next_payload",0,ISAKMP_payload_type),
  6433. XByteField("version",0x10),
  6434. ByteEnumField("exch_type",0,ISAKMP_exchange_type),
  6435. ByteField("flags",0), # XXX use a Flag field
  6436. IntField("id",0),
  6437. IntField("length",None)
  6438. ]
  6439. def answers(self, other):
  6440. if isinstance(other, ISAKMP):
  6441. if other.init_cookie == self.init_cookie:
  6442. return 1
  6443. return 0
  6444. def post_build(self, p, pay):
  6445. p += pay
  6446. if self.length is None:
  6447. p = p[:24]+struct.pack("!I",len(p))+p[28:]
  6448. return p
  6449. class ISAKMP_payload_Transform(ISAKMP_class):
  6450. name = "IKE Transform"
  6451. fields_desc = [
  6452. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6453. ByteField("res",0),
  6454. # ShortField("len",None),
  6455. ShortField("length",None),
  6456. ByteField("num",None),
  6457. ByteEnumField("id",1,{1:"KEY_IKE"}),
  6458. ShortField("res2",0),
  6459. ISAKMPTransformSetField("transforms",None,"length",shift=8)
  6460. # XIntField("enc",0x80010005L),
  6461. # XIntField("hash",0x80020002L),
  6462. # XIntField("auth",0x80030001L),
  6463. # XIntField("group",0x80040002L),
  6464. # XIntField("life_type",0x800b0001L),
  6465. # XIntField("durationh",0x000c0004L),
  6466. # XIntField("durationl",0x00007080L),
  6467. ]
  6468. def post_build(self, p, pay):
  6469. if self.length is None:
  6470. l = len(p)
  6471. p = p[:2]+chr((l>>8)&0xff)+chr(l&0xff)+p[4:]
  6472. p += pay
  6473. return p
  6474. class ISAKMP_payload_Proposal(ISAKMP_class):
  6475. name = "IKE proposal"
  6476. # ISAKMP_payload_type = 0
  6477. fields_desc = [
  6478. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6479. ByteField("res",0),
  6480. FieldLenField("length",None,"trans","H"),
  6481. ByteField("proposal",1),
  6482. ByteEnumField("proto",1,{1:"ISAKMP"}),
  6483. FieldLenField("SPIsize",None,"SPI","B"),
  6484. ByteField("trans_nb",None),
  6485. StrLenField("SPI","","SPIsize"),
  6486. PacketLenField("trans",Raw(),ISAKMP_payload_Transform,"length",shift=8),
  6487. ]
  6488. class ISAKMP_payload_metaclass(type):
  6489. def __new__(cls, name, bases, dct):
  6490. f = dct["fields_desc"]
  6491. f = [ ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6492. ByteField("res",0),
  6493. ShortField("length",None),
  6494. ] + f
  6495. dct["fields_desc"] = f
  6496. return super(ISAKMP_payload_metaclass, cls).__new__(cls, name, bases, dct)
  6497. class ISAKMP_payload(ISAKMP_class):
  6498. name = "ISAKMP payload"
  6499. fields_desc = [
  6500. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6501. ByteField("res",0),
  6502. FieldLenField("length",None,"load","H"),
  6503. StrLenField("load","","length",shift=4),
  6504. ]
  6505. class ISAKMP_payload_VendorID(ISAKMP_class):
  6506. name = "ISAKMP Vendor ID"
  6507. overload_fields = { ISAKMP: { "next_payload":13 }}
  6508. fields_desc = [
  6509. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6510. ByteField("res",0),
  6511. FieldLenField("length",None,"vendorID","H"),
  6512. StrLenField("vendorID","","length",shift=4),
  6513. ]
  6514. class ISAKMP_payload_SA(ISAKMP_class):
  6515. name = "ISAKMP SA"
  6516. overload_fields = { ISAKMP: { "next_payload":1 }}
  6517. fields_desc = [
  6518. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6519. ByteField("res",0),
  6520. FieldLenField("length",None,"prop","H"),
  6521. IntEnumField("DOI",1,{1:"IPSEC"}),
  6522. IntEnumField("situation",1,{1:"identity"}),
  6523. PacketLenField("prop",Raw(),ISAKMP_payload_Proposal,"length",shift=12),
  6524. ]
  6525. class ISAKMP_payload_Nonce(ISAKMP_class):
  6526. name = "ISAKMP Nonce"
  6527. overload_fields = { ISAKMP: { "next_payload":10 }}
  6528. fields_desc = [
  6529. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6530. ByteField("res",0),
  6531. FieldLenField("length",None,"load","H"),
  6532. StrLenField("load","","length",shift=4),
  6533. ]
  6534. class ISAKMP_payload_KE(ISAKMP_class):
  6535. name = "ISAKMP Key Exchange"
  6536. overload_fields = { ISAKMP: { "next_payload":4 }}
  6537. fields_desc = [
  6538. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6539. ByteField("res",0),
  6540. FieldLenField("length",None,"load","H"),
  6541. StrLenField("load","","length",shift=4),
  6542. ]
  6543. class ISAKMP_payload_ID(ISAKMP_class):
  6544. name = "ISAKMP Identification"
  6545. overload_fields = { ISAKMP: { "next_payload":5 }}
  6546. fields_desc = [
  6547. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6548. ByteField("res",0),
  6549. FieldLenField("length",None,"load","H"),
  6550. ByteEnumField("IDtype",1,{1:"IPv4_addr", 11:"Key"}),
  6551. ByteEnumField("ProtoID",0,{0:"Unused"}),
  6552. ShortEnumField("Port",0,{0:"Unused"}),
  6553. # IPField("IdentData","127.0.0.1"),
  6554. StrLenField("load","","length",shift=8),
  6555. ]
  6556. class ISAKMP_payload_Hash(ISAKMP_class):
  6557. name = "ISAKMP Hash"
  6558. overload_fields = { ISAKMP: { "next_payload":8 }}
  6559. fields_desc = [
  6560. ByteEnumField("next_payload",None,ISAKMP_payload_type),
  6561. ByteField("res",0),
  6562. FieldLenField("length",None,"load","H"),
  6563. StrLenField("load","","length",shift=4),
  6564. ]
  6565. ISAKMP_payload_type_overload = {}
  6566. for i in range(len(ISAKMP_payload_type)):
  6567. name = "ISAKMP_payload_%s" % ISAKMP_payload_type[i]
  6568. if name in globals():
  6569. ISAKMP_payload_type_overload[globals()[name]] = {"next_payload":i}
  6570. del(i)
  6571. del(name)
  6572. ISAKMP_class.overload_fields = ISAKMP_payload_type_overload.copy()
  6573. # Cisco Skinny protocol
  6574. # shamelessly ripped from Ethereal dissector
  6575. skinny_messages = {
  6576. # Station -> Callmanager
  6577. 0x0000: "KeepAliveMessage",
  6578. 0x0001: "RegisterMessage",
  6579. 0x0002: "IpPortMessage",
  6580. 0x0003: "KeypadButtonMessage",
  6581. 0x0004: "EnblocCallMessage",
  6582. 0x0005: "StimulusMessage",
  6583. 0x0006: "OffHookMessage",
  6584. 0x0007: "OnHookMessage",
  6585. 0x0008: "HookFlashMessage",
  6586. 0x0009: "ForwardStatReqMessage",
  6587. 0x000A: "SpeedDialStatReqMessage",
  6588. 0x000B: "LineStatReqMessage",
  6589. 0x000C: "ConfigStatReqMessage",
  6590. 0x000D: "TimeDateReqMessage",
  6591. 0x000E: "ButtonTemplateReqMessage",
  6592. 0x000F: "VersionReqMessage",
  6593. 0x0010: "CapabilitiesResMessage",
  6594. 0x0011: "MediaPortListMessage",
  6595. 0x0012: "ServerReqMessage",
  6596. 0x0020: "AlarmMessage",
  6597. 0x0021: "MulticastMediaReceptionAck",
  6598. 0x0022: "OpenReceiveChannelAck",
  6599. 0x0023: "ConnectionStatisticsRes",
  6600. 0x0024: "OffHookWithCgpnMessage",
  6601. 0x0025: "SoftKeySetReqMessage",
  6602. 0x0026: "SoftKeyEventMessage",
  6603. 0x0027: "UnregisterMessage",
  6604. 0x0028: "SoftKeyTemplateReqMessage",
  6605. 0x0029: "RegisterTokenReq",
  6606. 0x002A: "MediaTransmissionFailure",
  6607. 0x002B: "HeadsetStatusMessage",
  6608. 0x002C: "MediaResourceNotification",
  6609. 0x002D: "RegisterAvailableLinesMessage",
  6610. 0x002E: "DeviceToUserDataMessage",
  6611. 0x002F: "DeviceToUserDataResponseMessage",
  6612. 0x0030: "UpdateCapabilitiesMessage",
  6613. 0x0031: "OpenMultiMediaReceiveChannelAckMessage",
  6614. 0x0032: "ClearConferenceMessage",
  6615. 0x0033: "ServiceURLStatReqMessage",
  6616. 0x0034: "FeatureStatReqMessage",
  6617. 0x0035: "CreateConferenceResMessage",
  6618. 0x0036: "DeleteConferenceResMessage",
  6619. 0x0037: "ModifyConferenceResMessage",
  6620. 0x0038: "AddParticipantResMessage",
  6621. 0x0039: "AuditConferenceResMessage",
  6622. 0x0040: "AuditParticipantResMessage",
  6623. 0x0041: "DeviceToUserDataVersion1Message",
  6624. # Callmanager -> Station */
  6625. 0x0081: "RegisterAckMessage",
  6626. 0x0082: "StartToneMessage",
  6627. 0x0083: "StopToneMessage",
  6628. 0x0085: "SetRingerMessage",
  6629. 0x0086: "SetLampMessage",
  6630. 0x0087: "SetHkFDetectMessage",
  6631. 0x0088: "SetSpeakerModeMessage",
  6632. 0x0089: "SetMicroModeMessage",
  6633. 0x008A: "StartMediaTransmission",
  6634. 0x008B: "StopMediaTransmission",
  6635. 0x008C: "StartMediaReception",
  6636. 0x008D: "StopMediaReception",
  6637. 0x008F: "CallInfoMessage",
  6638. 0x0090: "ForwardStatMessage",
  6639. 0x0091: "SpeedDialStatMessage",
  6640. 0x0092: "LineStatMessage",
  6641. 0x0093: "ConfigStatMessage",
  6642. 0x0094: "DefineTimeDate",
  6643. 0x0095: "StartSessionTransmission",
  6644. 0x0096: "StopSessionTransmission",
  6645. 0x0097: "ButtonTemplateMessage",
  6646. 0x0098: "VersionMessage",
  6647. 0x0099: "DisplayTextMessage",
  6648. 0x009A: "ClearDisplay",
  6649. 0x009B: "CapabilitiesReqMessage",
  6650. 0x009C: "EnunciatorCommandMessage",
  6651. 0x009D: "RegisterRejectMessage",
  6652. 0x009E: "ServerResMessage",
  6653. 0x009F: "Reset",
  6654. 0x0100: "KeepAliveAckMessage",
  6655. 0x0101: "StartMulticastMediaReception",
  6656. 0x0102: "StartMulticastMediaTransmission",
  6657. 0x0103: "StopMulticastMediaReception",
  6658. 0x0104: "StopMulticastMediaTransmission",
  6659. 0x0105: "OpenReceiveChannel",
  6660. 0x0106: "CloseReceiveChannel",
  6661. 0x0107: "ConnectionStatisticsReq",
  6662. 0x0108: "SoftKeyTemplateResMessage",
  6663. 0x0109: "SoftKeySetResMessage",
  6664. 0x0110: "SelectSoftKeysMessage",
  6665. 0x0111: "CallStateMessage",
  6666. 0x0112: "DisplayPromptStatusMessage",
  6667. 0x0113: "ClearPromptStatusMessage",
  6668. 0x0114: "DisplayNotifyMessage",
  6669. 0x0115: "ClearNotifyMessage",
  6670. 0x0116: "ActivateCallPlaneMessage",
  6671. 0x0117: "DeactivateCallPlaneMessage",
  6672. 0x0118: "UnregisterAckMessage",
  6673. 0x0119: "BackSpaceReqMessage",
  6674. 0x011A: "RegisterTokenAck",
  6675. 0x011B: "RegisterTokenReject",
  6676. 0x0042: "DeviceToUserDataResponseVersion1Message",
  6677. 0x011C: "StartMediaFailureDetection",
  6678. 0x011D: "DialedNumberMessage",
  6679. 0x011E: "UserToDeviceDataMessage",
  6680. 0x011F: "FeatureStatMessage",
  6681. 0x0120: "DisplayPriNotifyMessage",
  6682. 0x0121: "ClearPriNotifyMessage",
  6683. 0x0122: "StartAnnouncementMessage",
  6684. 0x0123: "StopAnnouncementMessage",
  6685. 0x0124: "AnnouncementFinishMessage",
  6686. 0x0127: "NotifyDtmfToneMessage",
  6687. 0x0128: "SendDtmfToneMessage",
  6688. 0x0129: "SubscribeDtmfPayloadReqMessage",
  6689. 0x012A: "SubscribeDtmfPayloadResMessage",
  6690. 0x012B: "SubscribeDtmfPayloadErrMessage",
  6691. 0x012C: "UnSubscribeDtmfPayloadReqMessage",
  6692. 0x012D: "UnSubscribeDtmfPayloadResMessage",
  6693. 0x012E: "UnSubscribeDtmfPayloadErrMessage",
  6694. 0x012F: "ServiceURLStatMessage",
  6695. 0x0130: "CallSelectStatMessage",
  6696. 0x0131: "OpenMultiMediaChannelMessage",
  6697. 0x0132: "StartMultiMediaTransmission",
  6698. 0x0133: "StopMultiMediaTransmission",
  6699. 0x0134: "MiscellaneousCommandMessage",
  6700. 0x0135: "FlowControlCommandMessage",
  6701. 0x0136: "CloseMultiMediaReceiveChannel",
  6702. 0x0137: "CreateConferenceReqMessage",
  6703. 0x0138: "DeleteConferenceReqMessage",
  6704. 0x0139: "ModifyConferenceReqMessage",
  6705. 0x013A: "AddParticipantReqMessage",
  6706. 0x013B: "DropParticipantReqMessage",
  6707. 0x013C: "AuditConferenceReqMessage",
  6708. 0x013D: "AuditParticipantReqMessage",
  6709. 0x013F: "UserToDeviceDataVersion1Message",
  6710. }
  6711. class Skinny(Packet):
  6712. name="Skinny"
  6713. fields_desc = [ LEIntField("len",0),
  6714. LEIntField("res",0),
  6715. LEIntEnumField("msg",0,skinny_messages) ]
  6716. ### SEBEK
  6717. class SebekHead(Packet):
  6718. name = "Sebek header"
  6719. fields_desc = [ XIntField("magic", 0xd0d0d0),
  6720. ShortField("version", 1),
  6721. ShortEnumField("type", 0, {"read":0, "write":1,
  6722. "socket":2, "open":3}),
  6723. IntField("counter", 0),
  6724. IntField("time_sec", 0),
  6725. IntField("time_usec", 0) ]
  6726. def mysummary(self):
  6727. return self.sprintf("Sebek Header v%SebekHead.version% %SebekHead.type%")
  6728. # we need this because Sebek headers differ between v1 and v3, and
  6729. # between v3 type socket and v3 others
  6730. class SebekV1(Packet):
  6731. name = "Sebek v1"
  6732. fields_desc = [ IntField("pid", 0),
  6733. IntField("uid", 0),
  6734. IntField("fd", 0),
  6735. StrFixedLenField("command", "", 12),
  6736. FieldLenField("data_length", None, "data",fmt="I"),
  6737. StrLenField("data", "", "data_length") ]
  6738. def mysummary(self):
  6739. if isinstance(self.underlayer, SebekHead):
  6740. return self.underlayer.sprintf("Sebek v1 %SebekHead.type% (%SebekV1.command%)")
  6741. else:
  6742. return self.sprintf("Sebek v1 (%SebekV1.command%)")
  6743. class SebekV3(Packet):
  6744. name = "Sebek v3"
  6745. fields_desc = [ IntField("parent_pid", 0),
  6746. IntField("pid", 0),
  6747. IntField("uid", 0),
  6748. IntField("fd", 0),
  6749. IntField("inode", 0),
  6750. StrFixedLenField("command", "", 12),
  6751. FieldLenField("data_length", None, "data",fmt="I"),
  6752. StrLenField("data", "", "data_length") ]
  6753. def mysummary(self):
  6754. if isinstance(self.underlayer, SebekHead):
  6755. return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3.command%)")
  6756. else:
  6757. return self.sprintf("Sebek v3 (%SebekV3.command%)")
  6758. class SebekV2(SebekV3):
  6759. def mysummary(self):
  6760. if isinstance(self.underlayer, SebekHead):
  6761. return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2.command%)")
  6762. else:
  6763. return self.sprintf("Sebek v2 (%SebekV2.command%)")
  6764. class SebekV3Sock(Packet):
  6765. name = "Sebek v2 socket"
  6766. fields_desc = [ IntField("parent_pid", 0),
  6767. IntField("pid", 0),
  6768. IntField("uid", 0),
  6769. IntField("fd", 0),
  6770. IntField("inode", 0),
  6771. StrFixedLenField("command", "", 12),
  6772. IntField("data_length", 15),
  6773. IPField("dip", "127.0.0.1"),
  6774. ShortField("dport", 0),
  6775. IPField("sip", "127.0.0.1"),
  6776. ShortField("sport", 0),
  6777. ShortEnumField("call", 0, { "bind":2,
  6778. "connect":3, "listen":4,
  6779. "accept":5, "sendmsg":16,
  6780. "recvmsg":17, "sendto":11,
  6781. "recvfrom":12}),
  6782. ByteEnumField("proto", 0, IP_PROTOS) ]
  6783. def mysummary(self):
  6784. if isinstance(self.underlayer, SebekHead):
  6785. return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3Sock.command%)")
  6786. else:
  6787. return self.sprintf("Sebek v3 socket (%SebekV3Sock.command%)")
  6788. class SebekV2Sock(SebekV3Sock):
  6789. def mysummary(self):
  6790. if isinstance(self.underlayer, SebekHead):
  6791. return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2Sock.command%)")
  6792. else:
  6793. return self.sprintf("Sebek v2 socket (%SebekV2Sock.command%)")
  6794. class MGCP(Packet):
  6795. name = "MGCP"
  6796. longname = "Media Gateway Control Protocol"
  6797. fields_desc = [ StrStopField("verb","AUEP"," ", -1),
  6798. StrFixedLenField("sep1"," ",1),
  6799. StrStopField("transaction_id","1234567"," ", -1),
  6800. StrFixedLenField("sep2"," ",1),
  6801. StrStopField("endpoint","dummy@dummy.net"," ", -1),
  6802. StrFixedLenField("sep3"," ",1),
  6803. StrStopField("version","MGCP 1.0 NCS 1.0","\x0a", -1),
  6804. StrFixedLenField("sep4","\x0a",1),
  6805. ]
  6806. #class MGCP(Packet):
  6807. # name = "MGCP"
  6808. # longname = "Media Gateway Control Protocol"
  6809. # fields_desc = [ ByteEnumField("type",0, ["request","response","others"]),
  6810. # ByteField("code0",0),
  6811. # ByteField("code1",0),
  6812. # ByteField("code2",0),
  6813. # ByteField("code3",0),
  6814. # ByteField("code4",0),
  6815. # IntField("trasid",0),
  6816. # IntField("req_time",0),
  6817. # ByteField("is_duplicate",0),
  6818. # ByteField("req_available",0) ]
  6819. #
  6820. class GPRS(Packet):
  6821. name = "GPRSdummy"
  6822. fields_desc = [
  6823. StrStopField("dummy","","\x65\x00\x00",1)
  6824. ]
  6825. class HCI_Hdr(Packet):
  6826. name = "HCI header"
  6827. fields_desc = [ ByteEnumField("type",2,{1:"command",2:"ACLdata",3:"SCOdata",4:"event",5:"vendor"}),]
  6828. def mysummary(self):
  6829. return self.sprintf("HCI %type%")
  6830. class HCI_ACL_Hdr(Packet):
  6831. name = "HCI ACL header"
  6832. fields_desc = [ ByteField("handle",0), # Actually, handle is 12 bits and flags is 4.
  6833. ByteField("flags",0), # I wait to write a LEBitField
  6834. LEShortField("len",None), ]
  6835. def post_build(self, p, pay):
  6836. p += pay
  6837. if self.len is None:
  6838. l = len(p)-4
  6839. p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  6840. return p
  6841. class L2CAP_Hdr(Packet):
  6842. name = "L2CAP header"
  6843. fields_desc = [ LEShortField("len",None),
  6844. LEShortEnumField("cid",0,{1:"control"}),]
  6845. def post_build(self, p, pay):
  6846. p += pay
  6847. if self.len is None:
  6848. l = len(p)-4
  6849. p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  6850. return p
  6851. class L2CAP_CmdHdr(Packet):
  6852. name = "L2CAP command header"
  6853. fields_desc = [
  6854. ByteEnumField("code",8,{1:"rej",2:"conn_req",3:"conn_resp",
  6855. 4:"conf_req",5:"conf_resp",6:"disconn_req",
  6856. 7:"disconn_resp",8:"echo_req",9:"echo_resp",
  6857. 10:"info_req",11:"info_resp"}),
  6858. ByteField("id",0),
  6859. LEShortField("len",None) ]
  6860. def post_build(self, p, pay):
  6861. p += pay
  6862. if self.len is None:
  6863. l = len(p)-4
  6864. p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  6865. return p
  6866. def answers(self, other):
  6867. if other.id == self.id:
  6868. if self.code == 1:
  6869. return 1
  6870. if other.code in [2,4,6,8,10] and self.code == other.code+1:
  6871. if other.code == 8:
  6872. return 1
  6873. return self.payload.answers(other.payload)
  6874. return 0
  6875. class L2CAP_ConnReq(Packet):
  6876. name = "L2CAP Conn Req"
  6877. fields_desc = [ LEShortEnumField("psm",0,{1:"SDP",3:"RFCOMM",5:"telephony control"}),
  6878. LEShortField("scid",0),
  6879. ]
  6880. class L2CAP_ConnResp(Packet):
  6881. name = "L2CAP Conn Resp"
  6882. fields_desc = [ LEShortField("dcid",0),
  6883. LEShortField("scid",0),
  6884. LEShortEnumField("result",0,["no_info","authen_pend","author_pend"]),
  6885. LEShortEnumField("status",0,["success","pend","bad_psm",
  6886. "cr_sec_block","cr_no_mem"]),
  6887. ]
  6888. def answers(self, other):
  6889. return self.scid == other.scid
  6890. class L2CAP_CmdRej(Packet):
  6891. name = "L2CAP Command Rej"
  6892. fields_desc = [ LEShortField("reason",0),
  6893. ]
  6894. class L2CAP_ConfReq(Packet):
  6895. name = "L2CAP Conf Req"
  6896. fields_desc = [ LEShortField("dcid",0),
  6897. LEShortField("flags",0),
  6898. ]
  6899. class L2CAP_ConfResp(Packet):
  6900. name = "L2CAP Conf Resp"
  6901. fields_desc = [ LEShortField("scid",0),
  6902. LEShortField("flags",0),
  6903. LEShortEnumField("result",0,["success","unaccept","reject","unknown"]),
  6904. ]
  6905. def answers(self, other):
  6906. return self.scid == other.scid
  6907. class L2CAP_DisconnReq(Packet):
  6908. name = "L2CAP Disconn Req"
  6909. fields_desc = [ LEShortField("dcid",0),
  6910. LEShortField("scid",0), ]
  6911. class L2CAP_DisconnResp(Packet):
  6912. name = "L2CAP Disconn Resp"
  6913. fields_desc = [ LEShortField("dcid",0),
  6914. LEShortField("scid",0), ]
  6915. def answers(self, other):
  6916. return self.scid == other.scid
  6917. class L2CAP_InfoReq(Packet):
  6918. name = "L2CAP Info Req"
  6919. fields_desc = [ LEShortEnumField("type",0,{1:"CL_MTU",2:"FEAT_MASK"}),
  6920. StrField("data","")
  6921. ]
  6922. class L2CAP_InfoResp(Packet):
  6923. name = "L2CAP Info Resp"
  6924. fields_desc = [ LEShortField("type",0),
  6925. LEShortEnumField("result",0,["success","not_supp"]),
  6926. StrField("data",""), ]
  6927. def answers(self, other):
  6928. return self.type == other.type
  6929. class NetBIOS_DS(Packet):
  6930. name = "NetBIOS datagram service"
  6931. fields_desc = [
  6932. ByteEnumField("type",17, {17:"direct_group"}),
  6933. ByteField("flags",0),
  6934. XShortField("id",0),
  6935. IPField("src","127.0.0.1"),
  6936. ShortField("sport",138),
  6937. ShortField("len",None),
  6938. ShortField("ofs",0),
  6939. NetBIOSNameField("srcname",""),
  6940. NetBIOSNameField("dstname",""),
  6941. ]
  6942. def post_build(self, p, pay):
  6943. p += pay
  6944. if self.len is None:
  6945. l = len(p)-14
  6946. p = p[:10]+struct.pack("!H", l)+p[12:]
  6947. return p
  6948. # ShortField("length",0),
  6949. # ShortField("Delimitor",0),
  6950. # ByteField("command",0),
  6951. # ByteField("data1",0),
  6952. # ShortField("data2",0),
  6953. # ShortField("XMIt",0),
  6954. # ShortField("RSPCor",0),
  6955. # StrFixedLenField("dest","",16),
  6956. # StrFixedLenField("source","",16),
  6957. #
  6958. # ]
  6959. #
  6960. # IR
  6961. class IrLAPHead(Packet):
  6962. name = "IrDA Link Access Protocol Header"
  6963. fields_desc = [ XBitField("Address", 0x7f, 7),
  6964. BitEnumField("Type", 1, 1, {"Response":0,
  6965. "Command":1})]
  6966. class IrLAPCommand(Packet):
  6967. name = "IrDA Link Access Protocol Command"
  6968. fields_desc = [ XByteField("Control", 0),
  6969. XByteField("Format identifier", 0),
  6970. XIntField("Source address", 0),
  6971. XIntField("Destination address", 0xffffffffL),
  6972. XByteField("Discovery flags", 0x1),
  6973. ByteEnumField("Slot number", 255, {"final":255}),
  6974. XByteField("Version", 0)]
  6975. class IrLMP(Packet):
  6976. name = "IrDA Link Management Protocol"
  6977. fields_desc = [ XShortField("Service hints", 0),
  6978. XByteField("Character set", 0),
  6979. StrField("Device name", "") ]
  6980. #NetBIOS
  6981. # Name Query Request
  6982. # Node Status Request
  6983. class NBNSQueryRequest(Packet):
  6984. name="NBNS query request"
  6985. fields_desc = [ShortField("NAME_TRN_ID",0),
  6986. ShortField("FLAGS", 0x0110),
  6987. ShortField("QDCOUNT",1),
  6988. ShortField("ANCOUNT",0),
  6989. ShortField("NSCOUNT",0),
  6990. ShortField("ARCOUNT",0),
  6991. NetBIOSNameField("QUESTION_NAME","windows"),
  6992. ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  6993. ByteField("NULL",0),
  6994. ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  6995. ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"})]
  6996. # Name Registration Request
  6997. # Name Refresh Request
  6998. # Name Release Request or Demand
  6999. class NBNSRequest(Packet):
  7000. name="NBNS request"
  7001. fields_desc = [ShortField("NAME_TRN_ID",0),
  7002. ShortField("FLAGS", 0x2910),
  7003. ShortField("QDCOUNT",1),
  7004. ShortField("ANCOUNT",0),
  7005. ShortField("NSCOUNT",0),
  7006. ShortField("ARCOUNT",1),
  7007. NetBIOSNameField("QUESTION_NAME","windows"),
  7008. ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  7009. ByteField("NULL",0),
  7010. ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  7011. ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
  7012. ShortEnumField("RR_NAME",0xC00C,{0xC00C:"Label String Pointer to QUESTION_NAME"}),
  7013. ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  7014. ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  7015. IntField("TTL", 0),
  7016. ShortField("RDLENGTH", 6),
  7017. BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
  7018. BitEnumField("OWNER NODE TYPE",00,2,{00:"B node",01:"P node",02:"M node",03:"H node"}),
  7019. BitEnumField("UNUSED",0,13,{0:"Unused"}),
  7020. IPField("NB_ADDRESS", "127.0.0.1")]
  7021. # Name Query Response
  7022. # Name Registration Response
  7023. class NBNSQueryResponse(Packet):
  7024. name="NBNS query response"
  7025. fields_desc = [ShortField("NAME_TRN_ID",0),
  7026. ShortField("FLAGS", 0x8500),
  7027. ShortField("QDCOUNT",0),
  7028. ShortField("ANCOUNT",1),
  7029. ShortField("NSCOUNT",0),
  7030. ShortField("ARCOUNT",0),
  7031. NetBIOSNameField("RR_NAME","windows"),
  7032. ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  7033. ByteField("NULL",0),
  7034. ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  7035. ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
  7036. IntField("TTL", 0x493e0),
  7037. ShortField("RDLENGTH", 6),
  7038. ShortField("NB_FLAGS", 0),
  7039. IPField("NB_ADDRESS", "127.0.0.1")]
  7040. # Name Query Response (negative)
  7041. # Name Release Response
  7042. class NBNSQueryResponseNegative(Packet):
  7043. name="NBNS query response (negative)"
  7044. fields_desc = [ShortField("NAME_TRN_ID",0),
  7045. ShortField("FLAGS", 0x8506),
  7046. ShortField("QDCOUNT",0),
  7047. ShortField("ANCOUNT",1),
  7048. ShortField("NSCOUNT",0),
  7049. ShortField("ARCOUNT",0),
  7050. NetBIOSNameField("RR_NAME","windows"),
  7051. ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  7052. ByteField("NULL",0),
  7053. ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  7054. ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  7055. IntField("TTL",0),
  7056. ShortField("RDLENGTH",6),
  7057. BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
  7058. BitEnumField("OWNER NODE TYPE",00,2,{00:"B node",01:"P node",02:"M node",03:"H node"}),
  7059. BitEnumField("UNUSED",0,13,{0:"Unused"}),
  7060. IPField("NB_ADDRESS", "127.0.0.1")]
  7061. # Node Status Response
  7062. class NBNSNodeStatusResponse(Packet):
  7063. name="NBNS Node Status Response"
  7064. fields_desc = [ShortField("NAME_TRN_ID",0),
  7065. ShortField("FLAGS", 0x8500),
  7066. ShortField("QDCOUNT",0),
  7067. ShortField("ANCOUNT",1),
  7068. ShortField("NSCOUNT",0),
  7069. ShortField("ARCOUNT",0),
  7070. NetBIOSNameField("RR_NAME","windows"),
  7071. ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  7072. ByteField("NULL",0),
  7073. ShortEnumField("RR_TYPE",0x21, {0x20:"NB",0x21:"NBSTAT"}),
  7074. ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  7075. IntField("TTL",0),
  7076. ShortField("RDLENGTH",83),
  7077. ByteField("NUM_NAMES",1)]
  7078. # Service for Node Status Response
  7079. class NBNSNodeStatusResponseService(Packet):
  7080. name="NBNS Node Status Response Service"
  7081. fields_desc = [StrFixedLenField("NETBIOS_NAME","WINDOWS ",15),
  7082. ByteEnumField("SUFFIX",0,{0:"workstation",0x03:"messenger service",0x20:"file server service",0x1b:"domain master browser",0x1c:"domain controller", 0x1e:"browser election service"}),
  7083. ByteField("NAME_FLAGS",0x4),
  7084. ByteEnumField("UNUSED",0,{0:"unused"})]
  7085. # End of Node Status Response packet
  7086. class NBNSNodeStatusResponseEnd(Packet):
  7087. name="NBNS Node Status Response"
  7088. fields_desc = [SourceMACField("MAC_ADDRESS"),
  7089. BitField("STATISTICS",0,57*8)]
  7090. # Wait for Acknowledgement Response
  7091. class NBNSWackResponse(Packet):
  7092. name="NBNS Wait for Acknowledgement Response"
  7093. fields_desc = [ShortField("NAME_TRN_ID",0),
  7094. ShortField("FLAGS", 0xBC07),
  7095. ShortField("QDCOUNT",0),
  7096. ShortField("ANCOUNT",1),
  7097. ShortField("NSCOUNT",0),
  7098. ShortField("ARCOUNT",0),
  7099. NetBIOSNameField("RR_NAME","windows"),
  7100. ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  7101. ByteField("NULL",0),
  7102. ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  7103. ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  7104. IntField("TTL", 2),
  7105. ShortField("RDLENGTH",2),
  7106. BitField("RDATA",10512,16)] #10512=0010100100010000
  7107. class NBTDatagram(Packet):
  7108. name="NBT Datagram Packet"
  7109. fields_desc= [ByteField("Type", 0x10),
  7110. ByteField("Flags", 0x02),
  7111. ShortField("ID", 0),
  7112. IPField("SourceIP", "127.0.0.1"),
  7113. ShortField("SourcePort", 138),
  7114. ShortField("Length", 272),
  7115. ShortField("Offset", 0),
  7116. NetBIOSNameField("SourceName","windows"),
  7117. ShortEnumField("SUFFIX1",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  7118. ByteField("NULL",0),
  7119. NetBIOSNameField("DestinationName","windows"),
  7120. ShortEnumField("SUFFIX2",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  7121. ByteField("NULL",0)]
  7122. class NBTSession(Packet):
  7123. name="NBT Session Packet"
  7124. fields_desc= [ByteEnumField("TYPE",0,{0x00:"Session Message",0x81:"Session Request",0x82:"Positive Session Response",0x83:"Negative Session Response",0x84:"Retarget Session Response",0x85:"Session Keepalive"}),
  7125. BitField("RESERVED",0x00,7),
  7126. BitField("LENGTH",0,17)]
  7127. # SMB NetLogon Response Header
  7128. class SMBNetlogon_Protocol_Response_Header(Packet):
  7129. name="SMBNetlogon Protocol Response Header"
  7130. fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  7131. ByteEnumField("Command",0x25,{0x25:"Trans"}),
  7132. ByteField("Error_Class",0x02),
  7133. ByteField("Reserved",0),
  7134. LEShortField("Error_code",4),
  7135. ByteField("Flags",0),
  7136. LEShortField("Flags2",0x0000),
  7137. LEShortField("PIDHigh",0x0000),
  7138. LELongField("Signature",0x0),
  7139. LEShortField("Unused",0x0),
  7140. LEShortField("TID",0),
  7141. LEShortField("PID",0),
  7142. LEShortField("UID",0),
  7143. LEShortField("MID",0),
  7144. ByteField("WordCount",17),
  7145. LEShortField("TotalParamCount",0),
  7146. LEShortField("TotalDataCount",112),
  7147. LEShortField("MaxParamCount",0),
  7148. LEShortField("MaxDataCount",0),
  7149. ByteField("MaxSetupCount",0),
  7150. ByteField("unused2",0),
  7151. LEShortField("Flags3",0),
  7152. ByteField("TimeOut1",0xe8),
  7153. ByteField("TimeOut2",0x03),
  7154. LEShortField("unused3",0),
  7155. LEShortField("unused4",0),
  7156. LEShortField("ParamCount2",0),
  7157. LEShortField("ParamOffset",0),
  7158. LEShortField("DataCount",112),
  7159. LEShortField("DataOffset",92),
  7160. ByteField("SetupCount", 3),
  7161. ByteField("unused5", 0)]
  7162. # SMB MailSlot Protocol
  7163. class SMBMailSlot(Packet):
  7164. name = "SMB Mail Slot Protocol"
  7165. fields_desc = [LEShortField("opcode", 1),
  7166. LEShortField("priority", 1),
  7167. LEShortField("class", 2),
  7168. LEShortField("size", 135),
  7169. StrNullField("name","\MAILSLOT\NET\GETDC660")]
  7170. # SMB NetLogon Protocol Response Tail SAM
  7171. class SMBNetlogon_Protocol_Response_Tail_SAM(Packet):
  7172. name = "SMB Netlogon Protocol Response Tail SAM"
  7173. fields_desc = [ByteEnumField("Command", 0x17, {0x12:"SAM logon request", 0x17:"SAM Active directory Response"}),
  7174. ByteField("unused", 0),
  7175. ShortField("Data1", 0),
  7176. ShortField("Data2", 0xfd01),
  7177. ShortField("Data3", 0),
  7178. ShortField("Data4", 0xacde),
  7179. ShortField("Data5", 0x0fe5),
  7180. ShortField("Data6", 0xd10a),
  7181. ShortField("Data7", 0x374c),
  7182. ShortField("Data8", 0x83e2),
  7183. ShortField("Data9", 0x7dd9),
  7184. ShortField("Data10", 0x3a16),
  7185. ShortField("Data11", 0x73ff),
  7186. ByteField("Data12", 0x04),
  7187. StrFixedLenField("Data13", "rmff", 4),
  7188. ByteField("Data14", 0x0),
  7189. ShortField("Data16", 0xc018),
  7190. ByteField("Data18", 0x0a),
  7191. StrFixedLenField("Data20", "rmff-win2k", 10),
  7192. ByteField("Data21", 0xc0),
  7193. ShortField("Data22", 0x18c0),
  7194. ShortField("Data23", 0x180a),
  7195. StrFixedLenField("Data24", "RMFF-WIN2K", 10),
  7196. ShortField("Data25", 0),
  7197. ByteField("Data26", 0x17),
  7198. StrFixedLenField("Data27", "Default-First-Site-Name", 23),
  7199. ShortField("Data28", 0x00c0),
  7200. ShortField("Data29", 0x3c10),
  7201. ShortField("Data30", 0x00c0),
  7202. ShortField("Data31", 0x0200),
  7203. ShortField("Data32", 0x0),
  7204. ShortField("Data33", 0xac14),
  7205. ShortField("Data34", 0x0064),
  7206. ShortField("Data35", 0x0),
  7207. ShortField("Data36", 0x0),
  7208. ShortField("Data37", 0x0),
  7209. ShortField("Data38", 0x0),
  7210. ShortField("Data39", 0x0d00),
  7211. ShortField("Data40", 0x0),
  7212. ShortField("Data41", 0xffff)]
  7213. # SMB NetLogon Protocol Response Tail LM2.0
  7214. class SMBNetlogon_Protocol_Response_Tail_LM20(Packet):
  7215. name = "SMB Netlogon Protocol Response Tail LM20"
  7216. fields_desc = [ByteEnumField("Command",0x06,{0x06:"LM 2.0 Response to logon request"}),
  7217. ByteField("unused", 0),
  7218. StrFixedLenField("DblSlash", "\\\\", 2),
  7219. StrNullField("ServerName","WIN"),
  7220. LEShortField("LM20Token", 0xffff)]
  7221. # SMBNegociate Protocol Request Header
  7222. class SMBNegociate_Protocol_Request_Header(Packet):
  7223. name="SMBNegociate Protocol Request Header"
  7224. fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  7225. ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  7226. ByteField("Error_Class",0),
  7227. ByteField("Reserved",0),
  7228. LEShortField("Error_code",0),
  7229. ByteField("Flags",0x18),
  7230. LEShortField("Flags2",0x0000),
  7231. LEShortField("PIDHigh",0x0000),
  7232. LELongField("Signature",0x0),
  7233. LEShortField("Unused",0x0),
  7234. LEShortField("TID",0),
  7235. LEShortField("PID",1),
  7236. LEShortField("UID",0),
  7237. LEShortField("MID",2),
  7238. ByteField("WordCount",0),
  7239. LEShortField("ByteCount",12)]
  7240. # SMB Negociate Protocol Request Tail
  7241. class SMBNegociate_Protocol_Request_Tail(Packet):
  7242. name="SMB Negociate Protocol Request Tail"
  7243. fields_desc=[ByteField("BufferFormat",0x02),
  7244. StrNullField("BufferData","NT LM 0.12")]
  7245. # SMBNegociate Protocol Response Advanced Security
  7246. class SMBNegociate_Protocol_Response_Advanced_Security(Packet):
  7247. name="SMBNegociate Protocol Response Advanced Security"
  7248. fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  7249. ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  7250. ByteField("Error_Class",0),
  7251. ByteField("Reserved",0),
  7252. LEShortField("Error_Code",0),
  7253. ByteField("Flags",0x98),
  7254. LEShortField("Flags2",0x0000),
  7255. LEShortField("PIDHigh",0x0000),
  7256. LELongField("Signature",0x0),
  7257. LEShortField("Unused",0x0),
  7258. LEShortField("TID",0),
  7259. LEShortField("PID",1),
  7260. LEShortField("UID",0),
  7261. LEShortField("MID",2),
  7262. ByteField("WordCount",17),
  7263. LEShortField("DialectIndex",7),
  7264. ByteField("SecurityMode",0x03),
  7265. LEShortField("MaxMpxCount",50),
  7266. LEShortField("MaxNumberVC",1),
  7267. LEIntField("MaxBufferSize",16144),
  7268. LEIntField("MaxRawSize",65536),
  7269. LEIntField("SessionKey",0x0000),
  7270. LEShortField("ServerCapabilities",0xf3f9),
  7271. BitField("UnixExtensions",0,1),
  7272. BitField("Reserved2",0,7),
  7273. BitField("ExtendedSecurity",1,1),
  7274. BitField("CompBulk",0,2),
  7275. BitField("Reserved3",0,5),
  7276. # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  7277. LEIntField("ServerTimeHigh",0xD6228000L),
  7278. LEIntField("ServerTimeLow",0x1C4EF94),
  7279. LEShortField("ServerTimeZone",0x3c),
  7280. ByteField("EncryptionKeyLength",0),
  7281. LEFieldLenField("ByteCount", None, "SecurityBlob"),
  7282. BitField("GUID",0,128),
  7283. StrLenField("SecurityBlob", "", "ByteCount",shift=-16)]
  7284. # SMBNegociate Protocol Response No Security
  7285. # When using no security, with EncryptionKeyLength=8, you must have an EncryptionKey before the DomainName
  7286. class SMBNegociate_Protocol_Response_No_Security(Packet):
  7287. name="SMBNegociate Protocol Response No Security"
  7288. fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  7289. ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  7290. ByteField("Error_Class",0),
  7291. ByteField("Reserved",0),
  7292. LEShortField("Error_Code",0),
  7293. ByteField("Flags",0x98),
  7294. LEShortField("Flags2",0x0000),
  7295. LEShortField("PIDHigh",0x0000),
  7296. LELongField("Signature",0x0),
  7297. LEShortField("Unused",0x0),
  7298. LEShortField("TID",0),
  7299. LEShortField("PID",1),
  7300. LEShortField("UID",0),
  7301. LEShortField("MID",2),
  7302. ByteField("WordCount",17),
  7303. LEShortField("DialectIndex",7),
  7304. ByteField("SecurityMode",0x03),
  7305. LEShortField("MaxMpxCount",50),
  7306. LEShortField("MaxNumberVC",1),
  7307. LEIntField("MaxBufferSize",16144),
  7308. LEIntField("MaxRawSize",65536),
  7309. LEIntField("SessionKey",0x0000),
  7310. LEShortField("ServerCapabilities",0xf3f9),
  7311. BitField("UnixExtensions",0,1),
  7312. BitField("Reserved2",0,7),
  7313. BitField("ExtendedSecurity",0,1),
  7314. FlagsField("CompBulk",0,2,"CB"),
  7315. BitField("Reserved3",0,5),
  7316. # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  7317. LEIntField("ServerTimeHigh",0xD6228000L),
  7318. LEIntField("ServerTimeLow",0x1C4EF94),
  7319. LEShortField("ServerTimeZone",0x3c),
  7320. ByteField("EncryptionKeyLength",8),
  7321. LEShortField("ByteCount",24),
  7322. BitField("EncryptionKey",0,64),
  7323. StrNullField("DomainName","WORKGROUP"),
  7324. StrNullField("ServerName","RMFF1")]
  7325. # SMBNegociate Protocol Response No Security No Key
  7326. class SMBNegociate_Protocol_Response_No_Security_No_Key(Packet):
  7327. namez="SMBNegociate Protocol Response No Security No Key"
  7328. fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  7329. ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  7330. ByteField("Error_Class",0),
  7331. ByteField("Reserved",0),
  7332. LEShortField("Error_Code",0),
  7333. ByteField("Flags",0x98),
  7334. LEShortField("Flags2",0x0000),
  7335. LEShortField("PIDHigh",0x0000),
  7336. LELongField("Signature",0x0),
  7337. LEShortField("Unused",0x0),
  7338. LEShortField("TID",0),
  7339. LEShortField("PID",1),
  7340. LEShortField("UID",0),
  7341. LEShortField("MID",2),
  7342. ByteField("WordCount",17),
  7343. LEShortField("DialectIndex",7),
  7344. ByteField("SecurityMode",0x03),
  7345. LEShortField("MaxMpxCount",50),
  7346. LEShortField("MaxNumberVC",1),
  7347. LEIntField("MaxBufferSize",16144),
  7348. LEIntField("MaxRawSize",65536),
  7349. LEIntField("SessionKey",0x0000),
  7350. LEShortField("ServerCapabilities",0xf3f9),
  7351. BitField("UnixExtensions",0,1),
  7352. BitField("Reserved2",0,7),
  7353. BitField("ExtendedSecurity",0,1),
  7354. FlagsField("CompBulk",0,2,"CB"),
  7355. BitField("Reserved3",0,5),
  7356. # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  7357. LEIntField("ServerTimeHigh",0xD6228000L),
  7358. LEIntField("ServerTimeLow",0x1C4EF94),
  7359. LEShortField("ServerTimeZone",0x3c),
  7360. ByteField("EncryptionKeyLength",0),
  7361. LEShortField("ByteCount",16),
  7362. StrNullField("DomainName","WORKGROUP"),
  7363. StrNullField("ServerName","RMFF1")]
  7364. # Session Setup AndX Request
  7365. class SMBSession_Setup_AndX_Request(Packet):
  7366. name="Session Setup AndX Request"
  7367. fields_desc=[StrFixedLenField("Start","\xffSMB",4),
  7368. ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
  7369. ByteField("Error_Class",0),
  7370. ByteField("Reserved",0),
  7371. LEShortField("Error_Code",0),
  7372. ByteField("Flags",0x18),
  7373. LEShortField("Flags2",0x0001),
  7374. LEShortField("PIDHigh",0x0000),
  7375. LELongField("Signature",0x0),
  7376. LEShortField("Unused",0x0),
  7377. LEShortField("TID",0),
  7378. LEShortField("PID",1),
  7379. LEShortField("UID",0),
  7380. LEShortField("MID",2),
  7381. ByteField("WordCount",13),
  7382. ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
  7383. ByteField("Reserved2",0),
  7384. LEShortField("AndXOffset",96),
  7385. LEShortField("MaxBufferS",2920),
  7386. LEShortField("MaxMPXCount",50),
  7387. LEShortField("VCNumber",0),
  7388. LEIntField("SessionKey",0),
  7389. LEFieldLenField("ANSIPasswordLength",None,"ANSIPassword"),
  7390. LEShortField("UnicodePasswordLength",0),
  7391. LEIntField("Reserved3",0),
  7392. LEShortField("ServerCapabilities",0x05),
  7393. BitField("UnixExtensions",0,1),
  7394. BitField("Reserved4",0,7),
  7395. BitField("ExtendedSecurity",0,1),
  7396. BitField("CompBulk",0,2),
  7397. BitField("Reserved5",0,5),
  7398. LEShortField("ByteCount",35),
  7399. StrLenField("ANSIPassword", "Pass","ANSIPasswordLength"),
  7400. StrNullField("Account","GUEST"),
  7401. StrNullField("PrimaryDomain", ""),
  7402. StrNullField("NativeOS","Windows 4.0"),
  7403. StrNullField("NativeLanManager","Windows 4.0"),
  7404. ByteField("WordCount2",4),
  7405. ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
  7406. ByteField("Reserved6",0),
  7407. LEShortField("AndXOffset2",0),
  7408. LEShortField("Flags3",0x2),
  7409. LEShortField("PasswordLength",0x1),
  7410. LEShortField("ByteCount2",18),
  7411. ByteField("Password",0),
  7412. StrNullField("Path","\\\\WIN2K\\IPC$"),
  7413. StrNullField("Service","IPC")]
  7414. # Session Setup AndX Response
  7415. class SMBSession_Setup_AndX_Response(Packet):
  7416. name="Session Setup AndX Response"
  7417. fields_desc=[StrFixedLenField("Start","\xffSMB",4),
  7418. ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
  7419. ByteField("Error_Class",0),
  7420. ByteField("Reserved",0),
  7421. LEShortField("Error_Code",0),
  7422. ByteField("Flags",0x90),
  7423. LEShortField("Flags2",0x1001),
  7424. LEShortField("PIDHigh",0x0000),
  7425. LELongField("Signature",0x0),
  7426. LEShortField("Unused",0x0),
  7427. LEShortField("TID",0),
  7428. LEShortField("PID",1),
  7429. LEShortField("UID",0),
  7430. LEShortField("MID",2),
  7431. ByteField("WordCount",3),
  7432. ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
  7433. ByteField("Reserved2",0),
  7434. LEShortField("AndXOffset",66),
  7435. LEShortField("Action",0),
  7436. LEShortField("ByteCount",25),
  7437. StrNullField("NativeOS","Windows 4.0"),
  7438. StrNullField("NativeLanManager","Windows 4.0"),
  7439. StrNullField("PrimaryDomain",""),
  7440. ByteField("WordCount2",3),
  7441. ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
  7442. ByteField("Reserved3",0),
  7443. LEShortField("AndXOffset2",80),
  7444. LEShortField("OptionalSupport",0x01),
  7445. LEShortField("ByteCount2",5),
  7446. StrNullField("Service","IPC"),
  7447. StrNullField("NativeFileSystem","")]
  7448. class MobileIP(Packet):
  7449. name = "Mobile IP (RFC3344)"
  7450. fields_desc = [ ByteEnumField("type", 1, {1:"RRQ", 3:"RRP"}) ]
  7451. class MobileIPRRQ(Packet):
  7452. name = "Mobile IP Registration Request (RFC3344)"
  7453. fields_desc = [ XByteField("flags", 0),
  7454. ShortField("lifetime", 180),
  7455. IPField("homeaddr", "0.0.0.0"),
  7456. IPField("haaddr", "0.0.0.0"),
  7457. IPField("coaddr", "0.0.0.0"),
  7458. Field("id", "", "64s") ]
  7459. class MobileIPRRP(Packet):
  7460. name = "Mobile IP Registration Reply (RFC3344)"
  7461. fields_desc = [ ByteField("code", 0),
  7462. ShortField("lifetime", 180),
  7463. IPField("homeaddr", "0.0.0.0"),
  7464. IPField("haaddr", "0.0.0.0"),
  7465. Field("id", "", "64s") ]
  7466. class MobileIPTunnelData(Packet):
  7467. name = "Mobile IP Tunnel Data Message (RFC3519)"
  7468. fields_desc = [ ByteField("nexthdr", 4),
  7469. ShortField("res", 0) ]
  7470. # Cisco Netflow Protocol version 1
  7471. class NetflowHeader(Packet):
  7472. name = "Netflow Header"
  7473. fields_desc = [ ShortField("version", 1) ]
  7474. class NetflowHeaderV1(Packet):
  7475. name = "Netflow Header V1"
  7476. fields_desc = [ ShortField("count", 0),
  7477. IntField("sysUptime", 0),
  7478. IntField("unixSecs", 0),
  7479. IntField("unixNanoSeconds", 0) ]
  7480. class NetflowRecordV1(Packet):
  7481. name = "Netflow Record"
  7482. fields_desc = [ IPField("ipsrc", "0.0.0.0"),
  7483. IPField("ipdst", "0.0.0.0"),
  7484. IPField("nexthop", "0.0.0.0"),
  7485. ShortField("inputIfIndex", 0),
  7486. ShortField("outpuIfIndex", 0),
  7487. IntField("dpkts", 0),
  7488. IntField("dbytes", 0),
  7489. IntField("starttime", 0),
  7490. IntField("endtime", 0),
  7491. ShortField("srcport", 0),
  7492. ShortField("dstport", 0),
  7493. ShortField("padding", 0),
  7494. ByteField("proto", 0),
  7495. ByteField("tos", 0),
  7496. IntField("padding1", 0),
  7497. IntField("padding2", 0) ]
  7498. #################
  7499. ## Bind layers ##
  7500. #################
  7501. def bind_bottom_up(lower, upper, fval):
  7502. lower.payload_guess = lower.payload_guess[:]
  7503. lower.payload_guess.append((fval, upper))
  7504. def bind_top_down(lower, upper, fval):
  7505. upper.overload_fields = upper.overload_fields.copy()
  7506. upper.overload_fields[lower] = fval
  7507. def bind_layers(lower, upper, fval):
  7508. bind_top_down(lower, upper, fval)
  7509. bind_bottom_up(lower, upper, fval)
  7510. def split_bottom_up(lower, upper, fval):
  7511. def do_filter((f,u),upper=upper,fval=fval):
  7512. if u != upper:
  7513. return True
  7514. for k in fval:
  7515. if k not in f or f[k] != fval[k]:
  7516. return True
  7517. return False
  7518. lower.payload_guess = filter(do_filter, lower.payload_guess)
  7519. def split_top_down(lower, upper, fval):
  7520. if lower in upper.overload_fields:
  7521. ofval = upper.overload_fields[lower]
  7522. for k in fval:
  7523. if k not in ofval or ofval[k] != fval[k]:
  7524. return
  7525. upper.overload_fields = upper.overload_fields.copy()
  7526. del(upper.overload_fields[lower])
  7527. def split_layers(lower, upper, fval):
  7528. split_bottom_up(lower, upper, fval)
  7529. split_top_down(lower, upper, fval)
  7530. layer_bonds = [ ( Dot3, LLC, { } ),
  7531. ( GPRS, IP, { } ),
  7532. ( PrismHeader, Dot11, { }),
  7533. ( Dot11, LLC, { "type" : 2 } ),
  7534. ( PPP, IP, { "proto" : 0x0021 } ),
  7535. ( Ether, LLC, { "type" : 0x007a } ),
  7536. ( Ether, Dot1Q, { "type" : 0x8100 } ),
  7537. ( Ether, Ether, { "type" : 0x0001 } ),
  7538. ( Ether, ARP, { "type" : 0x0806 } ),
  7539. ( Ether, IP, { "type" : 0x0800 } ),
  7540. ( Ether, EAPOL, { "type" : 0x888e } ),
  7541. ( Ether, EAPOL, { "type" : 0x888e, "dst" : "01:80:c2:00:00:03" } ),
  7542. ( Ether, PPPoED, { "type" : 0x8863 } ),
  7543. ( Ether, PPPoE, { "type" : 0x8864 } ),
  7544. ( CookedLinux, LLC, { "proto" : 0x007a } ),
  7545. ( CookedLinux, Dot1Q, { "proto" : 0x8100 } ),
  7546. ( CookedLinux, Ether, { "proto" : 0x0001 } ),
  7547. ( CookedLinux, ARP, { "proto" : 0x0806 } ),
  7548. ( CookedLinux, IP, { "proto" : 0x0800 } ),
  7549. ( CookedLinux, EAPOL, { "proto" : 0x888e } ),
  7550. ( CookedLinux, PPPoED, { "proto" : 0x8863 } ),
  7551. ( CookedLinux, PPPoE, { "proto" : 0x8864 } ),
  7552. ( GRE, LLC, { "proto" : 0x007a } ),
  7553. ( GRE, Dot1Q, { "proto" : 0x8100 } ),
  7554. ( GRE, Ether, { "proto" : 0x0001 } ),
  7555. ( GRE, ARP, { "proto" : 0x0806 } ),
  7556. ( GRE, IP, { "proto" : 0x0800 } ),
  7557. ( GRE, EAPOL, { "proto" : 0x888e } ),
  7558. ( PPPoE, PPP, { "code" : 0x00 } ),
  7559. ( EAPOL, EAP, { "type" : EAPOL.EAP_PACKET } ),
  7560. ( LLC, STP, { "dsap" : 0x42 , "ssap" : 0x42, "ctrl":3 } ),
  7561. ( LLC, SNAP, { "dsap" : 0xAA , "ssap" : 0xAA, "ctrl":3 } ),
  7562. ( SNAP, Dot1Q, { "code" : 0x8100 } ),
  7563. ( SNAP, Ether, { "code" : 0x0001 } ),
  7564. ( SNAP, ARP, { "code" : 0x0806 } ),
  7565. ( SNAP, IP, { "code" : 0x0800 } ),
  7566. ( SNAP, EAPOL, { "code" : 0x888e } ),
  7567. ( IPerror,IPerror, { "frag" : 0, "proto" : socket.IPPROTO_IP } ),
  7568. ( IPerror,ICMPerror,{ "frag" : 0, "proto" : socket.IPPROTO_ICMP } ),
  7569. ( IPerror,TCPerror, { "frag" : 0, "proto" : socket.IPPROTO_TCP } ),
  7570. ( IPerror,UDPerror, { "frag" : 0, "proto" : socket.IPPROTO_UDP } ),
  7571. ( IP, IP, { "frag" : 0, "proto" : socket.IPPROTO_IP } ),
  7572. ( IP, ICMP, { "frag" : 0, "proto" : socket.IPPROTO_ICMP } ),
  7573. ( IP, TCP, { "frag" : 0, "proto" : socket.IPPROTO_TCP } ),
  7574. ( IP, UDP, { "frag" : 0, "proto" : socket.IPPROTO_UDP } ),
  7575. ( IP, GRE, { "frag" : 0, "proto" : socket.IPPROTO_GRE } ),
  7576. ( UDP, MGCP, { "dport" : 2727 } ),
  7577. ( UDP, MGCP, { "sport" : 2727 } ),
  7578. ( UDP, DNS, { "dport" : 53 } ),
  7579. ( UDP, DNS, { "sport" : 53 } ),
  7580. ( UDP, ISAKMP, { "sport" : 500, "dport" : 500 } ),
  7581. ( UDP, HSRP, { "sport" : 1985, "dport" : 1985} ),
  7582. ( UDP, NTP, { "sport" : 123, "dport" : 123 } ),
  7583. ( UDP, BOOTP, { "sport" : 68, "dport" : 67 } ),
  7584. ( UDP, BOOTP, { "sport" : 67, "dport" : 68 } ),
  7585. ( BOOTP, DHCP, { "options" : dhcpmagic } ),
  7586. ( UDP, RIP, { "sport" : 520 } ),
  7587. ( UDP, RIP, { "dport" : 520 } ),
  7588. ( RIP, RIPEntry, { } ),
  7589. ( RIPEntry,RIPEntry,{ } ),
  7590. ( Dot11, Dot11AssoReq, { "type" : 0, "subtype" : 0 } ),
  7591. ( Dot11, Dot11AssoResp, { "type" : 0, "subtype" : 1 } ),
  7592. ( Dot11, Dot11ReassoReq, { "type" : 0, "subtype" : 2 } ),
  7593. ( Dot11, Dot11ReassoResp, { "type" : 0, "subtype" : 3 } ),
  7594. ( Dot11, Dot11ProbeReq, { "type" : 0, "subtype" : 4 } ),
  7595. ( Dot11, Dot11ProbeResp, { "type" : 0, "subtype" : 5 } ),
  7596. ( Dot11, Dot11Beacon, { "type" : 0, "subtype" : 8 } ),
  7597. ( Dot11, Dot11ATIM , { "type" : 0, "subtype" : 9 } ),
  7598. ( Dot11, Dot11Disas , { "type" : 0, "subtype" : 10 } ),
  7599. ( Dot11, Dot11Auth, { "type" : 0, "subtype" : 11 } ),
  7600. ( Dot11, Dot11Deauth, { "type" : 0, "subtype" : 12 } ),
  7601. ( Dot11Beacon, Dot11Elt, {} ),
  7602. ( Dot11AssoReq, Dot11Elt, {} ),
  7603. ( Dot11AssoResp, Dot11Elt, {} ),
  7604. ( Dot11ReassoReq, Dot11Elt, {} ),
  7605. ( Dot11ReassoResp, Dot11Elt, {} ),
  7606. ( Dot11ProbeReq, Dot11Elt, {} ),
  7607. ( Dot11ProbeResp, Dot11Elt, {} ),
  7608. ( Dot11Auth, Dot11Elt, {} ),
  7609. ( Dot11Elt, Dot11Elt, {} ),
  7610. ( TCP, Skinny, { "dport": 2000 } ),
  7611. ( TCP, Skinny, { "sport": 2000 } ),
  7612. ( UDP, SebekHead, { "sport" : 1101 } ),
  7613. ( UDP, SebekHead, { "dport" : 1101 } ),
  7614. ( UDP, SebekHead, { "sport" : 1101,
  7615. "dport" : 1101 } ),
  7616. ( SebekHead, SebekV1, { "version" : 1 } ),
  7617. ( SebekHead, SebekV2Sock, { "version" : 2,
  7618. "type" : 2 } ),
  7619. ( SebekHead, SebekV2, { "version" : 2 } ),
  7620. ( SebekHead, SebekV3Sock, { "version" : 3,
  7621. "type" : 2 } ),
  7622. ( SebekHead, SebekV3, { "version" : 3 } ),
  7623. ( CookedLinux, IrLAPHead, { "proto" : 0x0017 } ),
  7624. ( IrLAPHead, IrLAPCommand, { "Type" : 1} ),
  7625. ( IrLAPCommand, IrLMP, {} ),
  7626. (UDP, NBNSQueryRequest, {"dport" : 137 }),
  7627. (UDP, NBNSRequest, {"dport" : 137 }),
  7628. (UDP, NBNSQueryResponse, {"sport" : 137}),
  7629. (UDP, NBNSQueryResponseNegative, {"sport" : 137}),
  7630. (UDP, NBNSNodeStatusResponse, {"sport" : 137}),
  7631. (NBNSNodeStatusResponse, NBNSNodeStatusResponseService, {}),
  7632. (NBNSNodeStatusResponse, NBNSNodeStatusResponseService, {}),
  7633. (NBNSNodeStatusResponseService, NBNSNodeStatusResponseService, {}),
  7634. (NBNSNodeStatusResponseService, NBNSNodeStatusResponseEnd, {}),
  7635. (UDP, NBNSWackResponse, {"sport" : 137}),
  7636. (UDP,NBTDatagram,{ "dport":138}),
  7637. (TCP,NBTSession,{"dport":139}),
  7638. (NBTSession, SMBNegociate_Protocol_Request_Header,{}),
  7639. (SMBNegociate_Protocol_Request_Header,SMBNegociate_Protocol_Request_Tail,{}),
  7640. (SMBNegociate_Protocol_Request_Tail,SMBNegociate_Protocol_Request_Tail,{}),
  7641. (NBTSession, SMBNegociate_Protocol_Response_Advanced_Security,{"ExtendedSecurity":1}),
  7642. (NBTSession, SMBNegociate_Protocol_Response_No_Security,{"ExtendedSecurity":0,"EncryptionKeyLength":8 }),
  7643. (NBTSession, SMBNegociate_Protocol_Response_No_Security_No_Key,{"ExtendedSecurity":0,"EncryptionKeyLength":0 }),
  7644. (NBTSession, SMBSession_Setup_AndX_Request,{}),
  7645. (NBTSession, SMBSession_Setup_AndX_Response,{}),
  7646. (HCI_Hdr, HCI_ACL_Hdr, {"type":2}),
  7647. (HCI_Hdr, Raw, {}),
  7648. (HCI_ACL_Hdr, L2CAP_Hdr, {}),
  7649. (L2CAP_Hdr, L2CAP_CmdHdr, {"cid":1}),
  7650. (L2CAP_CmdHdr, L2CAP_CmdRej, {"code":1}),
  7651. (L2CAP_CmdHdr, L2CAP_ConnReq, {"code":2}),
  7652. (L2CAP_CmdHdr, L2CAP_ConnResp, {"code":3}),
  7653. (L2CAP_CmdHdr, L2CAP_ConfReq, {"code":4}),
  7654. (L2CAP_CmdHdr, L2CAP_ConfResp, {"code":5}),
  7655. (L2CAP_CmdHdr, L2CAP_DisconnReq, {"code":6}),
  7656. (L2CAP_CmdHdr, L2CAP_DisconnResp, {"code":7}),
  7657. (L2CAP_CmdHdr, L2CAP_InfoReq, {"code":10}),
  7658. (L2CAP_CmdHdr, L2CAP_InfoResp, {"code":11}),
  7659. ( UDP, MobileIP, { "sport" : 434 } ),
  7660. ( UDP, MobileIP, { "dport" : 434 } ),
  7661. ( MobileIP, MobileIPRRQ, { "type" : 1 } ),
  7662. ( MobileIP, MobileIPRRP, { "type" : 3 } ),
  7663. ( MobileIP, MobileIPTunnelData, { "type" : 4 } ),
  7664. ( MobileIPTunnelData, IP, { "nexthdr" : 4 } ),
  7665. ( NetflowHeader, NetflowHeaderV1, { "version" : 1 } ),
  7666. ( NetflowHeaderV1, NetflowRecordV1, {} ),
  7667. ]
  7668. for l in layer_bonds:
  7669. bind_layers(*l)
  7670. del(l)
  7671. ###################
  7672. ## Fragmentation ##
  7673. ###################
  7674. def fragment(pkt, fragsize=1480):
  7675. fragsize = (fragsize+7)/8*8
  7676. pkt = pkt.copy()
  7677. pkt.flags = "MF"
  7678. lst = []
  7679. for p in pkt:
  7680. s = str(p.payload)
  7681. nb = (len(s)+fragsize-1)/fragsize
  7682. for i in range(nb):
  7683. q = p.copy()
  7684. del(q.payload)
  7685. r = Raw(load=s[i*fragsize:(i+1)*fragsize])
  7686. r.overload_fields = p.payload.overload_fields.copy()
  7687. if i == nb-1:
  7688. q.flags=0
  7689. q.frag = i*fragsize/8
  7690. q.add_payload(r)
  7691. lst.append(q)
  7692. return lst
  7693. ###################
  7694. ## Super sockets ##
  7695. ###################
  7696. def Ether_Dot3_Dispatcher(pkt=None, **kargs):
  7697. if pkt is str and len(pkt) >= 14 and struct.unpack("!H", pkt[12:14])[0] < 1500:
  7698. return Dot3(pkt, **kargs)
  7699. return Ether(pkt, **kargs)
  7700. # According to libdnet
  7701. LLTypes = { ARPHDR_ETHER : Ether_Dot3_Dispatcher,
  7702. ARPHDR_METRICOM : Ether_Dot3_Dispatcher,
  7703. ARPHDR_LOOPBACK : Ether_Dot3_Dispatcher,
  7704. 12 : IP,
  7705. 101 : IP,
  7706. 801 : Dot11,
  7707. 802 : PrismHeader,
  7708. 105 : Dot11,
  7709. 113 : CookedLinux,
  7710. 119 : PrismHeader, # for atheros
  7711. 144 : CookedLinux, # called LINUX_IRDA, similar to CookedLinux
  7712. 783 : IrLAPHead,
  7713. 0xB1E70073L : HCI_Hdr, # I invented this one
  7714. }
  7715. LLNumTypes = { Ether : ARPHDR_ETHER,
  7716. IP : 12,
  7717. IP : 101,
  7718. Dot11 : 801,
  7719. PrismHeader : 802,
  7720. Dot11 : 105,
  7721. CookedLinux : 113,
  7722. CookedLinux : 144,
  7723. IrLAPHead : 783
  7724. }
  7725. L3Types = { ETH_P_IP : IP,
  7726. ETH_P_ARP : ARP,
  7727. ETH_P_ALL : IP
  7728. }
  7729. class SuperSocket:
  7730. closed=0
  7731. def __init__(self, family=socket.AF_INET,type=socket.SOCK_STREAM, proto=0):
  7732. self.ins = socket.socket(family, type, proto)
  7733. self.outs = self.ins
  7734. self.promisc=None
  7735. def send(self, x):
  7736. return self.outs.send(str(x))
  7737. def recv(self, x):
  7738. return Raw(self.ins.recv(x))
  7739. def fileno(self):
  7740. return self.ins.fileno()
  7741. def close(self):
  7742. if self.closed:
  7743. return
  7744. self.closed=1
  7745. if self.ins != self.outs:
  7746. if self.outs and self.outs.fileno() != -1:
  7747. self.outs.close()
  7748. if self.ins and self.ins.fileno() != -1:
  7749. self.ins.close()
  7750. def bind_in(self, addr):
  7751. self.ins.bind(addr)
  7752. def bind_out(self, addr):
  7753. self.outs.bind(addr)
  7754. class L3RawSocket(SuperSocket):
  7755. def __init__(self, type = ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0):
  7756. self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
  7757. self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
  7758. self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  7759. def recv(self, x):
  7760. return Ether(self.ins.recv(x)).payload
  7761. def send(self, x):
  7762. try:
  7763. self.outs.sendto(str(x),(x.dst,0))
  7764. except socket.error,msg:
  7765. log_runtime.error(msg)
  7766. class L3PacketSocket(SuperSocket):
  7767. def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
  7768. self.type = type
  7769. self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  7770. self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
  7771. if not nofilter:
  7772. if conf.except_filter:
  7773. if filter:
  7774. filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  7775. else:
  7776. filter = "not (%s)" % conf.except_filter
  7777. if filter is not None:
  7778. attach_filter(self.ins, filter)
  7779. self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
  7780. self.outs = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  7781. self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
  7782. if promisc is None:
  7783. promisc = conf.promisc
  7784. self.promisc = promisc
  7785. if self.promisc:
  7786. if iface is None:
  7787. self.iff = get_if_list()
  7788. else:
  7789. if iface.__class__ is list:
  7790. self.iff = iface
  7791. else:
  7792. self.iff = [iface]
  7793. for i in self.iff:
  7794. set_promisc(self.ins, i)
  7795. def close(self):
  7796. if self.closed:
  7797. return
  7798. self.closed=1
  7799. if self.promisc:
  7800. for i in self.iff:
  7801. set_promisc(self.ins, i, 0)
  7802. SuperSocket.close(self)
  7803. def recv(self, x):
  7804. pkt, sa_ll = self.ins.recvfrom(x)
  7805. if sa_ll[2] == socket.PACKET_OUTGOING:
  7806. return None
  7807. if LLTypes.has_key(sa_ll[3]):
  7808. cls = LLTypes[sa_ll[3]]
  7809. lvl = 2
  7810. elif L3Types.has_key(sa_ll[1]):
  7811. cls = L3Types[sa_ll[1]]
  7812. lvl = 3
  7813. else:
  7814. warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
  7815. cls = Ether
  7816. lvl = 2
  7817. try:
  7818. pkt = cls(pkt)
  7819. except:
  7820. if conf.debug_dissector:
  7821. raise
  7822. pkt = Raw(pkt)
  7823. if lvl == 2:
  7824. pkt = pkt.payload
  7825. return pkt
  7826. def send(self, x):
  7827. if isinstance(x, IPv6):
  7828. iff,a,gw = conf.route6.route(x.dst)
  7829. elif hasattr(x,"dst"):
  7830. iff,a,gw = conf.route.route(x.dst)
  7831. else:
  7832. iff = conf.iface
  7833. sdto = (iff, self.type)
  7834. self.outs.bind(sdto)
  7835. sn = self.outs.getsockname()
  7836. if sn[3] == ARPHDR_PPP:
  7837. sdto = (iff, ETH_P_IP)
  7838. elif LLTypes.has_key(sn[3]):
  7839. x = LLTypes[sn[3]]()/x
  7840. self.outs.sendto(str(x), sdto)
  7841. class L2Socket(SuperSocket):
  7842. def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
  7843. if iface is None:
  7844. iface = conf.iface
  7845. self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  7846. self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
  7847. if not nofilter:
  7848. if conf.except_filter:
  7849. if filter:
  7850. filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  7851. else:
  7852. filter = "not (%s)" % conf.except_filter
  7853. if filter is not None:
  7854. attach_filter(self.ins, filter)
  7855. self.ins.bind((iface, type))
  7856. self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
  7857. self.outs = self.ins
  7858. self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
  7859. sa_ll = self.outs.getsockname()
  7860. if LLTypes.has_key(sa_ll[3]):
  7861. self.LL = LLTypes[sa_ll[3]]
  7862. elif L3Types.has_key(sa_ll[1]):
  7863. self.LL = L3Types[sa_ll[1]]
  7864. else:
  7865. warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
  7866. self.LL = Ether
  7867. def recv(self, x):
  7868. pkt, sa_ll = self.ins.recvfrom(x)
  7869. if sa_ll[2] == socket.PACKET_OUTGOING:
  7870. return None
  7871. try:
  7872. q = self.LL(pkt)
  7873. except:
  7874. if conf.debug_dissector:
  7875. raise
  7876. q = Raw(pkt)
  7877. return q
  7878. class L2ListenSocket(SuperSocket):
  7879. def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
  7880. self.type = type
  7881. self.outs = None
  7882. self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  7883. self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
  7884. if iface is not None:
  7885. self.ins.bind((iface, type))
  7886. if not nofilter:
  7887. if conf.except_filter:
  7888. if filter:
  7889. filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  7890. else:
  7891. filter = "not (%s)" % conf.except_filter
  7892. if filter is not None:
  7893. attach_filter(self.ins, filter)
  7894. if promisc is None:
  7895. promisc = conf.sniff_promisc
  7896. self.promisc = promisc
  7897. if iface is None:
  7898. self.iff = get_if_list()
  7899. else:
  7900. if iface.__class__ is list:
  7901. self.iff = iface
  7902. else:
  7903. self.iff = [iface]
  7904. if self.promisc:
  7905. for i in self.iff:
  7906. set_promisc(self.ins, i)
  7907. self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
  7908. def close(self):
  7909. if self.promisc:
  7910. for i in self.iff:
  7911. set_promisc(self.ins, i, 0)
  7912. SuperSocket.close(self)
  7913. def recv(self, x):
  7914. pkt, sa_ll = self.ins.recvfrom(x)
  7915. if LLTypes.has_key(sa_ll[3]):
  7916. cls = LLTypes[sa_ll[3]]
  7917. elif L3Types.has_key(sa_ll[1]):
  7918. cls = L3Types[sa_ll[1]]
  7919. else:
  7920. warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
  7921. cls = Ether
  7922. try:
  7923. pkt = cls(pkt)
  7924. except:
  7925. if conf.debug_dissector:
  7926. raise
  7927. pkt = Raw(pkt)
  7928. return pkt
  7929. def send(self, x):
  7930. raise Exception("Can't send anything with L2ListenSocket")
  7931. class L3dnetSocket(SuperSocket):
  7932. def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
  7933. self.iflist = {}
  7934. self.ins = pcap.pcapObject()
  7935. if iface is None:
  7936. iface = conf.iface
  7937. self.iface = iface
  7938. self.ins.open_live(iface, 1600, 0, 100)
  7939. try:
  7940. ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
  7941. except:
  7942. pass
  7943. if nofilter:
  7944. if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
  7945. filter = "ether proto %i" % type
  7946. else:
  7947. filter = None
  7948. else:
  7949. if conf.except_filter:
  7950. if filter:
  7951. filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  7952. else:
  7953. filter = "not (%s)" % conf.except_filter
  7954. if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
  7955. if filter:
  7956. filter = "(ether proto %i) and (%s)" % (type,filter)
  7957. else:
  7958. filter = "ether proto %i" % type
  7959. if filter:
  7960. self.ins.setfilter(filter, 0, 0)
  7961. def send(self, x):
  7962. if isinstance(x, IPv6):
  7963. iff,a,gw = conf.route6.route(x.dst)
  7964. elif hasattr(x,"dst"):
  7965. iff,a,gw = conf.route.route(x.dst)
  7966. else:
  7967. iff = conf.iface
  7968. ifs = self.iflist.get(iff)
  7969. if ifs is None:
  7970. self.iflist[iff] = ifs = dnet.eth(iff)
  7971. ifs.send(str(Ether()/x))
  7972. def recv(self,x=MTU):
  7973. ll = self.ins.datalink()
  7974. if LLTypes.has_key(ll):
  7975. cls = LLTypes[ll]
  7976. else:
  7977. warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
  7978. cls = Ether
  7979. pkt = self.ins.next()
  7980. if pkt is not None:
  7981. pkt = pkt[1]
  7982. if pkt is None:
  7983. return
  7984. try:
  7985. pkt = cls(pkt)
  7986. except:
  7987. if conf.debug_dissector:
  7988. raise
  7989. pkt = Raw(pkt)
  7990. return pkt.payload
  7991. def nonblock_recv(self):
  7992. self.ins.setnonblock(1)
  7993. p = self.recv()
  7994. self.ins.setnonblock(0)
  7995. return p
  7996. def close(self):
  7997. if hasattr(self, "ins"):
  7998. del(self.ins)
  7999. if hasattr(self, "outs"):
  8000. del(self.outs)
  8001. class L2dnetSocket(SuperSocket):
  8002. def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
  8003. if iface is None:
  8004. iface = conf.iface
  8005. self.iface = iface
  8006. self.ins = pcap.pcapObject()
  8007. self.ins.open_live(iface, 1600, 0, 100)
  8008. try:
  8009. ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
  8010. except:
  8011. pass
  8012. if nofilter:
  8013. if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
  8014. filter = "ether proto %i" % type
  8015. else:
  8016. filter = None
  8017. else:
  8018. if conf.except_filter:
  8019. if filter:
  8020. filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  8021. else:
  8022. filter = "not (%s)" % conf.except_filter
  8023. if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap
  8024. if filter:
  8025. filter = "(ether proto %i) and (%s)" % (type,filter)
  8026. else:
  8027. filter = "ether proto %i" % type
  8028. if filter:
  8029. self.ins.setfilter(filter, 0, 0)
  8030. self.outs = dnet.eth(iface)
  8031. def recv(self,x):
  8032. ll = self.ins.datalink()
  8033. if LLTypes.has_key(ll):
  8034. cls = LLTypes[ll]
  8035. else:
  8036. warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
  8037. cls = Ether
  8038. pkt = self.ins.next()
  8039. if pkt is not None:
  8040. pkt = pkt[1]
  8041. if pkt is None:
  8042. return
  8043. try:
  8044. pkt = cls(pkt)
  8045. except:
  8046. if conf.debug_dissector:
  8047. raise
  8048. pkt = Raw(pkt)
  8049. return pkt
  8050. def nonblock_recv(self):
  8051. self.ins.setnonblock(1)
  8052. p = self.recv(MTU)
  8053. self.ins.setnonblock(0)
  8054. return p
  8055. def close(self):
  8056. if hasattr(self, "ins"):
  8057. del(self.ins)
  8058. if hasattr(self, "outs"):
  8059. del(self.outs)
  8060. class L2pcapListenSocket(SuperSocket):
  8061. def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None):
  8062. self.type = type
  8063. self.outs = None
  8064. self.ins = pcap.pcapObject()
  8065. self.iface = iface
  8066. if iface is None:
  8067. iface = conf.iface
  8068. if promisc is None:
  8069. promisc = conf.sniff_promisc
  8070. self.promisc = promisc
  8071. self.ins.open_live(iface, 1600, self.promisc, 100)
  8072. try:
  8073. ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
  8074. except:
  8075. pass
  8076. if type == ETH_P_ALL: # Do not apply any filter if Ethernet type is given
  8077. if conf.except_filter:
  8078. if filter:
  8079. filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  8080. else:
  8081. filter = "not (%s)" % conf.except_filter
  8082. if filter:
  8083. self.ins.setfilter(filter, 0, 0)
  8084. def close(self):
  8085. del(self.ins)
  8086. def recv(self, x):
  8087. ll = self.ins.datalink()
  8088. if LLTypes.has_key(ll):
  8089. cls = LLTypes[ll]
  8090. else:
  8091. warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
  8092. cls = Ether
  8093. pkt = None
  8094. while pkt is None:
  8095. pkt = self.ins.next()
  8096. if pkt is not None:
  8097. pkt = pkt[1]
  8098. try:
  8099. pkt = cls(pkt)
  8100. except:
  8101. if conf.debug_dissector:
  8102. raise
  8103. pkt = Raw(pkt)
  8104. return pkt
  8105. def send(self, x):
  8106. raise Exception("Can't send anything with L2pcapListenSocket")
  8107. class SimpleSocket(SuperSocket):
  8108. def __init__(self, sock):
  8109. self.ins = sock
  8110. self.outs = sock
  8111. class StreamSocket(SimpleSocket):
  8112. def __init__(self, sock, basecls=Raw):
  8113. SimpleSocket.__init__(self, sock)
  8114. self.basecls = basecls
  8115. def recv(self, x=MTU):
  8116. pkt = self.ins.recv(x, socket.MSG_PEEK)
  8117. x = len(pkt)
  8118. pkt = self.basecls(pkt)
  8119. pad = pkt[Padding]
  8120. if pad is not None and pad.underlayer is not None:
  8121. del(pad.underlayer.payload)
  8122. while pad is not None and not isinstance(pad, NoPayload):
  8123. x -= len(pad.load)
  8124. pad = pad.payload
  8125. self.ins.recv(x)
  8126. return pkt
  8127. class BluetoothL2CAPSocket(SuperSocket):
  8128. def __init__(self, peer):
  8129. s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
  8130. socket.BTPROTO_L2CAP)
  8131. s.connect((peer,0))
  8132. self.ins = self.outs = s
  8133. def recv(self, x):
  8134. return L2CAP_HdrCmd(self.ins.recv(x))
  8135. class BluetoothHCISocket(SuperSocket):
  8136. def __init__(self, iface=0x10000, type=None):
  8137. s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
  8138. s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR,1)
  8139. s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP,1)
  8140. s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffffL,0xffffffffL,0xffffffffL,0)) #type mask, event mask, event mask, opcode
  8141. s.bind((iface,))
  8142. self.ins = self.outs = s
  8143. # s.connect((peer,0))
  8144. def recv(self, x):
  8145. return HCI_Hdr(self.ins.recv(x))
  8146. ####################
  8147. ## Send / Receive ##
  8148. ####################
  8149. def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
  8150. if not isinstance(pkt, Gen):
  8151. pkt = SetGen(pkt)
  8152. if verbose is None:
  8153. verbose = conf.verb
  8154. debug.recv = PacketList([],"Unanswered")
  8155. debug.sent = PacketList([],"Sent")
  8156. debug.match = SndRcvList([])
  8157. nbrecv=0
  8158. ans = []
  8159. # do it here to fix random fields, so that parent and child have the same
  8160. tobesent = [p for p in pkt]
  8161. notans = len(tobesent)
  8162. hsent={}
  8163. for i in tobesent:
  8164. h = i.hashret()
  8165. if h in hsent:
  8166. hsent[h].append(i)
  8167. else:
  8168. hsent[h] = [i]
  8169. if retry < 0:
  8170. retry = -retry
  8171. autostop=retry
  8172. else:
  8173. autostop=0
  8174. while retry >= 0:
  8175. found=0
  8176. if timeout < 0:
  8177. timeout = None
  8178. rdpipe,wrpipe = os.pipe()
  8179. rdpipe=os.fdopen(rdpipe)
  8180. wrpipe=os.fdopen(wrpipe,"w")
  8181. pid = os.fork()
  8182. if pid == 0:
  8183. sys.stdin.close()
  8184. rdpipe.close()
  8185. try:
  8186. i = 0
  8187. if verbose:
  8188. print "Begin emission:"
  8189. for p in tobesent:
  8190. pks.send(p)
  8191. i += 1
  8192. time.sleep(inter)
  8193. if verbose:
  8194. print "Finished to send %i packets." % i
  8195. except SystemExit:
  8196. pass
  8197. except KeyboardInterrupt:
  8198. pass
  8199. except:
  8200. log_runtime.exception("--- Error in child %i" % os.getpid())
  8201. log_runtime.info("--- Error in child %i" % os.getpid())
  8202. os._exit(0)
  8203. else:
  8204. cPickle.dump(arp_cache, wrpipe)
  8205. wrpipe.close()
  8206. os._exit(0)
  8207. elif pid < 0:
  8208. log_runtime.error("fork error")
  8209. else:
  8210. wrpipe.close()
  8211. stoptime = 0
  8212. remaintime = None
  8213. inmask = [rdpipe,pks]
  8214. try:
  8215. while 1:
  8216. if stoptime:
  8217. remaintime = stoptime-time.time()
  8218. if remaintime <= 0:
  8219. break
  8220. r = None
  8221. if FREEBSD or DARWIN:
  8222. inp, out, err = select(inmask,[],[], 0.05)
  8223. if len(inp) == 0 or pks in inp:
  8224. r = pks.nonblock_recv()
  8225. else:
  8226. inp, out, err = select(inmask,[],[], remaintime)
  8227. if len(inp) == 0:
  8228. break
  8229. if pks in inp:
  8230. r = pks.recv(MTU)
  8231. if rdpipe in inp:
  8232. if timeout:
  8233. stoptime = time.time()+timeout
  8234. del(inmask[inmask.index(rdpipe)])
  8235. if r is None:
  8236. continue
  8237. ok = 0
  8238. h = r.hashret()
  8239. if h in hsent:
  8240. hlst = hsent[h]
  8241. for i in range(len(hlst)):
  8242. if r.answers(hlst[i]):
  8243. ans.append((hlst[i],r))
  8244. if verbose > 1:
  8245. os.write(1, "*")
  8246. ok = 1
  8247. if not multi:
  8248. del(hlst[i])
  8249. notans -= 1;
  8250. else:
  8251. if not hasattr(hlst[i], '_answered'):
  8252. notans -= 1;
  8253. hlst[i]._answered = 1;
  8254. break
  8255. if notans == 0 and not multi:
  8256. break
  8257. if not ok:
  8258. if verbose > 1:
  8259. os.write(1, ".")
  8260. nbrecv += 1
  8261. if conf.debug_match:
  8262. debug.recv.append(r)
  8263. except KeyboardInterrupt:
  8264. if chainCC:
  8265. raise KeyboardInterrupt
  8266. try:
  8267. ac = cPickle.load(rdpipe)
  8268. except EOFError:
  8269. warning("Child died unexpectedly. Packets may have not been sent")
  8270. else:
  8271. arp_cache.update(ac)
  8272. os.waitpid(pid,0)
  8273. remain = reduce(list.__add__, hsent.values(), [])
  8274. if multi:
  8275. remain = filter(lambda p: not hasattr(p, '_answered'), remain);
  8276. if autostop and len(remain) > 0 and len(remain) != len(tobesent):
  8277. retry = autostop
  8278. tobesent = remain
  8279. if len(tobesent) == 0:
  8280. break
  8281. retry -= 1
  8282. if conf.debug_match:
  8283. debug.sent=PacketList(remain[:],"Sent")
  8284. debug.match=SndRcvList(ans[:])
  8285. #clean the ans list to delete the field _answered
  8286. if (multi):
  8287. for s,r in ans:
  8288. if hasattr(s, '_answered'):
  8289. del(s._answered)
  8290. if verbose:
  8291. print "\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans)
  8292. return SndRcvList(ans),PacketList(remain,"Unanswered"),debug.recv
  8293. def __gen_send(s, x, inter=0, loop=0, verbose=None, *args, **kargs):
  8294. if not isinstance(x, Gen):
  8295. x = SetGen(x)
  8296. if verbose is None:
  8297. verbose = conf.verb
  8298. n = 0
  8299. try:
  8300. while 1:
  8301. for p in x:
  8302. s.send(p)
  8303. n += 1
  8304. if verbose:
  8305. os.write(1,".")
  8306. time.sleep(inter)
  8307. if not loop:
  8308. break
  8309. except KeyboardInterrupt:
  8310. pass
  8311. s.close()
  8312. if verbose:
  8313. print "\nSent %i packets." % n
  8314. def send(x, inter=0, loop=0, verbose=None, *args, **kargs):
  8315. """Send packets at layer 3
  8316. send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
  8317. __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, verbose=verbose)
  8318. def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, verbose=None, *args, **kargs):
  8319. """Send packets at layer 2
  8320. send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
  8321. if iface is None and iface_hint is not None:
  8322. iface = conf.route.route(iface_hint)[0]
  8323. __gen_send(conf.L2socket(iface=iface, *args, **kargs), x, inter=inter, loop=loop, verbose=verbose)
  8324. def sr(x,filter=None, iface=None, *args,**kargs):
  8325. """Send and receive packets at layer 3
  8326. nofilter: put 1 to avoid use of bpf filters
  8327. retry: if positive, how many times to resend unanswered packets
  8328. if negative, how many times to retry when no more packets are answered
  8329. timeout: how much time to wait after the last packet has been sent
  8330. verbose: set verbosity level
  8331. multi: whether to accept multiple answers for the same stimulus
  8332. filter: provide a BPF filter
  8333. iface: listen answers only on the given interface"""
  8334. if not kargs.has_key("timeout"):
  8335. kargs["timeout"] = -1
  8336. s = conf.L3socket(filter=filter, iface=iface)
  8337. a,b,c=sndrcv(s,x,*args,**kargs)
  8338. s.close()
  8339. return a,b
  8340. def sr1(x,filter=None,iface=None, nofilter=0, *args,**kargs):
  8341. """Send packets at layer 3 and return only the first answer
  8342. nofilter: put 1 to avoid use of bpf filters
  8343. retry: if positive, how many times to resend unanswered packets
  8344. if negative, how many times to retry when no more packets are answered
  8345. timeout: how much time to wait after the last packet has been sent
  8346. verbose: set verbosity level
  8347. multi: whether to accept multiple answers for the same stimulus
  8348. filter: provide a BPF filter
  8349. iface: listen answers only on the given interface"""
  8350. if not kargs.has_key("timeout"):
  8351. kargs["timeout"] = -1
  8352. s=conf.L3socket(filter=filter, nofilter=nofilter, iface=iface)
  8353. a,b,c=sndrcv(s,x,*args,**kargs)
  8354. s.close()
  8355. if len(a) > 0:
  8356. return a[0][1]
  8357. else:
  8358. return None
  8359. def srp(x,iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs):
  8360. """Send and receive packets at layer 2
  8361. nofilter: put 1 to avoid use of bpf filters
  8362. retry: if positive, how many times to resend unanswered packets
  8363. if negative, how many times to retry when no more packets are answered
  8364. timeout: how much time to wait after the last packet has been sent
  8365. verbose: set verbosity level
  8366. multi: whether to accept multiple answers for the same stimulus
  8367. filter: provide a BPF filter
  8368. iface: work only on the given interface"""
  8369. if not kargs.has_key("timeout"):
  8370. kargs["timeout"] = -1
  8371. if iface is None and iface_hint is not None:
  8372. iface = conf.route.route(iface_hint)[0]
  8373. a,b,c=sndrcv(conf.L2socket(iface=iface, filter=filter, nofilter=nofilter, type=type),x,*args,**kargs)
  8374. return a,b
  8375. def srp1(*args,**kargs):
  8376. """Send and receive packets at layer 2 and return only the first answer
  8377. nofilter: put 1 to avoid use of bpf filters
  8378. retry: if positive, how many times to resend unanswered packets
  8379. if negative, how many times to retry when no more packets are answered
  8380. timeout: how much time to wait after the last packet has been sent
  8381. verbose: set verbosity level
  8382. multi: whether to accept multiple answers for the same stimulus
  8383. filter: provide a BPF filter
  8384. iface: work only on the given interface"""
  8385. if not kargs.has_key("timeout"):
  8386. kargs["timeout"] = -1
  8387. a,b=srp(*args,**kargs)
  8388. if len(a) > 0:
  8389. return a[0][1]
  8390. else:
  8391. return None
  8392. def __sr_loop(srfunc, pkts, prn=lambda x:x[1].summary(), prnfail=lambda x:x.summary(), inter=1, timeout=None, count=None, verbose=0, store=1, *args, **kargs):
  8393. n = 0
  8394. r = 0
  8395. ct = conf.color_theme
  8396. parity = 0
  8397. ans=[]
  8398. unans=[]
  8399. if timeout is None:
  8400. timeout = min(2*inter, 5)
  8401. try:
  8402. while 1:
  8403. parity ^= 1
  8404. col = [ct.even,ct.odd][parity]
  8405. if count is not None:
  8406. if count == 0:
  8407. break
  8408. count -= 1
  8409. start = time.time()
  8410. print "\rsend...\r",
  8411. res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=1, *args, **kargs)
  8412. n += len(res[0])+len(res[1])
  8413. r += len(res[0])
  8414. if prn and len(res[0]) > 0:
  8415. msg = "RECV %i:" % len(res[0])
  8416. print "\r"+ct.success(msg),
  8417. for p in res[0]:
  8418. print col(prn(p))
  8419. print " "*len(msg),
  8420. if prnfail and len(res[1]) > 0:
  8421. msg = "fail %i:" % len(res[1])
  8422. print "\r"+ct.fail(msg),
  8423. for p in res[1]:
  8424. print col(prnfail(p))
  8425. print " "*len(msg),
  8426. if not (prn or prnfail):
  8427. print "recv:%i fail:%i" % tuple(map(len, res[:2]))
  8428. if store:
  8429. ans += res[0]
  8430. unans += res[1]
  8431. end=time.time()
  8432. if end-start < inter:
  8433. time.sleep(inter+start-end)
  8434. except KeyboardInterrupt:
  8435. pass
  8436. if n>0:
  8437. print "%s\nSent %i packets, received %i packets. %3.1f%% hits." % (Color.normal,n,r,100.0*r/n)
  8438. return SndRcvList(ans),PacketList(unans)
  8439. def srloop(pkts, *args, **kargs):
  8440. """Send a packet at layer 3 in loop and print the answer each time
  8441. srloop(pkts, [prn], [inter], [count], ...) --> None"""
  8442. return __sr_loop(sr, pkts, *args, **kargs)
  8443. def srploop(pkts, *args, **kargs):
  8444. """Send a packet at layer 2 in loop and print the answer each time
  8445. srloop(pkts, [prn], [inter], [count], ...) --> None"""
  8446. return __sr_loop(srp, pkts, *args, **kargs)
  8447. ## Bluetooth
  8448. def srbt(peer, pkts, inter=0.1, *args, **kargs):
  8449. s = conf.BTsocket(peer=peer)
  8450. a,b,c=sndrcv(s,pkts,inter=inter,*args,**kargs)
  8451. s.close()
  8452. return a,b
  8453. def srbt1(peer, pkts, *args, **kargs):
  8454. a,b = srbt(peer, pkts, *args, **kargs)
  8455. if len(a) > 0:
  8456. return a[0][1]
  8457. #############################
  8458. ## pcap capture file stuff ##
  8459. #############################
  8460. def wrpcap(filename, pkt, *args, **kargs):
  8461. """Write a list of packets to a pcap file
  8462. gz: set to 1 to save a gzipped capture
  8463. linktype: force linktype value
  8464. endianness: "<" or ">", force endianness"""
  8465. PcapWriter(filename, *args, **kargs).write(pkt)
  8466. def rdpcap(filename, count=-1):
  8467. """Read a pcap file and return a packet list
  8468. count: read only <count> packets"""
  8469. return PcapReader(filename).read_all(count=count)
  8470. class PcapReader:
  8471. """A stateful pcap reader
  8472. Based entirely on scapy.rdpcap(), this class allows for packets
  8473. to be dispatched without having to be loaded into memory all at
  8474. once
  8475. """
  8476. def __init__(self, filename):
  8477. self.filename = filename
  8478. try:
  8479. self.f = gzip.open(filename,"rb")
  8480. magic = self.f.read(4)
  8481. except IOError:
  8482. self.f = open(filename,"rb")
  8483. magic = self.f.read(4)
  8484. if magic == "\xa1\xb2\xc3\xd4": #big endian
  8485. self.endian = ">"
  8486. elif magic == "\xd4\xc3\xb2\xa1": #little endian
  8487. self.endian = "<"
  8488. else:
  8489. raise RuntimeWarning, "Not a pcap capture file (bad magic)"
  8490. hdr = self.f.read(20)
  8491. if len(hdr)<20:
  8492. raise RuntimeWarning, "Invalid pcap file (too short)"
  8493. vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr)
  8494. self.LLcls = LLTypes.get(linktype, Raw)
  8495. if self.LLcls == Raw:
  8496. warning("PcapReader: unkonwon LL type [%i]/[%#x]. Using Raw packets" % (linktype,linktype))
  8497. def __iter__(self):
  8498. return self
  8499. def next(self):
  8500. """impliment the iterator protocol on a set of packets in a
  8501. pcap file
  8502. """
  8503. pkt = self.read_packet()
  8504. if pkt == None:
  8505. raise StopIteration
  8506. return pkt
  8507. def read_packet(self):
  8508. """return a single packet read from the file
  8509. returns None when no more packets are available
  8510. """
  8511. hdr = self.f.read(16)
  8512. if len(hdr) < 16:
  8513. return None
  8514. sec,usec,caplen,olen = struct.unpack(self.endian+"IIII", hdr)
  8515. s = self.f.read(caplen)
  8516. try:
  8517. p = self.LLcls(s)
  8518. except:
  8519. if conf.debug_dissector:
  8520. raise
  8521. p = Raw(s)
  8522. p.time = sec+0.000001*usec
  8523. return p
  8524. def dispatch(self, callback):
  8525. """call the specified callback routine for each packet read
  8526. This is just a convienience function for the main loop
  8527. that allows for easy launching of packet processing in a
  8528. thread.
  8529. """
  8530. p = self.read_packet()
  8531. while p != None:
  8532. callback(p)
  8533. p = self.read_packet()
  8534. def read_all(self,count=-1):
  8535. """return a list of all packets in the pcap file
  8536. """
  8537. res=[]
  8538. while count != 0:
  8539. count -= 1
  8540. p = self.read_packet()
  8541. if p is None:
  8542. break
  8543. res.append(p)
  8544. return PacketList(res,name = os.path.basename(self.filename))
  8545. def recv(self, size):
  8546. """ Emulate a socket
  8547. """
  8548. return self.read_packet()
  8549. def fileno(self):
  8550. return self.f.fileno()
  8551. class PcapWriter:
  8552. """A pcap writer with more control than wrpcap()
  8553. This routine is based entirely on scapy.wrpcap(), but adds capability
  8554. of writing one packet at a time in a streaming manner.
  8555. """
  8556. def __init__(self, filename, linktype=None, gz=0, endianness=""):
  8557. self.linktype = linktype
  8558. self.header_done = 0
  8559. if gz:
  8560. self.f = gzip.open(filename,"wb")
  8561. else:
  8562. self.f = open(filename,"wb")
  8563. self.endian = endianness
  8564. def fileno(self):
  8565. return self.f.fileno()
  8566. def write(self, pkt):
  8567. """accepts a either a single packet or a list of packets
  8568. to be written to the dumpfile
  8569. """
  8570. if self.header_done == 0:
  8571. if self.linktype == None:
  8572. if isinstance(pkt,Packet):
  8573. linktype = LLNumTypes.get(pkt.__class__,1)
  8574. else:
  8575. linktype = LLNumTypes.get(pkt[0].__class__,1)
  8576. self.f.write(struct.pack(self.endian+"IHHIIII", 0xa1b2c3d4L,
  8577. 2, 4, 0, 0, MTU, linktype))
  8578. self.header_done = 1
  8579. for p in pkt:
  8580. self._write_packet(p)
  8581. def _write_packet(self, packet):
  8582. """writes a single packet to the pcap file
  8583. """
  8584. s = str(packet)
  8585. l = len(s)
  8586. sec = int(packet.time)
  8587. usec = int((packet.time-sec)*1000000)
  8588. self.f.write(struct.pack(self.endian+"IIII", sec, usec, l, l))
  8589. self.f.write(s)
  8590. def import_hexcap():
  8591. p = ""
  8592. try:
  8593. while 1:
  8594. l = raw_input()
  8595. l = l.strip()
  8596. l = l[l.find(" "):]
  8597. l = l.strip()
  8598. l = l[:40]
  8599. l = l.replace(" ","")
  8600. p += l
  8601. except EOFError:
  8602. pass
  8603. p2=""
  8604. for i in range(len(p)/2):
  8605. p2 += chr(int(p[2*i:2*i+2],16))
  8606. return p2
  8607. #####################
  8608. ## knowledge bases ##
  8609. #####################
  8610. class KnowledgeBase:
  8611. def __init__(self, filename):
  8612. self.filename = filename
  8613. self.base = None
  8614. def lazy_init(self):
  8615. self.base = ""
  8616. def reload(self, filename = None):
  8617. if filename is not None:
  8618. self.filename = filename
  8619. oldbase = self.base
  8620. self.base = None
  8621. self.lazy_init()
  8622. if self.base is None:
  8623. self.base = oldbase
  8624. def get_base(self):
  8625. if self.base is None:
  8626. self.lazy_init()
  8627. return self.base
  8628. ##########################
  8629. ## IP location database ##
  8630. ##########################
  8631. class IPCountryKnowledgeBase(KnowledgeBase):
  8632. """
  8633. How to generate the base :
  8634. db = []
  8635. for l in open("GeoIPCountryWhois.csv").readlines():
  8636. s,e,c = l.split(",")[2:5]
  8637. db.append((int(s[1:-1]),int(e[1:-1]),c[1:-1]))
  8638. cPickle.dump(gzip.open("xxx","w"),db)
  8639. """
  8640. def lazy_init(self):
  8641. self.base = load_object(self.filename)
  8642. class CountryLocKnowledgeBase(KnowledgeBase):
  8643. def lazy_init(self):
  8644. f=open(self.filename)
  8645. self.base = {}
  8646. while 1:
  8647. l = f.readline()
  8648. if not l:
  8649. break
  8650. l = l.strip().split(",")
  8651. if len(l) != 3:
  8652. continue
  8653. c,lat,long = l
  8654. self.base[c] = (float(long),float(lat))
  8655. f.close()
  8656. def locate_ip(ip):
  8657. ip=map(int,ip.split("."))
  8658. ip = ip[3]+(ip[2]<<8L)+(ip[1]<<16L)+(ip[0]<<24L)
  8659. cloc = country_loc_kdb.get_base()
  8660. db = IP_country_kdb.get_base()
  8661. d=0
  8662. f=len(db)-1
  8663. while (f-d) > 1:
  8664. guess = (d+f)/2
  8665. if ip > db[guess][0]:
  8666. d = guess
  8667. else:
  8668. f = guess
  8669. s,e,c = db[guess]
  8670. if s <= ip and ip <= e:
  8671. return cloc.get(c,None)
  8672. ###############
  8673. ## p0f stuff ##
  8674. ###############
  8675. # File format (according to p0f.fp) :
  8676. #
  8677. # wwww:ttt:D:ss:OOO...:QQ:OS:Details
  8678. #
  8679. # wwww - window size
  8680. # ttt - initial TTL
  8681. # D - don't fragment bit (0=unset, 1=set)
  8682. # ss - overall SYN packet size
  8683. # OOO - option value and order specification
  8684. # QQ - quirks list
  8685. # OS - OS genre
  8686. # details - OS description
  8687. class p0fKnowledgeBase(KnowledgeBase):
  8688. def __init__(self, filename):
  8689. KnowledgeBase.__init__(self, filename)
  8690. #self.ttl_range=[255]
  8691. def lazy_init(self):
  8692. try:
  8693. f=open(self.filename)
  8694. except IOError:
  8695. warning("Can't open base %s" % self.filename)
  8696. return
  8697. try:
  8698. self.base = []
  8699. for l in f:
  8700. if l[0] in ["#","\n"]:
  8701. continue
  8702. l = tuple(l.split(":"))
  8703. if len(l) < 8:
  8704. continue
  8705. li = map(int,l[1:4])
  8706. #if li[0] not in self.ttl_range:
  8707. # self.ttl_range.append(li[0])
  8708. # self.ttl_range.sort()
  8709. self.base.append((l[0], li[0], li[1], li[2], l[4], l[5], l[6], l[7][:-1]))
  8710. except:
  8711. warning("Can't parse p0f database (new p0f version ?)")
  8712. self.base = None
  8713. f.close()
  8714. def packet2p0f(pkt):
  8715. while pkt.haslayer(IP) and pkt.haslayer(TCP):
  8716. pkt = pkt.getlayer(IP)
  8717. if isinstance(pkt.payload, TCP):
  8718. break
  8719. pkt = pkt.payload
  8720. if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
  8721. raise TypeError("Not a TCP/IP packet")
  8722. if pkt.payload.flags & 0x13 != 0x02: #S,!A,!F
  8723. raise TypeError("Not a syn packet")
  8724. #t = p0f_kdb.ttl_range[:]
  8725. #t += [pkt.ttl]
  8726. #t.sort()
  8727. #ttl=t[t.index(pkt.ttl)+1]
  8728. ttl = pkt.ttl
  8729. df = (pkt.flags & 2) / 2
  8730. ss = len(pkt)
  8731. # from p0f/config.h : PACKET_BIG = 100
  8732. if ss > 100:
  8733. ss = 0
  8734. ooo = ""
  8735. mss = -1
  8736. qqT = False
  8737. qqP = False
  8738. #qqBroken = False
  8739. ilen = (pkt[TCP].dataofs << 2) - 20 # from p0f.c
  8740. for option in pkt.payload.options:
  8741. ilen -= 1
  8742. if option[0] == "MSS":
  8743. ooo += "M" + str(option[1]) + ","
  8744. mss = option[1]
  8745. # FIXME: qqBroken
  8746. ilen -= 3
  8747. elif option[0] == "WScale":
  8748. ooo += "W" + str(option[1]) + ","
  8749. # FIXME: qqBroken
  8750. ilen -= 2
  8751. elif option[0] == "Timestamp":
  8752. if option[1][0] == 0:
  8753. ooo += "T0,"
  8754. else:
  8755. ooo += "T,"
  8756. if option[1][1] != 0:
  8757. qqT = True
  8758. ilen -= 9
  8759. elif option[0] == "SAckOK":
  8760. ooo += "S,"
  8761. ilen -= 1
  8762. elif option[0] == "NOP":
  8763. ooo += "N,"
  8764. elif option[0] == "EOL":
  8765. ooo += "E,"
  8766. if ilen > 0:
  8767. qqP = True
  8768. else:
  8769. ooo += "?,"
  8770. # FIXME: ilen
  8771. ooo = ooo[:-1]
  8772. if ooo == "": ooo = "."
  8773. win = pkt.payload.window
  8774. if mss != -1:
  8775. if win % mss == 0:
  8776. win = "S" + str(win/mss)
  8777. elif win % (mss + 40) == 0:
  8778. win = "T" + str(win/(mss+40))
  8779. win = str(win)
  8780. qq = ""
  8781. if qqP:
  8782. qq += "P"
  8783. if pkt[IP].id == 0:
  8784. qq += "Z"
  8785. if pkt[IP].options != '':
  8786. qq += "I"
  8787. if pkt[TCP].urgptr != 0:
  8788. qq += "U"
  8789. if pkt[TCP].reserved != 0:
  8790. qq += "X"
  8791. if pkt[TCP].ack != 0:
  8792. qq += "A"
  8793. if qqT:
  8794. qq += "T"
  8795. if pkt[TCP].flags & 40 != 0:
  8796. # U or P
  8797. qq += "F"
  8798. if not isinstance(pkt[TCP].payload, NoPayload):
  8799. qq += "D"
  8800. # FIXME : "!" - broken options segment
  8801. if qq == "":
  8802. qq = "."
  8803. return (win,
  8804. ttl,
  8805. df,
  8806. ss,
  8807. ooo,
  8808. qq)
  8809. def p0f_correl(x,y):
  8810. d = 0
  8811. # wwww can be "*" or "%nn"
  8812. d += (x[0] == y[0] or y[0] == "*" or (y[0][0] == "%" and x[0].isdigit() and (int(x[0]) % int(y[0][1:])) == 0))
  8813. # ttl
  8814. d += (y[1] >= x[1] and y[1] - x[1] < 32)
  8815. for i in [2, 3, 5]:
  8816. d += (x[i] == y[i])
  8817. xopt = x[4].split(",")
  8818. yopt = y[4].split(",")
  8819. if len(xopt) == len(yopt):
  8820. same = True
  8821. for i in range(len(xopt)):
  8822. if not (xopt[i] == yopt[i] or
  8823. (len(yopt[i]) == 2 and len(xopt[i]) > 1 and
  8824. yopt[i][1] == "*" and xopt[i][0] == yopt[i][0]) or
  8825. (len(yopt[i]) > 2 and len(xopt[i]) > 1 and
  8826. yopt[i][1] == "%" and xopt[i][0] == yopt[i][0] and
  8827. int(xopt[i][1:]) % int(yopt[i][2:]) == 0)):
  8828. same = False
  8829. break
  8830. if same:
  8831. d += len(xopt)
  8832. return d
  8833. def p0f(pkt):
  8834. """Passive OS fingerprinting: which OS emitted this TCP SYN ?
  8835. p0f(packet) -> accuracy, [list of guesses]
  8836. """
  8837. pb = p0f_kdb.get_base()
  8838. if not pb:
  8839. warning("p0f base empty.")
  8840. return []
  8841. s = len(pb[0][0])
  8842. r = []
  8843. sig = packet2p0f(pkt)
  8844. max = len(sig[4].split(",")) + 5
  8845. for b in pb:
  8846. d = p0f_correl(sig,b)
  8847. if d == max:
  8848. r.append((b[6], b[7], b[1] - pkt[IP].ttl))
  8849. return r
  8850. def prnp0f(pkt):
  8851. try:
  8852. r = p0f(pkt)
  8853. except:
  8854. return
  8855. if r == []:
  8856. r = ("UNKNOWN", "[" + ":".join(map(str, packet2p0f(pkt))) + ":?:?]", None)
  8857. else:
  8858. r = r[0]
  8859. uptime = None
  8860. try:
  8861. uptime = pkt2uptime(pkt)
  8862. except:
  8863. pass
  8864. if uptime == 0:
  8865. uptime = None
  8866. res = pkt.sprintf("%IP.src%:%TCP.sport% - " + r[0] + " " + r[1])
  8867. if uptime is not None:
  8868. res += pkt.sprintf(" (up: " + str(uptime/3600) + " hrs)\n -> %IP.dst%:%TCP.dport%")
  8869. else:
  8870. res += pkt.sprintf("\n -> %IP.dst%:%TCP.dport%")
  8871. if r[2] is not None:
  8872. res += " (distance " + str(r[2]) + ")"
  8873. print res
  8874. def pkt2uptime(pkt, HZ=100):
  8875. """Calculate the date the machine which emitted the packet booted using TCP timestamp
  8876. pkt2uptime(pkt, [HZ=100])"""
  8877. if not isinstance(pkt, Packet):
  8878. raise TypeError("Not a TCP packet")
  8879. if isinstance(pkt,NoPayload):
  8880. raise TypeError("Not a TCP packet")
  8881. if not isinstance(pkt, TCP):
  8882. return pkt2uptime(pkt.payload)
  8883. for opt in pkt.options:
  8884. if opt[0] == "Timestamp":
  8885. #t = pkt.time - opt[1][0] * 1.0/HZ
  8886. #return time.ctime(t)
  8887. t = opt[1][0] / HZ
  8888. return t
  8889. raise TypeError("No timestamp option")
  8890. #################
  8891. ## Queso stuff ##
  8892. #################
  8893. def quesoTCPflags(flags):
  8894. if flags == "-":
  8895. return "-"
  8896. flv = "FSRPAUXY"
  8897. v = 0
  8898. for i in flags:
  8899. v |= 2**flv.index(i)
  8900. return "%x" % v
  8901. class QuesoKnowledgeBase(KnowledgeBase):
  8902. def lazy_init(self):
  8903. try:
  8904. f = open(self.filename)
  8905. except IOError:
  8906. return
  8907. self.base = {}
  8908. p = None
  8909. try:
  8910. for l in f:
  8911. l = l.strip()
  8912. if not l or l[0] == ';':
  8913. continue
  8914. if l[0] == '*':
  8915. if p is not None:
  8916. p[""] = name
  8917. name = l[1:].strip()
  8918. p = self.base
  8919. continue
  8920. if l[0] not in list("0123456"):
  8921. continue
  8922. res = l[2:].split()
  8923. res[-1] = quesoTCPflags(res[-1])
  8924. res = " ".join(res)
  8925. if not p.has_key(res):
  8926. p[res] = {}
  8927. p = p[res]
  8928. if p is not None:
  8929. p[""] = name
  8930. except:
  8931. self.base = None
  8932. warning("Can't load queso base [%s]", self.filename)
  8933. f.close()
  8934. def queso_sig(target, dport=80, timeout=3):
  8935. p = queso_kdb.get_base()
  8936. ret = []
  8937. for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]:
  8938. ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()),
  8939. timeout=timeout, verbose=0)
  8940. if len(ans) == 0:
  8941. rs = "- - - -"
  8942. else:
  8943. s,r = ans[0]
  8944. rs = "%i" % (r.seq != 0)
  8945. if not r.ack:
  8946. r += " 0"
  8947. elif r.ack-s.seq > 666:
  8948. rs += " R" % 0
  8949. else:
  8950. rs += " +%i" % (r.ack-s.seq)
  8951. rs += " %X" % r.window
  8952. rs += " %x" % r.payload.flags
  8953. ret.append(rs)
  8954. return ret
  8955. def queso_search(sig):
  8956. p = queso_kdb.get_base()
  8957. sig.reverse()
  8958. ret = []
  8959. try:
  8960. while sig:
  8961. s = sig.pop()
  8962. p = p[s]
  8963. if p.has_key(""):
  8964. ret.append(p[""])
  8965. except KeyError:
  8966. pass
  8967. return ret
  8968. def queso(*args,**kargs):
  8969. """Queso OS fingerprinting
  8970. queso(target, dport=80, timeout=3)"""
  8971. return queso_search(queso_sig(*args, **kargs))
  8972. ######################
  8973. ## nmap OS fp stuff ##
  8974. ######################
  8975. class NmapKnowledgeBase(KnowledgeBase):
  8976. def lazy_init(self):
  8977. try:
  8978. f=open(self.filename)
  8979. except IOError:
  8980. return
  8981. self.base = []
  8982. name = None
  8983. try:
  8984. for l in f:
  8985. l = l.strip()
  8986. if not l or l[0] == "#":
  8987. continue
  8988. if l[:12] == "Fingerprint ":
  8989. if name is not None:
  8990. self.base.append((name,sig))
  8991. name = l[12:].strip()
  8992. sig={}
  8993. p = self.base
  8994. continue
  8995. elif l[:6] == "Class ":
  8996. continue
  8997. op = l.find("(")
  8998. cl = l.find(")")
  8999. if op < 0 or cl < 0:
  9000. warning("error reading nmap os fp base file")
  9001. continue
  9002. test = l[:op]
  9003. s = map(lambda x: x.split("="), l[op+1:cl].split("%"))
  9004. si = {}
  9005. for n,v in s:
  9006. si[n] = v
  9007. sig[test]=si
  9008. if name is not None:
  9009. self.base.append((name,sig))
  9010. except:
  9011. self.base = None
  9012. warning("Can't read nmap database [%s](new nmap version ?)" % self.filename)
  9013. f.close()
  9014. def TCPflags2str(f):
  9015. fl="FSRPAUEC"
  9016. s=""
  9017. for i in range(len(fl)):
  9018. if f & 1:
  9019. s = fl[i]+s
  9020. f >>= 1
  9021. return s
  9022. def nmap_tcppacket_sig(pkt):
  9023. r = {}
  9024. if pkt is not None:
  9025. # r["Resp"] = "Y"
  9026. r["DF"] = (pkt.flags & 2) and "Y" or "N"
  9027. r["W"] = "%X" % pkt.window
  9028. r["ACK"] = pkt.ack==2 and "S++" or pkt.ack==1 and "S" or "O"
  9029. r["Flags"] = TCPflags2str(pkt.payload.flags)
  9030. r["Ops"] = "".join(map(lambda x: x[0][0],pkt.payload.options))
  9031. else:
  9032. r["Resp"] = "N"
  9033. return r
  9034. def nmap_udppacket_sig(S,T):
  9035. r={}
  9036. if T is None:
  9037. r["Resp"] = "N"
  9038. else:
  9039. r["DF"] = (T.flags & 2) and "Y" or "N"
  9040. r["TOS"] = "%X" % T.tos
  9041. r["IPLEN"] = "%X" % T.len
  9042. r["RIPTL"] = "%X" % T.payload.payload.len
  9043. r["RID"] = S.id == T.payload.payload.id and "E" or "F"
  9044. r["RIPCK"] = S.chksum == T.getlayer(IPerror).chksum and "E" or T.getlayer(IPerror).chksum == 0 and "0" or "F"
  9045. r["UCK"] = S.payload.chksum == T.getlayer(UDPerror).chksum and "E" or T.getlayer(UDPerror).chksum ==0 and "0" or "F"
  9046. r["ULEN"] = "%X" % T.getlayer(UDPerror).len
  9047. r["DAT"] = T.getlayer(Raw) is None and "E" or S.getlayer(Raw).load == T.getlayer(Raw).load and "E" or "F"
  9048. return r
  9049. def nmap_match_one_sig(seen, ref):
  9050. c = 0
  9051. for k in seen.keys():
  9052. if ref.has_key(k):
  9053. if seen[k] in ref[k].split("|"):
  9054. c += 1
  9055. if c == 0 and seen.get("Resp") == "N":
  9056. return 0.7
  9057. else:
  9058. return 1.0*c/len(seen.keys())
  9059. def nmap_sig(target, oport=80, cport=81, ucport=1):
  9060. res = {}
  9061. tcpopt = [ ("WScale", 10),
  9062. ("NOP",None),
  9063. ("MSS", 256),
  9064. ("Timestamp",(123,0)) ]
  9065. tests = [ IP(dst=target, id=1)/TCP(seq=1, sport=5001, dport=oport, options=tcpopt, flags="CS"),
  9066. IP(dst=target, id=1)/TCP(seq=1, sport=5002, dport=oport, options=tcpopt, flags=0),
  9067. IP(dst=target, id=1)/TCP(seq=1, sport=5003, dport=oport, options=tcpopt, flags="SFUP"),
  9068. IP(dst=target, id=1)/TCP(seq=1, sport=5004, dport=oport, options=tcpopt, flags="A"),
  9069. IP(dst=target, id=1)/TCP(seq=1, sport=5005, dport=cport, options=tcpopt, flags="S"),
  9070. IP(dst=target, id=1)/TCP(seq=1, sport=5006, dport=cport, options=tcpopt, flags="A"),
  9071. IP(dst=target, id=1)/TCP(seq=1, sport=5007, dport=cport, options=tcpopt, flags="FPU"),
  9072. IP(str(IP(dst=target)/UDP(sport=5008,dport=ucport)/(300*"i"))) ]
  9073. ans, unans = sr(tests, timeout=2)
  9074. ans += map(lambda x: (x,None), unans)
  9075. for S,T in ans:
  9076. if S.sport == 5008:
  9077. res["PU"] = nmap_udppacket_sig(S,T)
  9078. else:
  9079. t = "T%i" % (S.sport-5000)
  9080. if T is not None and T.haslayer(ICMP):
  9081. warning("Test %s answered by an ICMP" % t)
  9082. T=None
  9083. res[t] = nmap_tcppacket_sig(T)
  9084. return res
  9085. def nmap_probes2sig(tests):
  9086. tests=tests.copy()
  9087. res = {}
  9088. if "PU" in tests:
  9089. res["PU"] = nmap_udppacket_sig(*tests["PU"])
  9090. del(tests["PU"])
  9091. for k in tests:
  9092. res[k] = nmap_tcppacket_sig(tests[k])
  9093. return res
  9094. def nmap_search(sigs):
  9095. guess = 0,[]
  9096. for os,fp in nmap_kdb.get_base():
  9097. c = 0.0
  9098. for t in sigs.keys():
  9099. if t in fp:
  9100. c += nmap_match_one_sig(sigs[t], fp[t])
  9101. c /= len(sigs.keys())
  9102. if c > guess[0]:
  9103. guess = c,[ os ]
  9104. elif c == guess[0]:
  9105. guess[1].append(os)
  9106. return guess
  9107. def nmap_fp(target, oport=80, cport=81):
  9108. """nmap fingerprinting
  9109. nmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy
  9110. """
  9111. sigs = nmap_sig(target, oport, cport)
  9112. return nmap_search(sigs)
  9113. def nmap_sig2txt(sig):
  9114. torder = ["TSeq","T1","T2","T3","T4","T5","T6","T7","PU"]
  9115. korder = ["Class", "gcd", "SI", "IPID", "TS",
  9116. "Resp", "DF", "W", "ACK", "Flags", "Ops",
  9117. "TOS", "IPLEN", "RIPTL", "RID", "RIPCK", "UCK", "ULEN", "DAT" ]
  9118. txt=[]
  9119. for i in sig.keys():
  9120. if i not in torder:
  9121. torder.append(i)
  9122. for t in torder:
  9123. sl = sig.get(t)
  9124. if sl is None:
  9125. continue
  9126. s = []
  9127. for k in korder:
  9128. v = sl.get(k)
  9129. if v is None:
  9130. continue
  9131. s.append("%s=%s"%(k,v))
  9132. txt.append("%s(%s)" % (t, "%".join(s)))
  9133. return "\n".join(txt)
  9134. ###################
  9135. ## User commands ##
  9136. ###################
  9137. def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg):
  9138. """Sniff packets
  9139. sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
  9140. count: number of packets to capture. 0 means infinity
  9141. store: wether to store sniffed packets or discard them
  9142. prn: function to apply to each packet. If something is returned,
  9143. it is displayed. Ex:
  9144. ex: prn = lambda x: x.summary()
  9145. lfilter: python function applied to each packet to determine
  9146. if further action may be done
  9147. ex: lfilter = lambda x: x.haslayer(Padding)
  9148. offline: pcap file to read packets from, instead of sniffing them
  9149. timeout: stop sniffing after a given time (default: None)
  9150. L2socket: use the provided L2socket
  9151. """
  9152. c = 0
  9153. if offline is None:
  9154. if L2socket is None:
  9155. L2socket = conf.L2listen
  9156. s = L2socket(type=ETH_P_ALL, *arg, **karg)
  9157. else:
  9158. s = PcapReader(offline)
  9159. lst = []
  9160. if timeout is not None:
  9161. stoptime = time.time()+timeout
  9162. remain = None
  9163. while 1:
  9164. try:
  9165. if timeout is not None:
  9166. remain = stoptime-time.time()
  9167. if remain <= 0:
  9168. break
  9169. sel = select([s],[],[],remain)
  9170. if s in sel[0]:
  9171. p = s.recv(MTU)
  9172. if p is None:
  9173. break
  9174. if lfilter and not lfilter(p):
  9175. continue
  9176. if store:
  9177. lst.append(p)
  9178. c += 1
  9179. if prn:
  9180. r = prn(p)
  9181. if r is not None:
  9182. print r
  9183. if count > 0 and c >= count:
  9184. break
  9185. except KeyboardInterrupt:
  9186. break
  9187. return PacketList(lst,"Sniffed")
  9188. def arpcachepoison(target, victim, interval=60):
  9189. """Poison target's cache with (your MAC,victim's IP) couple
  9190. arpcachepoison(target, victim, [interval=60]) -> None
  9191. """
  9192. tmac = getmacbyip(target)
  9193. p = Ether(dst=tmac)/ARP(op="who-has", psrc=victim, pdst=target)
  9194. try:
  9195. while 1:
  9196. sendp(p, iface_hint=target)
  9197. if conf.verb > 1:
  9198. os.write(1,".")
  9199. time.sleep(interval)
  9200. except KeyboardInterrupt:
  9201. pass
  9202. def traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), l4 = None, filter=None, timeout=2, **kargs):
  9203. """Instant TCP traceroute
  9204. traceroute(target, [maxttl=30], [dport=80], [sport=80]) -> None
  9205. """
  9206. if filter is None:
  9207. filter="(icmp and icmp[0]=11) or (tcp and (tcp[13] & 0x16 > 0x10))"
  9208. if l4 is None:
  9209. a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
  9210. timeout=timeout, filter=filter, **kargs)
  9211. else:
  9212. a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/l4,
  9213. timeout=timeout, **kargs)
  9214. a = TracerouteResult(a.res)
  9215. a.display()
  9216. return a,b
  9217. def arping(net, timeout=2, cache=0, **kargs):
  9218. """Send ARP who-has requests to determine which hosts are up
  9219. arping(net, cache=0, iface=conf.iface) -> None
  9220. Set cache=True if you want arping to modify internal ARP-Cache"""
  9221. ans,unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=net),
  9222. filter="arp and arp[7] = 2", timeout=timeout, iface_hint=net, **kargs)
  9223. ans = ARPingResult(ans.res)
  9224. if cache and ans is not None:
  9225. for pair in ans:
  9226. arp_cache[pair[1].psrc] = (pair[1].hwsrc, time.time())
  9227. ans.display()
  9228. return ans,unans
  9229. def dyndns_add(nameserver, name, rdata, type="A", ttl=10):
  9230. """Send a DNS add message to a nameserver for "name" to have a new "rdata"
  9231. dyndns_add(nameserver, name, rdata, type="A", ttl=10) -> result code (0=ok)
  9232. example: dyndns_add("ns1.toto.com", "dyn.toto.com", "127.0.0.1")
  9233. RFC2136
  9234. """
  9235. zone = name[name.find(".")+1:]
  9236. r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
  9237. qd=[DNSQR(qname=zone, qtype="SOA")],
  9238. ns=[DNSRR(rrname=name, type="A",
  9239. ttl=ttl, rdata=rdata)]),
  9240. verbose=0, timeout=5)
  9241. if r and r.haslayer(DNS):
  9242. return r.getlayer(DNS).rcode
  9243. else:
  9244. return -1
  9245. def dyndns_del(nameserver, name, type="ALL", ttl=10):
  9246. """Send a DNS delete message to a nameserver for "name"
  9247. dyndns_del(nameserver, name, type="ANY", ttl=10) -> result code (0=ok)
  9248. example: dyndns_del("ns1.toto.com", "dyn.toto.com")
  9249. RFC2136
  9250. """
  9251. zone = name[name.find(".")+1:]
  9252. r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
  9253. qd=[DNSQR(qname=zone, qtype="SOA")],
  9254. ns=[DNSRR(rrname=name, type=type,
  9255. rclass="ANY", ttl=0, rdata="")]),
  9256. verbose=0, timeout=5)
  9257. if r and r.haslayer(DNS):
  9258. return r.getlayer(DNS).rcode
  9259. else:
  9260. return -1
  9261. def is_promisc(ip, fake_bcast="ff:ff:00:00:00:00",**kargs):
  9262. """Try to guess if target is in Promisc mode. The target is provided by its ip."""
  9263. responses = srp1(Ether(dst=fake_bcast) / ARP(op="who-has", pdst=ip),type=ETH_P_ARP, iface_hint=ip, timeout=1, verbose=0,**kargs)
  9264. print responses
  9265. if responses is None:
  9266. return False
  9267. return True
  9268. def ikescan(ip):
  9269. return sr(IP(dst=ip)/UDP()/ISAKMP(init_cookie=RandString(8),
  9270. exch_type=2)/ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal()))
  9271. def dhcp_request(iface=None,**kargs):
  9272. if conf.checkIPaddr != 0:
  9273. warning("conf.checkIPaddr is not 0, I may not be able to match the answer")
  9274. if iface is None:
  9275. iface = conf.iface
  9276. fam,hw = get_if_raw_hwaddr(iface)
  9277. return srp1(Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)
  9278. /BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"]),iface=iface,**kargs)
  9279. #####################
  9280. ## Reporting stuff ##
  9281. #####################
  9282. def report_ports(target, ports):
  9283. """portscan a target and output a LaTeX table
  9284. report_ports(target, ports) -> string"""
  9285. ans,unans = sr(IP(dst=target)/TCP(dport=ports),timeout=5)
  9286. rep = "\\begin{tabular}{|r|l|l|}\n\\hline\n"
  9287. for s,r in ans:
  9288. if not r.haslayer(ICMP):
  9289. if r.payload.flags == 0x12:
  9290. rep += r.sprintf("%TCP.sport% & open & SA \\\\\n")
  9291. rep += "\\hline\n"
  9292. for s,r in ans:
  9293. if r.haslayer(ICMP):
  9294. rep += r.sprintf("%TCPerror.dport% & closed & ICMP type %ICMP.type%/%ICMP.code% from %IP.src% \\\\\n")
  9295. elif r.payload.flags != 0x12:
  9296. rep += r.sprintf("%TCP.sport% & closed & TCP %TCP.flags% \\\\\n")
  9297. rep += "\\hline\n"
  9298. for i in unans:
  9299. rep += i.sprintf("%TCP.dport% & ? & unanswered \\\\\n")
  9300. rep += "\\hline\n\\end{tabular}\n"
  9301. return rep
  9302. def __make_table(yfmtfunc, fmtfunc, endline, list, fxyz, sortx=None, sorty=None, seplinefunc=None):
  9303. vx = {}
  9304. vy = {}
  9305. vz = {}
  9306. vxf = {}
  9307. vyf = {}
  9308. l = 0
  9309. for e in list:
  9310. xx,yy,zz = map(str, fxyz(e))
  9311. l = max(len(yy),l)
  9312. vx[xx] = max(vx.get(xx,0), len(xx), len(zz))
  9313. vy[yy] = None
  9314. vz[(xx,yy)] = zz
  9315. vxk = vx.keys()
  9316. vyk = vy.keys()
  9317. if sortx:
  9318. vxk.sort(sortx)
  9319. else:
  9320. try:
  9321. vxk.sort(lambda x,y:int(x)-int(y))
  9322. except:
  9323. try:
  9324. vxk.sort(lambda x,y: cmp(struct.unpack("I", inet_aton(x))[0],struct.unpack("I", inet_aton(y))[0]))
  9325. except:
  9326. vxk.sort()
  9327. if sorty:
  9328. vyk.sort(sorty)
  9329. else:
  9330. try:
  9331. vyk.sort(lambda x,y:int(x)-int(y))
  9332. except:
  9333. try:
  9334. vyk.sort(lambda x,y: cmp(struct.unpack("I", inet_aton(x))[0],struct.unpack("I", inet_aton(y))[0]))
  9335. except:
  9336. vyk.sort()
  9337. if seplinefunc:
  9338. sepline = seplinefunc(l, map(lambda x:vx[x],vxk))
  9339. print sepline
  9340. fmt = yfmtfunc(l)
  9341. print fmt % "",
  9342. for x in vxk:
  9343. vxf[x] = fmtfunc(vx[x])
  9344. print vxf[x] % x,
  9345. print endline
  9346. if seplinefunc:
  9347. print sepline
  9348. for y in vyk:
  9349. print fmt % y,
  9350. for x in vxk:
  9351. print vxf[x] % vz.get((x,y), "-"),
  9352. print endline
  9353. if seplinefunc:
  9354. print sepline
  9355. def make_table(*args, **kargs):
  9356. __make_table(lambda l:"%%-%is" % l, lambda l:"%%-%is" % l, "", *args, **kargs)
  9357. def make_lined_table(*args, **kargs):
  9358. __make_table(lambda l:"%%-%is |" % l, lambda l:"%%-%is |" % l, "",
  9359. seplinefunc=lambda a,x:"+".join(map(lambda y:"-"*(y+2), [a-1]+x+[-2])),
  9360. *args, **kargs)
  9361. def make_tex_table(*args, **kargs):
  9362. __make_table(lambda l: "%s", lambda l: "& %s", "\\\\", seplinefunc=lambda a,x:"\\hline", *args, **kargs)
  9363. ######################
  9364. ## Online doc stuff ##
  9365. ######################
  9366. def lsc(cmd=None):
  9367. """List user commands"""
  9368. if cmd is None:
  9369. for c in user_commands:
  9370. doc = "No doc. available"
  9371. if c.__doc__:
  9372. doc = c.__doc__.split("\n")[0]
  9373. print "%-16s : %s" % (c.__name__, doc)
  9374. else:
  9375. print cmd.__doc__
  9376. def ls(obj=None):
  9377. """List available layers, or infos on a given layer"""
  9378. if obj is None:
  9379. import __builtin__
  9380. all = __builtin__.__dict__.copy()
  9381. all.update(globals())
  9382. objlst = filter(lambda (n,o): type(o) is types.TypeType and issubclass(o,Packet), all.items())
  9383. objlst.sort(lambda x,y:cmp(x[0],y[0]))
  9384. for n,o in objlst:
  9385. print "%-10s : %s" %(n,o.name)
  9386. else:
  9387. if type(obj) is types.TypeType and issubclass(obj, Packet):
  9388. for f in obj.fields_desc:
  9389. print "%-10s : %-20s = (%s)" % (f.name, f.__class__.__name__, repr(f.default))
  9390. elif isinstance(obj, Packet):
  9391. for f in obj.fields_desc:
  9392. print "%-10s : %-20s = %-15s (%s)" % (f.name, f.__class__.__name__, repr(getattr(obj,f.name)), repr(f.default))
  9393. if not isinstance(obj.payload, NoPayload):
  9394. print "--"
  9395. ls(obj.payload)
  9396. else:
  9397. print "Not a packet class. Type 'ls()' to list packet classes."
  9398. user_commands = [ sr, sr1, srp, srp1, srloop, srploop, sniff, p0f, arpcachepoison, send, sendp, traceroute, arping, ls, lsc, queso, nmap_fp, report_ports, dyndns_add, dyndns_del, is_promisc ]
  9399. ########################
  9400. ## Answering machines ##
  9401. ########################
  9402. class ReferenceAM(type):
  9403. def __new__(cls, name, bases, dct):
  9404. o = super(ReferenceAM, cls).__new__(cls, name, bases, dct)
  9405. if o.function_name:
  9406. globals()[o.function_name] = lambda o=o,*args,**kargs: o(*args,**kargs)()
  9407. return o
  9408. class AnsweringMachine(object):
  9409. __metaclass__ = ReferenceAM
  9410. function_name = ""
  9411. filter = None
  9412. sniff_options = { "store":0 }
  9413. sniff_options_list = [ "store", "iface", "count", "promisc", "filter", "type", "prn" ]
  9414. send_options = { "verbose":0 }
  9415. send_options_list = ["iface", "inter", "loop", "verbose"]
  9416. send_function = staticmethod(send)
  9417. def __init__(self, **kargs):
  9418. self.mode = 0
  9419. if self.filter:
  9420. kargs.setdefault("filter",self.filter)
  9421. kargs.setdefault("prn", self.reply)
  9422. self.optam1 = {}
  9423. self.optam2 = {}
  9424. self.optam0 = {}
  9425. doptsend,doptsniff = self.parse_all_options(1, kargs)
  9426. self.defoptsend = self.send_options.copy()
  9427. self.defoptsend.update(doptsend)
  9428. self.defoptsniff = self.sniff_options.copy()
  9429. self.defoptsniff.update(doptsniff)
  9430. self.optsend,self.optsniff = [{},{}]
  9431. def __getattr__(self, attr):
  9432. for d in [self.optam2, self.optam1]:
  9433. if attr in d:
  9434. return d[attr]
  9435. raise AttributeError,attr
  9436. def __setattr__(self, attr, val):
  9437. mode = self.__dict__.get("mode",0)
  9438. if mode == 0:
  9439. self.__dict__[attr] = val
  9440. else:
  9441. [self.optam1, self.optam2][mode-1][attr] = val
  9442. def parse_options(self):
  9443. pass
  9444. def parse_all_options(self, mode, kargs):
  9445. sniffopt = {}
  9446. sendopt = {}
  9447. for k in kargs.keys():
  9448. if k in self.sniff_options_list:
  9449. sniffopt[k] = kargs[k]
  9450. if k in self.send_options_list:
  9451. sendopt[k] = kargs[k]
  9452. if k in self.sniff_options_list+self.send_options_list:
  9453. del(kargs[k])
  9454. if mode != 2 or kargs:
  9455. if mode == 1:
  9456. self.optam0 = kargs
  9457. elif mode == 2 and kargs:
  9458. k = self.optam0.copy()
  9459. k.update(kargs)
  9460. self.parse_options(**k)
  9461. kargs = k
  9462. omode = self.__dict__.get("mode",0)
  9463. self.__dict__["mode"] = mode
  9464. self.parse_options(**kargs)
  9465. self.__dict__["mode"] = omode
  9466. return sendopt,sniffopt
  9467. def is_request(self, req):
  9468. return 1
  9469. def make_reply(self, req):
  9470. return req
  9471. def send_reply(self, reply):
  9472. self.send_function(reply, **self.optsend)
  9473. def print_reply(self, req, reply):
  9474. print "%s ==> %s" % (req.summary(),reply.summary())
  9475. def reply(self, pkt):
  9476. if not self.is_request(pkt):
  9477. return
  9478. reply = self.make_reply(pkt)
  9479. self.send_reply(reply)
  9480. if conf.verb >= 0:
  9481. self.print_reply(pkt, reply)
  9482. def run(self, *args, **kargs):
  9483. log_interactive.warning("run() method deprecated. The intance is now callable")
  9484. self(*args,**kargs)
  9485. def __call__(self, *args, **kargs):
  9486. optsend,optsniff = self.parse_all_options(2,kargs)
  9487. self.optsend=self.defoptsend.copy()
  9488. self.optsend.update(optsend)
  9489. self.optsniff=self.defoptsniff.copy()
  9490. self.optsniff.update(optsniff)
  9491. try:
  9492. self.sniff()
  9493. except KeyboardInterrupt:
  9494. print "Interrupted by user"
  9495. def sniff(self):
  9496. sniff(**self.optsniff)
  9497. class BOOTP_am(AnsweringMachine):
  9498. function_name = "bootpd"
  9499. filter = "udp and port 68 and port 67"
  9500. send_function = staticmethod(sendp)
  9501. def parse_options(self, ipset=Net("192.168.1.128/25"),gw="192.168.1.1"):
  9502. if type(ipset) is str:
  9503. ipset = Net(ipset)
  9504. if isinstance(ipset,Gen):
  9505. ipset = [k for k in ipset]
  9506. ipset.reverse()
  9507. if len(ipset) == 1:
  9508. ipset, = ipset
  9509. self.ipset = ipset
  9510. self.gw = gw
  9511. self.leases = {}
  9512. def is_request(self, req):
  9513. if not req.haslayer(BOOTP):
  9514. return 0
  9515. reqb = req.getlayer(BOOTP)
  9516. if reqb.op != 1:
  9517. return 0
  9518. return 1
  9519. def print_reply(self, req, reply):
  9520. print "Reply %s to %s" % (reply.getlayer(IP).dst,reply.dst)
  9521. def make_reply(self, req):
  9522. mac = req.src
  9523. if type(self.ipset) is list:
  9524. if not self.leases.has_key(mac):
  9525. self.leases[mac] = self.ipset.pop()
  9526. ip = self.leases[mac]
  9527. else:
  9528. ip = self.ipset
  9529. repb = req.getlayer(BOOTP).copy()
  9530. repb.options = ""
  9531. repb.op="BOOTREPLY"
  9532. repb.yiaddr = ip
  9533. repb.siaddr = self.gw
  9534. repb.ciaddr = self.gw
  9535. repb.giaddr = self.gw
  9536. rep=Ether(dst=mac)/IP(dst=ip)/UDP(sport=req.dport,dport=req.sport)/repb
  9537. return rep
  9538. class DHCP_am(BOOTP_am):
  9539. function_name="dhcpd"
  9540. def is_request(self, req):
  9541. if not BOOTP_am.is_request(self, req):
  9542. return 0
  9543. if req.getlayer(BOOTP).options[:4] != "'c\x82Sc":
  9544. return 0
  9545. return 1
  9546. def make_reply(self, req):
  9547. dhcprespmap={"\x01":"\x02","\x03":"\x05"}
  9548. resp = BOOTP_am.make_reply(self, req)
  9549. opt = req.getlayer(BOOTP).options
  9550. o = opt[:6]
  9551. if len(opt) > 6:
  9552. o += dhcprespmap.get(opt[6],opt[6])
  9553. if len(opt) > 7:
  9554. o += opt[7:]
  9555. resp.getlayer(BOOTP).options = o
  9556. class DNS_am(AnsweringMachine):
  9557. function_name="dns_spoof"
  9558. filter = "udp port 53"
  9559. def parse_options(self, joker="192.168.1.1", match=None):
  9560. if match is None:
  9561. self.match = {}
  9562. else:
  9563. self.match = match
  9564. self.joker=joker
  9565. def is_request(self, req):
  9566. return req.haslayer(DNS) and req.getlayer(DNS).qr == 0
  9567. def make_reply(self, req):
  9568. ip = req.getlayer(IP)
  9569. dns = req.getlayer(DNS)
  9570. resp = IP(dst=ip.src, src=ip.dst)/UDP(dport=ip.sport,sport=ip.dport)
  9571. rdata = self.match.get(dns.qd.qname, self.joker)
  9572. resp /= DNS(id=dns.id, qr=1, qd=dns.qd,
  9573. an=DNSRR(rrname=dns.qd.qname, ttl=10, rdata=rdata))
  9574. return resp
  9575. class WiFi_am(AnsweringMachine):
  9576. """Before using this, initialize "iffrom" and "ifto" interfaces:
  9577. iwconfig iffrom mode monitor
  9578. iwpriv orig_ifto hostapd 1
  9579. ifconfig ifto up
  9580. note: if ifto=wlan0ap then orig_ifto=wlan0
  9581. note: ifto and iffrom must be set on the same channel
  9582. ex:
  9583. ifconfig eth1 up
  9584. iwconfig eth1 mode monitor
  9585. iwconfig eth1 channel 11
  9586. iwpriv wlan0 hostapd 1
  9587. ifconfig wlan0ap up
  9588. iwconfig wlan0 channel 11
  9589. iwconfig wlan0 essid dontexist
  9590. iwconfig wlan0 mode managed
  9591. """
  9592. function_name = "airpwn"
  9593. filter = None
  9594. def parse_options(iffrom, ifto, replace, pattern="", ignorepattern=""):
  9595. self.iffrom = iffrom
  9596. self.ifto = ifto
  9597. ptrn = re.compile(pattern)
  9598. iptrn = re.compile(ignorepattern)
  9599. def is_request(self, pkt):
  9600. if not isinstance(pkt,Dot11):
  9601. return 0
  9602. if not pkt.FCfield & 1:
  9603. return 0
  9604. if not pkt.haslayer(TCP):
  9605. return 0
  9606. ip = pkt.getlayer(IP)
  9607. tcp = pkt.getlayer(TCP)
  9608. pay = str(tcp.payload)
  9609. if not self.ptrn.match(pay):
  9610. return 0
  9611. if self.iptrn.match(pay):
  9612. return 0
  9613. def make_reply(self, p):
  9614. ip = p.getlayer(IP)
  9615. tcp = p.getlayer(TCP)
  9616. pay = str(tcp.payload)
  9617. del(p.payload.payload.payload)
  9618. p.FCfield="from-DS"
  9619. p.addr1,p.addr2 = p.addr2,p.addr1
  9620. p /= IP(src=ip.dst,dst=ip.src)
  9621. p /= TCP(sport=tcp.dport, dport=tcp.sport,
  9622. seq=tcp.ack, ack=tcp.seq+len(pay),
  9623. flags="PA")
  9624. q = p.copy()
  9625. p /= self.replace
  9626. q.ID += 1
  9627. q.getlayer(TCP).flags="RA"
  9628. q.getlayer(TCP).seq+=len(replace)
  9629. return [p,q]
  9630. def print_reply(self):
  9631. print p.sprintf("Sent %IP.src%:%IP.sport% > %IP.dst%:%TCP.dport%")
  9632. def send_reply(self, reply):
  9633. sendp(reply, iface=self.ifto, **self.optsend)
  9634. def sniff(self):
  9635. sniff(iface=self.iffrom, **self.optsniff)
  9636. class ARP_am(AnsweringMachine):
  9637. function_name="farpd"
  9638. filter = "arp"
  9639. send_function = staticmethod(sendp)
  9640. def parse_options(self, IP_addr=None, iface=None, ARP_addr=None):
  9641. self.IP_addr=IP_addr
  9642. self.iface=iface
  9643. self.ARP_addr=ARP_addr
  9644. def is_request(self, req):
  9645. return (req.haslayer(ARP) and
  9646. req.getlayer(ARP).op == 1 and
  9647. (self.IP_addr == None or self.IP_addr == req.getlayer(ARP).pdst))
  9648. def make_reply(self, req):
  9649. ether = req.getlayer(Ether)
  9650. arp = req.getlayer(ARP)
  9651. iff,a,gw = conf.route.route(arp.psrc)
  9652. if self.iface != None:
  9653. iff = iface
  9654. ARP_addr = self.ARP_addr
  9655. IP_addr = arp.pdst
  9656. resp = Ether(dst=ether.src,
  9657. src=ARP_addr)/ARP(op="is-at",
  9658. hwsrc=ARP_addr,
  9659. psrc=IP_addr,
  9660. hwdst=arp.hwsrc,
  9661. pdst=arp.pdst)
  9662. return resp
  9663. def sniff(self):
  9664. sniff(iface=self.iface, **self.optsniff)
  9665. #############
  9666. ## Fuzzing ##
  9667. #############
  9668. def fuzz(p, _inplace=0):
  9669. if not _inplace:
  9670. p = p.copy()
  9671. q = p
  9672. while not isinstance(q, NoPayload):
  9673. for f in q.fields_desc:
  9674. if isinstance(f, PacketListField):
  9675. for r in getattr(q, f.name):
  9676. print "fuzzing", repr(r)
  9677. fuzz(r, _inplace=1)
  9678. elif f.default is not None:
  9679. rnd = f.randval()
  9680. if rnd is not None:
  9681. q.default_fields[f] = rnd
  9682. q = q.payload
  9683. return p
  9684. ###################
  9685. ## Testing stuff ##
  9686. ###################
  9687. def merge(x,y):
  9688. if len(x) > len(y):
  9689. y += "\x00"*(len(x)-len(y))
  9690. elif len(x) < len(y):
  9691. x += "\x00"*(len(y)-len(x))
  9692. m = ""
  9693. for i in range(len(x)/ss):
  9694. m += x[ss*i:ss*(i+1)]+y[ss*i:ss*(i+1)]
  9695. return m
  9696. # return "".join(map(str.__add__, x, y))
  9697. def voip_play(s1,list=None,**kargs):
  9698. FIFO="/tmp/conv1.%i.%%i" % os.getpid()
  9699. FIFO1=FIFO % 1
  9700. FIFO2=FIFO % 2
  9701. os.mkfifo(FIFO1)
  9702. os.mkfifo(FIFO2)
  9703. try:
  9704. os.system("soxmix -t .ul %s -t .ul %s -t ossdsp /dev/dsp &" % (FIFO1,FIFO2))
  9705. c1=open(FIFO1,"w", 4096)
  9706. c2=open(FIFO2,"w", 4096)
  9707. fcntl.fcntl(c1.fileno(),fcntl.F_SETFL, os.O_NONBLOCK)
  9708. fcntl.fcntl(c2.fileno(),fcntl.F_SETFL, os.O_NONBLOCK)
  9709. # dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp")
  9710. def play(pkt,last=[]):
  9711. if not pkt:
  9712. return
  9713. if not pkt.haslayer(UDP):
  9714. return
  9715. ip=pkt.getlayer(IP)
  9716. if s1 in [ip.src, ip.dst]:
  9717. if not last:
  9718. last.append(pkt)
  9719. return
  9720. load=last.pop()
  9721. # x1 = load.load[12:]
  9722. c1.write(load.load[12:])
  9723. if load.getlayer(IP).src == ip.src:
  9724. # x2 = ""
  9725. c2.write("\x00"*len(load.load[12:]))
  9726. last.append(pkt)
  9727. else:
  9728. # x2 = pkt.load[:12]
  9729. c2.write(pkt.load[12:])
  9730. # dsp.write(merge(x1,x2))
  9731. if list is None:
  9732. sniff(store=0, prn=play, **kargs)
  9733. else:
  9734. for p in list:
  9735. play(p)
  9736. finally:
  9737. os.unlink(FIFO1)
  9738. os.unlink(FIFO2)
  9739. def voip_play1(s1,list=None,**kargs):
  9740. dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp")
  9741. def play(pkt):
  9742. if not pkt:
  9743. return
  9744. if not pkt.haslayer(UDP):
  9745. return
  9746. ip=pkt.getlayer(IP)
  9747. if s1 in [ip.src, ip.dst]:
  9748. dsp.write(pkt.getlayer(Raw).load[12:])
  9749. try:
  9750. if list is None:
  9751. sniff(store=0, prn=play, **kargs)
  9752. else:
  9753. for p in list:
  9754. play(p)
  9755. finally:
  9756. dsp.close()
  9757. rd.close()
  9758. def voip_play2(s1,**kargs):
  9759. dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp")
  9760. def play(pkt,last=[]):
  9761. if not pkt:
  9762. return
  9763. if not pkt.haslayer(UDP):
  9764. return
  9765. ip=pkt.getlayer(IP)
  9766. if s1 in [ip.src, ip.dst]:
  9767. if not last:
  9768. last.append(pkt)
  9769. return
  9770. load=last.pop()
  9771. x1 = load.load[12:]
  9772. # c1.write(load.load[12:])
  9773. if load.getlayer(IP).src == ip.src:
  9774. x2 = ""
  9775. # c2.write("\x00"*len(load.load[12:]))
  9776. last.append(pkt)
  9777. else:
  9778. x2 = pkt.load[:12]
  9779. # c2.write(pkt.load[12:])
  9780. dsp.write(merge(x1,x2))
  9781. sniff(store=0, prn=play, **kargs)
  9782. def voip_play3(lst=None,**kargs):
  9783. dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp")
  9784. try:
  9785. def play(pkt, dsp=dsp):
  9786. if pkt and pkt.haslayer(UDP) and pkt.haslayer(Raw):
  9787. dsp.write(pkt.getlayer(Raw).load[12:])
  9788. if lst is None:
  9789. sniff(store=0, prn=play, **kargs)
  9790. else:
  9791. for p in lst:
  9792. play(p)
  9793. finally:
  9794. try:
  9795. dsp.close()
  9796. rd.close()
  9797. except:
  9798. pass
  9799. def IPID_count(lst, funcID=lambda x:x[1].id, funcpres=lambda x:x[1].summary()):
  9800. idlst = map(funcID, lst)
  9801. idlst.sort()
  9802. classes = [idlst[0]]+map(lambda x:x[1],filter(lambda (x,y): abs(x-y)>50, map(lambda x,y: (x,y),idlst[:-1], idlst[1:])))
  9803. lst = map(lambda x:(funcID(x), funcpres(x)), lst)
  9804. lst.sort()
  9805. print "Probably %i classes:" % len(classes), classes
  9806. for id,pr in lst:
  9807. print "%5i" % id, pr
  9808. last=None
  9809. def tethereal(*args,**kargs):
  9810. sniff(prn=lambda x: x.display(),*args,**kargs)
  9811. def fragleak(target,sport=123, dport=123, timeout=0.2, onlyasc=0):
  9812. load = "XXXXYYYYYYYYYY"
  9813. # getmacbyip(target)
  9814. # pkt = IP(dst=target, id=RandShort(), options="\x22"*40)/UDP()/load
  9815. pkt = IP(dst=target, id=RandShort(), options="\x00"*40, flags=1)/UDP(sport=sport, dport=sport)/load
  9816. s=conf.L3socket()
  9817. intr=0
  9818. found={}
  9819. try:
  9820. while 1:
  9821. try:
  9822. if not intr:
  9823. s.send(pkt)
  9824. sin,sout,serr = select([s],[],[],timeout)
  9825. if not sin:
  9826. continue
  9827. ans=s.recv(1600)
  9828. if not isinstance(ans, IP): #TODO: IPv6
  9829. continue
  9830. if not isinstance(ans.payload, ICMP):
  9831. continue
  9832. if not isinstance(ans.payload.payload, IPerror):
  9833. continue
  9834. if ans.payload.payload.dst != target:
  9835. continue
  9836. if ans.src != target:
  9837. print "leak from", ans.src,
  9838. # print repr(ans)
  9839. if not ans.haslayer(Padding):
  9840. continue
  9841. # print repr(ans.payload.payload.payload.payload)
  9842. # if not isinstance(ans.payload.payload.payload.payload, Raw):
  9843. # continue
  9844. # leak = ans.payload.payload.payload.payload.load[len(load):]
  9845. leak = ans.getlayer(Padding).load
  9846. if leak not in found:
  9847. found[leak]=None
  9848. linehexdump(leak, onlyasc=onlyasc)
  9849. except KeyboardInterrupt:
  9850. if intr:
  9851. raise KeyboardInterrupt
  9852. intr=1
  9853. except KeyboardInterrupt:
  9854. pass
  9855. def fragleak2(target, timeout=0.4, onlyasc=0):
  9856. found={}
  9857. try:
  9858. while 1:
  9859. p = sr1(IP(dst=target, options="\x00"*40, proto=200)/"XXXXYYYYYYYYYYYY",timeout=timeout,verbose=0)
  9860. if not p:
  9861. continue
  9862. if Padding in p:
  9863. leak = p[Padding].load
  9864. if leak not in found:
  9865. found[leak]=None
  9866. linehexdump(leak,onlyasc=onlyasc)
  9867. except:
  9868. pass
  9869. plst=[]
  9870. def get_toDS():
  9871. global plst
  9872. while 1:
  9873. p,=sniff(iface="eth1",count=1)
  9874. if not isinstance(p,Dot11):
  9875. continue
  9876. if p.FCfield & 1:
  9877. plst.append(p)
  9878. print "."
  9879. # if not ifto.endswith("ap"):
  9880. # print "iwpriv %s hostapd 1" % ifto
  9881. # os.system("iwpriv %s hostapd 1" % ifto)
  9882. # ifto += "ap"
  9883. #
  9884. # os.system("iwconfig %s mode monitor" % iffrom)
  9885. #
  9886. def airpwn(iffrom, ifto, replace, pattern="", ignorepattern=""):
  9887. """Before using this, initialize "iffrom" and "ifto" interfaces:
  9888. iwconfig iffrom mode monitor
  9889. iwpriv orig_ifto hostapd 1
  9890. ifconfig ifto up
  9891. note: if ifto=wlan0ap then orig_ifto=wlan0
  9892. note: ifto and iffrom must be set on the same channel
  9893. ex:
  9894. ifconfig eth1 up
  9895. iwconfig eth1 mode monitor
  9896. iwconfig eth1 channel 11
  9897. iwpriv wlan0 hostapd 1
  9898. ifconfig wlan0ap up
  9899. iwconfig wlan0 channel 11
  9900. iwconfig wlan0 essid dontexist
  9901. iwconfig wlan0 mode managed
  9902. """
  9903. ptrn = re.compile(pattern)
  9904. iptrn = re.compile(ignorepattern)
  9905. def do_airpwn(p, ifto=ifto, replace=replace, ptrn=ptrn, iptrn=iptrn):
  9906. if not isinstance(p,Dot11):
  9907. return
  9908. if not p.FCfield & 1:
  9909. return
  9910. if not p.haslayer(TCP):
  9911. return
  9912. ip = p.getlayer(IP)
  9913. tcp = p.getlayer(TCP)
  9914. pay = str(tcp.payload)
  9915. # print "got tcp"
  9916. if not ptrn.match(pay):
  9917. return
  9918. # print "match 1"
  9919. if iptrn.match(pay):
  9920. return
  9921. # print "match 2"
  9922. del(p.payload.payload.payload)
  9923. p.FCfield="from-DS"
  9924. p.addr1,p.addr2 = p.addr2,p.addr1
  9925. q = p.copy()
  9926. p /= IP(src=ip.dst,dst=ip.src)
  9927. p /= TCP(sport=tcp.dport, dport=tcp.sport,
  9928. seq=tcp.ack, ack=tcp.seq+len(pay),
  9929. flags="PA")
  9930. q = p.copy()
  9931. p /= replace
  9932. q.ID += 1
  9933. q.getlayer(TCP).flags="RA"
  9934. q.getlayer(TCP).seq+=len(replace)
  9935. sendp([p,q], iface=ifto, verbose=0)
  9936. # print "send",repr(p)
  9937. # print "send",repr(q)
  9938. print p.sprintf("Sent %IP.src%:%IP.sport% > %IP.dst%:%TCP.dport%")
  9939. sniff(iface=iffrom,prn=do_airpwn)
  9940. ##################
  9941. ## Color themes ##
  9942. ##################
  9943. class Color:
  9944. normal = "\033[0m"
  9945. black = "\033[30m"
  9946. red = "\033[31m"
  9947. green = "\033[32m"
  9948. yellow = "\033[33m"
  9949. blue = "\033[34m"
  9950. purple = "\033[35m"
  9951. cyan = "\033[36m"
  9952. grey = "\033[37m"
  9953. bold = "\033[1m"
  9954. uline = "\033[4m"
  9955. blink = "\033[5m"
  9956. invert = "\033[7m"
  9957. class ColorTheme:
  9958. def __repr__(self):
  9959. return "<%s>" % self.__class__.__name__
  9960. def __getattr__(self, attr):
  9961. return lambda x:x
  9962. class NoTheme(ColorTheme):
  9963. pass
  9964. class AnsiColorTheme(ColorTheme):
  9965. def __getattr__(self, attr):
  9966. s = "style_%s" % attr
  9967. if s in self.__class__.__dict__:
  9968. before = getattr(self, s)
  9969. after = self.style_normal
  9970. else:
  9971. before = after = ""
  9972. def do_style(val, fmt=None, before=before, after=after):
  9973. if fmt is None:
  9974. if type(val) is not str:
  9975. val = str(val)
  9976. else:
  9977. val = fmt % val
  9978. return before+val+after
  9979. return do_style
  9980. style_normal = ""
  9981. style_prompt = ""
  9982. style_punct = ""
  9983. style_id = ""
  9984. style_not_printable = ""
  9985. style_layer_name = ""
  9986. style_field_name = ""
  9987. style_field_value = ""
  9988. style_emph_field_name = ""
  9989. style_emph_field_value = ""
  9990. style_packetlist_name = ""
  9991. style_packetlist_proto = ""
  9992. style_packetlist_value = ""
  9993. style_fail = ""
  9994. style_success = ""
  9995. style_odd = ""
  9996. style_even = ""
  9997. style_opening = ""
  9998. style_active = ""
  9999. style_closed = ""
  10000. class BlackAndWhite(AnsiColorTheme):
  10001. pass
  10002. class DefaultTheme(AnsiColorTheme):
  10003. style_normal = Color.normal
  10004. style_prompt = Color.blue+Color.bold
  10005. style_punct = Color.normal
  10006. style_id = Color.blue+Color.bold
  10007. style_not_printable = Color.grey
  10008. style_layer_name = Color.red+Color.bold
  10009. style_field_name = Color.blue
  10010. style_field_value = Color.purple
  10011. style_emph_field_name = Color.blue+Color.uline+Color.bold
  10012. style_emph_field_value = Color.purple+Color.uline+Color.bold
  10013. style_packetlist_name = Color.red+Color.bold
  10014. style_packetlist_proto = Color.blue
  10015. style_packetlist_value = Color.purple
  10016. style_fail = Color.red+Color.bold
  10017. style_success = Color.blue+Color.bold
  10018. style_even = Color.black+Color.bold
  10019. style_odd = Color.black
  10020. style_opening = Color.yellow
  10021. style_active = Color.black
  10022. style_closed = Color.grey
  10023. class BrightTheme(AnsiColorTheme):
  10024. style_normal = Color.normal
  10025. style_punct = Color.normal
  10026. style_id = Color.yellow+Color.bold
  10027. style_layer_name = Color.red+Color.bold
  10028. style_field_name = Color.yellow+Color.bold
  10029. style_field_value = Color.purple+Color.bold
  10030. style_emph_field_name = Color.yellow+Color.bold
  10031. style_emph_field_value = Color.green+Color.bold
  10032. style_packetlist_name = Color.red+Color.bold
  10033. style_packetlist_proto = Color.yellow+Color.bold
  10034. style_packetlist_value = Color.purple+Color.bold
  10035. style_fail = Color.red+Color.bold
  10036. style_success = Color.blue+Color.bold
  10037. style_even = Color.black+Color.bold
  10038. style_odd = Color.black
  10039. class RastaTheme(AnsiColorTheme):
  10040. style_normal = Color.green+Color.bold
  10041. style_prompt = Color.yellow+Color.bold
  10042. style_punct = Color.red
  10043. style_id = Color.green+Color.bold
  10044. style_not_printable = Color.green
  10045. style_layer_name = Color.red+Color.bold
  10046. style_field_name = Color.yellow+Color.bold
  10047. style_field_value = Color.green+Color.bold
  10048. style_emph_field_name = Color.green
  10049. style_emph_field_value = Color.green
  10050. style_packetlist_name = Color.red+Color.bold
  10051. style_packetlist_proto = Color.yellow+Color.bold
  10052. style_packetlist_value = Color.green+Color.bold
  10053. style_fail = Color.red
  10054. style_success = Color.red+Color.bold
  10055. style_even = Color.yellow
  10056. style_odd = Color.green
  10057. class FormatTheme(ColorTheme):
  10058. def __getattr__(self, attr):
  10059. col = self.__class__.__dict__.get("style_%s" % attr, "%s")
  10060. def do_style(val, fmt=None, col=col):
  10061. if fmt is None:
  10062. if type(val) is not str:
  10063. val = str(val)
  10064. else:
  10065. val = fmt % val
  10066. return col % val
  10067. return do_style
  10068. class LatexTheme(FormatTheme):
  10069. style_prompt = r"\textcolor{blue}{%s}"
  10070. style_not_printable = r"\textcolor{gray}{%s}"
  10071. style_layer_name = r"\textcolor{red}{\bf %s}"
  10072. style_field_name = r"\textcolor{blue}{%s}"
  10073. style_field_value = r"\textcolor{purple}{%s}"
  10074. style_emph_field_name = r"\textcolor{blue}{\underline{%s}}" #ul
  10075. style_emph_field_value = r"\textcolor{purple}{\underline{%s}}" #ul
  10076. style_packetlist_name = r"\textcolor{red}{\bf %s}"
  10077. style_packetlist_proto = r"\textcolor{blue}{%s}"
  10078. style_packetlist_value = r"\textcolor{purple}{%s}"
  10079. style_fail = r"\textcolor{red}{\bf %s}"
  10080. style_success = r"\textcolor{blue}{\bf %s}"
  10081. # style_even = r"}{\bf "
  10082. # style_odd = ""
  10083. class LatexTheme2(FormatTheme):
  10084. style_prompt = r"@`@textcolor@[@blue@]@@[@%s@]@"
  10085. style_not_printable = r"@`@textcolor@[@gray@]@@[@%s@]@"
  10086. style_layer_name = r"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@"
  10087. style_field_name = r"@`@textcolor@[@blue@]@@[@%s@]@"
  10088. style_field_value = r"@`@textcolor@[@purple@]@@[@%s@]@"
  10089. style_emph_field_name = r"@`@textcolor@[@blue@]@@[@@`@underline@[@%s@]@@]@"
  10090. style_emph_field_value = r"@`@textcolor@[@purple@]@@[@@`@underline@[@%s@]@@]@"
  10091. style_packetlist_name = r"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@"
  10092. style_packetlist_proto = r"@`@textcolor@[@blue@]@@[@%s@]@"
  10093. style_packetlist_value = r"@`@textcolor@[@purple@]@@[@%s@]@"
  10094. style_fail = r"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@"
  10095. style_success = r"@`@textcolor@[@blue@]@@[@@`@bfserices@[@@]@%s@]@"
  10096. style_even = r"@`@textcolor@[@gray@]@@[@@`@bfseries@[@@]@%s@]@"
  10097. # style_odd = r"@`@textcolor@[@black@]@@[@@`@bfseries@[@@]@%s@]@"
  10098. class HTMLTheme(FormatTheme):
  10099. style_prompt = "<span class=prompt>%s</span>"
  10100. style_not_printable = "<span class=not_printable>%s</span>"
  10101. style_layer_name = "<span class=layer_name>%s</span>"
  10102. style_field_name = "<span class=field_name>%s</span>"
  10103. style_field_value = "<span class=field_value>%s</span>"
  10104. style_emph_field_name = "<span class=emph_field_name>%s</span>"
  10105. style_emph_field_value = "<span class=emph_field_value>%s</span>"
  10106. style_packetlist_name = "<span class=packetlist_name>%s</span>"
  10107. style_packetlist_proto = "<span class=packetlist_proto>%s</span>"
  10108. style_packetlist_value = "<span class=packetlist_value>%s</span>"
  10109. style_fail = "<span class=fail>%s</span>"
  10110. style_success = "<span class=success>%s</span>"
  10111. style_even = "<span class=even>%s</span>"
  10112. style_odd = "<span class=odd>%s</span>"
  10113. class HTMLTheme2(HTMLTheme):
  10114. style_prompt = "#[#span class=prompt#]#%s#[#/span#]#"
  10115. style_not_printable = "#[#span class=not_printable#]#%s#[#/span#]#"
  10116. style_layer_name = "#[#span class=layer_name#]#%s#[#/span#]#"
  10117. style_field_name = "#[#span class=field_name#]#%s#[#/span#]#"
  10118. style_field_value = "#[#span class=field_value#]#%s#[#/span#]#"
  10119. style_emph_field_name = "#[#span class=emph_field_name#]#%s#[#/span#]#"
  10120. style_emph_field_value = "#[#span class=emph_field_value#]#%s#[#/span#]#"
  10121. style_packetlist_name = "#[#span class=packetlist_name#]#%s#[#/span#]#"
  10122. style_packetlist_proto = "#[#span class=packetlist_proto#]#%s#[#/span#]#"
  10123. style_packetlist_value = "#[#span class=packetlist_value#]#%s#[#/span#]#"
  10124. style_fail = "#[#span class=fail#]#%s#[#/span#]#"
  10125. style_success = "#[#span class=success#]#%s#[#/span#]#"
  10126. style_even = "#[#span class=even#]#%s#[#/span#]#"
  10127. style_odd = "#[#span class=odd#]#%s#[#/span#]#"
  10128. class ColorPrompt:
  10129. __prompt = ">>> "
  10130. def __str__(self):
  10131. try:
  10132. ct = conf.color_theme
  10133. if isinstance(ct, AnsiColorTheme):
  10134. ## ^A and ^B delimit invisible caracters for readline to count right
  10135. return "\001%s\002" % ct.prompt("\002"+conf.prompt+"\001")
  10136. else:
  10137. return ct.prompt(conf.prompt)
  10138. except:
  10139. return self.__prompt
  10140. ############
  10141. ## Config ##
  10142. ############
  10143. class ConfClass:
  10144. def configure(self, cnf):
  10145. self.__dict__ = cnf.__dict__.copy()
  10146. def __repr__(self):
  10147. return str(self)
  10148. def __str__(self):
  10149. s="Version = %s\n" % VERSION
  10150. keys = self.__class__.__dict__.copy()
  10151. keys.update(self.__dict__)
  10152. keys = keys.keys()
  10153. keys.sort()
  10154. for i in keys:
  10155. if i[0] != "_":
  10156. s += "%-10s = %s\n" % (i, repr(getattr(self, i)))
  10157. return s[:-1]
  10158. def reset(self):
  10159. self.__dict__ = {}
  10160. class ProgPath(ConfClass):
  10161. pdfreader = "acroread"
  10162. psreader = "gv"
  10163. dot = "dot"
  10164. display = "display"
  10165. tcpdump = "tcpdump"
  10166. class Conf(ConfClass):
  10167. """This object contains the configuration of scapy.
  10168. session : filename where the session will be saved
  10169. stealth : if 1, prevents any unwanted packet to go out (ARP, DNS, ...)
  10170. checkIPID: if 0, doesn't check that IPID matches between IP sent and ICMP IP citation received
  10171. if 1, checks that they either are equal or byte swapped equals (bug in some IP stacks)
  10172. if 2, strictly checks that they are equals
  10173. checkIPsrc: if 1, checks IP src in IP and ICMP IP citation match (bug in some NAT stacks)
  10174. check_TCPerror_seqack: if 1, also check that TCP seq and ack match the ones in ICMP citation
  10175. iff : selects the default output interface for srp() and sendp(). default:"eth0")
  10176. verb : level of verbosity, from 0 (almost mute) to 3 (verbose)
  10177. promisc : default mode for listening socket (to get answers if you spoof on a lan)
  10178. sniff_promisc : default mode for sniff()
  10179. filter : bpf filter added to every sniffing socket to exclude traffic from analysis
  10180. histfile : history file
  10181. padding : includes padding in desassembled packets
  10182. except_filter : BPF filter for packets to ignore
  10183. debug_match : when 1, store received packet that are not matched into debug.recv
  10184. route : holds the Scapy routing table and provides methods to manipulate it
  10185. warning_threshold : how much time between warnings from the same place
  10186. """
  10187. session = ""
  10188. stealth = "not implemented"
  10189. iface = get_working_if()
  10190. checkIPID = 1
  10191. checkIPsrc = 1
  10192. checkIPaddr = 1
  10193. check_TCPerror_seqack = 0
  10194. verb = 2
  10195. prompt = ">>> "
  10196. promisc = 1
  10197. sniff_promisc = 1
  10198. L3socket = L3PacketSocket
  10199. L2socket = L2Socket
  10200. L2listen = L2ListenSocket
  10201. BTsocket = BluetoothL2CAPSocket
  10202. histfile = os.path.join(os.environ["HOME"], ".scapy_history")
  10203. padding = 1
  10204. p0f_base ="/etc/p0f/p0f.fp"
  10205. queso_base ="/etc/queso.conf"
  10206. nmap_base ="/usr/share/nmap/nmap-os-fingerprints"
  10207. IPCountry_base = "GeoIPCountry4Scapy.gz"
  10208. countryLoc_base = "countryLoc.csv"
  10209. gnuplot_world = "world.dat"
  10210. except_filter = ""
  10211. debug_match = 0
  10212. route = Route()
  10213. wepkey = ""
  10214. debug_dissector = 0
  10215. color_theme = DefaultTheme()
  10216. warning_threshold = 5
  10217. prog = ProgPath()
  10218. conf=Conf()
  10219. if PCAP:
  10220. conf.L2listen=L2pcapListenSocket
  10221. if DNET:
  10222. conf.L3socket=L3dnetSocket
  10223. conf.L2socket=L2dnetSocket
  10224. p0f_kdb = p0fKnowledgeBase(conf.p0f_base)
  10225. queso_kdb = QuesoKnowledgeBase(conf.queso_base)
  10226. nmap_kdb = NmapKnowledgeBase(conf.nmap_base)
  10227. IP_country_kdb = IPCountryKnowledgeBase(conf.IPCountry_base)
  10228. country_loc_kdb = CountryLocKnowledgeBase(conf.countryLoc_base)
  10229. #########################
  10230. ##### Autorun stuff #####
  10231. #########################
  10232. class ScapyAutorunInterpreter(code.InteractiveInterpreter):
  10233. def __init__(self, *args, **kargs):
  10234. code.InteractiveInterpreter.__init__(self, *args, **kargs)
  10235. self.error = 0
  10236. def showsyntaxerror(self, *args, **kargs):
  10237. self.error = 1
  10238. return code.InteractiveInterpreter.showsyntaxerror(self, *args, **kargs)
  10239. def showtraceback(self, *args, **kargs):
  10240. self.error = 1
  10241. return code.InteractiveInterpreter.showtraceback(self, *args, **kargs)
  10242. def autorun_commands(cmds,verb=0):
  10243. sv = conf.verb
  10244. import __builtin__
  10245. try:
  10246. conf.verb = verb
  10247. interp = ScapyAutorunInterpreter(globals())
  10248. cmd = ""
  10249. cmds = cmds.splitlines()
  10250. cmds.append("") # ensure we finish multiline commands
  10251. cmds.reverse()
  10252. __builtin__.__dict__["_"] = None
  10253. while 1:
  10254. if cmd:
  10255. sys.stderr.write(sys.__dict__.get("ps2","... "))
  10256. else:
  10257. sys.stderr.write(str(sys.__dict__.get("ps1",ColorPrompt())))
  10258. l = cmds.pop()
  10259. print l
  10260. cmd += "\n"+l
  10261. if interp.runsource(cmd):
  10262. continue
  10263. if interp.error:
  10264. return 0
  10265. cmd = ""
  10266. if len(cmds) <= 1:
  10267. break
  10268. finally:
  10269. conf.verb = sv
  10270. return _
  10271. def autorun_get_interactive_session(cmds):
  10272. class StringWriter:
  10273. def __init__(self):
  10274. self.s = ""
  10275. def write(self, x):
  10276. self.s += x
  10277. sw = StringWriter()
  10278. sstdout,sstderr = sys.stdout,sys.stderr
  10279. try:
  10280. sys.stdout = sys.stderr = sw
  10281. res = autorun_commands(cmds)
  10282. finally:
  10283. sys.stdout,sys.stderr = sstdout,sstderr
  10284. return sw.s,res
  10285. def autorun_get_text_interactive_session(cmds):
  10286. ct = conf.color_theme
  10287. try:
  10288. conf.color_theme = NoTheme()
  10289. s,res = autorun_get_interactive_session(cmds)
  10290. finally:
  10291. conf.color_theme = ct
  10292. return s,res
  10293. def autorun_get_ansi_interactive_session(cmds):
  10294. ct = conf.color_theme
  10295. try:
  10296. conf.color_theme = DefaultTheme()
  10297. s,res = autorun_get_interactive_session(cmds)
  10298. finally:
  10299. conf.color_theme = ct
  10300. return s,res
  10301. def autorun_get_html_interactive_session(cmds):
  10302. ct = conf.color_theme
  10303. try:
  10304. conf.color_theme = HTMLTheme2()
  10305. s,res = autorun_get_interactive_session(cmds)
  10306. finally:
  10307. conf.color_theme = ct
  10308. s = s.replace("<","&lt;").replace(">","&gt;").replace("#[#","<").replace("#]#",">")
  10309. return s,res
  10310. def autorun_get_latex_interactive_session(cmds):
  10311. ct = conf.color_theme
  10312. try:
  10313. conf.color_theme = LatexTheme2()
  10314. s,res = autorun_get_interactive_session(cmds)
  10315. finally:
  10316. conf.color_theme = ct
  10317. s = tex_escape(s)
  10318. s = s.replace("@[@","{").replace("@]@","}").replace("@`@","\\")
  10319. return s,res
  10320. ################
  10321. ##### Main #####
  10322. ################
  10323. def scapy_write_history_file(readline):
  10324. if conf.histfile:
  10325. readline.write_history_file(conf.histfile)
  10326. def interact(mydict=None,argv=None,mybanner=None,loglevel=1):
  10327. import code,sys,cPickle,types,os,imp,getopt,logging
  10328. logging.getLogger("scapy").setLevel(loglevel)
  10329. the_banner = "Welcome to Scapy (%s)"
  10330. if mybanner is not None:
  10331. the_banner += "\n"
  10332. the_banner += mybanner
  10333. if argv is None:
  10334. argv = sys.argv
  10335. # scapy_module = argv[0][argv[0].rfind("/")+1:]
  10336. # if not scapy_module:
  10337. # scapy_module = "scapy"
  10338. # else:
  10339. # if scapy_module.endswith(".py"):
  10340. # scapy_module = scapy_module[:-3]
  10341. #
  10342. # scapy=imp.load_module("scapy",*imp.find_module(scapy_module))
  10343. import __builtin__
  10344. # __builtin__.__dict__.update(scapy.__dict__)
  10345. __builtin__.__dict__.update(globals())
  10346. if mydict is not None:
  10347. __builtin__.__dict__.update(mydict)
  10348. import re, atexit
  10349. try:
  10350. import rlcompleter,readline
  10351. except ImportError:
  10352. log_loading.info("Can't load Python libreadline or completer")
  10353. READLINE=0
  10354. else:
  10355. READLINE=1
  10356. class ScapyCompleter(rlcompleter.Completer):
  10357. def global_matches(self, text):
  10358. matches = []
  10359. n = len(text)
  10360. for lst in [dir(__builtin__), session.keys()]:
  10361. for word in lst:
  10362. if word[:n] == text and word != "__builtins__":
  10363. matches.append(word)
  10364. return matches
  10365. def attr_matches(self, text):
  10366. m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
  10367. if not m:
  10368. return
  10369. expr, attr = m.group(1, 3)
  10370. try:
  10371. object = eval(expr)
  10372. except:
  10373. object = eval(expr, session)
  10374. if isinstance(object, Packet):
  10375. words = filter(lambda x: x[0]!="_",dir(object))
  10376. words += map(str, object.fields_desc)
  10377. else:
  10378. words = dir(object)
  10379. if hasattr( object,"__class__" ):
  10380. words = words + rlcompleter.get_class_members(object.__class__)
  10381. matches = []
  10382. n = len(attr)
  10383. for word in words:
  10384. if word[:n] == attr and word != "__builtins__":
  10385. matches.append("%s.%s" % (expr, word))
  10386. return matches
  10387. readline.set_completer(ScapyCompleter().complete)
  10388. readline.parse_and_bind("C-o: operate-and-get-next")
  10389. readline.parse_and_bind("tab: complete")
  10390. session=None
  10391. session_name=""
  10392. opts=getopt.getopt(argv[1:], "hs:")
  10393. iface = None
  10394. try:
  10395. for opt, parm in opts[0]:
  10396. if opt == "-h":
  10397. usage()
  10398. elif opt == "-s":
  10399. session_name = parm
  10400. if len(opts[1]) > 0:
  10401. raise getopt.GetoptError("Too many parameters : [%s]" % string.join(opts[1]),None)
  10402. except getopt.error, msg:
  10403. log_loading.error(msg)
  10404. sys.exit(1)
  10405. if session_name:
  10406. try:
  10407. os.stat(session_name)
  10408. except OSError:
  10409. log_loading.info("New session [%s]" % session_name)
  10410. else:
  10411. try:
  10412. try:
  10413. session = cPickle.load(gzip.open(session_name,"rb"))
  10414. except IOError:
  10415. session = cPickle.load(open(session_name,"rb"))
  10416. log_loading.info("Using session [%s]" % session_name)
  10417. except EOFError:
  10418. log_loading.error("Error opening session [%s]" % session_name)
  10419. except AttributeError:
  10420. log_loading.error("Error opening session [%s]. Attribute missing" % session_name)
  10421. if session:
  10422. if "conf" in session:
  10423. conf.configure(session["conf"])
  10424. session["conf"] = conf
  10425. else:
  10426. conf.session = session_name
  10427. session={"conf":conf}
  10428. else:
  10429. session={"conf": conf}
  10430. __builtin__.__dict__["scapy_session"] = session
  10431. if READLINE:
  10432. if conf.histfile:
  10433. try:
  10434. readline.read_history_file(conf.histfile)
  10435. except IOError:
  10436. pass
  10437. atexit.register(scapy_write_history_file,readline)
  10438. sys.ps1 = ColorPrompt()
  10439. code.interact(banner = the_banner % (VERSION), local=session)
  10440. if conf.session:
  10441. save_session(conf.session, session)
  10442. sys.exit()
  10443. if __name__ == "__main__":
  10444. interact()