peass-ng/PEASS-ng · error · IOException
unexpected end-of-contents marker
Error message
unexpected end-of-contents marker
What it means
Asn1InputStream.ReadObject throws this IOException when the first byte of an expected ASN.1 object is 0x00, which in BER/DER is the end-of-contents (EOC) marker for indefinite-length constructions, not a valid object tag. It signals the stream's structure does not match what the caller expects — usually an extra or misplaced EOC byte.
Source
Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/asn1/Asn1InputStream.cs:169
internal virtual DerSequence CreateDerSequence(
DefiniteLengthInputStream dIn)
{
return DerSequence.FromVector(ReadVector(dIn));
}
internal virtual DerSet CreateDerSet(
DefiniteLengthInputStream dIn)
{
return DerSet.FromVector(ReadVector(dIn), false);
}
public Asn1Object ReadObject()
{
int tag = ReadByte();
if (tag <= 0)
{
if (tag == 0)
throw new IOException("unexpected end-of-contents marker");
return null;
}
//
// calculate tag number
//
int tagNo = ReadTagNumber(this.s, tag);
bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
//
// calculate length
//
int length = ReadLength(this.s, limit, false);
if (length < 0) // indefinite-length method
{View on GitHub (pinned to 53fb989abc)
Solutions
- Stop looping when ReadObject returns null (it signals end-of-data after an EOC) instead of expecting an exception-free loop to a fixed count.
- Check the stream/offset alignment — you are likely positioned at an EOC marker byte (0x00) that belongs to an enclosing indefinite-length structure.
- If indefinite-length BER is expected, use Asn1StreamParser instead of Asn1InputStream, which handles EOC markers correctly.
- Trim trailing zero padding from the input before parsing.
Example fix
// before
while (true) { Asn1Object o = stream.ReadObject(); Process(o); }
// after
Asn1Object o;
while ((o = stream.ReadObject()) != null) { Process(o); } // null on EOC/end Defensive patterns
Strategy: validation
Validate before calling
static IEnumerable<Asn1Object> ReadAll(Asn1InputStream s)
{
Asn1Object o;
while ((o = s.ReadObject()) != null) // null = EOC/end, never loop past it
yield return o;
}
// also trim trailing zero padding:
// while (data.Length > 0 && data[data.Length-1] == 0) Array.Resize(ref data, data.Length-1); Try / catch
try {
Asn1Object obj = stream.ReadObject();
} catch (IOException ex) when (ex.Message == "unexpected end-of-contents marker") {
// stream positioned at an EOC byte: adjust offset or stop parsing
return null;
} Prevention
- Treat a null return from ReadObject as normal end-of-stream, not an error to retry past
- Use Asn1StreamParser instead of Asn1InputStream when indefinite-length BER is expected
- Do not hand-slice byte arrays by guessed offsets — parse from the enclosing object instead
- Strip trailing zero padding before constructing the input stream
When it happens
Trigger: ReadObject is called on a stream positioned at a 0x00 byte — typically after an indefinite-length object's content was fully consumed but the caller calls ReadObject again, or the byte offset into the buffer is wrong by one (parsing trailing padding/EOC bytes as a new object).
Common situations: Calling ReadObject in a loop over a BER stream containing indefinite-length encoded data whose EOC terminator is then read as a top-level object; hand-slicing a byte array with a wrong offset; parsing data with trailing zero padding.
Related errors
- unknown object encountered in constructed OCTET STRING:
- indefinite-length primitive encoding encountered
- unknown tag {tagNo} encountered
- DER length more than 4 bytes:
- cannot recognise object in stream
AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02).
Data as JSON: /api/errors/9ac2cd90c2520929.
Report an issue: GitHub.