Is there any way to crack/decrypt the WinXP CONSUMER activation system to generate Activation IDs?

Discussion in 'Windows XP / Older OS' started by ENZOLU, Aug 20, 2019.

  1. TheoFaron

    TheoFaron MDL Novice

    Oct 23, 2019
    3
    1
    0
    I have little knowledge of the details of the activation, but if private keys are impossible to crack is it possible to exchange the certificates in the client?
     
  2. diamondggg

    diamondggg MDL Novice

    Sep 30, 2016
    4
    8
    0
    The certificate is built in system executables, not in a separate replaceable file/registry. So one would need to patch important system files.

    From the point of view of a battle of wits between attackers and protectors, the patching means admitting defeat.

    From the practical point of view, the patching comes with a lot of drawbacks. Less importantly, winlogon.exe/licdll.dll have a number of internal checks to protect the important data, including the certificate, so one would either need to patch out those as well, or be extra careful to make a replacement certificate with the same checksum as the original one (which might be possible). More importantly, patching a system file automatically means problems with system protection mechanisms like SFC, with updates, with antiviruses, with WGA checker, leaves easily detectable traces of intrusion.

    It could work if it would be the only way to go (IIRC some early anti-WPA hacks did patch winlogon.exe, although not in this way), but it makes no practical sense in presence of other anti-WPA methods that won't provide a validatable activation in this concrete way but do provide a better solution of the problem as a whole.
     
  3. TheoFaron

    TheoFaron MDL Novice

    Oct 23, 2019
    3
    1
    0
    #43 TheoFaron, Jan 19, 2021
    Last edited: Jan 19, 2021
    Well, I don't think cracking an RSA-1024 key is a realistic outlook. But then again I haven't found any recent numbers on the computation cost. So the two options left is either to find a flaw in the client logic so that it will accept stuff signed with a fake key or to steal the keys from Microsoft.
     
  4. Mishakaaka

    Mishakaaka MDL Novice

    Mar 2, 2021
    1
    0
    0
    The windows XP Leaked source code contains source code for pidgen.dll
     
  5. trashe33

    trashe33 MDL Junior Member

    May 8, 2016
    57
    17
    0
    no it did not, however the anons or someone else have coded a substitute for pidgen (based on win2000 leak?!) that accepts any Server 2003 Enterprise key (afaik) which must be compiled alongside a winlogon.exe reconstructed from leaked win2000 source code (which from my experience was prone to crash if you stay on the logon screen for too long) to bypass the product activation related stuff in a normal xp/server 2003 winlogon.exe. Also, if you have source code that does not seem to be in the original leak from october, you can try to hit up the "devs" working on the leaked source code in their matrix chat group, they would probably appreciate that.

    tl;dr: The source code leak did not include Windows Product Activation-related stuff
     
  6. Exe Csrss

    Exe Csrss MDL Senior Member

    Dec 9, 2020
    393
    348
    10
    #46 Exe Csrss, Mar 5, 2021
    Last edited: Mar 5, 2021
     
  7. Carlos Detweiller

    Carlos Detweiller MDL Spinning Tortoise

    Dec 21, 2012
    4,514
    4,541
    150
  8. sk00ter

    sk00ter MDL Novice

    Apr 30, 2017
    19
    18
    0
    I've looked into DPCDLL122Func() a bit more and wish to adjust the struct and enum.
    Code:
    enum LicenseType : DWORD { // matches the license type field in DigitalProductId3
      LT_RETAIL,
      LT_UPGRADE,
      LT_OEM,
      LT_VOL, // volume license (previously Microsoft Select)
      LT_MLP, // Microsoft License Pack for stuff like CALs probably?
      LT_MOLP, // Microsoft Open License Program
      LT_MSDN
    };
    struct Lic {
      DWORD dwIndex; // index into the license index
      struct BlessedLic { // BlessedLic is signed
        DWORD dwId; // always same as dwIndex in practice
        DWORD dwBinkId; // ID of the relevant BINK
        DWORD dwMinSiteId; // minimum channel/site ID
        DWORD dwMaxSiteId; // maximum channel/site ID
        LicenseType dwLicenseType; // type of license
        DWORD dwDaysToActivate; // time to activate before OS stops working, 0x7fffffff for no activation needed
        DWORD dwTrialDays; // time for a trial installation before it disables itself
      } blessed;
      DWORD dwSignatureLength; // signature length in bytes
      CONST BYTE *pabSignature; // signature
    };
    HRESULT WINAPI DPCDLL122Func(DWORD dwBinkId, DWORD dwSiteId, DWORD dwBuildId, struct Lic *pLic);
    
    The license type enum actually matches what's in use with pidgen.dll.

    The Lic struct has a signature. The "blessed" sub-struct is signed.

    The signature uses RSA-1024 with PKCS#1 padding and SHA1. The public key is stored as a CryptoAPI blob in winlogon.exe, which also makes it the apparently only caller that I know of.

    To save you some trouble, here's an example taken from XP volume license dpcdll.dll (same signing key used for other languages as well; not sure if retail shares the same key or even the entire struct list, but it probably shares both; not sure if 2003 shares the same key, but it probably doesn't):

    Code:
    #!/usr/bin/env ruby
    # frozen_string_literal: true
    
    require 'base64'
    require 'openssl'
    
    # winlogon.exe @ 0x1016cb8, converted from blob to PEM
    PUBKEY = <<EOK
    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsKGLtQ8bUveKs8GYDs+/b+Vs2
    tG3btT2g/ZSI9ExWXZCTyrnsxdMIoiyEFovYulodzu60QReEree3szKnpobay04c
    qpqr4n3IfFUaWpOYCFtdKosgQrCsKoXNN+w3rqz4UxAAE0LEZvci0+Qo22/VRKSo
    sOX+w8C+8ss1KhxsJwIDAQAB
    -----END PUBLIC KEY-----
    EOK
    
    # This is the data of a struct Lic.
    # The pointer to the signature is 0x012d89b0 for demo.
    #
    # struct Lic {
    #   .dwIndex = 0x0e,
    #   .blessed = {
    #     .dwId = 0x0e,
    #     .dwBinkId = 0x28,
    #     .dwMinSiteId = 5,
    #     .dwMaxSiteId = 110,
    #     .dwLicenseType = 3, // LT_VOL
    #     .dwTrialDays = 14,
    #     .dwTrialDays = 125
    #   },
    #   .dwSignatureLength = 0x80,
    #   .abSignature = 0x012d89b0
    # };
    lic = Base64.decode64('DgAAAA4AAAAoAAAABQAAAG4AAAADAAAADgAAAH0AAACAAAAAsIktAQ==')
    
    signed = lic[4...(4+(7*4))]
    signature_encoded = <<EOSIG
    KhS4yXIrs9bISyve8GadyYtfvE5G2ynvxJbFPfuUbMGi7VqC5wBoQpw1N9/F
    c4g9lkPDl0UbtnPDgMAalRs4BJ667yscrOI8bocE3NB96FiyqB0lfIEKJeWU
    kZbQbCfYcxi7/P4WLDLbMjJAE9CPx78TBfkt74XjXFON1TOHa1w=
    EOSIG
    # reverse the bytes in the signature because OpenSSL uses big-endian numbers,
    # but OpenSSL uses little-endian
    signature = Base64.decode64(signature_encoded).reverse
    
    rsa = OpenSSL::PKey::RSA.new(PUBKEY)
    puts(rsa.verify('SHA1', signature, signed)) # true
    
    You won't be able to sign your own dpcdll.dll structs. Breaking RSA-1024 is computationally infeasible (Schnorr's recent paper has been debunked).