wiki:KrakenPcap
Last modified 2 years ago

Kraken PCAP

Introduction

Kraken PCAP is java based TCP/IP stack implementation for network sniffer. You maybe have experienced various Unix and C oriented opensource solutions. They are fast and efficient, but very hard to customize and extend. If you are network engineer, you will want to automate a lot of tedious jobs. Network intelligence can be useful for anything, and Java technology is used everywhere nowadays, but where is opensource TCP/IP stack for Java world? How can I add network intelligence to existing enterprise solutions?

Kraken PCAP is here for you.

Author

Requirements

  • winpcap or libpcap is required for live sniffing and injection.

Tutorial

Usage

Basic concepts

Kraken PCAP uses pipeline architecture style. Protocol decoders form protocol decoding pipeline. For example, EthernetDecoder accepts PcapPacket, decodes ethernet frame, and dispatches an ethernet frame to all EthernetProcessor callbacks. IpDecoder is a EthernetProcessor, and it accepts EthernetFrame which has ethertype 0x0800, decodes IpPacket, and dispatches an ip packet to all IpProcessor, and so on. You can build your own protocol decoding pipeline, or add your own protocol decoder.

Let's see an example:

public static void main(String[] args) throws Exception {
	File f = new File("sample.pcap");

	EthernetDecoder eth = new EthernetDecoder();
	IpDecoder ip = new IpDecoder();
	TcpDecoder tcp = new TcpDecoder(new TcpPortProtocolMapper());
	UdpDecoder udp = new UdpDecoder(new UdpPortProtocolMapper());

	eth.register(EthernetType.IPV4, ip);
	ip.register(InternetProtocol.TCP, tcp);
	ip.register(InternetProtocol.UDP, udp);

	PcapInputStream is = new PcapFileInputStream(f);
	while (true) {
		// getPacket() will throws EOFException and you should call is.close() 
		PcapPacket packet = is.getPacket();
		eth.decode(packet);
	}
}

It just sets up pipeline and decodes ethernet, ip, tcp, udp packets, and do nothing for you. But I hope you understand basic concepts and idea from this example. TcpPortProtocolMapper binds port to specific protocol. You can use another tcp/udp protocol mapper. (e.g. heuristic protocol mapper)

This is flexible and pluggable approach, however it's very tedious job. PcapFileRunner and PcapLiveRunner do all this kinds of initialization steps, so you can just set application protocol decoder and run immediately.

About Buffer

TODO: I will explain details later.

public interface Buffer {
	List<byte[]> getBuffers();
	
	int getCapacity();
	
	int getBufIndex();
	
	int getOffset();	

	// chain new buffer
	void addFirst(Buffer buffer);

	void addLast(Buffer buffer);
	
	void addLast(Buffer buffer, int length); 
	
	void addFirst(byte[] buffer);

	void addLast(byte[] buffer);

	// getters	
	byte get();

	short getShort();

	int getInt();

	long getLong();

	String getString(int length);

	String getString(int length, String charsetName);

	String getString(int length, Charset charset);

	void gets(byte[] buffer);

	void gets(byte[] buffer, int offset, int length);

	// position manipulation
	void discardReadBytes();

	boolean isEOB();

	int position();

	Buffer position(int newPosition);

	void mark();

	Buffer skip(int pos);

	void rewind();

	Buffer reset();

	Buffer clear();

	// search
	int bytesBefore(byte[] target);

	int readableBytes();
}

IPv6 Issue

public interface Ipv6Processor {
	void process(Ipv6Packet p);
}

Kraken PCAP can support IPv6, but it's still experimental. For now, IPv6 decoder do not support IPv6 header extension (e.g. fragmentation header) TCP/UDP stack use InetAddress for addressing, therefore it's future-proof.

ARP Processor

ICMP Processor

There are ICMP processor and ICMPv6 processor.

public interface IcmpProcessor {
	void process(IcmpPacket p);
}

