>>> BERcodec_INTEGER.enc(7)'\x02\x01\x07'>>> BERcodec_BIT_STRING.enc("egg")'\x03\x03egg'>>> BERcodec_STRING.enc("egg")'\x04\x03egg'>>> BERcodec_STRING.dec('\x04\x03egg')(<ASN1_STRING['egg']>, '')>>> BERcodec_STRING.dec('\x03\x03egg')Traceback (most recent call last):
File "<console>", line 1, in ?
File "/usr/bin/scapy", line 2099, in decreturncls.do_dec(s,context,safe)
File "/usr/bin/scapy", line 2178, in do_decl,s,t=cls.check_type_check_len(s)
File "/usr/bin/scapy", line 2076, in check_type_check_lenl,s3=cls.check_type_get_len(s)
File "/usr/bin/scapy", line 2069, in check_type_get_lens2=cls.check_type(s)
File "/usr/bin/scapy", line 2065, in check_type(cls.__name__,ord(s[0]),ord(s[0]),cls.tag),remaining=s)BER_BadTag_Decoding_Error: BERcodec_STRING: Got tag [3/0x3] while expecting <ASN1Tag STRING[4]>### Already decoded ###None### Remaining ###'\x03\x03egg'>>> BERcodec_Object.dec('\x03\x03egg')(<ASN1_BIT_STRING['egg']>, '')
>>> cert="""... MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMC... VVMxHTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNB... bWVyaWNhIE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIg... Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAw... MFoXDTM3MDkyODIzNDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRB... T0wgVGltZSBXYXJuZXIgSW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUg... SW5jLjE3MDUGA1UEAxMuQU9MIFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNh... dGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC... ggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ7ouZzU9AhqS2TcnZsdw8TQ2FTBVs... RotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilbm2BPJoPRYxJWSXakFsKlnUWs... i4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOYxFSMFkpBd4aVdQxHAWZg... /BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZYYCLqJV+FNwSbKTQ... 2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbqJS5Gr42whTg0... ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fxI2rSAG2X... +Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETzkxml... J85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh... EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNo... Kk/SBtc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJ... Kg71ZDIMgtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1Ex... MVCgyhwn2RAurda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMB... Af8wHQYDVR0OBBYEFE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaA... FE9pbQN+nZ8HGEO8txBO1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG... 9w0BAQUFAAOCAgEAO/Ouyuguh4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0... cnAxa8cZmIDJgt43d15Ui47y6mdPyXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRF... ASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q7C+qPBR7V8F+GBRn7iTGvboVsNIY... vbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKTRuidDV29rs4prWPVVRaAMCf/... drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ClTluUI8JPu3B5wwn3la... 5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyBM5kYJRF3p+v9WAks... mWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQmy8YJPamTQr5... O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xOAU++CrYD... 062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT9Y41... xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H... hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOL... Z8/5fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg=... """.decode("base64")>>> (dcert,remain)=BERcodec_Object.dec(cert)Traceback (most recent call last):
File "<console>", line 1, in ?
File "/usr/bin/scapy", line 2099, in decreturncls.do_dec(s,context,safe)
File "/usr/bin/scapy", line 2094, in do_decreturncodec.dec(s,context,safe)
File "/usr/bin/scapy", line 2099, in decreturncls.do_dec(s,context,safe)
File "/usr/bin/scapy", line 2218, in do_deco,s=BERcodec_Object.dec(s,context,safe)
File "/usr/bin/scapy", line 2099, in decreturncls.do_dec(s,context,safe)
File "/usr/bin/scapy", line 2094, in do_decreturncodec.dec(s,context,safe)
File "/usr/bin/scapy", line 2099, in decreturncls.do_dec(s,context,safe)
File "/usr/bin/scapy", line 2218, in do_deco,s=BERcodec_Object.dec(s,context,safe)
File "/usr/bin/scapy", line 2099, in decreturncls.do_dec(s,context,safe)
File "/usr/bin/scapy", line 2092, in do_decraiseBER_Decoding_Error("Unknown prefix [%02x] for [%r]"%(p,t),remaining=s)BER_Decoding_Error: Unknown prefix [a0] for ['\xa0\x03\x02\x01\x02\x02\x01\x010\r\x06\t*\x86H...']### Already decoded ###[[]]### Remaining ###'\xa0\x03\x02\x01\x02\x02\x01\x010\r\x06\t*\x86H\x86\xf7\r\x01\x01\x05\x05\x000\x81\x831\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x1d0\x1b\x06\x03U\x04\n\x13\x14AOL Time Warner Inc.1\x1c0\x1a\x06\x03U\x04\x0b\x13\x13America Online Inc.1705\x06\x03U\x04\x03\x13.AOL Time Warner Root Certification Authority 20\x1e\x17\r020529060000Z\x17\r370928234300Z0\x81\x831\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x1d0\x1b\x06\x03U\x04\n\x13\x14AOL Time Warner Inc.1\x1c0\x1a\x06\x03U\x04\x0b\x13\x13America Online Inc.1705\x06\x03U\x04\x03\x13.AOL Time Warner Root Certification Authority 20\x82\x02"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\xb47Z\x08\x16\x99\x14\xe8U\xb1\x1b$k\xfc\xc7\x8b\xe6\x87\xa9\x89\xee\x8b\x99\xcdO@\x86\xa4\xb6M\xc9\xd9\xb1\xdc<M\r\x85L\x15lF\x8bRx\x9f\xf8#\xfdg\xf5$:h]\xd0\xf7daAT\xa3\x8b\xa5\x08\xd2)[\x9b`O&\x83\xd1c\x12VIv\xa4\x16\xc2\xa5\x9dE\xac\x8b\x84\x95\xa8\x16\xb1\xec\x9f\xea$\x1a\xef\xb9W\\\x9a$!,M\x0eq\x1f\xa6\xac]Et\x03\x98\xc4T\x8c\x16JAw\x86\x95u\x0cG\x01f`\xfc\x15\xf1\x0f\xea\xf5\x14x\xc7\x0e\xd7n\x81\x1c^\xbf^\xe7:*\xd8\x97\x170|\x00\xad\x08\x9d3\xaf\xb8\x99a\x80\x8b\xa8\x95~\x14\xdc\x12l\xa4\xd0\xd8\xef@I\x026\xf9n\xa9\xd6\x1d\x96V\x04\xb2\xb3-\x16V\x86\x8f\xd9 W\x80\xcdg\x10m\xb0L\xf0\xdaF\xb6\xea%.F\xaf\x8d\xb0\x8584\x8b\x14&\x82+\xac\xae\x99\x0b\x8e\x14\xd7R\xbd\x9ei\xc3\x86\x02\x0b\xeavu1\t\xce3\x19!\x85C\xe6\x89-\x9f%7g\xf1#j\xd2\x00m\x97\xf9\x9f\xe7)\xca\xdd\x1f\xd7\x06\xea\xb8\xc9\xb9\t!\x9f\xc8?\x06\xc5\xd2\xe9\x12F\x00N{\x08\xebB=+Hn\x9dg\xddK\x02\xe4D\xf3\x93\x19\xa5\'\xceiz\xbeg\xd3\xfcP\xa4,\xab\xc3k\xb9\xe3\x80L\xcf\x05aK+\xdc\x1b\xb9\xa6\xd2\xd0\xaa\xf5+s\xfb\xce\x905\x9f\x0cR\x1c\xbf\\!a\x11[\x15K\xa9$Q\xfc\xa4\\\xf7\x17\x9d\xb0\xd2\xfa\x07\xe9\x8fV\xe4\x1a\x8ch\x8a\x04\xd3|Z\xe3\x9e\xa2\xa1\xcaq[\xa2\xd4\xa0\xe7)\x85]\x03h*O\xd2\x06\xd7=\xf9\xc3\x03/?e\xf9g\x1eG@\xd3c\x0f\xe3\xd5\x8e\xf9\x85\xab\x97L\xb3\xd7&\xeb\x96\n\x94\xde\x856\x9c\xc8\x7f\x81\t\x02I*\x0e\xf5d2\x0c\x82\xd1\xbaj\x82\x1b\xb3Kt\x11\xf3\x8cw\xd6\x9f\xbf\xdc7\xa4\xa7U\x04/\xd41\xe8\xd3F\xb9\x03|\xda\x12NYd\xb7Q11P\xa0\xca\x1c\'\xd9\x10.\xad\xd6\xbd\x10f+\xc3\xb0"J\x12[\x02\x03\x01\x00\x01\xa3c0a0\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff0\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x14Oim\x03~\x9d\x9f\x07\x18C\xbc\xb7\x10N\xd5\xbf\xa9\xc4 (0\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14Oim\x03~\x9d\x9f\x07\x18C\xbc\xb7\x10N\xd5\xbf\xa9\xc4 (0\x0e\x06\x03U\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x860\r\x06\t*\x86H\x86\xf7\r\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00;\xf3\xae\xca\xe8.\x87\x85\xfbeY\xe7\xad\x11\x14\xa5W\xbcX\x9f$\x12W\xbb\xfb?4\xda\xee\xadz*4rp1k\xc7\x19\x98\x80\xc9\x82\xde7w^T\x8b\x8e\xf2\xeagO\xc9t\x84\x91V\t\xd5\xe5z\x9a\x81\xb6\x81\xc2\xad6\xe4\xf1T\x11S\xf34E\x01&\xc8\xe5\x1a\xbc4D!\xde\xad%\xfcv\x16w!\x90\x80\x98W\x9dN\xea\xec/\xaa<\x14{W\xc1~\x18\x14g\xee$\xc6\xbd\xba\x15\xb0\xd2\x18\xbd\xb7U\x81\xacS\xc0\xe8\xddi\x12\x13B\xb7\x02\xb5\x05A\xcayPn\x82\x0eqr\x93F\xe8\x9d\r]\xbd\xae\xce)\xadc\xd5U\x16\x800\'\xffv\xba\xf7\xb8\xd6J\xe3\xd9\xb5\xf9R\xd0N@\xa9\xc7\xe5\xc22\xc7\xaav$\xe1k\x05P\xeb\xc5\xbf\nT\xe5\xb9B<$\xfb\xb7\x07\x9c0\x9fyZ\xe6\xe0@R\x15\xf4\xfc\xaa\xf4V\xf9D\x97\x87\xed\x0eer^\xbe&\xfbM\xa4-\x08\x07\xde\xd8\\\xa0\xdc\x813\x99\x18%\x11w\xa7\xeb\xfdX\t,\x99k\x1b\x8a\xf3R?\x1aMH`\xf1\xa0\xf63\x02S\x8b\xed%\t\xb8\r-\xed\x97s\xec\xd7\x96\x1f\x8e`\x0e\xda\x10\x9b/\x18$\xf6\xa6M\n\xf9;\xcbu\xc2\xcc/\xce$i\xc9\n"\x8eY\xa7\xf7\x82\x0c\xd7\xd7k5\x9cC\x00j\xc4\x95g\xba\x9cE\xcb\xb8\x0e7\xf7\xdcN\x01O\xbe\n\xb6\x03\xd3\xad\x8aE\xf7\xda\'M)\xb1H\xdf\xe4\x11\xe4\x96F\xbdl\x02>\xd6Q\xc8\x95\x17\x01\x15\xa9\xf2\xaa\xaa\xf2\xbf/e\x1bo\xd0\xb9\x1a\x93\xf5\x8e5\xc4\x80\x87>\x94/f\xe4\xe9\xa8\xffA\x9cp*O*9\x18\x95\x1e~\xfba\x01<Q\x08.(\x18\xa4\x16\x0f1\xfd:l#\x93 v\xe1\xfd\x07\x85\xd1[?\xd2\x1cs2\xdd\xfa\xb9\xf8\x8c\xcf\x02\x87z\x9a\x96\xe4\xedO\x89\x8dSC\xab\x0e\x13\xc0\x01\x15\xb4y8\xdb\xfcn=\x9eQ\xb6\xb8\x13\x8bg\xcf\xf9|\xd9"\x1d\xf6]\xc5\x1c\x01/\x98\xe8z$\x18\xbc\x84\xd7\xfa\xdcr[\xf7\xc1:h'
classHelloWorld(Automaton):@ATMT.state(initial=1)defBEGIN(self):print"State=BEGIN"@ATMT.condition(BEGIN)defwait_for_nothing(self):print"Wait for nothing..."raiseself.END()@ATMT.action(wait_for_nothing)defon_nothing(self):print"Action on 'nothing' condition"@ATMT.state(final=1)defEND(self):print"State=END"
classExample(Automaton):@ATMT.state(initial=1)defBEGIN(self):pass@ATMT.state()defSOME_STATE(self):pass@ATMT.state(final=1)defEND(self):return"Result of the automaton: 42"@ATMT.state(error=1)defERROR(self):return"Partial result, or explanation"# [...]
classExample(Automaton):@ATMT.state(initial=1)defBEGIN(self):pass@ATMT.state(final=1)defEND(self):pass@ATMT.condition(BEGIN,prio=1)defmaybe_go_to_end(self):ifrandom()>0.5:raiseself.END()@ATMT.condition(BEGIN,prio=2)defcertainly_go_to_end(self):raiseself.END()@ATMT.action(maybe_go_to_end)defmaybe_action(self):print"We are lucky..."@ATMT.action(certainly_go_to_end)defcertainly_action(self):print"We are not lucky..."@ATMT.action(maybe_go_to_end,prio=1)@ATMT.action(certainly_go_to_end,prio=1)defalways_action(self):print"This wasn't luck!..."
两个可能的输出是:
>>> a=Example()>>> a.run()We are not lucky...This wasn't luck!...>>> a.run()We are lucky...This wasn't luck!...
Due to limitations of the pcap format, all packets must be of
the same link type. This class will not mutate packets to conform with
the expected link type.
Some special sort of Drains exists: the Trigger Drains.
Trigger Drains are special drains, that on receiving data not only pass it by but also send a “Trigger” input, that is received and handled by the next triggered drain (if it exists).
For example, here is a basic TriggerDrain usage:
>>> a=CLIFeeder()>>> d=TriggerDrain(lambdamsg:True)# Pass messages and trigger when a condition is met>>> d2=TriggeredValve()>>> s=ConsoleSink()>>> a>d>d2>s>>> d^d2# Link the triggers>>> p=PipeEngine(s)>>> p.start()INFO: Pipe engine thread started.>>>>>> a.send("this will be printed")>'this will be printed'>>> a.send("this won't, because the valve was switched")>>> a.send("this will, because the valve was switched again")>'this will, because the valve was switched again'>>> p.stop()
Several triggering Drains exist, they are pretty explicit. It is highly recommended to check the doc using help([theclass])
TriggeredMessage : Send a preloaded message when triggered and trigger in chain
TriggerDrain : Pass messages and trigger when a condition is met
TriggeredValve : Let messages alternatively pass or not, changing on trigger
TriggeredQueueingValve : Let messages alternatively pass or queued, changing on trigger
TriggeredSwitch : Let messages alternatively high or low, changing on trigger
高级用法¶
ASN.1和SNMP¶
什么是ASN.1?¶
注意
这只是我对ASN.1的观点,请尽可能简单地解释一下。对于更多的理论或学术观点,我相信您会在Internet上找到更好的选择。
ASN.1是一种符号,其目的是指定数据交换的格式。它与数据编码方式无关。数据编码在编码规则中指定。
最常用的编码规则是BER(基本编码规则)和DER(特殊编码规则)。两者看起来相同,但指定后者以保证编码的唯一性。当谈论密码,哈希和签名时,此属性非常有趣。
ASN.1提供了基本对象:整数,多种字符串,浮点数,布尔值,容器等。它们被分组在所谓的通用类中。给定的协议可以提供其他对象,这些对象将在Context类中分组。例如,SNMP定义PDU_GET或PDU_SET对象。还有Application和Private类。
这些对象中的每一个都有一个标记,编码规则将使用该标记。来自1的标签用于通用类。1是布尔值,2是整数,3是位串,6是OID,48是序列。
Context
该类中的标签始于0xa0。遇到标有0xa0的对象时,我们需要知道上下文才能对其进行解码。例如,在SNMP上下文中,0xa0是PDU_GET对象,而在X509上下文中,它是证书版本的容器。通过组装所有这些基本砖块对象来创建其他对象。使用先前定义或现有对象的序列和数组(集合)完成合成。最终对象(X509证书,SNMP数据包)是一棵树,其非叶子节点是序列和集合对象(或派生的上下文对象),并且叶子节点是整数,字符串,OID等。
Scapy的和ASN.1 ¶
Scapy提供了一种轻松编码或解码ASN.1并对这些编码器/解码器进行编程的方法。它比ASN.1解析器应有的宽松得多,并且它会忽略约束。它不会取代ASN.1解析器或ASN.1编译器。实际上,它已经被编写为能够对损坏的ASN.1进行编码和解码。它可以处理损坏的编码字符串,也可以创建它们。
ASN.1引擎¶
注意:此处提供的许多类定义都使用元类。如果您不完全看待源代码,而仅依靠我的捕获,您可能会认为它们有时表现出某种魔术行为。``Scapy ASN.1引擎提供了用于链接对象及其标签的类。他们从继承
ASN1_Class
。第一个是ASN1_Class_UNIVERSAL
,它为大多数通用对象提供标签。每个新的上下文(SNMP
,X509
)将从其继承并添加自己的对象。所有ASN.1对象都由简单的Python实例表示,这些实例充当原始值的外壳。简单逻辑
ASN1_Object
由其继承者处理。因此,它们非常简单:可以组合这些实例以创建ASN.1树:
编码引擎¶
与标准一样,ASN.1和编码是独立的。我们刚刚看到了如何创建复合的ASN.1对象。要对其进行编码或解码,我们需要选择一个编码规则。Scapy目前仅提供BER(实际上,它可能是DER。DER看起来像BER,除了仅授权了最小限度的编码,这很可能就是我所做的)。我将此称为ASN.1编解码器。
使用编解码器提供的类方法完成编码和解码。例如,
BERcodec_INTEGER
该类提供了.enc()
和.dec()
类方法,可以在编码的字符串和其类型的值之间进行转换。它们都继承自BERcodec_Object,它能够解码任何类型的对象:ASN.1对象使用其
.enc()
方法进行编码。必须使用我们要使用的编解码器调用此方法。在ASN1_Codecs对象中引用了所有编解码器。raw()
也可以使用。在这种情况下,将使用默认编解码器(conf.ASN1_default_codec
)。默认情况下,使用
Universal
该类完成解码,这意味着Context
将不会解码该类中定义的对象。这样做有充分的理由:解码取决于上下文!该
Context
班必须指定:ASN.1层¶
尽管这可能不错,但这只是一个ASN.1编码器/解码器。与Scapy无关。
ASN.1字段¶
Scapy提供ASN.1字段。它们将包装ASN.1对象,并提供必要的逻辑以将字段名称绑定到该值。ASN.1数据包将被描述为ASN.1字段的树。然后,每个字段名将以普通形式作为普通
Packet
对象提供(例如:访问SNMP数据包的version字段,您不需要知道有多少个容器包装它)。每个ASN.1字段都通过其标签链接到ASN.1对象。
ASN.1数据包¶
ASN.1数据包继承自Packet类。
fields_desc
它们定义字段ASN1_codec
和ASN1_root
属性,而不是字段列表。第一个是编解码器(例如:)ASN1_Codecs.BER
,第二个是与ASN.1字段混合的树。一个完整的例子:SNMP¶
SNMP定义了新的ASN.1对象。我们需要定义它们:
这些对象是PDU,实际上是序列容器的新名称(上下文对象通常是这种情况:它们是具有新名称的旧容器)。这意味着创建相应的ASN.1对象和BER编解码器非常简单:
元类为所有事物都自动注册并且ASN.1对象和BER编解码器可以相互找到这一事实提供了魔力。
ASN.1字段也很简单:
现在,最困难的部分是ASN.1数据包:
那不是那么困难。如果您认为实现SNMP编码/解码的时间不能太短,并且我可能已经削减了太多,那么请看完整的源代码。
现在,如何使用它?照常:
从MIB解析OID¶
关于OID对象¶
OID对象使用一个
ASN1_OID
类创建:加载一个MIB¶
Scapy可以解析MIB文件,并知道OID及其名称之间的映射:
我已使用的MIB文件附在此页面上。
Scapy的MIB数据库¶
所有MIB信息都存储在conf.mib对象中。该对象可用于查找名称的OID
或解决OID:
甚至可以用图形表示:
自动机¶
Scapy可以轻松创建网络自动机。Scapy不会遵循特定模型,例如Moore或Mealy自动机。它为您提供了一种灵活的选择方式。
Scapy中的自动机是确定性的。它具有不同的状态。一个开始状态以及一些结束和错误状态。从一种状态过渡到另一种状态。转换可以是特定条件下的转换,特定数据包接收时的转换或超时的转换。进行过渡时,可以运行一个或多个动作。一个动作可以绑定许多转换。参数可以从状态传递到转换,也可以从状态传递到状态和动作。
从程序员的角度来看,状态,转换和动作是Automaton子类的方法。装饰它们以提供自动机工作所需的元信息。
第一个例子¶
让我们从一个简单的例子开始。我习惯用大写字母写状态,但是任何使用Python语法有效的方法也可以使用。
在此示例中,我们可以看到3个装饰器:
ATMT.state
用于表示方法是状态,并且对于特殊状态,可以将初始,最终和错误可选参数设置为非零。ATMT.condition
指示当自动机状态达到指示状态时要运行的方法。参数是表示该状态的方法的名称ATMT.action
将方法绑定到过渡并在进行过渡时运行。运行此示例将得到以下结果:
下图描述了这个简单的自动机:
可以使用以下代码从代码中自动绘制图形:
改变状态¶
所述
ATMT.state
装饰变换的方法成返回异常的功能。如果引发该异常,则自动机状态将更改。如果更改发生在过渡中,则将调用绑定到该过渡的动作。保留给替换方法的函数的参数,并最终将其传递给该方法。异常具有方法action_parameters,可以在引发异常之前调用该方法,以便它将存储要传递给绑定到当前转换的所有操作的参数。例如,让我们考虑以下状态:
可以通过以下代码达到此状态:
假设我们想将一个动作绑定到此过渡,这还需要一些参数:
条件应变为:
真实的例子¶
这是来自Scapy的真实示例。它实现了可以发出读取请求的TFTP客户端。
它可以像这样运行,例如:
详细文档¶
装饰器¶
状态装饰器¶
状态是由
ATMT.state
函数的结果修饰的方法。它可以采取3个可选参数,initial
,final
和error
,即,当设置为True
,表示状态是声母,韵母或错误状态。过渡的装饰器¶
转变是由某种原因引起的装饰方法
ATMT.condition
,ATMT.receive_condition
,ATMT.timeout
。它们都以与它们相关的状态方法作为参数。ATMT.timeout
还具有一个必填timeout
参数,以秒为单位提供超时值。ATMT.condition
并ATMT.receive_condition
具有一个可选prio
参数,以便可以强制评估条件的顺序。默认优先级为0。具有相同优先级的转换按不确定的顺序调用。当自动机切换到给定状态时,将执行该状态的方法。然后,在特定时刻调用transitions方法,直到触发一个新状态(类似)。首先,在状态方法返回后,修饰的方法通过增加prio来运行。然后,每次接收到一个数据包并由主过滤器接受时,所有装饰的样板都将通过生长prio进行调用。自从我们进入当前空间以来达到超时时,将调用相应的修饰方法。
raise self.MY_NEW_STATE()
ATMT.condition
ATMT.receive_condition
ATMT.timeout
装饰器¶
动作是由
ATMT.action
函数的返回修饰的方法。此函数将绑定到的过渡方法作为第一个参数,并将可选的优先级prio
作为第二个参数。默认优先级为0。可以将操作方法进行多次修饰以绑定到许多转换。两个可能的输出是:
重载方法¶
钩子有两种方法可以重载:
parse_args()
使用在__init__()
和指定的参数调用该方法run()
。使用它来参数化自动机的行为。master_filter()
每次嗅探数据包时都会调用此方法,并确定自动机是否感兴趣。在使用特定协议时,您将在这里确保数据包属于您所属于的连接,因此您无需在每个转换中都进行所有的健全性检查。PipeTools ¶
Pipetool是一个智能管道系统,可以执行复杂的流数据管理。PipeTools和自动机之间有多种区别:
PipeTools没有状态:数据总是按照相同的模式发送
PipeTools不是基于套接字的,而是可以处理多种数据源(和输出),例如用户输入,pcap输入(还可以进行嗅探)
PipeTools不是基于类的,而是通过手动链接其所有零件来实现的。这样做有缺点,但允许动态添加源,运行时消耗并为同一源设置多个消耗
注意
Pipetool默认对象位于内部
scapy.pipetool
类的类型¶
数据管理使用三种不同的对象类别:
Sources
Drains
Sinks
它们由
PipeEngine
对象执行和处理。运行时,pipetool引擎会等待源中的所有可用数据,然后将其发送到链接到它的排水管中。然后,数据从“排水”到“排水”,直到到达接收器(该数据的最终状态)为止。
这是PipeTool系统可以执行的基本演示
例如,此引擎是使用以下代码生成的:
让我们启动PipeEngine:
现在,让我们玩一下:
让我们研究一下这里发生的情况:
PipeEngine中有两条运河,一条较低,一条较高。有些资料写在较低的一个上,有些资料写在较高的一个上,有些都写在两个上。
大多数水源都可以与上下渠中的任何排水系统相连。使用>表示在下层运河上的链接,而在>>上表示上层的链接。
如上所示,当我们在下运河中的s中发送一些数据时,它经过排水管,然后被发送到QueueSink和ConsoleSink
当我们在s2中发送一些数据时,它先经过Drain,然后经过TransformDrain,在此之前,数据被反转(请参阅lambda),然后才发送到ConsoleSink。这就解释了为什么我们只有QueueSink内部的较低来源的数据:较高的来源尚未链接。
大部分水槽都从上下运河接收。这可以使用help(ConsoleSink)进行验证
来源¶
Source是生成一些数据的类。
与Scapy集成有多种源类型,可以按原样使用,但您也可以创建自己的源。
默认源类¶
对于任何此类,请查看
help([theclass])
以获取更多信息或所需的参数。CLIFeeder:专门用于交互式软件的源。它
send(data)
在下运河产生事件数据CLIHighFeeder:与CLIFeeder相同,但写在较高的运河上
PeriodicSource:定期在低运河上生成消息。
自动来源:默认来源,必须扩展以创建自定义来源。
创建自定义源¶
要创建自定义源,必须扩展
AutoSource
该类。Source
除非您真的确定自己在做什么,否则不要使用默认类:它仅在内部使用,并且缺少某些实现。该AutoSource
是由使用。要通过它发送数据,对象必须调用其
self._gen_data(msg)
或self._gen_high_data(msg)
函数,这些函数将数据发送到PipeEngine中。Source也应(如果可能)设置
self.is_exhausted
为True
空,以允许干净地停止PipeEngine
。如果源是无限的,则将需要强制停止(请参阅下面的PipeEngine)例如,以下是CLIHighFeeder的实现方式:
排水管¶
默认Drain类¶
漏极需要链接到您正在使用的条目上。它可以位于较低的一个(使用
>
)或较高的一个(使用>>
)上。请参阅上面的基本示例。排水:最基本的排水方式。如果链接正确,将同时通过高低输入。
TransformDrain:将功能应用于消息上下限较高的消息
UpDrain:从低入口到高出口重复消息
DownDrain:重复从高入口到低出口的消息
创建一个自定义的Drain¶
要创建自定义流失,必须扩展
Drain
类。甲
Drain
对象将从其下部管接收数据push
的方法,以及从其较高运河high_push
方法。要将数据发送回下一个链接的“漏极/接收器”,它必须调用
self._send(msg)
或self._high_send(msg)
方法。例如,以下是TransformDrain的实现方式:
水槽¶
接收器是消息的目的地。
A
Sink
接收数据,如Drain
,但之后不发送任何消息。低条目的
push()
消息来自,高条目的消息来自high_push()
。默认接收器类¶
Sink
¶什么也没做; 接口以扩展自定义接收器。
所有接收器均具有以下构造函数参数:
名称(str)–元素的易读名称
所有接收器都应至少实现以下方法之一:
push
()¶PipeEngine
低端条目有新消息时调用。msg –消息数据
没有
没有
high_push
()¶PipeEngine
当出现新的高位消息时调用。msg –消息数据
没有
没有
ConsoleSink
¶将消息的低和高条目打印到
stdout
。RawConsoleSink
¶使用,在低和高条目上打印消息
os.write()
。换行符(bool)–打印每个数据包后,请包含换行符。默认为True。
TermSink
¶在单独的终端(xterm或cmd)上的低和高条目上打印消息。
keepterm(bool)–
stop()
调用后使终端窗口保持打开状态。默认为True。换行符(bool)–打印每个数据包后,请包含换行符。默认为True。
openearly(bool)–在调用构造函数时自动启动终端,而不是等待
start()
。默认为True。QueueSink
¶将消息中的低位和高位收集到
Queue
。邮件以出队
recv()
。高和低条目共享相同的内容
Queue
。recv
()¶从队列中读取下一条消息。
如果队列中没有可用消息,则返回无。
block(bool)–阻止执行,直到队列中有可用数据包为止。默认为True。
超时(无,整数或浮点数)–控制的等待时间,如果
block=True
。如果为None(默认),则此方法将永远等待。如果为非负数,则为放弃(并返回无)之前要等待的秒数。WiresharkSink
¶流
Packet
从低进入Wireshark的。数据包被写入
pcap
流(如WrpcapSink
),并在其上流式传输到新的Wireshark进程stdin
。Wireshark使用自变量运行,这导致它被 视为捕获设备。之后的参数将被追加。
-ki -
stdin
args
Extends
WrpcapSink
.linktype (None or int) – See
WrpcapSink.linktype
.args (None or list[str]) – See
args
.args
¶Additional arguments for the Wireshark process.
This must be either
None
(the default), or alist
ofstr
.This attribute has no effect after calling
PipeEngine.start()
.See wireshark(1) for more details.
WrpcapSink
¶Writes
Packet
on the low entry to apcap
file.Ignores all messages on the high entry.
Note
Due to limitations of the
pcap
format, all packets must be of the same link type. This class will not mutate packets to conform with the expected link type.fname (str) – Filename to write packets to.
linktype (None or int) – See
linktype
.linktype
¶Set an explicit link-type (
DLT_
) for packets. This must be anint
orNone
.This is the same as the
wrpcap()
linktype
parameter.If
None
(the default), the linktype will be auto-detected on the first packet. This field will not be updated with the result of this auto-detection.This attribute has no effect after calling
PipeEngine.start()
.Create a custom Sink¶
To create a custom sink, one must extend
Sink
and implementpush()
and/orhigh_push()
.This is a simplified version of
ConsoleSink
:Link objects¶
As shown in the example, most sources can be linked to any drain, on both low and high entry.
The use of
>
indicates a link on the low entry, and>>
on the high entry.For example, to link
a
,b
andc
on the low entries:This wouldn’t link the high entries, so something like this would do nothing:
Because
b
(Drain
) andc
(ConsoleSink
) are not linked on the high entry.However, using a
DownDrain
would bring the high messages fromCLIHighFeeder
to the lower channel:The PipeEngine class¶
The
PipeEngine
class is the core class of the Pipetool system. It must be initialized and passed the list of all Sources.There are two ways of passing sources:
during initialization:
p = PipeEngine(source1, source2, ...)
using the
add(source)
methodA
PipeEngine
class must be started with.start()
function. It may be force-stopped with the.stop()
, or cleanly stopped with.wait_and_stop()
A clean stop only works if the Sources is exhausted (has no data to send left).
It can be printed into a graph using
.graph()
methods. seehelp(do_graph)
for the list of available keyword arguments.Scapy advanced PipeTool objects¶
Note
Unlike the previous objects, those are not located in
scapy.pipetool
but inscapy.scapypipes
Now that you know the default PipeTool objects, here are some more advanced ones, based on packet functionalities.
SniffSource : Read packets from an interface and send them to low exit.
RdpcapSource : Read packets from a PCAP file send them to low exit.
InjectSink : Packets received on low input are injected (sent) to an interface
WrpcapSink : Packets received on low input are written to PCAP file
UDPDrain : UDP payloads received on high entry are sent over UDP (complicated, have a look at
help(UDPDrain)
)FDSourceSink : Use a file descriptor as source and sink
TCPConnectPipe : TCP connect to addr:port and use it as source and sink
TCPListenPipe : TCP listen on [addr:]port and use the first connection as source and sink (complicated, have a look at
help(TCPListenPipe)
)Triggering¶
Some special sort of Drains exists: the Trigger Drains.
Trigger Drains are special drains, that on receiving data not only pass it by but also send a “Trigger” input, that is received and handled by the next triggered drain (if it exists).
For example, here is a basic TriggerDrain usage:
Several triggering Drains exist, they are pretty explicit. It is highly recommended to check the doc using
help([the class])
TriggeredMessage : Send a preloaded message when triggered and trigger in chain
TriggerDrain : Pass messages and trigger when a condition is met
TriggeredValve : Let messages alternatively pass or not, changing on trigger
TriggeredQueueingValve : Let messages alternatively pass or queued, changing on trigger
TriggeredSwitch : Let messages alternatively high or low, changing on trigger
©版权所有2008-2019 Philippe Biondi和Scapy社区 修订版
9bf51c28
。