Marshaling

com.etdon.winj.marshal

The Marshaling API can be used to convert Java types to byte arrays in specific formats that might be needed either for the interaction with native functions and types or writing shellcode.

In order to serialize a specific type you'll need to use its corresponding Marshal class. All Marshal implementations have a #marshal method, which takes the input as well as a MarshalContext implementation instance as its parameters.

The MarshalContext class is used to provide additional context regarding how the input should be marshaled. It can also be used to provide an optional MarshalStrategy which allows for different marshaling strategies for the same type that effectively override the default method.

To get a better understanding of how to use the API we're going to marshal a Java String to an XOR-ed byte array:

final byte[] output = StringMarshal.getInstance().marshal(
    "calc.exe",
    StringMarshalContext.builder()
        .strategy(XorStringMarshalStrategy.withKey(0xFF))
        .build()
)

The returns byte array contains our string in an XOR-ed format as raw bytes. The charset used depends on your system, but usually defaults to UTF-8. In order to change the charset simply invoke the #charset method of the StringMarshalContext builder like this:

final byte[] output = StringMarshal.getInstance().marshal(
    "calc.exe",
    StringMarshalContext.builder()
        .strategy(XorStringMarshalStrategy.withKey(0xFF))
        .charset(StandardCharsets.UTF_16LE)
        .build()
)

If you prefer a unified place to initiate marshaling you can utilize the AutoMarshal utility class that'll automatically look for the corresponding implementation in its registry:

final byte[] output = AutoMarshal.marshal(
    "calc.exe",
    StringMarshalContext.builder()
        .strategy(XorStringMarshalStrategy.withKey(0xFF))
        .charset(StandardCharsets.UTF_16LE)
        .build()
)

Last updated