├── 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 | --------------------------------------------------------------------------------