使用jna调用windows api,前提是jna提供了dll的一些操作方法, 但是具体接口映射需要在java实现一遍映射
这里分了几个小文件做映射
先看main class
/*
* This source file was generated by the Gradle 'init' task
*/
package wpcap.app;
import java.net.InetAddress;
import com.sun.jna.ptr.IntByReference;
import wpcap.library.WinSock2Library;
import wpcap.library.structure.WsaDataStructure;
import wpcap.library.structure.SockaddrInStructure;
public class Main {
public static void main(String[] args) {
// 开启 WSAStartup
WsaDataStructure WsaDataStructure = new WsaDataStructure();
int errno = WinSock2Library.INSTANCE.WSAStartup((short)0x0202, WsaDataStructure);
if (errno != 0) {
System.out.println("WSAStartup: " + errno);
return;
}
System.out.println(new String( WsaDataStructure.szDescription ) );
// 创建 socket
long raw_socket = WinSock2Library.INSTANCE.socket(WinSock2Library.AF_INET, WinSock2Library.SOCK_RAW, WinSock2Library.IPPROTO_IP);
System.out.println("socket: " + raw_socket);
if (raw_socket == 0) {
System.out.println("socket: " + errno);
return;
}
// 允许接收ip头
byte[] enable = {1};
WinSock2Library.INSTANCE.setsockopt(
raw_socket,
WinSock2Library.IPPROTO_IP,
WinSock2Library.IP_HDRINCL,
enable,
Integer.SIZE
);
// 绑定监听的ip和端口
SockaddrInStructure SockaddrInStructure = new SockaddrInStructure();
SockaddrInStructure.sin_family = (short)WinSock2Library.AF_INET;
SockaddrInStructure.sin_port = (short)0;
try {
InetAddress localHost = InetAddress.getLocalHost();
byte[] ip = localHost.getAddress();
System.arraycopy(ip, 0, SockaddrInStructure.sin_addr, 0, 4);
} catch (Exception e) {
System.out.println(e);
}
errno = WinSock2Library.INSTANCE.bind(raw_socket, SockaddrInStructure, SockaddrInStructure.size());
if (errno != 0) {
System.out.println("bind: " + errno);
return;
}
// 设置混杂模式
IntByReference dwValue = new IntByReference( WinSock2Library.SIO_RCVALL_ON );
errno = WinSock2Library.INSTANCE.ioctlsocket( raw_socket, WinSock2Library.SIO_RCVALL, dwValue );
if (errno != 0) {
System.out.println("WSAGetLastError: " + errno);
return;
}
System.out.println("启动成功");
// 开始接收数据包
byte[] buf = new byte[512];
while (true) {
int rec = WinSock2Library.INSTANCE.recv(raw_socket, buf, 512, 0);
if ( rec != -1 ) {
System.out.println("rec: " + rec);
}
}
}
}
接着是WinSock2Library.java 映射WinSock2.h
package wpcap.library;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
import wpcap.library.structure.WsaDataStructure;
import wpcap.library.structure.SockaddrInStructure;
// char* ByteByReference或Pointer
// char** PointerByReference
// char& PointerByReference
// int* IntByReference或Pointer
// int& IntByReference
// float* FloatByReference或Pointer
// double* DoubleByReference或Pointer
// void ** PointerByReference
// void* Pointer
// LPCVOID byte[]/Pointer
// DWORD int/long
// LPDWORD IntByReference/LongByReference
// LPOVERLAPPED com.sun.jna.platform.win32.WinBase.OVERLAPPED
// OVERLAPPED com.sun.jna.platform.win32.WinNT.OVERLAPPED_COMPLETION_ROUTINE
// LPCWSTR String
// LPWSTR char[]/String
// HANDLE com.sun.jna.platform.win32.WinNT.HANDLE
// SIZE_T int/long
// PDWORD DWORDByReference
// Pointer Memory
// DWORD DWORD
public interface WinSock2Library extends Library {
WinSock2Library INSTANCE = (WinSock2Library) Native.load("ws2_32", WinSock2Library.class);
int WSAStartup(short wVersionRequired, WsaDataStructure lpWSAData);
long socket(int family, int socktype, int protocol);
int setsockopt(long socket, int protocol, int opt, byte[] optVal, int optLen);
int bind(long socket, SockaddrInStructure sockaddr, int sockaddr_len);
int ioctlsocket(long socket, long dwIoControlCode, IntByReference lpvInBuffer);
int recv(long socket, byte[] buf, int len, int flags);
int WSAGetLastError();
int AF_INET = 2;
int SOCK_RAW = 3;
int IPPROTO_IP = 0;
long SIO_RCVALL = 0x98000001L; // 2550136833
int SIO_RCVALL_ON = 0x00000001;
int IP_HDRINCL = 2;
}
接着是结构体映射
WsaDataStructure.java
package wpcap.library.structure;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
@FieldOrder({"wVersion", "wHighVersion", "szDescription", "szSystemStatus", "iMaxSockets", "iMaxUdpDg", "lpVendorInfo"})
public class WsaDataStructure extends Structure {
public short wVersion;
public short wHighVersion;
public short iMaxSockets;
public short iMaxUdpDg;
public char lpVendorInfo;
public byte[] szDescription = new byte[WSADESCRIPTION_LEN + 1];
public byte[] szSystemStatus = new byte[WSASYS_STATUS_LEN + 1];
public static final int WSADESCRIPTION_LEN = 256;
public static final int WSASYS_STATUS_LEN = 128;
}
SockaddrInStructure.java
package wpcap.library.structure;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
@FieldOrder({"sin_family", "sin_port", "sin_addr", "sin_zero"})
public class SockaddrInStructure extends Structure {
public short sin_family;
public short sin_port;
public byte[] sin_addr = new byte[4];
public byte[] sin_zero = new byte[8];
}
Library是映射对应的dll接口
Struture是映射一些数据结构
以这种映射的方法达到java使用jna来调用windows api实现抓包