-
Notifications
You must be signed in to change notification settings - Fork 37
Developing PacketProxy
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.
- Run the gradlew command.
$ ./gradlew assemble
- Run PacketProxy.
$ ./gradlew run
-
Select import
- Select
import projects…
after launching Eclipse.
- Select
-
Select Gradle project
- In the import project dialogue, select
Gradle
->Existing Gradle
Project.
- In the import project dialogue, select
-
Load cloned project
- In the project selection dialogue, load the cloned PacketProxy.
-
Build and implement PacketProxy
- From the
Gradle Tasks
tab, selectPacketProxy
->application
->run
.
- From the
*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.
-
Load project
- After launching IntelliJ IDEA, select
import Project
, and load cloned PacketProxy project.
- After launching IntelliJ IDEA, select
-
Select Gradle project
- In the import project dialogue, select
Import project from external model
->Gradle
.
- In the import project dialogue, select
-
Build and run PacketProxy。
- From the project tree, right click on
src/main/java/core/packetproxy/PacketProxy.java
and selectRun PacketProxy.main()
.
- From the project tree, right click on
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.
Encode modules are a class that runs the four processes labelled decode and encode in the chart below.
*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.
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).
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();
}
}
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;
}
}
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;
}
}
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.
- When you build
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