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 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(); 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 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()); } }