All Projects → Marcono1234 → serial-builder

Marcono1234 / serial-builder

Licence: MIT license
Library for manually creating Java serialization data.

Programming Languages

java
68154 projects - #9 most used programming language
kotlin
9241 projects

Projects that are alternatives of or similar to serial-builder

Ysoserial
A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization.
Stars: ✭ 4,808 (+23940%)
Mutual labels:  serialization, javadeser
Java Deserialization Cheat Sheet
The cheat sheet about Java Deserialization vulnerabilities
Stars: ✭ 2,286 (+11330%)
Mutual labels:  javadeser, java-deserialization
urlpack
Pure JavaScript toolkit for data URLs (MessagePack, Base58 and Base62)
Stars: ✭ 51 (+155%)
Mutual labels:  serialization
JAson
Creation a JSON object with data of different types and run serialization and deserialization of JSON data.
Stars: ✭ 38 (+90%)
Mutual labels:  serialization
HTTP-Wrapper
A simple http wrapper
Stars: ✭ 13 (-35%)
Mutual labels:  serialization
edap
No description or website provided.
Stars: ✭ 22 (+10%)
Mutual labels:  serialization
json5
Header only JSON/JSON5 parser and serializer for C++
Stars: ✭ 22 (+10%)
Mutual labels:  serialization
jim
Immediate Mode JSON Serialization Library in C
Stars: ✭ 35 (+75%)
Mutual labels:  serialization
serde
🚝 (unmaintained) A framework for defining, serializing, deserializing, and validating data structures
Stars: ✭ 49 (+145%)
Mutual labels:  serialization
json struct
json_struct is a single header only C++ library for parsing JSON directly to C++ structs and vice versa
Stars: ✭ 279 (+1295%)
Mutual labels:  serialization
kafka-serde-scala
Implicitly converts typeclass encoders to kafka Serializer, Deserializer, Serde.
Stars: ✭ 52 (+160%)
Mutual labels:  serialization
veriform
Security-oriented protobuf-like serialization format with "Merkleized" content hashing support
Stars: ✭ 114 (+470%)
Mutual labels:  serialization
Unity-SerializeReferenceExtensions
Provide popup to specify the type of the field serialized by the [SerializeReference] attribute in the inspector.
Stars: ✭ 255 (+1175%)
Mutual labels:  serialization
msgpack-smalltalk
MessagePack serialization library for various Smalltalk dialects / msgpack.org[Smalltalk]
Stars: ✭ 22 (+10%)
Mutual labels:  serialization
surge
Simple, specialised, and efficient binary marshaling
Stars: ✭ 36 (+80%)
Mutual labels:  serialization
bytecodec
A tiny Rust framework for implementing encoders/decoders of byte-oriented protocols
Stars: ✭ 21 (+5%)
Mutual labels:  serialization
Json-to-Dart-Model
marketplace.visualstudio.com/items?itemName=hirantha.json-to-dart
Stars: ✭ 84 (+320%)
Mutual labels:  serialization
break-fast-serial
A proof of concept that demonstrates asynchronous scanning for Java deserialization bugs
Stars: ✭ 53 (+165%)
Mutual labels:  serialization
sexpresso
An s-expression library for C++
Stars: ✭ 41 (+105%)
Mutual labels:  serialization
flextool
C++ compile-time programming (serialization, reflection, code modification, enum to string, better enum, enum to json, extend or parse language, etc.)
Stars: ✭ 32 (+60%)
Mutual labels:  serialization

⚠️ This library is currently experimental, its behavior and API might change in the future.


serial-builder

Library for creating Java serialization data; mainly intended for research purposes. It is not recommended to use it in production as alternative for ObjectOutputStream.

Compared to using Java's ObjectOutputStream this library has the following advantages:

  • It is not necessary to have the target classes on the classpath; it is possible to refer to classes only by their name.
  • It is possible to write arbitrary field values without having to access the internals of the target class with reflection.
  • It is possible to omit data or add additional serialization data which would normally not be written.

The entrypoints of this library are the classes SerialBuilder and SimpleSerialBuilder. The API structure of SerialBuilder is pretty close to the actual serialization data format. This allows low level creation of serialization data, at the cost of verbose usage and reduced error checking. SimpleSerialBuilder operates on a higher level, which makes its usage more concise and less error-prone. In most cases the API offered by SimpleSerialBuilder should suffice.

The API offered by this library uses a 'fluent builder style', where all methods calls are chained after each other (with indentation to increase readability) until the end of the chain is reached, and the resulting serialization data in the form of byte[] is returned. Using the API in any other way is not supported and might cause exceptions. It is recommended to follow the IDE code completion suggestions while using the API, looking at the builder API interfaces is most likely not that helpful.