public interface Icmpv6Processor {
	void process(Icmpv6Packet p);
}

Icmpv6Decoder should be plugged to the Ipv6Decoder. For example:

Ipv6Decoder ipv6 = new Ipv6Decoder();
Icmpv6Decoder icmpv6 = new Icmpv6Decoder();
icmpv6.register(YOUR_ICMPV6_PROCESSOR);
ipv6.register(InternetProtocol.ICMPV6, icmpv6);

TCP Segment Callback

In some cases, you need to receive tcp packets instead of reassembled tcp stream. For example, TCP port scan probes do not establish connections, therefore you need a TCP segment callback. Sometimes you may want to summarize TCP protocol usage statistics. In these cases, implement TcpSegmentCallback interface and invoke TcpDecoder.registerSegmentCallback().

public interface TcpSegmentCallback {
	void onReceive(TcpSession session, TcpSegment segment);
}

TcpSession parameter can be null if it does not belong to any session.

TCP Processor

If you want to implement new TCP protocol decoder, you should implement TcpProcessor callback interface.

public interface TcpProcessor {
	void onEstablish(TcpSessionKey key);
	
	void onFinish(TcpSessionKey key);

	void onReset(TcpSessionKey key);	

	// byte[] will be replaced by Buffer (in 1.4.0)	
	void handleTx(TcpSessionKey session, byte[] data);
	
	void handleRx(TcpSessionKey session, byte[] data);
}

Build your own application session object when onEstablish() is called, and clean up session when onFinish() or onReset() is called. handleTx() means client to server data, and handleRx() means server to client data. If Tx/Rx concept is confusing, imagine TCP client view. TCP client transmits (TX) to server, and receives (RX) from server. TcpSessionKey contains client ip address and server ip address. (support both IPv4 and IPv6 address using InetAddress)

UDP Processor

It's very simple to implement new UDP protocol decoder. Just implement UdpProcessor callback interface:

public interface UdpProcessor {
	void process(UdpPacket p);
}

Then add UdpProcessor like this:

runner.setUdpProcessor(Protocol.DHCP, new DhcpProcessor());

Dump Analysis

HTTP dump analysis can be done with few lines of code. (See Kraken Http Decoder for details)

PcapFileRunner runner = new PcapFileRunner(new File("http.pcap"));
HttpDecoder http = new HttpDecoder();
http.register(new DefaultHttpProcessor() {
	@Override
	public void onRequest(HttpRequest req) {
	}

	@Override
	public void onResponse(HttpRequest req, HttpResponse resp) {
		System.out.println(req.getURL());
	}
});
runner.setTcpProcessor(Protocol.HTTP, http);
runner.run();

There are many pre-built application protocol decoders, and they provide callback mechanism. In this example, HttpDecoder accepts HttpProcessor callback, and dispatches fully decoded HttpRequest and/or HttpResponse to callbacks. Even if you don't know anything about HTTP specification, you can analyze http traffic. Just add your own callback.

Dump Merging

Merge splitted pcap files:

PcapMerger.merge(File to, File from);

PcapMerger.merge(File output, File first, File second);

Live Analysis and Injection

Prepare Native Library

  • If you do not run Kraken PCAP on OSGi container (e.g. Kraken Core), you should load kpcap library first.
    • System.loadLibrary("kpcap");
    • Kraken PCAP embeds all platform binaries in JAR file, and OSGi container loads appropriate native binary automatically.
  • Check out source, build kpcap library, and install on java.library.path.
    • svn export http://krakenapps.org/svn/kraken-pcap/src/main/c/
    • Linux: make clean; make; make install
    • Windows: Open kpcap.sln and build it using Visual Studio.

Device Enumeration

PcapDeviceManager manages all pcap device, and recommends device for target ip.

Enumerate all pcap devices:

