shadow1ng/fscan · error

Unsupported version

Error message

Unsupported version

What it means

ServerCertificate.Unpack in gcc.go parses the server's certificate blob carried in the GCC Server Security Data during the RDP connection sequence. The DwVersion field must be CERT_CHAIN_VERSION_1 (proprietary) or CERT_CHAIN_VERSION_2 (X.509); any other value hits the default branch and returns this error. It means the library cannot decode the certificate format the server sent.

Source

Thrown at libs/grdp/protocol/t125/gcc/gcc.go:515

}
type ServerCertificate struct {
	DwVersion uint32
	CertData  CertData
}

func (sc *ServerCertificate) Unpack(r io.Reader) error {
	sc.DwVersion, _ = core.ReadUInt32LE(r)
	var cd CertData
	switch CertificateType(sc.DwVersion & 0x7fffffff) {
	case CERT_CHAIN_VERSION_1:
		glog.Debug("ProprietaryServerCertificate")
		cd = &ProprietaryServerCertificate{}
	case CERT_CHAIN_VERSION_2:
		glog.Debug("X509CertificateChain")
		cd = &X509CertificateChain{}
	default:
		glog.Error("Unsupported version:", sc.DwVersion&0x7fffffff)
		return errors.New("Unsupported version")
	}
	if cd != nil {
		err := cd.Unpack(r)
		if err != nil {
			glog.Error("Unpack:", err)
			return err
		}
	}
	sc.CertData = cd

	return nil
}

type ServerSecurityData struct {
	EncryptionMethod  uint32 `struc:"little"`
	EncryptionLevel   uint32 `struc:"little"`
	ServerRandomLen   uint32 //0x00000020
	ServerCertLen     uint32

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Verify the target is a standard Microsoft RDP server; test with mstsc or FreeRDP to confirm the handshake format.
  2. Dump the raw bytes (glog already prints the version) and check the stream is not desynchronized earlier in the GCC block parse.
  3. Add a case for the unsupported version in gcc.go ServerCertificate.Unpack, implementing a CertData Unpack for that format.
  4. If security policy allows, downgrade the server to use standard PROPRIETARYCHAIN (version 1) or X509 (version 2) certificates.

Example fix

// before
case CERT_CHAIN_VERSION_2:
    glog.Debug("X509CertificateChain")
    cd = &X509CertificateChain{}
default:
    return errors.New("Unsupported version")
// after
case CERT_CHAIN_VERSION_2:
    cd = &X509CertificateChain{}
case 3: // version added by target server
    cd = &X509CertificateChain{}
default:
    return fmt.Errorf("Unsupported version: %d", sc.DwVersion&0x7fffffff)
Defensive patterns

Strategy: validation

Validate before calling

// Check server cert version support before/at connect time by catching the parse:
if dwVersion&0x7fffffff != 1 && dwVersion&0x7fffffff != 2 {
    return fmt.Errorf("server certificate version %d unsupported by client", dwVersion&0x7fffffff)
}

Try / catch

client.On("error", func(err error) {
    if strings.Contains(err.Error(), "Unsupported version") {
        // fall back to a server/protocol known to use X.509 or proprietary certs
    }
})

Prevention

When it happens

Trigger: The 32-bit DwVersion field of the server certificate, masked with 0x7fffffff (the top bit is the CA-issued flag), decodes to a value other than 1 (CERT_CHAIN_VERSION_1) or 2 (CERT_CHAIN_VERSION_2) while parsing the server's GCC conference create response.

Common situations: Connecting to a non-Microsoft or non-standard RDP server (xrdp, FreeRDP-based gateways, custom VDI brokers) that emits a different certificate version; a corrupted or desynchronized stream so the wrong 4 bytes are read as DwVersion; hitting a newer server implementation with a certificate version this library does not know.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/96b57e76f781fcfd. Report an issue: GitHub.