Skip to content

Developing PacketProxy

funa-tk edited this page Aug 5, 2021 · 12 revisions

Set up Development Environment

First, install Java11 (11.0.5+).

Next, clone the PacketProxy source code from GitHub.

$ git clone https://github.com/DeNA/PacketProxy.git

When you’re done cloning, pick one of the following three to implement your build.

  • Build and run from command line
  • Build and run using Eclipse
  • Build and run using IntelliJ IDEA

More detailed instructions for each method follow.

Build and run from command line

  1. Run the gradlew command.
    $ ./gradlew assemble
  2. Run PacketProxy.
    $ ./gradlew run

Build and run using Eclipse

  1. Select import
    • Select import projects… after launching Eclipse.
  2. Select Gradle project
    • In the import project dialogue, select Gradle -> Existing Gradle Project.
  3. Load cloned project
    • In the project selection dialogue, load the cloned PacketProxy.
  4. Build and implement PacketProxy
    • From the Gradle Tasks tab, select PacketProxy -> application -> run.

*If you would prefer to develop as an Eclipse project rather than a Gradle project, run ./graldew eclipse and then import as an Eclipse project.

Build and run using IntelliJ IDEA

  1. Load project
    • After launching IntelliJ IDEA, select import Project, and load cloned PacketProxy project.
  2. Select Gradle project
    • In the import project dialogue, select Import project from external model -> Gradle.
  3. Build and run PacketProxy
    • From the project tree, right click on src/main/java/core/packetproxy/PacketProxy.java and select Run PacketProxy.main().

Develop Encode Module

What is an Encode Module?

Major communication protocols such as HTTP and HTTPS are built in to PacketProxy, but other protocols are not implemented (ex: game-specific encryption communication protocols).

For that reason, if you want to look at game communication, you will need to develop an expansion (encode module) for protocols for games.

Developing an encode module will enable you to automatically decrypt, decode, and show packets in the PacketProxy history screen, as well as automatically encode them for forwarding, making it easier to run vulnerability diagnostics.

How Encode Modules Work

Encode modules are a class that runs the four processes labelled decode and encode in the chart below.

How to work encode module

*The Display Screen and User Rewrite processes are not encode module processes, but they are included to make it easier to understand the encode module processes.

Encode Module Code 1

See the follow example for the simplest encode module code (There are other methods that require defining, but we cover them later).

public class EncodeSample extends Encoder {
	public EncodeSample() {
	}
	public EncodeSample(String ALPN) throws Exception {
		super(ALPN);
	}
	@Override
	public byte[] decodeClientRequest(byte[] input_data) throws Exception {
		return input_data;
	}
	@Override
	public byte[] encodeClientRequest(byte[] input_data) throws Exception {
		return input_data;
	}
	@Override
	public byte[] decodeServerResponse(byte[] input_data) throws Exception {
		return input_data;
	}
	@Override
	public byte[] encodeServerResponse(byte[] input_data) throws Exception {
		return input_data;
	}
}

The code for this encode module sets it up so that it does not do anything in the encoding or decoding process (the data is returned as is).

Encode Module Code 2

Here is another example.

In this encode module, packet data input in lower case letters is changed to upper case.

Using this encode module allows you to handle packet data in PacketProxy in upper case. When going outside of PacketProxy, there is a process to return to lower case letters.

public class EncodeSampleUpperCase extends Encoder {
	public EncodeSampleUpperCase() {
	}
	public EncodeSampleUpperCase(String ALPN) throws Exception {
		super(ALPN);
	}
	@Override
	public byte[] decodeClientRequest(byte[] input_data) throws Exception {
		return new String(input_data).toUpperCase().getBytes();
	}
	@Override
	public byte[] encodeClientRequest(byte[] input_data) throws Exception {
		return new String(input_data).toLowerCase().getBytes();
	}
	@Override
	public byte[] decodeServerResponse(byte[] input_data) throws Exception {
		return new String(input_data).toUpperCase().getBytes();
 }
	@Override
	public byte[] encodeServerResponse(byte[] input_data) throws Exception {
		return new String(input_data).toLowerCase().getBytes();
 }
}

Other Methods Required for Encode Modules

There are two other methods that need to be defined, in addition to the four described above.

One is the method called String getName(), which defines the encode module name. This name is shown as the label to select this encode module when using the PacketProxy settings screen.

The second is int checkDelimiter(byte[] input_data). This method returns the byte where the packet break is located. It is called every time binary data arrived.

The checkDelimiter method is used when packets are cut out from continually arriving binary data. If binary data only for cutting out a packet has not arrived yet, make sure it returns -1.

This is an example of a complete encode module.

public class EncodeSample extends Encoder {
	public EncodeSample() {
	}
	public EncodeSample(String ALPN) throws Exception {
		super(ALPN);
	}
	@Override
	public String getName() {
		return "Sample";
	}
	@Override
	public int checkDelimiter(byte[] input_data) throws Exception {
		// we handle arrived data as a packet
		return input_data.length; 
	}
	@Override
	public byte[] decodeClientRequest(byte[] input_data) throws Exception {
		return input_data;
	}
	@Override
	public byte[] encodeClientRequest(byte[] input_data) throws Exception {
		return input_data;
	}
	@Override
	public byte[] decodeServerResponse(byte[] input_data) throws Exception {
		return input_data;
	}
	@Override
	public byte[] encodeServerResponse(byte[] input_data) throws Exception {
		return input_data;
	}
}

Encode Module Code 3

When developing encode modules in an HTTP protocol base, if you inherit the Encoder class then you will need to parse the input binary data as HTTP data, which is annoying.

For convenience, we have created an EncodeHTTPBase class that parses input binary data as HTTP data and then passes as an argument. By inheriting the EncodeHTTPBase class, it is a lot easier to develop an encode module with an HTTP base.

public class EncodeSampleHTTP extends EncodeHTTPBase
{
	public EncodeSampleHTTP() {
	}
	public EncodeSampleHTTP(String ALPN) throws Exception {
		super(ALPN);
	}
	@Override
	public String getName() {
		return "SampleHTTP";
	}
	@Override
	protected Http decodeClientRequestHttp(Http inputHttp) throws Exception {
		byte[] body = inputHttp.getBody();
		// ... operate body data ...
		inputHttp.setBody(body);
		return inputHttp;
	}
	@Override
	protected Http encodeClientRequestHttp(Http inputHttp) throws Exception {
		return inputHttp;
	}
	@Override
	protected Http decodeServerResponseHttp(Http inputHttp) throws Exception {
		return inputHttp;
	}
	@Override
	protected Http encodeServerResponseHttp(Http inputHttp) throws Exception {
		return inputHttp;
	}
}

Starting Implementation

There are two ways to start implementation.

  • First method: Clone PacketProxy and directly implement the encode module into the PacketProxy source code tree.
  • Second method: Clone PacketProxyPlugin (project for developing encode modules) and develop encode module.
    • When you build PacketProxyPlugin-VERSION-all.jar will be output, and put into $HOME/.packetproxy/plugins/. This enabled it to be automatically loaded when PacketProxy launches. For more details, see the README.md of the PacketProxyPlugin repository.

Generate Release Files

If you updated PacketProxy itself, you can generate new release files (including the installer) from the command line. Generating Mac release files requires a key for the signature and a notary account and password. Make sure to setup them in the build.gradle before generating the release file.

$ ./gradlew release

The following release files will be generated in [Project Root]/build/distributions.

  • Windows 64bit
    • win64/PacketProxy-[Version]-Installer-Win64.exe
  • MacOS
    • mac/PacketProxy-[Version]-Installer-Mac-Signed.dmg