System.loadLibrary("kpcap");
for (PcapDeviceMetadata metadata : PcapDeviceManager.getDeviceMetadataList() {
	System.out.println(metadata);
}

// will print out
name={BCEFC3FC-73EC-41C5-9EBC-25A4F645D748}, description=MS Tunnel Interface Driver, mac=00:00:00:00:00:00
name={AFF4C6CC-2C74-485A-8A7F-807712D18A24}, description=TAP-Win32 Adapter V8, mac=00:FF:AF:F4:C6:CC
name={5E955A8C-E8A8-4A02-8EDB-161136A6886A}, description=Microsoft, mac=00:22:69:D3:4E:33
name={FE8D1EF3-3E0B-46ED-B776-217C4F180D15}, description=Marvell Yukon Ethernet Controller., mac=00:13:77:B9:E5:47
name={A569FFF6-617E-4B48-92D3-D086C63857AD}, description=Microsoft, mac=00:16:EA:D3:A6:0F

Get device metadata by name or target address:

PcapDeviceMetadata getDeviceMetadata(String name);

PcapDeviceMetadata getDeviceMetadata(InetAddress target);

Open Device

PcapDeviceManager can open pcap device.

Open pcap device for specific ip address:

PcapDevice openFor(InetAddress target, int timeout);

PcapDevice openFor(InetAddress target, Promiscuous promisc, int timeout);

Open device by name:

PcapDevice open(String name, int milliseconds);

PcapDevice open(String name, Promiscuous promisc, int milliseconds);

PcapDevice open(String name, Promiscuous promisc, int milliseconds, int snaplen);

Dump Live Traffic

Generate pcap dump file which contains 1000 packets:

PcapInputStream is = PcapDeviceManager.open("eth0", Promiscuous.On, 5000);
PcapOutputStream os = new PcapFileOutputStream(new File("dump.pcap"));

for (int i = 0; i < 1000; i++)
        os.write(is.getPacket());

is.close();
os.close();

Routing Table

Kraken PCAP uses routing table for automatic device selection.

System.loadLibrary("kpcap");

for (RoutingEntry entry : RoutingTable.getRoutingEntries()) {
	System.out.println(entry);
}

// will print out (windows example)
name={A569FFF6-617E-4B48-92D3-D086C63857AD}, destination=0.0.0.0, mask=0.0.0.0, gateway=192.168.0.1, metric=25
name={3A539854-6A70-11DB-887C-806E6F6E6963}, destination=127.0.0.0, mask=255.0.0.0, gateway=127.0.0.1, metric=306
name={3A539854-6A70-11DB-887C-806E6F6E6963}, destination=127.0.0.1, mask=255.255.255.255, gateway=127.0.0.1, metric=306
name={3A539854-6A70-11DB-887C-806E6F6E6963}, destination=127.255.255.255, mask=255.255.255.255, gateway=127.0.0.1, metric=306
name={A569FFF6-617E-4B48-92D3-D086C63857AD}, destination=192.168.0.0, mask=255.255.255.0, gateway=192.168.0.5, metric=281
name={A569FFF6-617E-4B48-92D3-D086C63857AD}, destination=192.168.0.5, mask=255.255.255.255, gateway=192.168.0.5, metric=281
name={A569FFF6-617E-4B48-92D3-D086C63857AD}, destination=192.168.0.255, mask=255.255.255.255, gateway=192.168.0.5, metric=281
name={3A539854-6A70-11DB-887C-806E6F6E6963}, destination=224.0.0.0, mask=240.0.0.0, gateway=127.0.0.1, metric=306
name={A569FFF6-617E-4B48-92D3-D086C63857AD}, destination=224.0.0.0, mask=240.0.0.0, gateway=192.168.0.5, metric=284
name={3A539854-6A70-11DB-887C-806E6F6E6963}, destination=255.255.255.255, mask=255.255.255.255, gateway=127.0.0.1, metric=306
name={A569FFF6-617E-4B48-92D3-D086C63857AD}, destination=255.255.255.255, mask=255.255.255.255, gateway=192.168.0.5, metric=281

Sniffing

Replay

This is a java equivalent of TCP Replay. (and it works on windows!)

Replay your traffic dump:

PcapDumpReplay.replay(PcapDevice device, File file);

Implementation is also very simple:

PcapInputStream is = new PcapFileInputStream(file);
try {
	while (true)
		device.write(is.getPacket());
} catch (EOFException e) {
}

Packet Construction

All packets should implement Injectable interface.

public interface Injectable {
	Buffer getBuffer();
}

Each packet class embeds Builder which implements PacketBuilder interface.

public interface PacketBuilder {
	// build serializable object.
	Injectable build();

	// retrieves default value from this bulider or from upper builders.
	Object getDefault(String name);
}

TODO: I will explain details later.

ARPing

// query one mac address for specific ip
MacAddress query(InetAddress target, int timeout);

// scan all target addresses within timeout (fast)
Map<InetAddress, MacAddress> scan(String deviceName, Collection<InetAddress> targets, int timeout);

// for example
MacAddress mac = Arping.query(InetAddress.getByName("192.168.0.1"), 1000); 

Arping.query() automatically detects pcap device using routing table and target ip, and sends ARP request. Kraken PCAP does not cache ARP replies.

Ping

Ping class implements ICMP echo request.

// timeout in milliseconds
IcmpPacket Ping.ping(InetAddress target, int timeout) throws IOException, TimeoutException;

// for example
IcmpPacket reply = Ping.ping(InetAddress.getByName("krakenapps.org"), 2000);

TCP Port Scan

TcpPortScanner provides four methods for stealth scan.

  • SYN scan will returns SYN/ACK packet for opened port.
  • FIN, XMAX, NULL scan methods will returns RST packet for closed port.
TcpPortScanner.synScan(target, timeout);
TcpPortScanner.finScan(target, timeout);
TcpPortScanner.xmasScan(target, timeout);
TcpPortScanner.nullScan(target, timeout);

How can I build this probe packets? very easy.

import static org.krakenapps.pcap.util.PacketManipulator.*;

// syn scan packet
IP().data(TCP().syn().dst(target);

// fin scan packet
IP().data(TCP().fin().dst(target);

// xmas scan packet
IP().data(TCP().fin().urg().psh().dst(target);

// null scan packet
IP().data(TCP().dst(target);

Land attack

ARP Spoofing

Wake on Lan

You can send WOL packet using just one line of code.

WakeOnLan.wake(new MacAddress("00:11:22:aa:bb:cc"));

WOL packet construction in details:

import static org.krakenapps.pcap.util.PacketManipulator.*;

class WakeOnLanBuilder implements PacketBuilder {
	private MacAddress target;

	public WakeOnLanBuilder(MacAddress target) {
		this.target = target;
	}

	@Override
	public Injectable build() {
		byte ff = (byte) 0xff;
		byte[] b = target.getBytes();

		final Buffer buf = new ChainBuffer(new byte[] { ff, ff, ff, ff, ff, ff });
		for (int i = 0; i < 16; i++)
			buf.addLast(b);

		return new Injectable() {
			@Override
			public Buffer getBuffer() {
				return buf;
			}
		};
	}

	@Override
	public Object getDefault(String name) {
		return null;
	}
}

broadcast(ETH().dst(target).type(0x0842).data(new WakeOnLanBuilder(target)));

broadcast() opens all pcap devices and injects data.

If you feel that packet builder is too verbose, you can build and pass a pre-encoded buffer to data(). But it's not readable because it does not expose packet structure.

Maven Configuration

  • Repository:  http://download.krakenapps.org
    <project>
      <dependencies>
        <dependency>
          <groupId>org.krakenapps</groupId>
          <artifactId>kraken-pcap</artifactId>
          <version>1.3.0</version>
        </dependency>
      </dependencies>
    </project>
    

See Also

  • Applications
    • Kraken Sonar
    • Kraken Stormbringer

Release History

  • 1.3.0 (unstable)