Usage

Requires Java 17 or newer

Currently this library is not published to Maven Central. You can either build the project locally or you can use JitPack as Maven repository serving this library.

When using JitPack it is recommended to put the jitpack.io repository last in the list of declared repositories for better performance and to avoid pulling undesired dependencies from it. When using Gradle as build tool you should also use repository content filtering:

repositories {
    mavenCentral()
    exclusiveContent {
        forRepository {
            maven {
                url = uri("https://jitpack.io")
            }
        }
        filter {
            // Only use JitPack for the `serial-builder` library
            includeModule("com.github.Marcono1234.serial-builder", "serial-builder")
        }
    }
}

API usage examples (SimpleSerialBuilder)

Note: This project also supports generating Java code using this API to recreate existing serialization data, see the code generation section below.

Class hierarchy

Let's assume you have these two classes:

class ClassA implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    public String a;
}

class ClassB extends ClassA {
    @Serial
    private static final long serialVersionUID = 1L;

    public String b;
}

To create serialization data for an instance of ClassB, you can use the API in the following way:

byte[] serialData = SimpleSerialBuilder.startSerializableObject()
    // Start at the superclass
    .beginClassData(ClassA.class)
        .beginObjectField("a", String.class)
            .string("value-a")
        .endField()
    .endClassData()
    .beginClassData(ClassB.class)
        .beginObjectField("b", String.class)
            .string("value-b")
        .endField()
    .endClassData()
.endObject();

writeObject method

Let's assume you have the following class with writeObject and readObject methods:

class ClassWithWriteObject implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    public int i;
    public String s;

    public transient int i2;
    public transient String s2;

    @Serial
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();

        out.writeInt(i2);
        out.writeObject(s2);
    }

    @Serial
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();

        i2 = in.readInt();
        s2 = (String) in.readObject();
    }
}

To create serialization data for it, you can use the API in the following way:

byte[] serialData = SimpleSerialBuilder.startSerializableObject()
    .beginClassData(ClassWithWriteObject.class)
        // Represents the data written by the `defaultWriteObject()` call
        .primitiveIntField("i", 1)
        .beginObjectField("s", String.class)
            .string("test")
        .endField()
        // Represents the data manually written by `writeObject`
        .writeObjectWith(writer -> {
            writer.writeInt(2);
            writer.string("manually-written");
        })
    .endClassData()
.endObject();

Proxy instances

Let's assume you have the following java.lang.reflect.InvocationHandler implementation:

class CustomInvocationHandler implements InvocationHandler, Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    public String result;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        return result;
    }
}

To create serialization data for a java.lang.reflect.Proxy instance which uses an instance of that invocation handler, you can use the API in the following way:

// Starts a Proxy object which implements the Callable interface
byte[] serialData = SimpleSerialBuilder.startProxyObject(Callable.class)
    .beginSerializableInvocationHandler()
        .beginClassData(CustomInvocationHandler.class)
            .beginObjectField("result", String.class)
                .string("custom-result")
            .endField()
        .endClassData()
    .endObject()
.endProxyObject();

Handles

The serialization protocol supports handles which refer to a previously written instance. This API supports this feature through the Handle class. First you create a new (unassigned) Handle, then you pass it to one of the builder methods with Handle parameter and afterwards you can use it to refer to the previously written object.

This library does not support using Handle in all cases where the serialization protocol supports it, but all interesting cases should be covered (if you are missing support for a use case, feel free to create a GitHub issue).

Let's assume you have the following class:

class Container implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    public Serializable element;
}

To create serialization data for an instance of this class which contains itself, you can use the API in the following way:

// First create a new unassigned handle
Handle selfHandle = new Handle();
// Then pass the handle here as argument to assign the written object to it
byte[] serialData = SimpleSerialBuilder.startSerializableObject(selfHandle)
    .beginClassData(Container.class)
        .beginObjectField("element", Serializable.class)
            // Finally, write a reference to the previously written object
            .objectHandle(selfHandle)
        .endField()
    .endClassData()
.endObject();

Code generation

Especially when using this API for existing large serialization data, it can be cumbersome to manually write all the Java code to recreate the serialization data. Therefore, this project provides code generation functionality which, for given serialization data, generates the corresponding API calls to recreate the serialization data (as close as possible). See the README of the subproject for more information.

Project structure

This project is a multi-project Gradle build. It has the following subprojects:

Building

This project uses Gradle for building; just run:

./gradlew build

It is built against Java 17, but there is no need to manually install the correct JDK; Gradle's toolchain feature automatically downloads the needed JDK. Some IDEs do not support toolchains yet, so you might have to configure them manually.

Similar / related projects

License

This project uses the MIT license; all contributions are implicitly under that license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].