Closed TeamB1-GP closed 3 months ago
When the trailer option is enabled, PCAPdroid will add a fake ethernet header to the packet. So in this case you need to parse the packet as Ethernet, try to replace IpV4Packet with EthernetPacket
This is as simple as changing the parsing function in CaptureThread.java
to make an Ethernet packet:
EthernetPacket pkt = EthernetPacket.newPacket(buf, 16, len - 16);
Then, in the callback (here I made a new one onEthPacketReceived
):
void onPacketReceived(EthernetPacket pkt) {
if (pkt.getPayload() instanceof IpV4Packet) {
IpV4Packet ipV4Packet = (IpV4Packet) pkt.getPayload();
IpV4Packet.IpV4Header hdr = ipV4Packet.getHeader();
mLog.append(String.format("[%s] %s -> %s [%d B]\n",
hdr.getProtocol(),
hdr.getSrcAddr().getHostAddress(), hdr.getDstAddr().getHostAddress(),
ipV4Packet.length()));
} else {
Log.w(TAG, "Received non-IPv4 packet");
}
}
To actually handle the trailer contents, you can add a bit of code:
private static final int PCAPDROID_TRAILER_SIZE = 32;
private static final int PCAPDROID_MAGIC = 0x01072021;
private static final int FCS_SIZE = 4;
void onPacketReceived(EthernetPacket pkt) {
int ethPayloadLength = pkt.length();
if (ethPayloadLength < PCAPDROID_TRAILER_SIZE) {
Log.w(TAG, "Packet too short to contain trailer");
return;
}
byte[] trailer = Arrays.copyOfRange(pkt.getRawData(), ethPayloadLength - PCAPDROID_TRAILER_SIZE, ethPayloadLength - FCS_SIZE);
ByteBuffer trailerBuffer = ByteBuffer.wrap(trailer);
int magic = trailerBuffer.getInt(0);
int uid = trailerBuffer.getInt(4);
byte[] appNameBytes = new byte[20];
trailerBuffer.position(8);
trailerBuffer.get(appNameBytes, 0, 20);
String appName = new String(appNameBytes, StandardCharsets.UTF_8).trim();
if (magic != PCAPDROID_MAGIC) {
Log.w(TAG, "Invalid magic number: " + Integer.toHexString(magic));
return;
}
if (pkt.getPayload() instanceof IpV4Packet) {
IpV4Packet ipV4Packet = (IpV4Packet) pkt.getPayload();
// Handle the IPv4 packet (similar to the previous example)
IpV4Packet.IpV4Header hdr = ipV4Packet.getHeader();
mLog.append(String.format("[%s] %s -> %s [%d B] (App: %s, UID: %d)\n",
hdr.getProtocol(),
hdr.getSrcAddr().getHostAddress(), hdr.getDstAddr().getHostAddress(),
ipV4Packet.length(), appName, uid));
} else {
Log.w(TAG, "Received non-IPv4 packet");
}
}
This prints the app and UID:
@slhck this would be a great addition for a pull request 😉
If I set the pcapdroid_trailer property to true in the intent, the CaptureThread always sees an exception thrown when trying to parse the IPv4 packet. If I set the property to false or remove it, I see lots of happy packets.
The actual exception is "org.pcap4j.packet.IllegalRawDataException: The ihl must be equal or more than5but it is: 0". The error happens in the ipV4Packet parsing code, but that was called from line 62 in CaptureThread.
I speculate that when the trailer packet is appended, the packet parsing or the size difference might be getting confused? Maybe it just doesn't see it as the trailer and thinks it must be another IP header/packet? Maybe the "len - 16" needs some adjusting if the trailer is in place? Something else?