mirror of
https://bitbucket.org/projectswg/packet-master.git
synced 2026-07-13 21:01:00 -04:00
201 lines
5.6 KiB
Java
201 lines
5.6 KiB
Java
package me.joshlarson;
|
|
|
|
import java.io.IOException;
|
|
import java.net.InetAddress;
|
|
import java.net.UnknownHostException;
|
|
import java.nio.ByteBuffer;
|
|
import java.util.List;
|
|
import java.util.Vector;
|
|
|
|
import javax.swing.UIManager;
|
|
import javax.swing.UnsupportedLookAndFeelException;
|
|
|
|
import me.joshlarson.gui.GUI;
|
|
import me.joshlarson.gui.GUIPacket;
|
|
|
|
import org.jnetpcap.Pcap;
|
|
import org.jnetpcap.nio.JBuffer;
|
|
import org.jnetpcap.packet.Payload;
|
|
import org.jnetpcap.packet.PcapPacket;
|
|
import org.jnetpcap.protocol.network.Ip4;
|
|
|
|
import com.swgnge.network.PacketType;
|
|
import com.swgnge.network.Utilities;
|
|
import com.swgnge.network.encryption.Encryption;
|
|
import com.swgnge.network.packets.Packet;
|
|
import com.swgnge.network.packets.soe.DataChannelA;
|
|
import com.swgnge.network.packets.soe.MultiPacket;
|
|
import com.swgnge.network.packets.soe.SessionResponse;
|
|
import com.swgnge.network.packets.swg.SWGPacket;
|
|
|
|
public class PacketMaster {
|
|
|
|
private static final int REMOTE_PING_PORT = 44462;
|
|
|
|
public enum ConnectionState {
|
|
NONE,
|
|
CONNECTING,
|
|
CONNECTED,
|
|
DISCONNECTING,
|
|
DISCONNECTED
|
|
}
|
|
|
|
private GUI gui;
|
|
private String [] files;
|
|
private PacketAnalysis packetAnalysis;
|
|
private List <GUIPacket> packets;
|
|
private InetAddress client;
|
|
private int crc = 0x76FBC4BA;
|
|
|
|
public static final void main(String [] args) throws Exception {
|
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
PacketMaster master = new PacketMaster();
|
|
master.initialize();
|
|
master.run();
|
|
master.destroy();
|
|
System.exit(0);
|
|
}
|
|
|
|
public PacketMaster() {
|
|
packetAnalysis = new PacketAnalysis();
|
|
packets = new Vector<GUIPacket>();
|
|
gui = new GUI(packets);
|
|
}
|
|
|
|
public void initialize() throws IOException {
|
|
packetAnalysis.initialize();
|
|
files = new String [] {
|
|
// "Packets/Crafting/craft_BH_armor_set_0xEEDD424D.cap",
|
|
// "Packets/Crafting/craft_lava_resist_kit_0x1EBF709D.cap",
|
|
// "Packets/Crafting/craft_mabari-armor_set_0x7BF2F1CD.cap",
|
|
// "Packets/Crafting/craft_RIS_armor_set_0x7BF9455D.cap",
|
|
// "Packets/Crafting/craft_tailor_bandoliers_AIO Cap_0x7EBF5F20.cap",
|
|
// "Packets/Full PSWG Capture.pcap",
|
|
// "Packets/pswg_capture2.cap",
|
|
// "Packets/corellia_city.cap",
|
|
// "Packets/dantooine_city.cap",
|
|
// "Packets/mandalore.cap",
|
|
// "Packets/talus_city.cap",
|
|
"Packets/tattoine_city.cap",
|
|
// "Packets/tattoine_wayfar.cap",
|
|
// "Packets/speak_to_romo_vax.pcap"
|
|
// "Packets/kill_romo_vax.pcap"
|
|
};
|
|
}
|
|
|
|
public void run() throws UnknownHostException {
|
|
final StringBuilder errbuf = new StringBuilder(); // For any error msgs
|
|
for (String file : files) {
|
|
System.out.printf("Opening file for reading: %s%n", file);
|
|
Pcap pcap = Pcap.openOffline(file, errbuf);
|
|
if (pcap == null) {
|
|
System.err.printf("Error while opening device for capture: " + errbuf.toString());
|
|
return;
|
|
}
|
|
runAnalysis(pcap);
|
|
pcap.close();
|
|
}
|
|
while (!gui.isClosed()) {
|
|
try { Thread.sleep(50); } catch (InterruptedException e) { break; }
|
|
}
|
|
}
|
|
|
|
public void destroy() {
|
|
packetAnalysis.summarize();
|
|
}
|
|
|
|
private void runAnalysis(Pcap pcap) throws UnknownHostException {
|
|
PcapPacket packet = new PcapPacket(500);
|
|
int packetCount = 0;
|
|
Ip4 ip = new Ip4();
|
|
InetAddress addr = null;
|
|
Payload p = null;
|
|
while (pcap.nextEx(packet) == 1) {
|
|
if (packet == null)
|
|
return;
|
|
if (packet.hasHeader(ip)) {
|
|
addr = InetAddress.getByAddress(ip.source());
|
|
}
|
|
p = new Payload();
|
|
JBuffer buffer = packet.getHeader(p);
|
|
onPacket(addr, buffer.getByteArray(0, new byte[buffer.size()]), 0);
|
|
packetCount++;
|
|
if (packetCount == -1)
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void onPacket(InetAddress addr, byte [] data, int port) {
|
|
int length = data.length;
|
|
if (length < 2)
|
|
return;
|
|
if (port != REMOTE_PING_PORT) {
|
|
if (data[0] == 0 && data[1] == 1) {
|
|
// System.out.println("Client: " + addr.toString());
|
|
this.client = addr;
|
|
packetAnalysis.setClient(addr);
|
|
} else if (data[0] == 0 && data[1] == 2) { // SessionResponse
|
|
// System.out.println("Server: " + addr.toString());
|
|
packetAnalysis.setServer(addr);
|
|
processSessionResponse(data);
|
|
} else {
|
|
ByteBuffer decrypt = Encryption.decode(ByteBuffer.wrap(data), crc);
|
|
if (decrypt.array().length >= 2) {
|
|
process(addr, decrypt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void process(InetAddress addr, ByteBuffer data) {
|
|
if (data.remaining() < 2)
|
|
return;
|
|
short opcode = data.getShort();
|
|
switch (opcode) {
|
|
case 3: {
|
|
MultiPacket multi = new MultiPacket();
|
|
multi.decode(data);
|
|
for (Packet p : multi.getPackets())
|
|
process(addr, p.getData());
|
|
break;
|
|
}
|
|
case 9:
|
|
processDataChannelA(addr, data);
|
|
break;
|
|
}
|
|
if (opcode >= 0x1E) {
|
|
data.position(0);
|
|
Packet.getShort(data); // Priority
|
|
int swgOpcode = Packet.getInt(data);
|
|
data.position(0);
|
|
process(addr, swgOpcode, data);
|
|
}
|
|
}
|
|
|
|
private void processDataChannelA(InetAddress addr, ByteBuffer buf) {
|
|
DataChannelA data = new DataChannelA(buf);
|
|
Vector<SWGPacket> packets = data.getPackets();
|
|
for (SWGPacket packet : packets) {
|
|
ByteBuffer pData = packet.getData();
|
|
pData.position(0);
|
|
process(addr, packet.getSWGOpcode(), pData);
|
|
}
|
|
}
|
|
|
|
private void process(InetAddress addr, int opcode, ByteBuffer data) {
|
|
// packetAnalysis.onPacket(addr, opcode, data);
|
|
data.position(0);
|
|
SWGPacket packet = PacketType.getForCrc(opcode);
|
|
packet.decode(data);
|
|
packets.add(new GUIPacket(packet, PacketType.fromCrc(opcode), opcode, addr.equals(client)));
|
|
gui.repaint();
|
|
}
|
|
|
|
private void processSessionResponse(byte [] data) {
|
|
SessionResponse res = new SessionResponse(ByteBuffer.wrap(data));
|
|
crc = res.getCrcSeed();
|
|
// System.out.println("New CRC: 0x" + Integer.toHexString(crc).toUpperCase());
|
|
}
|
|
|
|
}
|