├── Data
├── _WRITE0.bin
└── _WRITE1.bin
├── HPACK.dll
├── HPACK_src
├── HPACKInteger
│ ├── bin
│ │ └── Debug
│ │ │ ├── HPACK.dll
│ │ │ └── HPACK.pdb
│ ├── Huffman.cs
│ ├── HuffmanTransformer.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── HPACK.csproj
│ ├── HuffmanEncoder.cs
│ ├── HPACKInteger.cs
│ ├── HuffmanDecoder.cs
│ └── HpackUtil.cs
└── HPACKInteger.sln
├── TLSProxy
├── server.key
├── server.crt
├── ca.crt
└── h2unwrap.py
├── mscer2.py
├── HTTP2_State.xml
├── mscer2monitor.py
├── HTTP2_Client.xml
├── README.md
├── HTTP2_Data.xml
└── clrtype.py
/Data/_WRITE0.bin:
--------------------------------------------------------------------------------
1 | d
--------------------------------------------------------------------------------
/HPACK.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirusdv/EdgeHTTP2Fuzzer/HEAD/HPACK.dll
--------------------------------------------------------------------------------
/Data/_WRITE1.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirusdv/EdgeHTTP2Fuzzer/HEAD/Data/_WRITE1.bin
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/bin/Debug/HPACK.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirusdv/EdgeHTTP2Fuzzer/HEAD/HPACK_src/HPACKInteger/bin/Debug/HPACK.dll
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/bin/Debug/HPACK.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirusdv/EdgeHTTP2Fuzzer/HEAD/HPACK_src/HPACKInteger/bin/Debug/HPACK.pdb
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HPACK", "HPACKInteger\HPACK.csproj", "{AA6EBDD2-8B46-4B23-8B16-E901AB95C8B6}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {AA6EBDD2-8B46-4B23-8B16-E901AB95C8B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {AA6EBDD2-8B46-4B23-8B16-E901AB95C8B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {AA6EBDD2-8B46-4B23-8B16-E901AB95C8B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {AA6EBDD2-8B46-4B23-8B16-E901AB95C8B6}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/Huffman.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Twitter, Inc
3 | * This file is a derivative work modified by Ringo Leese
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | namespace HPACK
18 | {
19 | public class Huffman
20 | {
21 | ///
22 | /// Huffman Decoder
23 | ///
24 | public static HuffmanDecoder DECODER = new HuffmanDecoder(HpackUtil.HUFFMAN_CODES, HpackUtil.HUFFMAN_CODE_LENGTHS);
25 |
26 | ///
27 | /// Huffman Encoder
28 | ///
29 | public static HuffmanEncoder ENCODER = new HuffmanEncoder(HpackUtil.HUFFMAN_CODES, HpackUtil.HUFFMAN_CODE_LENGTHS);
30 |
31 | private Huffman()
32 | {
33 | // utility class
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/HuffmanTransformer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 |
8 | using Peach.Core;
9 | using Peach.Core.IO;
10 | using Peach.Core.Dom;
11 |
12 | namespace HPACK
13 | {
14 | [Transformer("HuffmanTransformer", true)]
15 | [Serializable]
16 | public class HuffmanTransformer : Transformer
17 | {
18 |
19 | public HuffmanTransformer(DataElement parent, Dictionary args)
20 | : base(parent, args)
21 | {
22 |
23 | }
24 | protected override BitStream internalDecode(BitStream data)
25 | {
26 |
27 | byte[] buf = new byte[data.Length];
28 | data.Read(buf, 0, (int)data.Length);
29 | return new BitStream(Huffman.DECODER.Decode(buf));
30 | }
31 |
32 | protected override BitwiseStream internalEncode(BitwiseStream data)
33 | {
34 | byte[] buf = new byte[data.Length];
35 | data.Read(buf, 0, (int)data.Length);
36 |
37 |
38 | byte[] retbuf = new byte[Huffman.ENCODER.GetEncodedLength(buf)];
39 | MemoryStream ms = new MemoryStream(retbuf);
40 | using (BinaryWriter bw = new BinaryWriter(ms))
41 | Huffman.ENCODER.Encode(bw, buf);
42 |
43 | return new BitStream(retbuf);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("HPACKInteger")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("HPACKInteger")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("aa6ebdd2-8b46-4b23-8b16-e901ab95c8b6")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/TLSProxy/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCrDPcpAjZ5n6wr
3 | tNInw7lxUB4q4mX+FlqfNa8ydK6MIu0xgE90en89I10b/pSL9kbr+jzrKncY/pnJ
4 | d3Wh6SvlCn/G/juaG2CJriO+uAWx0kOq7UWzkiVdmnpu3IRiYL8mzkvZfFSSDed+
5 | u6kJH9ZiouqQZW7ILTmuDttyEKRDqmH65n7kyA/7ILYJruD5lF5cXAvhdvmSwEfm
6 | EXrOT1hwAzfVWgOitTJxnx4BwqOxHsznFM6YSXqQsTVx7gFxsGQrDQJmapkEW1DQ
7 | jCyk7PVnlFsvATH8dzqV1VE+jW0V/qrg5cCPXV6wh29t1CQfXTiXgKn8AhtVcw2S
8 | /HKxXny1AgMBAAECggEAKvnc9464xSIbDfgmfRst8oxgqAGuAoL3Td0dIZ4zZL45
9 | viAw1mEYqvHBqRDznZ7I/u0mdSd8OOlvFjFPetis0KUsqYCi1Ptf6/e2v2pY8+6S
10 | VdW7l3x2qufvLv90u4r3O/bFE+WrEe8wZKUduU8ofCvWp2T0ypKiVVsiQ6xuuRki
11 | blp8TRKSQccpfEhhCu6X38eFRh21a6oyPR/qo3i1v4QmtZ+xiWrx619A6BRcUBur
12 | yDfQGa+kxIQ0f8qdH4QSwnx0MTyQzamDdiDi47icpHJgqM4pMNTQ0qpkj5suv8LL
13 | gzKaBu/rB795PxaC2G/EGNhdxUu6sCAOOVtsPDDAQQKBgQDkCuh7p96Ci+9JswdK
14 | OiiQ+pPWDirGKepKvdKXnPuqd0Sc8Y0hSwYNTiLlj0Z4gVi307l/6D5sB2BlPQtQ
15 | UbpZ+sJEWnmNewsF9YURC7r1F70E1Xot+CfvpvZFIVsX4KwkWVqR63HLeMfV0zHP
16 | y4UwedjNS+piLrQ6NHIMk1FtnQKBgQDABV70aay2Ebt+YcHnumuqVTLBGk1L3APy
17 | qGoM1mrDhDxI9axfWxDij4Ub8awkJumAIqFbqWyPyxCuUFMVduHi6GIFgZ88Mg7S
18 | Pv2jqHB208I89VQdQALGWs/ioljCjXNvRV+Bs1gIYvY3peTfVfLjkgjl5aUcEJg7
19 | a5Mclc+r+QKBgQCO6gco99uLFQexuHEpI6mosmFUFSzZZAthK/V+7vMJshVeBkPc
20 | SZhRXlagZ1pSyz0+d4IZlwMH0NeomsksXQvcuDpnfAwRjrsp0OTD+gYA9A+Rp/ga
21 | NxtQJeLREEZ2gGdhoF4SdOusCNW0O9dL0tB1wOcOQjVxsrNght2y4+B0QQKBgQCz
22 | Fo9H/yMQsBshNQWHHUv7EfkDNoeu36Vi9QXrsTLj5Pngxhic2q81zstDk7OMCCqw
23 | 0huSBML2nVqSaOIEW9szKK77GbisiLdgCVXABIHXoYpAFkL8AM5Vty653dZQpWJq
24 | /dWkfuL0929R2UxLq7qb2oCoAfVq5mNE0ADloSeN6QKBgFBCor6Oxu0XpIHRYHyH
25 | rdtEwCAp61jPaNRoOqPCYhUgdoZJtWBkZ/w3UYn8sXsnygsqpAsIb3jmpvIObap+
26 | wzgyKf1zQgaHwGdw++4iMeDtj4IkZCJ7SkF/czIK+qu5lHN5f9tvZiyxV2In6VTH
27 | 8eyGPC1USSXesnx6Bc7NuVU9
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/TLSProxy/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIGJTCCAg0CCQC1RnC2lL3uUzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJB
3 | VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
4 | cyBQdHkgTHRkMQwwCgYDVQQDDANtYWMwHhcNMTYwODI2MDAxMjExWhcNMjYwNzA1
5 | MDAxMjExWjBWMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8G
6 | A1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ8wDQYDVQQDDAZUQVJHRVQw
7 | ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrDPcpAjZ5n6wrtNInw7lx
8 | UB4q4mX+FlqfNa8ydK6MIu0xgE90en89I10b/pSL9kbr+jzrKncY/pnJd3Wh6Svl
9 | Cn/G/juaG2CJriO+uAWx0kOq7UWzkiVdmnpu3IRiYL8mzkvZfFSSDed+u6kJH9Zi
10 | ouqQZW7ILTmuDttyEKRDqmH65n7kyA/7ILYJruD5lF5cXAvhdvmSwEfmEXrOT1hw
11 | AzfVWgOitTJxnx4BwqOxHsznFM6YSXqQsTVx7gFxsGQrDQJmapkEW1DQjCyk7PVn
12 | lFsvATH8dzqV1VE+jW0V/qrg5cCPXV6wh29t1CQfXTiXgKn8AhtVcw2S/HKxXny1
13 | AgMBAAEwDQYJKoZIhvcNAQELBQADggQBAGOSwxonzSw9zHkK5FkvyYUlZkrcPFNw
14 | MF79Tqd2RX2FfFb1Zg9vwbKVQH1dbWRT9IoR2VfLc4EJMVo9T1MtDHNz6lqI6h1r
15 | EC8jK31FPn11mIuhkfxbVADAHEeShJ/d0xtaJiA0VBepTEv9y7j3f2ZxsLYUPN0R
16 | faPIZLCj4CLB1qcznLeYGpJ0B1faG7Sau/P23Xx45JAIqEonbSePdg5cBYkpiqaF
17 | q9A/3CyTBa5oNvXibFnUDQoXeW90BvkEyADm0m2YU6BBlwBG3wW/eI0QLI1omWcR
18 | tnxS/AxlHefcwyBAeek2sKo+uihgaQ8v5OBWJ4KZBjyc519z8vTEe0oYFBByPBwa
19 | EE52bHVGOGNY8DJb+/fvzP/mWmfbUUkijqBcMnPjsCm1Zr0P3l6HIJs1N5faYqMR
20 | G1Gwu5DTiDEO/cXPhVCpNcttiD6p8t4WzXwvwlpXyRH0XAF1m1X4PdF3t7mH38Ru
21 | +7Hbmos69XMxWpxJB7kSJf7xmJ7t6qfXK9R97ut0rKRTQp9dUmw7pMlaeuqDL3qo
22 | kAhx+9AWkLFKAJATV0GLDsVCSyT2ywhzUI0VX2m9asG1IijZEfq/7un8exh8NKeW
23 | MQiW4du89LY5cHxKeuAFLJb5dRWzYIU2f/y4Nt44CNUxBdJUZoo678vuWUS31Dpb
24 | lIb2EfvExP/YO2RjFGJ/l5BrmCmZyV3yVyyYYKW8jHIFxfoO8B8f5zFyPE39rv2G
25 | yZIXBzcn9/QEWsBUKrU5SKKnT9czIWUYCjf2A4ARM8TZyrzx+DPq2Avwzdjdzlnw
26 | HPrPyRyVInIlz2XAxanuOTfF/7cMGOXOxcd2FyKkgLpJPP4tHEdLhJzD2ywVdON6
27 | W5h6eFff29RPx6Yuv5AF15MZDsa43ONPGodP/wTep+dQPVCQf5lqjaHy1hv2It2A
28 | n/2dfULoj7B/+0AfyvhahAQd9+pQhMqE4Ai9MxrcL1gkZRL6+SKVKcC96g4Cilvt
29 | u791PYtxsumfY9kxZ/xz+jHYHz0gpujqvDZaFI8x033zMnpacEfkmaxYGbJNMVEJ
30 | oHeaFvB+1crfsLmg5LU4sZ1asrEjd3WlWeiiu0HhGkfge1+SfJ29A1+iYjFXxfiH
31 | ssDxVZWythW+ZPGZwgzetqPkYrZDfng+4/TpBPgjMQpJPz9mItZ98PIZh9wAH0fx
32 | zmhvtztfSAEUqcc2HaK9AitzXAilvJHlmx9W2iQt8uwgtvLOhcmBcQV6E/DvypPd
33 | x+Ls+cgXN17UmpG9weA/MfYUgwwrWgzYVTUbRRtl4JUMVqE0bgdkWCQ+B48YpU70
34 | 1DLZVJ+qHpmSJNREGLi55nA/uh5e/5N+Jny/7Cxg3PfBy/HUj7Jtcfs=
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/HPACK.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {AA6EBDD2-8B46-4B23-8B16-E901AB95C8B6}
8 | Library
9 | Properties
10 | HPACK
11 | HPACK
12 | v4.5.2
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\..\..\..\..\..\..\Peach\Peach.Core.dll
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
62 |
--------------------------------------------------------------------------------
/mscer2.py:
--------------------------------------------------------------------------------
1 | '''
2 | Created on Sep 7, 2016
3 |
4 | @author: sirus
5 | '''
6 |
7 | from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
8 | import threading
9 | import xml.etree.ElementTree as ET
10 |
11 | import time
12 |
13 | class ServerThread(threading.Thread):
14 | def __init__(self, callback, handlerClass, port = 8881, address='0.0.0.0'):
15 | threading.Thread.__init__(self)
16 | self._stop = False
17 | self._port = port
18 | self._addr = address
19 | self._handlerClass = handlerClass
20 | self._handlerArgs = callback;
21 |
22 | def handler(*args):
23 | return self._handlerClass(self._handlerArgs, *args)
24 |
25 | self._httpd = HTTPServer((self._addr, self._port), handler)
26 |
27 | def shutdown(self):
28 | print "Shutting down httpd"
29 | try:
30 | self._httpd.shutdown()
31 | except:
32 | pass
33 |
34 | def run(self):
35 | print "Starting httpd"
36 | self._httpd.serve_forever()
37 |
38 |
39 |
40 |
41 | class MSCER2Handler(BaseHTTPRequestHandler):
42 |
43 | def __init__(self, callback, *args):
44 | self._callback = callback
45 | BaseHTTPRequestHandler.__init__(self, *args)
46 |
47 |
48 | def do_POST(self):
49 | self.data_string = self.rfile.read(int(self.headers['Content-Length'])).decode('utf-16').encode('utf-8')
50 | print "POST", self.path, self.data_string
51 |
52 | try:
53 |
54 | root = ET.fromstring(self.data_string)
55 |
56 | appInfo = root.find("APPLICATIONINFO")
57 | signature = root.find("SIGNATURE")
58 | eventInfo = root.find("EVENTINFO")
59 |
60 | appName = appInfo.attrib['appname']
61 | appPath = appInfo.attrib['apppath']
62 | eventType = eventInfo.attrib['eventtype']
63 |
64 | params = {}
65 | for param in signature.findall('PARAMETER'):
66 | params[param.attrib['name']] = param.attrib['value']
67 |
68 |
69 | print appName, repr(params)
70 |
71 | if self._callback != None:
72 | self._callback(appName, appPath, eventType, params)
73 |
74 |
75 | except Exception as e:
76 | print "EX", e
77 |
78 |
79 | self.send_response(404)
80 | self.end_headers()
81 |
82 |
83 | def test_callback(appName, appPath, eventType, params):
84 | print "CALLBACK", "appName", appName,"appPath", appPath, "eventType", eventType, "params", params
85 |
86 | if __name__ == "__main__":
87 | server = ServerThread(test_callback, MSCER2Handler)
88 | server.daemon = True
89 | server.start()
90 |
91 | try:
92 | while True:
93 | time.sleep(1)
94 |
95 | except KeyboardInterrupt:
96 | server.shutdown()
97 |
98 |
--------------------------------------------------------------------------------
/HTTP2_State.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/TLSProxy/ca.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIJeTCCBWGgAwIBAgIJAIVo/ARTcMe7MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV
3 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
4 | aWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMMA21hYzAeFw0xNjA4MjYwMDA0MjNaFw0y
5 | NjA4MjQwMDA0MjNaMFMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRl
6 | MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDDAKBgNVBAMMA21h
7 | YzCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAKtHM+M1u0zkrA56wnX2
8 | DeI6yQoKFY0mT2XGEGduq6ndolBZzOn0aOtAGyyewquNg17ndYVPHz7lDBvs9ME8
9 | 6xhiyzsCDIn9DOzRxTWHnGrWl1ljXi5GPrpHweNrvZm506LND4nvvsLkAvYVTYUh
10 | BjhqX6/m2tjYZYVEECTrWC1zsfCEaPTobws3cLPCZ8NLdFSPwaFNwpC3w45isKKG
11 | 6ZVn1MhZYqQjh0nkeERlWk1TqrZRpWKzthLp5eb0E9EPsb21KeNfG1ptgSPmtxHr
12 | wpf6Yls5YQ+rOV1+/3nSTggMr3DlTeA4TDJwCGSPzJDi5+6yWBE1vTMn+jau5+bM
13 | TwtVVQgo1EfLwyRY1YRWubmMA17Pd6e4h3FoXmkPBBuGlPdE4wfn+iYNm0woYOTo
14 | 1EGojpt2I28gF6PzK5qCKeyoOy8axmsBZDoX/rFxopdT2CKY90rv/y3O8Z6A/R62
15 | niqRB8/RFmGlsRsID3vlXWOznSRCRuuP0/mt2V9ofXvg3cQjevj04k3fyd398ESo
16 | 9inmiNPKvVcBn3eb89D3SKN2vMerWa7XhNrPp2+dHF8+ksgztQsKP1kEuzdQyr9g
17 | 0iKBvKBxNY92r+JhUINBUJd612VEHFKh9ECusDOs5Wa7VRVcb9VwSBu3NOFiEdPD
18 | Jq+ICDKCNc5B+4qjVgn7FR/yo/Mpe88czRy6eP6aLH6RWe3ZaO4+umPwB1q5H2jI
19 | P3Tx2x0BRzOreCWoEa/I38IOrJdqxrWJekzq5G7VMjPZ7Ctj8tZJtJyBsVlSbmjC
20 | HTvtyY00CDGDveoMQjCcqwUDSHS6kog0xBCA/wwZ6oHY8tT1kbzrFw+iw5GwDCG5
21 | BEA4X1NoklVofMyBiOEzGfADGCbj4Fvh21SRZ05x/iVdgsImANOejDl5aSsYpJ0Z
22 | 3XNi9mNMbQVkta/dtGy1p3ccLVnPiMDDU9FdhCAmC0AaBZS6sGWhdbGNMfDRzJkn
23 | 7QXEbYIq37veKo5lP9xG2Jumt/nubYSltUQb/Gh/rbRYFz/rR40XKJ7/jbJj+Z1c
24 | Ew/bkkbMIACvgKnMUYCpk/QtV/m7uLPHSFRknSBXIEfkucsNQlXkrVQfkUINvmIF
25 | JqPT2XPK+No/DBCea93a0h9LUScRvXJfjlSmo7nbAOudpagG60er1mzaozhldSlN
26 | hVrYHtkj+JHBW1OhuaO8+4TXjylQkJC4beatd68uWdR3MW9KPE7Ga+l6+ynbM4BT
27 | 061/g4078DKxtjaxm33tpVbXGXr7qeZXiyjOhBHNZlNObGNr4kdfRi2Aqv6fpyXB
28 | syEfj0rhhYZbaGrMxv9NxIa2M4G8QbjyIbL0J5jw/9eiiyVrY4w/B05f5NQIUSyu
29 | ZZECAwEAAaNQME4wHQYDVR0OBBYEFGri111zDT/gr7oemBL0vdPe8V4SMB8GA1Ud
30 | IwQYMBaAFGri111zDT/gr7oemBL0vdPe8V4SMAwGA1UdEwQFMAMBAf8wDQYJKoZI
31 | hvcNAQELBQADggQBAIVguqv00QDQEJhMnL0uaj3aKlkMR334j3r/1BmVmo08z34S
32 | 1YtcnG2szAKT3M6AmtIN7PZQ9mIAFxDmGBdskRGaYuoyNyGFTj8TkWZDZaSXVfRl
33 | SC1cO9phOzaEUZX6nXnc8Bvig1z8AumYyqmlDzVNCNVIt/QgVTKAXiNOBZ9RZNc0
34 | 8kxVH3c6VVz4/FvYF8X6d/Q0kti5sx0IeUi6MzdcHA1+1rOQzi2+/fJEN3mvu8Ie
35 | dmWYtgVvD1eSESTofJgzNwf8REw2lApkf8kDh63usV/aWHNlyI9UF9ff9XBQYYf0
36 | E2J9b9Z39s9nM4p7Djyk246hd3byIGbXkZukjn5YpDwUwDa4Ox0P4tVU+hTdGbGJ
37 | 1L5m96pGFyR57GhyUdOVXEHi4w3n18/aCbgJUlxK1INg4Tn3Bn/OTc6Q97BbHiSV
38 | LGXtGN7OfhVYxPI9ZDuzE3p/DnvR7Kq2ZfIm2PEETug7oKqLljyL1uVqlV/SQfxj
39 | SGFwqD45oQNkQLXzHdFc9PU6ijAYQ93Bx6GU35sthD+nfoRJeHZMpNeOYBulT299
40 | JISq5qkse/WQ01prGneEk8mycmAEuPk7PcjNFSh5U+aIWoRErWzAULn1IWV7VIGi
41 | WoDtJXZwIlrozyqu1ZTkxb/PVLE1fW0BJWQvocj3dYeDZSrPC8yvJLdQ0D8FI3gk
42 | FjUbihiJGieygId2GPPYngd0i1nSiRsJubrShZC/LrReD1gg+l4PKCsNKGtznXK8
43 | DPZIhaovaqHUc/m8d5MhwwXkK/OViUCI2G0goF6hjz4lbOw5F8h9WvoO9dNMKCZ5
44 | LKxcjdRR5b7mZ23UOLPZ98VmnDUantsozlXxBaGN3aRd5URJdBhTX2YfA3n14QWU
45 | LAbkdx3i9/KUhFtoe28Bwbm/ap8feB42cpV46o63FW7XB3rjRxPDoQr/gNWp0gIA
46 | KOi9BDGiS/kX05xfIBGisiUBbEfbZcg5qkliLLITO1yCWGrZHbcbPf+q3qSkWp9D
47 | SJ+3D4lXI7TVrQdi/wyaodP06v6bnWx9NXBqG811h1P70Qkh6/V4c3kcpB2Qy/TZ
48 | VXX9lOTVmA4rscpsPPN46YF9tWI4HevYpnBkFkrWUhqwT14VShFotpD5h68ZJqdE
49 | QmtI2l9P8LNa7N5btGO2DLlCleNMBMuaY4FktxGOHvGL5TGb6vt49GbISIDQoXWw
50 | pGpxHbNK9d0UpJLivM1eFsbr5LlAy2aPK+ir1ssId67EldHPMs58c/XiSlbrAJiz
51 | FdRxM8YsvF9LnX9/vkTprhLxJVcozDzfUGsbBvORUDcRNZIeWoW6kmNe6cHcnN8F
52 | mhQuPvXgMwlFiTilnIlCsgUUgn60X0Nf6HAlviA=
53 | -----END CERTIFICATE-----
54 |
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/HuffmanEncoder.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Twitter, Inc
3 | * This file is a derivative work modified by Ringo Leese
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | using System;
18 | using System.IO;
19 |
20 | namespace HPACK
21 | {
22 | public class HuffmanEncoder
23 | {
24 | private int[] codes;
25 | private byte[] lengths;
26 |
27 | ///
28 | /// Creates a new Huffman encoder with the specified Huffman coding.
29 | ///
30 | /// the Huffman codes indexed by symbol
31 | /// the length of each Huffman code
32 | public HuffmanEncoder(int[] codes, byte[] lengths)
33 | {
34 | this.codes = codes;
35 | this.lengths = lengths;
36 | }
37 |
38 | ///
39 | /// Compresses the input string literal using the Huffman coding.
40 | ///
41 | /// the output stream for the compressed data
42 | /// the string literal to be Huffman encoded
43 | /// if an I/O error occurs.
44 | ///
45 | public void Encode(BinaryWriter output, byte[] data)
46 | {
47 | this.Encode(output, data, 0, data.Length);
48 | }
49 |
50 | ///
51 | /// Compresses the input string literal using the Huffman coding.
52 | ///
53 | /// the output stream for the compressed data
54 | /// the string literal to be Huffman encoded
55 | /// the start offset in the data
56 | /// the number of bytes to encode
57 | /// if an I/O error occurs. In particular, an IOException may be thrown if the output stream has been closed.
58 | public void Encode(BinaryWriter output, byte[] data, int off, int len)
59 | {
60 | if (output == null)
61 | {
62 | throw new NullReferenceException("out");
63 | }
64 | else if (data == null)
65 | {
66 | throw new NullReferenceException("data");
67 | }
68 | else if (off < 0 || len < 0 || (off + len) < 0 || off > data.Length || (off + len) > data.Length)
69 | {
70 | throw new IndexOutOfRangeException();
71 | }
72 | else if (len == 0)
73 | {
74 | return;
75 | }
76 |
77 | var current = 0L;
78 | var n = 0;
79 |
80 | for (var i = 0; i < len; i++)
81 | {
82 | var b = data[off + i] & 0xFF;
83 | var code = (uint)this.codes[b];
84 | var nbits = (int)lengths[b];
85 |
86 | current <<= nbits;
87 | current |= code;
88 | n += nbits;
89 |
90 | while (n >= 8)
91 | {
92 | n -= 8;
93 | output.Write(((byte)(current >> n)));
94 | }
95 | }
96 |
97 | if (n > 0)
98 | {
99 | current <<= (8 - n);
100 | current |= (uint)(0xFF >> n); // this should be EOS symbol
101 | output.Write((byte)current);
102 | }
103 | }
104 |
105 | ///
106 | /// Returns the number of bytes required to Huffman encode the input string literal.
107 | ///
108 | /// the number of bytes required to Huffman encode data
109 | /// the string literal to be Huffman encoded
110 | public int GetEncodedLength(byte[] data)
111 | {
112 | if (data == null)
113 | {
114 | throw new NullReferenceException("data");
115 | }
116 | var len = 0L;
117 | foreach (var b in data)
118 | {
119 | len += lengths[b & 0xFF];
120 | }
121 | return (int)((len + 7) >> 3);
122 | }
123 | }
124 | }
--------------------------------------------------------------------------------
/mscer2monitor.py:
--------------------------------------------------------------------------------
1 |
2 | import clr, clrtype
3 |
4 | clr.AddReference("Peach.Core")
5 | clr.AddReference("Peach.Pro")
6 |
7 | import System
8 | import Peach.Core
9 | from Peach.Core import Variant
10 | from Peach.Core.Agent import IterationStartingArgs, MonitorData
11 | from Peach.Core.Agent.MonitorData import Info
12 | from Peach.Pro.Core.Agent.Monitors import BasePythonMonitor
13 |
14 | import mscer2
15 | import time
16 |
17 |
18 | # Create wrappers for class attributes we will use
19 | MonitorAttr = clrtype.attribute(Peach.Core.Agent.MonitorAttribute)
20 | DescriptionAttr = clrtype.attribute(System.ComponentModel.DescriptionAttribute)
21 | ParameterAttr = clrtype.attribute(Peach.Core.ParameterAttribute)
22 |
23 | class MSCER2Monitor(BasePythonMonitor):
24 |
25 | __metaclass__ = clrtype.ClrClass
26 | _clrnamespace = "PythonExamples"
27 |
28 | _clrclassattribs = [
29 | MonitorAttr("MSCER2Monitor"),
30 | DescriptionAttr("MSCER2 Monitor"),
31 | ]
32 |
33 | @clrtype.accepts(clr.GetClrType(str))
34 | @clrtype.returns()
35 | def __init__(self, name):
36 | #print ">>>> MONITOR INIT %s" % name
37 | pass
38 |
39 |
40 |
41 | def cercallback(self, appName, appPath, eventType, params):
42 | #print "GOT CALLBACK", appName, appPath, eventType, params
43 |
44 | with open("appNames.txt", "a") as fd:
45 | fd.write(appName + "," + appPath + "\r\n")
46 |
47 | for trigger in self._triggers:
48 | if trigger.lower() in appPath.lower():
49 | self._faulted = True
50 | self._faultedData = (appName, eventType, params)
51 | break
52 |
53 |
54 |
55 | @clrtype.returns()
56 | @clrtype.accepts(System.Collections.Generic.Dictionary[clr.GetClrType(str), clr.GetClrType(str)])
57 | def StartMonitor(self, args):
58 | #print ">>>> START MONITOR '%s/%s' FROM PYTHON" % (self.Name, self.Class)
59 |
60 | self._faulted = False
61 | self._faultedData = None
62 | self._triggers = []
63 | port = 8881
64 | host = "127.0.0.1"
65 | for kv in args:
66 | #print ">>>> PARAM '%s' = '%s'" % (kv.Key, kv.Value)
67 | if kv.Key == 'Triggers':
68 | self._triggers = kv.Value.split(';')
69 | #print ">>>>", repr(self._triggers)
70 |
71 | if kv.Key == 'Port':
72 | port = int(kv.Value)
73 |
74 | if kv.Key == 'Host':
75 | host = kv.Value
76 |
77 |
78 |
79 | self._server = mscer2.ServerThread(self.cercallback, mscer2.MSCER2Handler, port, host)
80 | self._server.daemon = True
81 | self.count = 0
82 | pass
83 |
84 |
85 |
86 | @clrtype.accepts()
87 | @clrtype.returns()
88 | def StopMonitor(self):
89 | #print ">>>> STOP MONITOR FROM PYTHON"
90 | self._server.shutdown()
91 | pass
92 |
93 | @clrtype.accepts()
94 | @clrtype.returns()
95 | def SessionStarting (self):
96 | #print ">>>> SESSION STARTING FROM PYTHON"
97 | self._server.start()
98 | pass
99 |
100 | @clrtype.accepts()
101 | @clrtype.returns()
102 | def SessionFinished(self):
103 | #print ">>>> SESSION FINISHED FROM PYTHON"
104 | self._server.shutdown()
105 | pass
106 |
107 | @clrtype.accepts(IterationStartingArgs)
108 | @clrtype.returns()
109 | def IterationStarting(self, args):
110 | #print ">>>> ITERATION STARTING FROM PYTHON"
111 | self.isReproduction = args.IsReproduction
112 | self.lastWasFault = args.LastWasFault
113 | self.count += 1
114 | pass
115 |
116 | @clrtype.accepts()
117 | @clrtype.returns()
118 | def IterationFinished(self):
119 | #print ">>>> ITERATION FINISHED FROM PYTHON"
120 | pass
121 |
122 | @clrtype.accepts()
123 | @clrtype.returns(clr.GetClrType(bool))
124 | def DetectedFault(self):
125 | time.sleep(3)
126 | #time.sleep(0.25)
127 | fault = self._faulted
128 | #print ">>>> DETECTED FAULT: %s" % fault
129 | return fault
130 |
131 |
132 | @clrtype.accepts()
133 | @clrtype.returns(MonitorData)
134 | def GetMonitorData(self):
135 | #print ">>> GET MONITOR DATA"
136 | data = MonitorData()
137 | if self._faulted:
138 | appName, eventType, params = self._faultedData
139 | self._faultedData = None
140 | self._faulted = False
141 | print "name", appName, "evtType", eventType, "params", params
142 |
143 | ex = ''
144 | mod = ''
145 | addr = ''
146 |
147 | if 'Exception Code' in params.keys():
148 | ex = params['Exception Code']
149 | if 'Fault Module Name' in params.keys():
150 | mod = params['Fault Module Name']
151 | if 'Exception Offset' in params.keys():
152 | addr = params['Exception Offset']
153 |
154 |
155 | data.Title = "%s %s in %s!%s" % (eventType, ex, appName, mod)
156 | data.Fault = MonitorData.Info()
157 | data.Fault.Description = "im: %s ex: %s mod: %s addr: %s\r\n\r\n%s" % (appName, ex, mod, addr, repr(params))
158 | data.Fault.MajorHash = self.Hash(appName + eventType)
159 | data.Fault.MinorHash = self.Hash(ex + mod + addr)
160 | data.Fault.Risk = "UNKNOWN"
161 | data.Fault.MustStop = False
162 | return data
163 |
164 | @clrtype.accepts(clr.GetClrType(str))
165 | @clrtype.returns()
166 | def Message(self, name):
167 | #print ">>>> MESSAGE '%s' FROM PYTHON" % name
168 | pass
169 |
170 | # end
171 |
172 |
173 |
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/HPACKInteger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Peach.Core;
8 | using Peach.Core.Analyzers;
9 | using Peach.Core.Dom;
10 | using Peach.Core.IO;
11 |
12 | using ValueType = Peach.Core.Dom.ValueType;
13 | using Peach.Core.Cracker;
14 | using System.IO;
15 | using System.Xml;
16 |
17 | namespace HPACK
18 | {
19 |
20 | [DataElement("HPACKInteger", DataElementTypes.NonDataElements)]
21 | [PitParsable("HPACKInteger")]
22 | [Parameter("name", typeof(string), "Element name", "")]
23 | [Parameter("length", typeof(uint?), "Length in data element", "")]
24 | [Parameter("lengthType", typeof(LengthType), "Units of the length attribute", "bytes")]
25 | [Parameter("value", typeof(int), "Default value", "0")]
26 | [Parameter("valueType", typeof(ValueType), "Format of value attribute", "string")]
27 | [Parameter("mutable", typeof(bool), "Is element mutable", "true")]
28 | [Parameter("constraint", typeof(string), "Scripting expression that evaluates to true or false", "")]
29 | [Parameter("minOccurs", typeof(int), "Minimum occurances", "1")]
30 | [Parameter("maxOccurs", typeof(int), "Maximum occurances", "1")]
31 | [Parameter("occurs", typeof(int), "Actual occurances", "1")]
32 | [Parameter("prefixBits", typeof(int), "Number of HPACK prefix bits.", "1")]
33 | [Serializable]
34 | public class HPACKInteger : Number
35 | {
36 | public int prefixBits { get; set; }
37 |
38 |
39 | public HPACKInteger()
40 | {
41 | lengthType = LengthType.Bits;
42 | length = 64;
43 | Signed = false;
44 | LittleEndian = true;
45 | DefaultValue = new Variant(0);
46 |
47 | }
48 | public HPACKInteger(string name)
49 | : base(name)
50 | {
51 | lengthType = LengthType.Bits;
52 | length = 64;
53 | Signed = false;
54 | LittleEndian = true;
55 | DefaultValue = new Variant(0);
56 | }
57 |
58 |
59 | public static new DataElement PitParser(PitParser context, XmlNode node, DataElementContainer parent)
60 | {
61 | var ret = Generate(node, parent);
62 |
63 |
64 | ret.prefixBits = node.getAttrInt("prefixBits");
65 |
66 | context.handleCommonDataElementAttributes(node, ret);
67 | context.handleCommonDataElementChildren(node, ret);
68 | context.handleCommonDataElementValue(node, ret);
69 |
70 | return ret;
71 | }
72 |
73 | public override bool hasLength { get { return false; } }
74 | public override bool isDeterministic { get { return true; } }
75 |
76 | protected override Variant GetDefaultValue(BitStream data, long? size)
77 | {
78 |
79 | int val = 0;
80 |
81 | int max_number = (1 << prefixBits) - 1;
82 | int mask = 0xFF >> (8 - prefixBits);
83 |
84 | int index = 0;
85 | ulong uread = 0;
86 | if (data.ReadBits(out uread, prefixBits) != prefixBits)
87 | throw new SoftException("Out of bits.");
88 |
89 | int read = (int)(uread);
90 |
91 | val = read & mask;
92 | if (val == max_number)
93 | {
94 | for (;;)
95 | {
96 | index++;
97 | int next = data.ReadByte();
98 | if (read == -1)
99 | throw new SoftException("Out of bytes");
100 |
101 | if (next >= 128)
102 | val += (next - 128) * ((int)Math.Pow(128, index - 1));
103 | else
104 | {
105 | val += next * ((int)Math.Pow(128, index - 1));
106 | break;
107 | }
108 | }
109 | }
110 |
111 | return new Variant(val);
112 | }
113 |
114 | protected override BitwiseStream InternalValueToBitStream()
115 | {
116 |
117 | var val = (ulong)InternalValue;
118 | var ret = new BitStream();
119 |
120 | ulong max_number = (ulong)((1 << prefixBits) - 1);
121 |
122 | if (val < max_number)
123 | {
124 | ret.WriteByte((byte)val);
125 | }
126 | else
127 | {
128 | ret.WriteByte((byte)max_number);
129 |
130 | val -= max_number;
131 |
132 | while (val >= 128)
133 | {
134 | ret.WriteByte((byte)((val % 128) + 128));
135 | val /= 128;
136 | }
137 | ret.WriteByte((byte)val);
138 | }
139 |
140 | ret.SeekBits(8 - prefixBits, SeekOrigin.Begin);
141 |
142 | var ret2 = new BitStream();
143 | ret.CopyTo(ret2);
144 | ret2.Seek(0, SeekOrigin.Begin);
145 | return ret2;
146 | }
147 |
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/HTTP2_Client.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # HTTP/2 Peach Pit for Microsoft Edge
3 |
4 | :fire: To make use of this Peach pit you must have a commercial copy of the [Peach Fuzzer](https://peachfuzzer.com). :fire:
5 |
6 | Here at [Duo Labs](https://duo.com/labs) we believe that open sourcing security research tools helps the the greater research community push technology forward. If you find this release useful please consider joining us in sharing your tools which are typically considered proprietary with the public in the spirit of bettering security for everyone.
7 |
8 | This peach pit implements the HTTP/2 protocol ([RFC-7540](https://tools.ietf.org/html/rfc7540)) and is targetted at Microsoft Edge. It was developed as part of a Duo Labs research project and has been run through about 150,000 iterations. Traffic samples within this release were generated with the use of the [h2o](https://github.com/h2o/h2o) server. With a little bit of work and understanding of the protocol, it should be retargetable to Firefox/Chrome.
9 |
10 | -- [@sirus](https://twitter.com/sirus)
11 |
12 | ## Details
13 |
14 |
15 | #### HPACK_src/**
16 | Contains C# code implementing the ```HPACKInteger``` packed integer type and the ```HuffmanTransformer``` string transformer as laid out in [RFC-7541](https://tools.ietf.org/html/rfc7541).
17 |
18 | #### TLSProxy/**
19 | As Peach currently does not support setting ALPNs on the ```SSlListener``` a pass through proxy was implemented. It must be run alongside the main Peach.exe instance. Also contains CA cert that must be installed on the target.
20 |
21 | #### Data/**
22 | Contains binary samples to feed Peach. Exercises PUSH_PROMISE and related functionality.
23 |
24 |
25 | #### HTTP2_Data.xml
26 | Contains all the data models in the HTTP/2 protocol.
27 |
28 | #### HTTP2_State.xml
29 | Contains Peach state model for driving testing of Edge.
30 |
31 | #### HTTP2_Client.xml
32 | Contains agent configurations and the fuzzer run configuration. Defaults to using MSCER-2 monitoring but direct ```WindowsDebugger``` monitors are available.
33 |
34 | #### mscer2*.py
35 | As Edge launches five separate processes per fuzzing iteration attaching to all of them takes a significant amount of time. As an alternative I've implemented a [MSCER-2](https://msdn.microsoft.com/en-us/library/dd942170.aspx) monitor. MSCER-2 is the Windows Error Reporting protocol. Details on how to leverage this can be found [here](https://duo.com/blog/remote-fuzzer-monitoring-with-windows-error-reporting-wer).
36 |
37 | ## Fuzzer Configuration
38 | In this section SUT (system under test) will refer to a Windows 10 host that is to be running Edge with an IP of ```10.23.1.74```. Host will refer to the system running Peach.exe with the IP of ```10.23.1.53```.
39 |
40 | ### SUT Preparation
41 |
42 | #### Install CA Cert
43 | Using the windows certificate manager install the ```TLSProxy/ca.crt``` in to the trusted CA cert store.
44 |
45 | #### Hostname Configuration
46 | An entry pointing at the Host machine must be made in ```C:\windows\system32\drivers\etc\hosts``` under the name ```TARGET``` to for TLS to work:
47 | ```
48 | 10.23.1.53 TARGET
49 | ```
50 |
51 | #### PageHeap Configuration
52 | The easiest way to configure page heap is by utilizing the [EdgeDbg](https://github.com/SkyLined/EdgeDbg) package by Skylined and running ```EdgePageHeap.cmd ON``` otherwise manually configure through ``gflags.exe`` for the following five images:
53 | * microsoftedge.exe
54 | * microsoftedgecp.exe
55 | * runtimebroker.exe
56 | * browser_broker.exe
57 | * applicationframehost.exe
58 |
59 | #### MS-CER2 Collection
60 |
61 | To use the native crash collection facilities of Windows the following registry key must be imported:
62 |
63 | ```
64 | Windows Registry Editor Version 5.00
65 |
66 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting]
67 | "CorporateWerPortNumber"=dword:000022b1
68 | "CorporateWerServer"="TARGET"
69 | "Disabled"=dword:00000000
70 | "EnableZip"=dword:00000001
71 | "DisableQueue"=dword:00000001
72 |
73 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Consent]
74 | "DefaultConsent"=dword:00000004
75 | ```
76 |
77 | #### Start Peach Agent
78 | Launch the PeachAgent.exe binary from an elevated command prompt and configure firewall settings to allow incoming connections from your Host machine.
79 |
80 | ### Host Preparation
81 |
82 | #### Configure Pit
83 | Edit ```HTTP2_Client.xml``` and change the IP address of the remote agent to point to your SUT:
84 | ```
85 |
86 | ```
87 | Further down, configure the interface that for the MS-CER2 monitor to bind to:
88 | ```
89 |
90 | ```
91 |
92 |
93 |
94 | ## Start Fuzzing
95 |
96 | #### Run TLSProxy
97 | Start the TLS unwrapping proxy by executing:
98 | ```
99 | python2 TLSProxy/h2unwrap.py
100 | ```
101 | You will be able to monitor the traffic going to and from the SUT.
102 |
103 | #### Test Peach
104 | You should be good to go! Run a validation pass to make sure all the plumbing is working with:
105 |
106 | ```
107 | mono Peach.exe --plugins=. -1 HTTP2_Client.xml
108 | ```
109 | You should see Edge start, a page load and then edge close.
110 |
111 | #### Start Fuzzing
112 | If all goes well you should be ready to start fuzzing by dropping the ```-1``` argument:
113 |
114 | ```
115 | mono Peach.exe --plugins=. HTTP2_Client.xml
116 | ```
117 |
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/HuffmanDecoder.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Twitter, Inc
3 | * This file is a derivative work modified by Ringo Leese
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | using System;
18 | using System.IO;
19 |
20 | namespace HPACK
21 | {
22 | public class HuffmanDecoder
23 | {
24 | private Node root = null;
25 |
26 | ///
27 | /// Creates a new Huffman decoder with the specified Huffman coding.
28 | ///
29 | /// the Huffman codes indexed by symbol
30 | /// the length of each Huffman code
31 | public HuffmanDecoder(int[] codes, byte[] lengths)
32 | {
33 | if (codes.Length != 257 || codes.Length != lengths.Length)
34 | {
35 | throw new ArgumentException("invalid Huffman coding");
36 | }
37 | this.root = BuildTree(codes, lengths);
38 | }
39 |
40 | ///
41 | /// Decompresses the given Huffman coded string literal.
42 | ///
43 | /// the string literal to be decoded
44 | /// the output stream for the compressed data
45 | /// throws IOException if an I/O error occurs. In particular, an IOException may be thrown if the output stream has been closed.
46 | public byte[] Decode(byte[] buf)
47 | {
48 | using (var baos = new MemoryStream())
49 | {
50 | var node = this.root;
51 | var current = 0;
52 | var bits = 0;
53 | for (var i = 0; i < buf.Length; i++)
54 | {
55 | var b = buf[i] & 0xFF;
56 | current = (current << 8) | b;
57 | bits += 8;
58 | while (bits >= 8)
59 | {
60 | var c = (current >> (bits - 8)) & 0xFF;
61 | node = node.Children[c];
62 | bits -= node.Bits;
63 | if (node.IsTerminal())
64 | {
65 | if (node.Symbol == HpackUtil.HUFFMAN_EOS)
66 | {
67 | throw new IOException("EOS Decoded");
68 | }
69 | baos.Write(new byte[] { (byte)node.Symbol }, 0, 1);
70 | node = this.root;
71 | }
72 | }
73 | }
74 |
75 | while (bits > 0)
76 | {
77 | var c = (current << (8 - bits)) & 0xFF;
78 | node = node.Children[c];
79 | if (node.IsTerminal() && node.Bits <= bits)
80 | {
81 | bits -= node.Bits;
82 | baos.Write(new byte[] { (byte)node.Symbol }, 0, 1);
83 | node = this.root;
84 | }
85 | else
86 | {
87 | break;
88 | }
89 | }
90 |
91 | // Section 5.2. String Literal Representation
92 | // Padding not corresponding to the most significant bits of the code
93 | // for the EOS symbol (0xFF) MUST be treated as a decoding error.
94 | var mask = (1 << bits) - 1;
95 | if ((current & mask) != mask)
96 | {
97 | throw new IOException("Invalid Padding");
98 | }
99 |
100 | return baos.ToArray();
101 | }
102 | }
103 |
104 | public class Node
105 | {
106 | private int symbol;
107 | // terminal nodes have a symbol
108 | private int bits;
109 | // number of bits matched by the node
110 | private Node[] children;
111 | // internal nodes have children
112 |
113 | public int Symbol { get { return this.symbol; } }
114 |
115 | public int Bits { get { return this.bits; } }
116 |
117 | public Node[] Children { get { return this.children; } }
118 |
119 | ///
120 | /// Initializes a new instance of the class.
121 | ///
122 | public Node()
123 | {
124 | this.symbol = 0;
125 | this.bits = 8;
126 | this.children = new Node[256];
127 | }
128 |
129 | ///
130 | /// Initializes a new instance of the class.
131 | ///
132 | /// the symbol the node represents
133 | /// the number of bits matched by this node
134 | public Node(int symbol, int bits)
135 | {
136 | //assert(bits > 0 && bits <= 8);
137 | this.symbol = symbol;
138 | this.bits = bits;
139 | this.children = null;
140 | }
141 |
142 | public bool IsTerminal()
143 | {
144 | return (this.children == null) ? true : false;
145 | }
146 | }
147 |
148 | private static Node BuildTree(int[] codes, byte[] lengths)
149 | {
150 | var root = new Node();
151 | for (var i = 0; i < codes.Length; i++)
152 | {
153 | Insert(root, i, codes[i], lengths[i]);
154 | }
155 | return root;
156 | }
157 |
158 | private static void Insert(Node root, int symbol, int code, byte length)
159 | {
160 | // traverse tree using the most significant bytes of code
161 | var current = root;
162 | while (length > 8)
163 | {
164 | if (current.IsTerminal())
165 | {
166 | throw new InvalidDataException("invalid Huffman code: prefix not unique");
167 | }
168 | length -= 8;
169 | var i = (code >> length) & 0xFF;
170 | if (current.Children[i] == null)
171 | {
172 | current.Children[i] = new Node();
173 | }
174 | current = current.Children[i];
175 | }
176 |
177 | var terminal = new Node(symbol, length);
178 | var shift = 8 - length;
179 | var start = (code << shift) & 0xFF;
180 | var end = 1 << shift;
181 | for (var i = start; i < start + end; i++)
182 | {
183 | current.Children[i] = terminal;
184 | }
185 | }
186 | }
187 | }
--------------------------------------------------------------------------------
/TLSProxy/h2unwrap.py:
--------------------------------------------------------------------------------
1 | '''
2 | Created on Aug 24, 2016
3 |
4 | @author: sirus
5 | '''
6 |
7 | import os, socket,threading,time
8 | import SocketServer
9 | from OpenSSL import SSL
10 | import hexdump
11 | from _socket import SHUT_RDWR
12 |
13 | class SSLWrapper:
14 | """
15 | This whole class exists just to filter out a parameter
16 | passed in to the shutdown() method in SimpleXMLRPC.doPOST()
17 | """
18 | def __init__(self, conn):
19 | """
20 | Connection is not yet a new-style class,
21 | so I'm making a proxy instead of subclassing.
22 | """
23 | self.__dict__["conn"] = conn
24 |
25 | def __getattr__(self, name):
26 | return getattr(self.__dict__["conn"], name)
27 |
28 | def __setattr__(self, name, value):
29 | setattr(self.__dict__["conn"], name, value)
30 |
31 | def shutdown(self, how=1):
32 | """
33 | SimpleXMLRpcServer.doPOST calls shutdown(1),
34 | and Connection.shutdown() doesn't take
35 | an argument. So we just discard the argument.
36 | """
37 | try:
38 | self.__dict__["conn"].shutdown()
39 | except Exception as e:
40 | print "Got exception on shutdown", e
41 | pass
42 |
43 |
44 |
45 | def accept(self):
46 | """
47 |
48 | This is the other part of the shutdown() workaround.
49 | Since servers create new sockets, we have to infect
50 | them with our magic. :)
51 | """
52 | c, a = self.__dict__["conn"].accept()
53 | return (SSLWrapper(c), a)
54 |
55 |
56 | class SecureTCPServer(SocketServer.TCPServer):
57 |
58 | def __init__(self, addr, port, key, cert, request_handler_class):
59 | self._addr = addr
60 | self._port = port
61 | self._key = key
62 | self._cert = cert
63 | self._handler = request_handler_class
64 |
65 | SocketServer.BaseServer.__init__(self, (addr, port), request_handler_class)
66 |
67 | ctx = SSL.Context(SSL.SSLv23_METHOD)
68 | #ctx = SSL.Context(SSL.TLSv1_2_METHOD)
69 | ctx.set_options(SSL.OP_NO_SSLv2)
70 |
71 |
72 | ctx.use_privatekey_file(key)
73 | ctx.use_certificate_file(cert)
74 |
75 |
76 | def cb_ALPN(conn, protos):
77 | print "ALPN CALLBACK"
78 | return b'h2'
79 |
80 | ctx.set_alpn_select_callback(cb_ALPN)
81 |
82 | def cb_NPN(conn, protos):
83 | print "NPN CALLBACK"
84 | return b'h2'
85 | ctx.set_npn_select_callback(cb_NPN)
86 |
87 |
88 | #Must be .socket
89 | self.socket = SSLWrapper(SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type)))
90 | self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
91 |
92 | self.server_bind()
93 | self.server_activate()
94 |
95 |
96 | class ForwardingSecureTCPServer(SecureTCPServer):
97 |
98 | class ConnectionForwardingHandler(SocketServer.BaseRequestHandler):
99 |
100 |
101 | class Forwarder(threading.Thread):
102 | def __init__(self, source, forward_addr, forward_port, connect_on_data = False, log_data = True):
103 | threading.Thread.__init__(self)
104 | self.source = source
105 | self.dest = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
106 | self.forward_addr = forward_addr
107 | self.forward_port = forward_port
108 | self.connect_on_data = connect_on_data
109 | self.log_data = log_data
110 | self.terminate = False
111 |
112 | if log_data:
113 | self.id = str(threading.current_thread().ident)
114 | print "TID", self.id
115 | self.initer = 0
116 | self.outiter = 0
117 |
118 |
119 | self.connected = False
120 |
121 | print "initializing forwarder for (%s,%d)" % (forward_addr, forward_port)
122 |
123 | if not connect_on_data:
124 | self.dest.connect((forward_addr, forward_port))
125 | self.connected = True
126 |
127 | def run(self):
128 | print "starting forwarder... "
129 |
130 | try:
131 | while True:
132 | if not self.connected and not self.terminate:
133 | time.sleep(0.01)
134 | continue
135 |
136 | if self.terminate:
137 | break
138 |
139 | data = self.dest.recv(4096*10)
140 | if len(data) == 0:
141 | raise Exception("endpoint closed")
142 | print "Received from dest: " + str(len(data))
143 | hexdump.hexdump(data)
144 | if self.log_data:
145 | with open(self.id + "_in" + str(self.initer)+".bin", "wb") as fd:
146 | fd.write(data)
147 | self.initer = self.initer+1
148 |
149 |
150 | self.source.write_to_source(data)
151 | except Exception as e:
152 | print "EXCEPTION reading from dest", e
153 |
154 | self.source.stop_forwarding()
155 | print "...ending forwarder."
156 |
157 | def write_to_dest(self, data):
158 | print "Sending to dest: " + str(len(data))
159 | hexdump.hexdump(data)
160 | if self.log_data:
161 | with open(self.id + "_out"+str(self.outiter)+".bin", "wb") as fd:
162 | fd.write(data)
163 | self.outiter = self.outiter+1
164 |
165 | if not self.connected:
166 | self.dest.connect((self.forward_addr, self.forward_port))
167 | self.connected = True
168 |
169 | self.dest.sendall(data)
170 |
171 | def stop_forwarding(self):
172 | print "...closing forwarding socket"
173 |
174 | try:
175 | self.dest.shutdown(SHUT_RDWR)
176 | except Exception:
177 | pass
178 |
179 | self.dest.close()
180 | self.terminate = True
181 |
182 |
183 |
184 | def handle(self):
185 | print "GOT CONNECTION."
186 | f = ForwardingSecureTCPServer.ConnectionForwardingHandler.Forwarder(self, self.server.forward_addr, self.server.forward_port, True, False)
187 | f.daemon = True
188 | f.start()
189 |
190 | try:
191 | while True:
192 | data = self.request.recv(4096*10)
193 | if len(data) == 0:
194 | raise Exception("endpoint closed")
195 | print "Received from SSL: " + str(len(data))
196 | f.write_to_dest(data)
197 | except Exception as e:
198 | print "Exception reading from SSL socket.", e
199 |
200 | f.stop_forwarding()
201 |
202 | print "CONNECTION FINISHED"
203 |
204 |
205 | def write_to_source(self, data):
206 | self.request.sendall(data)
207 |
208 | def stop_forwarding(self):
209 | print "...closing SSL socket"
210 | self.request.close()
211 |
212 |
213 |
214 |
215 | def __init__(self, listen_addr, listen_port, listen_key, listen_cert, forward_addr, forward_port):
216 | SecureTCPServer.__init__(self, listen_addr, listen_port, listen_key, listen_cert, ForwardingSecureTCPServer.ConnectionForwardingHandler)
217 | self.forward_addr = forward_addr
218 | self.forward_port = forward_port
219 |
220 |
221 | if __name__ == "__main__":
222 | print "starting"
223 | ForwardingSecureTCPServer("0.0.0.0", 8182, "server.key", "server.crt", "127.0.0.1", 1234).serve_forever()
224 |
225 |
226 |
227 |
228 |
229 |
230 |
--------------------------------------------------------------------------------
/HPACK_src/HPACKInteger/HpackUtil.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Twitter, Inc
3 | * This file is a derivative work modified by Ringo Leese
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | using System;
18 | using System.Text;
19 |
20 | namespace HPACK
21 | {
22 | public class HpackUtil
23 | {
24 | ///
25 | /// A string compare that doesn't leak timing information.
26 | ///
27 | /// S1.
28 | /// S2.
29 | public static bool Equals(byte[] s1, byte[] s2)
30 | {
31 | if (s1.Length != s2.Length)
32 | {
33 | return false;
34 | }
35 | var c = 0;
36 | for (var i = 0; i < s1.Length; i++)
37 | {
38 | c |= (s1[i] ^ s2[i]);
39 | }
40 | return c == 0;
41 | }
42 |
43 | ///
44 | /// Checks that the specified object reference is not {@code null}.
45 | ///
46 | /// The non null.
47 | /// Object.
48 | public static object RequireNonNull(object obj)
49 | {
50 | if (obj == null)
51 | {
52 | throw new NullReferenceException();
53 | }
54 | return obj;
55 | }
56 |
57 | // Section 6.2. Literal Header Field Representation
58 | public enum IndexType
59 | {
60 | INCREMENTAL, // Section 6.2.1. Literal Header Field with Incremental Indexing
61 | NONE, // Section 6.2.2. Literal Header Field without Indexing
62 | NEVER // Section 6.2.3. Literal Header Field never Indexed
63 | }
64 |
65 | // Appendix B: Huffman Codes
66 | // http://tools.ietf.org/html/rfc7541#appendix-B
67 | public static int[] HUFFMAN_CODES = {
68 | 0x1ff8,
69 | 0x7fffd8,
70 | 0xfffffe2,
71 | 0xfffffe3,
72 | 0xfffffe4,
73 | 0xfffffe5,
74 | 0xfffffe6,
75 | 0xfffffe7,
76 | 0xfffffe8,
77 | 0xffffea,
78 | 0x3ffffffc,
79 | 0xfffffe9,
80 | 0xfffffea,
81 | 0x3ffffffd,
82 | 0xfffffeb,
83 | 0xfffffec,
84 | 0xfffffed,
85 | 0xfffffee,
86 | 0xfffffef,
87 | 0xffffff0,
88 | 0xffffff1,
89 | 0xffffff2,
90 | 0x3ffffffe,
91 | 0xffffff3,
92 | 0xffffff4,
93 | 0xffffff5,
94 | 0xffffff6,
95 | 0xffffff7,
96 | 0xffffff8,
97 | 0xffffff9,
98 | 0xffffffa,
99 | 0xffffffb,
100 | 0x14,
101 | 0x3f8,
102 | 0x3f9,
103 | 0xffa,
104 | 0x1ff9,
105 | 0x15,
106 | 0xf8,
107 | 0x7fa,
108 | 0x3fa,
109 | 0x3fb,
110 | 0xf9,
111 | 0x7fb,
112 | 0xfa,
113 | 0x16,
114 | 0x17,
115 | 0x18,
116 | 0x0,
117 | 0x1,
118 | 0x2,
119 | 0x19,
120 | 0x1a,
121 | 0x1b,
122 | 0x1c,
123 | 0x1d,
124 | 0x1e,
125 | 0x1f,
126 | 0x5c,
127 | 0xfb,
128 | 0x7ffc,
129 | 0x20,
130 | 0xffb,
131 | 0x3fc,
132 | 0x1ffa,
133 | 0x21,
134 | 0x5d,
135 | 0x5e,
136 | 0x5f,
137 | 0x60,
138 | 0x61,
139 | 0x62,
140 | 0x63,
141 | 0x64,
142 | 0x65,
143 | 0x66,
144 | 0x67,
145 | 0x68,
146 | 0x69,
147 | 0x6a,
148 | 0x6b,
149 | 0x6c,
150 | 0x6d,
151 | 0x6e,
152 | 0x6f,
153 | 0x70,
154 | 0x71,
155 | 0x72,
156 | 0xfc,
157 | 0x73,
158 | 0xfd,
159 | 0x1ffb,
160 | 0x7fff0,
161 | 0x1ffc,
162 | 0x3ffc,
163 | 0x22,
164 | 0x7ffd,
165 | 0x3,
166 | 0x23,
167 | 0x4,
168 | 0x24,
169 | 0x5,
170 | 0x25,
171 | 0x26,
172 | 0x27,
173 | 0x6,
174 | 0x74,
175 | 0x75,
176 | 0x28,
177 | 0x29,
178 | 0x2a,
179 | 0x7,
180 | 0x2b,
181 | 0x76,
182 | 0x2c,
183 | 0x8,
184 | 0x9,
185 | 0x2d,
186 | 0x77,
187 | 0x78,
188 | 0x79,
189 | 0x7a,
190 | 0x7b,
191 | 0x7ffe,
192 | 0x7fc,
193 | 0x3ffd,
194 | 0x1ffd,
195 | 0xffffffc,
196 | 0xfffe6,
197 | 0x3fffd2,
198 | 0xfffe7,
199 | 0xfffe8,
200 | 0x3fffd3,
201 | 0x3fffd4,
202 | 0x3fffd5,
203 | 0x7fffd9,
204 | 0x3fffd6,
205 | 0x7fffda,
206 | 0x7fffdb,
207 | 0x7fffdc,
208 | 0x7fffdd,
209 | 0x7fffde,
210 | 0xffffeb,
211 | 0x7fffdf,
212 | 0xffffec,
213 | 0xffffed,
214 | 0x3fffd7,
215 | 0x7fffe0,
216 | 0xffffee,
217 | 0x7fffe1,
218 | 0x7fffe2,
219 | 0x7fffe3,
220 | 0x7fffe4,
221 | 0x1fffdc,
222 | 0x3fffd8,
223 | 0x7fffe5,
224 | 0x3fffd9,
225 | 0x7fffe6,
226 | 0x7fffe7,
227 | 0xffffef,
228 | 0x3fffda,
229 | 0x1fffdd,
230 | 0xfffe9,
231 | 0x3fffdb,
232 | 0x3fffdc,
233 | 0x7fffe8,
234 | 0x7fffe9,
235 | 0x1fffde,
236 | 0x7fffea,
237 | 0x3fffdd,
238 | 0x3fffde,
239 | 0xfffff0,
240 | 0x1fffdf,
241 | 0x3fffdf,
242 | 0x7fffeb,
243 | 0x7fffec,
244 | 0x1fffe0,
245 | 0x1fffe1,
246 | 0x3fffe0,
247 | 0x1fffe2,
248 | 0x7fffed,
249 | 0x3fffe1,
250 | 0x7fffee,
251 | 0x7fffef,
252 | 0xfffea,
253 | 0x3fffe2,
254 | 0x3fffe3,
255 | 0x3fffe4,
256 | 0x7ffff0,
257 | 0x3fffe5,
258 | 0x3fffe6,
259 | 0x7ffff1,
260 | 0x3ffffe0,
261 | 0x3ffffe1,
262 | 0xfffeb,
263 | 0x7fff1,
264 | 0x3fffe7,
265 | 0x7ffff2,
266 | 0x3fffe8,
267 | 0x1ffffec,
268 | 0x3ffffe2,
269 | 0x3ffffe3,
270 | 0x3ffffe4,
271 | 0x7ffffde,
272 | 0x7ffffdf,
273 | 0x3ffffe5,
274 | 0xfffff1,
275 | 0x1ffffed,
276 | 0x7fff2,
277 | 0x1fffe3,
278 | 0x3ffffe6,
279 | 0x7ffffe0,
280 | 0x7ffffe1,
281 | 0x3ffffe7,
282 | 0x7ffffe2,
283 | 0xfffff2,
284 | 0x1fffe4,
285 | 0x1fffe5,
286 | 0x3ffffe8,
287 | 0x3ffffe9,
288 | 0xffffffd,
289 | 0x7ffffe3,
290 | 0x7ffffe4,
291 | 0x7ffffe5,
292 | 0xfffec,
293 | 0xfffff3,
294 | 0xfffed,
295 | 0x1fffe6,
296 | 0x3fffe9,
297 | 0x1fffe7,
298 | 0x1fffe8,
299 | 0x7ffff3,
300 | 0x3fffea,
301 | 0x3fffeb,
302 | 0x1ffffee,
303 | 0x1ffffef,
304 | 0xfffff4,
305 | 0xfffff5,
306 | 0x3ffffea,
307 | 0x7ffff4,
308 | 0x3ffffeb,
309 | 0x7ffffe6,
310 | 0x3ffffec,
311 | 0x3ffffed,
312 | 0x7ffffe7,
313 | 0x7ffffe8,
314 | 0x7ffffe9,
315 | 0x7ffffea,
316 | 0x7ffffeb,
317 | 0xffffffe,
318 | 0x7ffffec,
319 | 0x7ffffed,
320 | 0x7ffffee,
321 | 0x7ffffef,
322 | 0x7fffff0,
323 | 0x3ffffee,
324 | 0x3fffffff // EOS
325 | };
326 |
327 | public static byte[] HUFFMAN_CODE_LENGTHS = {
328 | 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
329 | 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
330 | 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
331 | 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
332 | 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
333 | 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
334 | 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
335 | 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
336 | 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
337 | 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
338 | 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
339 | 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
340 | 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
341 | 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
342 | 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
343 | 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
344 | 30 // EOS
345 | };
346 |
347 | public static int HUFFMAN_EOS = 256;
348 |
349 | private HpackUtil()
350 | {
351 | // utility class
352 | }
353 | }
354 | }
--------------------------------------------------------------------------------
/HTTP2_Data.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
--------------------------------------------------------------------------------
/clrtype.py:
--------------------------------------------------------------------------------
1 | #####################################################################################
2 | #
3 | # Copyright (c) Microsoft Corporation. All rights reserved.
4 | #
5 | # This source code is subject to terms and conditions of the Microsoft Public License. A
6 | # copy of the license can be found in the License.html file at the root of this distribution. If
7 | # you cannot locate the Microsoft Public License, please send an email to
8 | # ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 | # by the terms of the Microsoft Public License.
10 | #
11 | # You must not remove this notice, or any other, from this software.
12 | #
13 | #
14 | #####################################################################################
15 |
16 | __all__ = ["ClrClass", "ClrInterface", "accepts", "returns", "attribute", "propagate_attributes"]
17 |
18 | import clr
19 | clr.AddReference("Microsoft.Dynamic")
20 | clr.AddReference("Microsoft.Scripting")
21 | clr.AddReference("IronPython")
22 | import System
23 | from System import Char, Void, Boolean, Array, Type, AppDomain
24 | from System.Reflection import FieldAttributes, MethodAttributes, PropertyAttributes, ParameterAttributes
25 | from System.Reflection import CallingConventions, TypeAttributes, AssemblyName
26 | from System.Reflection.Emit import OpCodes, CustomAttributeBuilder, AssemblyBuilderAccess
27 | from System.Runtime.InteropServices import DllImportAttribute, CallingConvention, CharSet
28 | from Microsoft.Scripting.Generation import Snippets
29 | from Microsoft.Scripting.Runtime import DynamicOperations
30 | from IronPython.Runtime import NameType, PythonContext
31 | from IronPython.Runtime.Types import PythonType, ReflectedField, ReflectedProperty
32 |
33 | def validate_clr_types(signature_types, var_signature = False):
34 | if not isinstance(signature_types, tuple):
35 | signature_types = (signature_types,)
36 | for t in signature_types:
37 | if type(t) is type(System.IComparable): # type overloaded on generic arity, eg IComparable and IComparable[T]
38 | t = t[()] # select non-generic version
39 | clr_type = clr.GetClrType(t)
40 | if t == Void:
41 | raise TypeError("Void cannot be used in signature")
42 | is_typed = clr.GetPythonType(clr_type) == t
43 | # is_typed needs to be weakened until the generated type
44 | # gets explicitly published as the underlying CLR type
45 | is_typed = is_typed or (hasattr(t, "__metaclass__") and t.__metaclass__ in [ClrInterface, ClrClass])
46 | if not is_typed:
47 | raise Exception, "Invalid CLR type %s" % str(t)
48 | if not var_signature:
49 | if clr_type.IsByRef:
50 | raise TypeError("Byref can only be used as arguments and locals")
51 | # ArgIterator is not present in Silverlight
52 | if hasattr(System, "ArgIterator") and t == System.ArgIterator:
53 | raise TypeError("Stack-referencing types can only be used as arguments and locals")
54 |
55 | class TypedFunction(object):
56 | """
57 | A strongly-typed function can get wrapped up as a staticmethod, a property, etc.
58 | This class represents the raw function, but with the type information
59 | it is decorated with.
60 | Other information is stored as attributes on the function. See propagate_attributes
61 | """
62 | def __init__(self, function, is_static = False, prop_name_if_prop_get = None, prop_name_if_prop_set = None):
63 | self.function = function
64 | self.is_static = is_static
65 | self.prop_name_if_prop_get = prop_name_if_prop_get
66 | self.prop_name_if_prop_set = prop_name_if_prop_set
67 |
68 | class ClrType(type):
69 | """
70 | Base metaclass for creating strongly-typed CLR types
71 | """
72 |
73 | def is_typed_method(self, function):
74 | if hasattr(function, "arg_types") != hasattr(function, "return_type"):
75 | raise TypeError("One of @accepts and @returns is missing for %s" % function.func_name)
76 |
77 | return hasattr(function, "arg_types")
78 |
79 | def get_typed_properties(self):
80 | for item_name, item in self.__dict__.items():
81 | if isinstance(item, property):
82 | if item.fget:
83 | if not self.is_typed_method(item.fget): continue
84 | prop_type = item.fget.return_type
85 | else:
86 | if not self.is_typed_method(item.fset): continue
87 | prop_type = item.fset.arg_types[0]
88 | validate_clr_types(prop_type)
89 | clr_prop_type = clr.GetClrType(prop_type)
90 | yield item, item_name, clr_prop_type
91 |
92 | def emit_properties(self, typebld):
93 | for prop, prop_name, clr_prop_type in self.get_typed_properties():
94 | self.emit_property(typebld, prop, prop_name, clr_prop_type)
95 |
96 | def emit_property(self, typebld, prop, name, clrtype):
97 | prpbld = typebld.DefineProperty(name, PropertyAttributes.None, clrtype, None)
98 | if prop.fget:
99 | getter = self.emitted_methods[(prop.fget.func_name, prop.fget.arg_types)]
100 | prpbld.SetGetMethod(getter)
101 | if prop.fset:
102 | setter = self.emitted_methods[(prop.fset.func_name, prop.fset.arg_types)]
103 | prpbld.SetSetMethod(setter)
104 |
105 | def dummy_function(self): raise RuntimeError("this should not get called")
106 |
107 | def get_typed_methods(self):
108 | """
109 | Get all the methods with @accepts (and @returns) decorators
110 | Functions are assumed to be instance methods, unless decorated with @staticmethod
111 | """
112 |
113 | # We avoid using the "types" library as it is not a builtin
114 | FunctionType = type(ClrType.__dict__["dummy_function"])
115 |
116 | for item_name, item in self.__dict__.items():
117 | function = None
118 | is_static = False
119 | if isinstance(item, FunctionType):
120 | function, is_static = item, False
121 | elif isinstance(item, staticmethod):
122 | function, is_static = getattr(self, item_name), True
123 | elif isinstance(item, property):
124 | if item.fget and self.is_typed_method(item.fget):
125 | if item.fget.func_name == item_name:
126 | # The property hides the getter. So yield the getter
127 | yield TypedFunction(item.fget, False, item_name, None)
128 | if item.fset and self.is_typed_method(item.fset):
129 | if item.fset.func_name == item_name:
130 | # The property hides the setter. So yield the setter
131 | yield TypedFunction(item.fset, False, None, item_name)
132 | continue
133 | else:
134 | continue
135 | if self.is_typed_method(function):
136 | yield TypedFunction(function, is_static)
137 |
138 | def emit_methods(self, typebld):
139 | # We need to track the generated methods so that we can emit properties
140 | # referring these methods.
141 | # Also, the hash is indexed by name *and signature*. Even though Python does
142 | # not have method overloading, property getter and setter functions can have
143 | # the same func_name attribute
144 | self.emitted_methods = {}
145 | for function_info in self.get_typed_methods():
146 | method_builder = self.emit_method(typebld, function_info)
147 | function = function_info.function
148 | if self.emitted_methods.has_key((function.func_name, function.arg_types)):
149 | raise TypeError("methods with clashing names")
150 | self.emitted_methods[(function.func_name, function.arg_types)] = method_builder
151 |
152 | def emit_classattribs(self, typebld):
153 | if hasattr(self, '_clrclassattribs'):
154 | for attrib_info in self._clrclassattribs:
155 | if isinstance(attrib_info, type):
156 | ci = clr.GetClrType(attrib_info).GetConstructor(())
157 | cab = CustomAttributeBuilder(ci, ())
158 | elif isinstance(attrib_info, CustomAttributeDecorator):
159 | cab = attrib_info.GetBuilder()
160 | else:
161 | make_decorator = attrib_info()
162 | cab = make_decorator.GetBuilder()
163 | typebld.SetCustomAttribute(cab)
164 |
165 | def get_clr_type_name(self):
166 | if hasattr(self, "_clrnamespace"):
167 | return self._clrnamespace + "." + self.__name__
168 | else:
169 | return self.__name__
170 |
171 | def create_type(self, typebld):
172 | self.emit_members(typebld)
173 | new_type = typebld.CreateType()
174 | self.map_members(new_type)
175 | return new_type
176 |
177 | class ClrInterface(ClrType):
178 | """
179 | Set __metaclass__ in a Python class declaration to declare a
180 | CLR interface type.
181 | You need to specify object as the base-type if you do not specify any other
182 | interfaces as the base interfaces
183 | """
184 |
185 | def __init__(self, *args):
186 | return super(ClrInterface, self).__init__(*args)
187 |
188 | def emit_method(self, typebld, function_info):
189 | assert(not function_info.is_static)
190 | function = function_info.function
191 | attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Abstract
192 | method_builder = typebld.DefineMethod(
193 | function.func_name,
194 | attributes,
195 | function.return_type,
196 | function.arg_types)
197 |
198 | instance_offset = 0 if function_info.is_static else 1
199 | arg_names = function.func_code.co_varnames
200 | for i in xrange(len(function.arg_types)):
201 | # TODO - set non-trivial ParameterAttributes, default value and custom attributes
202 | p = method_builder.DefineParameter(i + 1, ParameterAttributes.None, arg_names[i + instance_offset])
203 |
204 | if hasattr(function, "CustomAttributeBuilders"):
205 | for cab in function.CustomAttributeBuilders:
206 | method_builder.SetCustomAttribute(cab)
207 |
208 | return method_builder
209 |
210 | def emit_members(self, typebld):
211 | self.emit_methods(typebld)
212 | self.emit_properties(typebld)
213 | self.emit_classattribs(typebld)
214 |
215 | def map_members(self, new_type): pass
216 |
217 | interface_module_builder = None
218 |
219 | @staticmethod
220 | def define_interface(typename, bases):
221 | for b in bases:
222 | validate_clr_types(b)
223 | if not ClrInterface.interface_module_builder:
224 | name = AssemblyName("interfaces")
225 | access = AssemblyBuilderAccess.Run
226 | # Workaround for http://ironpython.codeplex.com/WorkItem/View.aspx?WorkItemId=25330
227 | for i in xrange(1000):
228 | try:
229 | ad = AppDomain.CurrentDomain
230 | assembly_builder = ad.DefineDynamicAssembly(name, access)
231 | except: pass
232 | else: break
233 | ClrInterface.interface_module_builder = assembly_builder.DefineDynamicModule("interfaces")
234 | attrs = TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract
235 | return ClrInterface.interface_module_builder.DefineType(typename, attrs, None, bases)
236 |
237 | def map_clr_type(self, clr_type):
238 | """
239 | TODO - Currently "t = clr.GetPythonType(clr.GetClrType(C)); t == C" will be False
240 | for C where C.__metaclass__ is ClrInterface, even though both t and C
241 | represent the same CLR type. This can be fixed by publishing a mapping
242 | between t and C in the IronPython runtime.
243 | """
244 | pass
245 |
246 | def __clrtype__(self):
247 | # CFoo below will use ClrInterface as its metaclass, but the user will not expect CFoo
248 | # to be an interface in this case:
249 | #
250 | # class IFoo(object):
251 | # __metaclass__ = ClrInterface
252 | # class CFoo(IFoo): pass
253 | if not "__metaclass__" in self.__dict__:
254 | return super(ClrInterface, self).__clrtype__()
255 |
256 | bases = list(self.__bases__)
257 | bases.remove(object)
258 | bases = tuple(bases)
259 | if False: # Snippets currently does not support creating interfaces
260 | typegen = Snippets.Shared.DefineType(self.get_clr_type_name(), bases, True, False)
261 | typebld = typegen.TypeBuilder
262 | else:
263 | typebld = ClrInterface.define_interface(self.get_clr_type_name(), bases)
264 | clr_type = self.create_type(typebld)
265 | self.map_clr_type(clr_type)
266 | return clr_type
267 |
268 | # Note that ClrClass inherits from ClrInterface to satisfy Python requirements of metaclasses.
269 | # A metaclass of a subtype has to be subtype of the metaclass of a base type. As a result,
270 | # if you define a type hierarchy as shown below, it requires ClrClass to be a subtype
271 | # of ClrInterface:
272 | #
273 | # class IFoo(object):
274 | # __metaclass__ = ClrInterface
275 | # class CFoo(IFoo):
276 | # __metaclass__ = ClrClass
277 | class ClrClass(ClrInterface):
278 | """
279 | Set __metaclass__ in a Python class declaration to specify strong-type
280 | information for the class or its attributes. The Python class
281 | retains its Python attributes, like being able to add or remove methods.
282 | """
283 |
284 | # Holds the FieldInfo for a static CLR field which points to a
285 | # Microsoft.Scripting.Runtime.DynamicOperations corresponding to the current ScriptEngine
286 | dynamic_operations_field = None
287 |
288 | def emit_fields(self, typebld):
289 | if hasattr(self, "_clrfields"):
290 | for fldname in self._clrfields:
291 | field_type = self._clrfields[fldname]
292 | validate_clr_types(field_type)
293 | typebld.DefineField(
294 | fldname,
295 | clr.GetClrType(field_type),
296 | FieldAttributes.Public)
297 |
298 | def map_fields(self, new_type):
299 | if hasattr(self, "_clrfields"):
300 | for fldname in self._clrfields:
301 | fldinfo = new_type.GetField(fldname)
302 | setattr(self, fldname, ReflectedField(fldinfo))
303 |
304 | @staticmethod
305 | def get_dynamic_operations_field():
306 | if ClrClass.dynamic_operations_field:
307 | return ClrClass.dynamic_operations_field
308 | python_context = clr.GetCurrentRuntime().GetLanguage(PythonContext)
309 | dynamic_operations = DynamicOperations(python_context)
310 |
311 | typegen = Snippets.Shared.DefineType(
312 | "DynamicOperationsHolder" + str(hash(python_context)),
313 | object,
314 | True,
315 | False)
316 | typebld = typegen.TypeBuilder
317 | typebld.DefineField(
318 | "DynamicOperations",
319 | DynamicOperations,
320 | FieldAttributes.Public | FieldAttributes.Static)
321 | new_type = typebld.CreateType()
322 | ClrClass.dynamic_operations_field = new_type.GetField("DynamicOperations")
323 |
324 | ClrClass.dynamic_operations_field.SetValue(None, dynamic_operations)
325 |
326 | return ClrClass.dynamic_operations_field
327 |
328 | def emit_typed_stub_to_python_method(self, typebld, function_info):
329 | function = function_info.function
330 | """
331 | Generate a stub method that repushes all the arguments and
332 | dispatches to DynamicOperations.InvokeMember
333 | """
334 | invoke_member = clr.GetClrType(DynamicOperations).GetMethod(
335 | "InvokeMember",
336 | Array[Type]((object, str, Array[object])))
337 |
338 | # Type.GetMethod raises an AmbiguousMatchException if there is a generic and a non-generic method
339 | # (like DynamicOperations.GetMember) with the same name and signature. So we have to do things
340 | # the hard way
341 | get_member_search = [m for m in clr.GetClrType(DynamicOperations).GetMethods() if m.Name == "GetMember" and not m.IsGenericMethod and m.GetParameters().Length == 2]
342 | assert(len(get_member_search) == 1)
343 | get_member = get_member_search[0]
344 |
345 | set_member_search = [m for m in clr.GetClrType(DynamicOperations).GetMethods() if m.Name == "SetMember" and not m.IsGenericMethod and m.GetParameters().Length == 3]
346 | assert(len(set_member_search) == 1)
347 | set_member = set_member_search[0]
348 |
349 | convert_to = clr.GetClrType(DynamicOperations).GetMethod(
350 | "ConvertTo",
351 | Array[Type]((object, Type)))
352 | get_type_from_handle = clr.GetClrType(Type).GetMethod("GetTypeFromHandle")
353 |
354 | attributes = MethodAttributes.Public
355 | if function_info.is_static: attributes |= MethodAttributes.Static
356 | if function.func_name == "__new__":
357 | if function_info.is_static: raise TypeError
358 | method_builder = typebld.DefineConstructor(
359 | attributes,
360 | CallingConventions.HasThis,
361 | function.arg_types)
362 | raise NotImplementedError("Need to call self.baseType ctor passing in self.get_python_type_field()")
363 | else:
364 | method_builder = typebld.DefineMethod(
365 | function.func_name,
366 | attributes,
367 | function.return_type,
368 | function.arg_types)
369 |
370 | instance_offset = 0 if function_info.is_static else 1
371 | arg_names = function.func_code.co_varnames
372 | for i in xrange(len(function.arg_types)):
373 | # TODO - set non-trivial ParameterAttributes, default value and custom attributes
374 | p = method_builder.DefineParameter(i + 1, ParameterAttributes.None, arg_names[i + instance_offset])
375 |
376 | ilgen = method_builder.GetILGenerator()
377 |
378 | args_array = ilgen.DeclareLocal(Array[object])
379 | args_count = len(function.arg_types)
380 | ilgen.Emit(OpCodes.Ldc_I4, args_count)
381 | ilgen.Emit(OpCodes.Newarr, object)
382 | ilgen.Emit(OpCodes.Stloc, args_array)
383 | for i in xrange(args_count):
384 | arg_type = function.arg_types[i]
385 | if clr.GetClrType(arg_type).IsByRef:
386 | raise NotImplementedError("byref params not supported")
387 | ilgen.Emit(OpCodes.Ldloc, args_array)
388 | ilgen.Emit(OpCodes.Ldc_I4, i)
389 | ilgen.Emit(OpCodes.Ldarg, i + int(not function_info.is_static))
390 | ilgen.Emit(OpCodes.Box, arg_type)
391 | ilgen.Emit(OpCodes.Stelem_Ref)
392 |
393 | has_return_value = True
394 | if function_info.prop_name_if_prop_get:
395 | ilgen.Emit(OpCodes.Ldsfld, ClrClass.get_dynamic_operations_field())
396 | ilgen.Emit(OpCodes.Ldarg, 0)
397 | ilgen.Emit(OpCodes.Ldstr, function_info.prop_name_if_prop_get)
398 | ilgen.Emit(OpCodes.Callvirt, get_member)
399 | elif function_info.prop_name_if_prop_set:
400 | ilgen.Emit(OpCodes.Ldsfld, ClrClass.get_dynamic_operations_field())
401 | ilgen.Emit(OpCodes.Ldarg, 0)
402 | ilgen.Emit(OpCodes.Ldstr, function_info.prop_name_if_prop_set)
403 | ilgen.Emit(OpCodes.Ldarg, 1)
404 | ilgen.Emit(OpCodes.Callvirt, set_member)
405 | has_return_value = False
406 | else:
407 | ilgen.Emit(OpCodes.Ldsfld, ClrClass.get_dynamic_operations_field())
408 | if function_info.is_static:
409 | raise NotImplementedError("need to load Python class object from a CLR static field")
410 | # ilgen.Emit(OpCodes.Ldsfld, class_object)
411 | else:
412 | ilgen.Emit(OpCodes.Ldarg, 0)
413 |
414 | ilgen.Emit(OpCodes.Ldstr, function.func_name)
415 | ilgen.Emit(OpCodes.Ldloc, args_array)
416 | ilgen.Emit(OpCodes.Callvirt, invoke_member)
417 |
418 | if has_return_value:
419 | if function.return_type == Void:
420 | ilgen.Emit(OpCodes.Pop)
421 | else:
422 | ret_val = ilgen.DeclareLocal(object)
423 | ilgen.Emit(OpCodes.Stloc, ret_val)
424 | ilgen.Emit(OpCodes.Ldsfld, ClrClass.get_dynamic_operations_field())
425 | ilgen.Emit(OpCodes.Ldloc, ret_val)
426 | ilgen.Emit(OpCodes.Ldtoken, clr.GetClrType(function.return_type))
427 | ilgen.Emit(OpCodes.Call, get_type_from_handle)
428 | ilgen.Emit(OpCodes.Callvirt, convert_to)
429 | ilgen.Emit(OpCodes.Unbox_Any, function.return_type)
430 | ilgen.Emit(OpCodes.Ret)
431 | return method_builder
432 |
433 | def emit_method(self, typebld, function_info):
434 | function = function_info.function
435 | if hasattr(function, "DllImportAttributeDecorator"):
436 | dllImportAttributeDecorator = function.DllImportAttributeDecorator
437 | name = function.func_name
438 | dllName = dllImportAttributeDecorator.args[0]
439 | entryName = function.func_name
440 | attributes = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl
441 | callingConvention = CallingConventions.Standard
442 | returnType = function.return_type
443 | returnTypeRequiredCustomModifiers = ()
444 | returnTypeOptionalCustomModifiers = ()
445 | parameterTypes = function.arg_types
446 | parameterTypeRequiredCustomModifiers = None
447 | parameterTypeOptionalCustomModifiers = None
448 | nativeCallConv = CallingConvention.Winapi
449 | nativeCharSet = CharSet.Auto
450 | method_builder = typebld.DefinePInvokeMethod(
451 | name,
452 | dllName,
453 | entryName,
454 | attributes,
455 | callingConvention,
456 | returnType,
457 | returnTypeRequiredCustomModifiers,
458 | returnTypeOptionalCustomModifiers,
459 | parameterTypes,
460 | parameterTypeRequiredCustomModifiers,
461 | parameterTypeOptionalCustomModifiers,
462 | nativeCallConv,
463 | nativeCharSet)
464 | else:
465 | method_builder = self.emit_typed_stub_to_python_method(typebld, function_info)
466 |
467 | if hasattr(function, "CustomAttributeBuilders"):
468 | for cab in function.CustomAttributeBuilders:
469 | method_builder.SetCustomAttribute(cab)
470 |
471 | return method_builder
472 |
473 | def map_pinvoke_methods(self, new_type):
474 | pythonType = clr.GetPythonType(new_type)
475 | for function_info in self.get_typed_methods():
476 | function = function_info.function
477 | if hasattr(function, "DllImportAttributeDecorator"):
478 | # Overwrite the Python function with the pinvoke_method
479 | pinvoke_method = getattr(pythonType, function.func_name)
480 | setattr(self, function.func_name, pinvoke_method)
481 |
482 | def emit_python_type_field(self, typebld):
483 | return typebld.DefineField(
484 | "PythonType",
485 | PythonType,
486 | FieldAttributes.Public | FieldAttributes.Static)
487 |
488 | def set_python_type_field(self, new_type):
489 | self.PythonType = new_type.GetField("PythonType")
490 | self.PythonType.SetValue(None, self)
491 |
492 | def add_wrapper_ctors(self, baseType, typebld):
493 | python_type_field = self.emit_python_type_field(typebld)
494 | for ctor in baseType.GetConstructors():
495 | ctorparams = ctor.GetParameters()
496 |
497 | # leave out the PythonType argument
498 | assert(ctorparams[0].ParameterType == clr.GetClrType(PythonType))
499 | ctorparams = ctorparams[1:]
500 |
501 | ctorbld = typebld.DefineConstructor(
502 | ctor.Attributes,
503 | ctor.CallingConvention,
504 | tuple([p.ParameterType for p in ctorparams]))
505 | ilgen = ctorbld.GetILGenerator()
506 | ilgen.Emit(OpCodes.Ldarg, 0)
507 | ilgen.Emit(OpCodes.Ldsfld, python_type_field)
508 | for index in xrange(len(ctorparams)):
509 | ilgen.Emit(OpCodes.Ldarg, index + 1)
510 | ilgen.Emit(OpCodes.Call, ctor)
511 | ilgen.Emit(OpCodes.Ret)
512 |
513 | def emit_members(self, typebld):
514 | self.emit_fields(typebld)
515 | self.add_wrapper_ctors(self.baseType, typebld)
516 | super(ClrClass, self).emit_members(typebld)
517 |
518 | def map_members(self, new_type):
519 | self.map_fields(new_type)
520 | self.map_pinvoke_methods(new_type)
521 | self.set_python_type_field(new_type)
522 | super(ClrClass, self).map_members(new_type)
523 |
524 | def __clrtype__(self):
525 | # CDerived below will use ClrClass as its metaclass, but the user may not expect CDerived
526 | # to be a typed .NET class in this case:
527 | #
528 | # class CBase(object):
529 | # __metaclass__ = ClrClass
530 | # class CDerived(CBase): pass
531 | if not "__metaclass__" in self.__dict__:
532 | return super(ClrClass, self).__clrtype__()
533 |
534 | # Create a simple Python type first.
535 | self.baseType = super(ClrType, self).__clrtype__()
536 | # We will now subtype it to create a customized class with the
537 | # CLR attributes as defined by the user
538 | typegen = Snippets.Shared.DefineType(self.get_clr_type_name(), self.baseType, True, False)
539 | typebld = typegen.TypeBuilder
540 | return self.create_type(typebld)
541 |
542 | def make_cab(attrib_type, *args, **kwds):
543 | clrtype = clr.GetClrType(attrib_type)
544 | argtypes = tuple(map(lambda x:clr.GetClrType(type(x)), args))
545 | ci = clrtype.GetConstructor(argtypes)
546 |
547 | props = ([],[])
548 | fields = ([],[])
549 |
550 | for kwd in kwds:
551 | pi = clrtype.GetProperty(kwd)
552 | if pi is not None:
553 | props[0].append(pi)
554 | props[1].append(kwds[kwd])
555 | else:
556 | fi = clrtype.GetField(kwd)
557 | if fi is not None:
558 | fields[0].append(fi)
559 | fields[1].append(kwds[kwd])
560 | else:
561 | raise TypeError("No %s Member found on %s" % (kwd, clrtype.Name))
562 |
563 | return CustomAttributeBuilder(ci, args,
564 | tuple(props[0]), tuple(props[1]),
565 | tuple(fields[0]), tuple(fields[1]))
566 |
567 | def accepts(*args):
568 | """
569 | TODO - needs to be merged with clr.accepts
570 | """
571 | validate_clr_types(args, True)
572 | def decorator(function):
573 | function.arg_types = args
574 | return function
575 | return decorator
576 |
577 | def returns(return_type = Void):
578 | """
579 | TODO - needs to be merged with clr.returns
580 | """
581 | if return_type != Void:
582 | validate_clr_types(return_type)
583 | def decorator(function):
584 | function.return_type = return_type
585 | return function
586 | return decorator
587 |
588 | class CustomAttributeDecorator(object):
589 | """
590 | This represents information about a custom-attribute applied to a type or a method
591 | Note that we cannot use an instance of System.Attribute to capture this information
592 | as it is not possible to go from an instance of System.Attribute to an instance
593 | of System.Reflection.Emit.CustomAttributeBuilder as the latter needs to know
594 | how to represent information in metadata to later *recreate* a similar instance of
595 | System.Attribute.
596 |
597 | Also note that once a CustomAttributeBuilder is created, it is not possible to
598 | query it. Hence, we need to store the arguments required to store the
599 | CustomAttributeBuilder so that pseudo-custom-attributes can get to the information.
600 | """
601 | def __init__(self, attrib_type, *args, **kwargs):
602 | self.attrib_type = attrib_type
603 | self.args = args
604 | self.kwargs = kwargs
605 |
606 | def __call__(self, function):
607 | if self.attrib_type == DllImportAttribute:
608 | function.DllImportAttributeDecorator = self
609 | else:
610 | if not hasattr(function, "CustomAttributeBuilders"):
611 | function.CustomAttributeBuilders = []
612 | function.CustomAttributeBuilders.append(self.GetBuilder())
613 | return function
614 |
615 | def GetBuilder(self):
616 | assert not self.attrib_type in [DllImportAttribute]
617 | return make_cab(self.attrib_type, *self.args, **self.kwargs)
618 |
619 | def attribute(attrib_type):
620 | """
621 | This decorator is used to specify a CustomAttribute for a type or method.
622 | """
623 | def make_decorator(*args, **kwargs):
624 | return CustomAttributeDecorator(attrib_type, *args, **kwargs)
625 | return make_decorator
626 |
627 | def propagate_attributes(old_function, new_function):
628 | """
629 | Use this if you replace a function in a type with ClrInterface or ClrClass as the metaclass.
630 | This will typically be needed if you are defining a decorator which wraps functions with
631 | new functions, and want it to work in conjunction with clrtype
632 | """
633 | if hasattr(old_function, "return_type"):
634 | new_function.func_name = old_function.func_name
635 | new_function.return_type = old_function.return_type
636 | new_function.arg_types = old_function.arg_types
637 | if hasattr(old_function, "CustomAttributeBuilders"):
638 | new_function.CustomAttributeBuilders = old_function.CustomAttributeBuilders
639 | if hasattr(old_function, "CustomAttributeBuilders"):
640 | new_function.DllImportAttributeDecorator = old_function.DllImportAttributeDecorator
641 |
--------------------------------------------------------------------------------