jpacp插件实现魔兽局域网连接,难点解决
程序员文章站
2024-03-17 19:37:58
...
很久没写技术型博文了,最近一直在研究java的第三方jar包jpacp。想研究研究这玩意是否能实现局域网搜索。经过20多天的努力,将几个技术难点通通解决,最终得出结论,完全可以用它来实现局域网互连,只是如果做出来后,没有著名的WarSeacher那么简洁,精巧,方便。因为它比较依赖于安装环境,1,必须装wincacp 2、必须装jdk。3.界面的美观与操作性也是个问题。
下面我将列出这些天攻克的技术难点。
第一。怎么抓war发送的搜索包,地图包,与建主包。是需要用java写,还是利用开源的项目。
第二。抓到包以后需不需要自己解析,然后发给war,告诉它这是我解析后的包。
第三。抓到以后在局域网里能看到,但你点击它就是无法加入游戏。
很幸运的,我在网上找到了java语言的第三方jar包,后来经过仔细研究源代码,发现可以干很多底层的事情,比如,发送带ip报头的数据包,修改,ip报头的ip地址。
先说解决的难点。利用jpacp抓网络上的包。先声明下,以下的所有环节,都是建立在先装好wincacp,jdk,jpacp的环境上的。(有些图片不能即时插入到对应的文字下面,就只好都放到附件里面了,大家对应着看吧)
利用jpacp的抓包程序
这段代码我整了好久的,主要是分析抓到的包里面的data是什么东西,因为都是16进制的,所以,在网上查了好多资料,才弄明白对应的都是什么意思。这是我用txt文档记录的一些日志。
[i]客户端收到从主机发来的包: f7 32 10 00 03 00 00 00 01 00 00 00 0a 00 00 00 (我建主了)
客户端向主机发送的搜索包: F7 2F 10 00 50 58 33 57 15 00 00 00 00 00 00 00 (我看看你建的什么主)
Dota /6.74c 版本的地图包:
f7 30 9e 00 50 58 33 57 0-7
18 00 00 00 02 00 00 00 8-15
e2 1c fd 0d 74 65 73 74 16-23
20 70 6c 61 79 20 64 6f 24-31
74 61 20 62 79 20 6c 69 32-39
79 61 68 75 69 2e 8f 20 40-47
28 77 77 00 00 01 03 49 48-55
07 01 01 77 01 91 79 01 56-63
e3 f1 8f 87 4d cb 61 71 64-71
73 5d 45 6f 77 19 6f 6d 72-79
6f 61 65 5d 45 0b 6f 75 80-87
41 21 77 37 2f 6b 37 35 88-95
63 2f 77 33 79 9d 01 77 96-103
77 77 63 63 73 f1 01 01 104-111
ff 19 e7 f1 71 73 d1 e5 112-119
07 8b 97 e1 27 07 b3 c7 120-127
1f 1f 89 9d a5 01 f1 00 128-135
0a 00 00 00 01 00 00 00 136-143
01 00 00 00 0a 00 00 00 144-151
63 00 00 00 e0 17 152-157
地图包的byte类型 :
-9, 48, -98, 0, 80, 88, 51, 87, 24, 0, 0-9
0, 0, 1, 0, 0, 0, 114, -27, 101, 11, 10-19
116, 101, 115, 116, 32, 112, 108, 97, 121, 32, 20-29 // 从第二十个开始,32个 游戏信息,大部分是:“当地局域网内游戏(X……”
100, 111, 116, 97, 32, 98, 121, 32, 108, 105, 30-39
121, 97, 104, 117, 105, 46, -113, 32, 40, 119, 40-49
119, 0, 0, 1, 3, 73, 7, 1, 1, 119, 50-59
1, -111, 121, 1, -29, -15, -113, -121, 77, -53, 60-69 // 从69个开始,地图路径,大概32个
97, 113, 115, 93, 69, 111, 119, 25, 111, 109, 70-79
111, 97, 101, 93, 69, 11, 111, 117, 65, 33, 80-89
119, 55, 47, 107, 55, 53, 99, 47, 119, 51, 90-99
121, -99, 1, 119, 119, 119, 99, 99, 115, -15, 100-109
1, 1, -1, 25, -25, -15, 113, 115, -47, -27, 110-119
7, -117, -105, -31, 39, 7, -77, -57, 31, 31, 120-129
-119, -99, -91, 1, -15, 0, 10, 0, 0, 0, 130-139
1, 0, 0, 0, 1, 0, 0, 0, 10, 0, 140-149
0, 0, -71, 0, 0, 0, -32, 23 150-157[/i]
不过后来我才发现,有现成的东西去截取网络数据包,并能很好的分析它。CommView就是一款很好的IP包捕获,分析软件。我后来就都是用它来监测的,非常好用,非常方便。附件里有CommView的截图
报文截取到了,当时那个兴奋啊。。好了,有数据了我就天天分析那些16进制代码,发现有地图包,但是打开war.exe后,在局域网里怎么也看不到我用javaw.exe程序发送的地图包,经过网上的资料搜索后,发现原来是地图版本的问题,在报文头里面有一个字节是代表war版本的,如果对不上,当然就看不到,所以我就改,改成了正确的版本。
这个0x18是1.24的版本,原来是0x14(是比较早的1.20的版本),改过来后,在魔兽局域网里代开一看,我了个擦,看到了发java建的主,也就是过javaw.exe发过来的数据包,那个兴奋劲哦。真过瘾。
好了,到了这一步,就碰到了最难,解决时间最长的问题。在局域网里点击那个java建的主之后,显示“无法加入游戏”。
我到网上查了资料,说是因为那个IP包里的IP是本机的IP,war收到后,相当于用本机的ip连本机的ip,所以当然不行。解决办法是,必须把那个src_ip也就是来源ip改掉,改成真正建主的ip。
经过一番努力,发现jpacp可以改,并且改成功了。
至于这个过程是比较辛苦,就不谈了,因为毕竟是一个人在干,什么都不明白,只能摸着石头过河,靠网上找资料,自己分析,实验,来检验网上的程序正确性。
我就直接贴代码吧。这是利用jpacp改IP包头的程序。经过测试,利用两台机器,一台机器建主,一台机器连主机,主机跑这个java程序,实验结果是可以连上。连上之后,我在公司控制主自己的兴奋,写了这篇文章。
以上几个关键点都解决了,相信开发出一个java写的魔兽局域网搜索器不是问题。
在这里先做个总结吧,以后有时间了,再开发出一套完整的客户端来。
还有,以上内容都是在工作时间写,由于近来公司刚结束完一个项目,所以一直比较闲,也没学公司的资料,就一直在偷偷的搞这个。写的比较粗糙,以后慢慢再改,仅供对jpacp,udp的学习参考。
下面我将列出这些天攻克的技术难点。
第一。怎么抓war发送的搜索包,地图包,与建主包。是需要用java写,还是利用开源的项目。
第二。抓到包以后需不需要自己解析,然后发给war,告诉它这是我解析后的包。
第三。抓到以后在局域网里能看到,但你点击它就是无法加入游戏。
很幸运的,我在网上找到了java语言的第三方jar包,后来经过仔细研究源代码,发现可以干很多底层的事情,比如,发送带ip报头的数据包,修改,ip报头的ip地址。
先说解决的难点。利用jpacp抓网络上的包。先声明下,以下的所有环节,都是建立在先装好wincacp,jdk,jpacp的环境上的。(有些图片不能即时插入到对应的文字下面,就只好都放到附件里面了,大家对应着看吧)
利用jpacp的抓包程序
package com.lyh.test;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import com.lyh.common.Util;
import jpcap.*;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;
import jpcap.packet.UDPPacket;
class Tcpdump implements PacketReceiver {
public static Packet packet ;
public static NetworkInterface[] devices = JpcapCaptor.getDeviceList();
public static JpcapSender jp;
public void receivePacket(Packet packet) {
this.packet = packet;
System.out.println("======================================");
System.out.println(packet);
System.out.println("sec --"+packet.sec);
System.out.println("uec --"+packet.usec);
System.out.println("datalink dst_mac[]--"+packet.datalink);
System.out.println("datalink src_mac[]--"+packet.datalink);
System.out.println("header --" +" length--"+ packet.header.length + "--" + Arrays.toString(packet.header));
System.out.println("data --"+" length--" +packet.data.length + " --"+ Arrays.toString(packet.data));
System.out.println("len --" + packet.len);
System.out.println("caplen -- " + packet.caplen);
System.out.println("header[] --"+Util.bytesToHexString(packet.header));
System.out.println("data[] --"+Util.bytesToHexString(packet.data));
System.out.println("======================================");
System.out.println();
try {
Thread.sleep(1);
IPPacket ip = (IPPacket)packet ;
try {
ip.setIPv4Parameter(ip.priority, ip.d_flag, ip.t_flag, ip.r_flag, ip.rsv_tos, ip.rsv_frag, ip.dont_frag, ip.more_frag, ip.offset, ip.ident, ip.hop_limit, ip.protocol, InetAddress.getByName("172.29.31.202"), ip.dst_ip);
} catch (UnknownHostException e) {
e.printStackTrace();
}
jp.sendPacket(ip);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
if(args.length>1){
for (int i = 0; i < devices.length; i++) {
System.out.println("the index '"+i+"' :"+devices[i].name + "(" + devices[i].description+")");
System.out.println(" data link:"+devices[i].datalink_name + "("
+ devices[i].datalink_description+")");
System.out.print(" MAC address:");
for (byte b : devices[i].mac_address)
System.out.print(Integer.toHexString(b&0xff) + ":");
System.out.println();
for (NetworkInterfaceAddress a : devices[i].addresses)
System.out.println(" address:"+a.address + " " + a.subnet + " "
+ a.broadcast);
}
}else{
JpcapCaptor jpcap = JpcapCaptor.openDevice(devices[0], 1024 * 10 , false, 20);
jpcap.setFilter("host 172.29.31.211", true);
jp = JpcapSender.openDevice(devices[0]);
jpcap.loopPacket(-1, new Tcpdump());
}
}
}
这段代码我整了好久的,主要是分析抓到的包里面的data是什么东西,因为都是16进制的,所以,在网上查了好多资料,才弄明白对应的都是什么意思。这是我用txt文档记录的一些日志。
[i]客户端收到从主机发来的包: f7 32 10 00 03 00 00 00 01 00 00 00 0a 00 00 00 (我建主了)
客户端向主机发送的搜索包: F7 2F 10 00 50 58 33 57 15 00 00 00 00 00 00 00 (我看看你建的什么主)
Dota /6.74c 版本的地图包:
f7 30 9e 00 50 58 33 57 0-7
18 00 00 00 02 00 00 00 8-15
e2 1c fd 0d 74 65 73 74 16-23
20 70 6c 61 79 20 64 6f 24-31
74 61 20 62 79 20 6c 69 32-39
79 61 68 75 69 2e 8f 20 40-47
28 77 77 00 00 01 03 49 48-55
07 01 01 77 01 91 79 01 56-63
e3 f1 8f 87 4d cb 61 71 64-71
73 5d 45 6f 77 19 6f 6d 72-79
6f 61 65 5d 45 0b 6f 75 80-87
41 21 77 37 2f 6b 37 35 88-95
63 2f 77 33 79 9d 01 77 96-103
77 77 63 63 73 f1 01 01 104-111
ff 19 e7 f1 71 73 d1 e5 112-119
07 8b 97 e1 27 07 b3 c7 120-127
1f 1f 89 9d a5 01 f1 00 128-135
0a 00 00 00 01 00 00 00 136-143
01 00 00 00 0a 00 00 00 144-151
63 00 00 00 e0 17 152-157
地图包的byte类型 :
-9, 48, -98, 0, 80, 88, 51, 87, 24, 0, 0-9
0, 0, 1, 0, 0, 0, 114, -27, 101, 11, 10-19
116, 101, 115, 116, 32, 112, 108, 97, 121, 32, 20-29 // 从第二十个开始,32个 游戏信息,大部分是:“当地局域网内游戏(X……”
100, 111, 116, 97, 32, 98, 121, 32, 108, 105, 30-39
121, 97, 104, 117, 105, 46, -113, 32, 40, 119, 40-49
119, 0, 0, 1, 3, 73, 7, 1, 1, 119, 50-59
1, -111, 121, 1, -29, -15, -113, -121, 77, -53, 60-69 // 从69个开始,地图路径,大概32个
97, 113, 115, 93, 69, 111, 119, 25, 111, 109, 70-79
111, 97, 101, 93, 69, 11, 111, 117, 65, 33, 80-89
119, 55, 47, 107, 55, 53, 99, 47, 119, 51, 90-99
121, -99, 1, 119, 119, 119, 99, 99, 115, -15, 100-109
1, 1, -1, 25, -25, -15, 113, 115, -47, -27, 110-119
7, -117, -105, -31, 39, 7, -77, -57, 31, 31, 120-129
-119, -99, -91, 1, -15, 0, 10, 0, 0, 0, 130-139
1, 0, 0, 0, 1, 0, 0, 0, 10, 0, 140-149
0, 0, -71, 0, 0, 0, -32, 23 150-157[/i]
不过后来我才发现,有现成的东西去截取网络数据包,并能很好的分析它。CommView就是一款很好的IP包捕获,分析软件。我后来就都是用它来监测的,非常好用,非常方便。附件里有CommView的截图
报文截取到了,当时那个兴奋啊。。好了,有数据了我就天天分析那些16进制代码,发现有地图包,但是打开war.exe后,在局域网里怎么也看不到我用javaw.exe程序发送的地图包,经过网上的资料搜索后,发现原来是地图版本的问题,在报文头里面有一个字节是代表war版本的,如果对不上,当然就看不到,所以我就改,改成了正确的版本。
public static byte[] warSearch = { (byte) 0xf7, 0x2f, 0x10, 0x00, 0x50,
0x58, 0x33, 0x57, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
这个0x18是1.24的版本,原来是0x14(是比较早的1.20的版本),改过来后,在魔兽局域网里代开一看,我了个擦,看到了发java建的主,也就是过javaw.exe发过来的数据包,那个兴奋劲哦。真过瘾。
好了,到了这一步,就碰到了最难,解决时间最长的问题。在局域网里点击那个java建的主之后,显示“无法加入游戏”。
我到网上查了资料,说是因为那个IP包里的IP是本机的IP,war收到后,相当于用本机的ip连本机的ip,所以当然不行。解决办法是,必须把那个src_ip也就是来源ip改掉,改成真正建主的ip。
经过一番努力,发现jpacp可以改,并且改成功了。
至于这个过程是比较辛苦,就不谈了,因为毕竟是一个人在干,什么都不明白,只能摸着石头过河,靠网上找资料,自己分析,实验,来检验网上的程序正确性。
我就直接贴代码吧。这是利用jpacp改IP包头的程序。经过测试,利用两台机器,一台机器建主,一台机器连主机,主机跑这个java程序,实验结果是可以连上。连上之后,我在公司控制主自己的兴奋,写了这篇文章。
package com.lyh.test;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Arrays;
import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.PacketReceiver;
import jpcap.packet.EthernetPacket;
import jpcap.packet.Packet;
import jpcap.packet.UDPPacket;
class TestWar4 implements PacketReceiver {
public static Packet packet ;
public static NetworkInterface[] devices = JpcapCaptor.getDeviceList();
public static JpcapSender jp;
static byte[] data;
static boolean t_flag = false;
public static byte[] warSearch = { (byte) 0xf7, 0x2f, 0x10, 0x00, 0x50,
0x58, 0x33, 0x57, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
public static byte[] replaceDataHead = { 0x00, 0x0B, 0x2F, 0x76, (byte) 0x8D,
0x21, 0x00, 0x23, (byte) 0xAE, (byte) 0xB4, (byte) 0xE0,
(byte) 0xD3, 0x08, 0x00, 0x45, 0x00, 0x00, (byte) 0xBA, 0x5B, 0x57,
0x00, 0x00, 0x40, 0x11, (byte) 0x86, (byte) 0xF0, (byte) 0xAC,
0x1D, 0x1F, (byte) 0xE7, (byte) 0xAC, 0x1D, 0x1F, (byte) 0xCA,
0x17, (byte) 0xE1, 0x17, (byte) 0xE0, 0x00, (byte) 0xA6, 0x0C, 0x6F };
public static byte[] src_mac = { 0x00,0x23, (byte)0xAE, (byte)0xB4,(byte)0xE0, (byte)0xD3};
public static byte[] dst_mac = { 0x00, 0x0B, 0x2F, 0x76, (byte)0x8D, 0x21};
public static byte[] src_port = {0x17,(byte) 0xE1};
public static byte[] dst_port = {0x17,(byte) 0xE0};
public static int len = 42;
DatagramSocket server;
DatagramPacket p;
void init() throws Exception{
server = new DatagramSocket(6113);
p = new DatagramPacket(warSearch, 16, InetAddress.getByName("172.29.31.202"), 6112);
server.send(p);
data = new byte[1024];
p = new DatagramPacket(data, data.length);
server.receive(p);
System.out.println("data[]:" + Arrays.toString(data));
t_flag = true;
}
public void receivePacket(Packet packet) {
try {
if (packet.toString().endsWith("6112") && t_flag) {
this.packet = packet;
Thread.sleep(1000);
UDPPacket udp = (UDPPacket) packet;
//1.改以太网头
EthernetPacket ep = (EthernetPacket)udp.datalink;
ep.src_mac = dst_mac;
ep.dst_mac = src_mac;
//2.修改IP头,将发包地址变为建主的IP。
udp.length = 187;
udp.setIPv4Parameter(udp.priority, udp.d_flag, udp.t_flag,
udp.r_flag, udp.rsv_tos, udp.rsv_frag, udp.dont_frag,
udp.more_frag, 0, 23383, udp.hop_limit,
udp.protocol, InetAddress.getByName("172.29.31.202"),
InetAddress.getByName("172.29.31.211"));
byte[] t_data = new byte[168];
for (int i = 0; i < t_data.length; i++) {
t_data[i] = data[i];
}
//3.改udp头
udp.dst_port = 6112;
udp.src_port = 6113;
udp.data = t_data;
udp.datalink = ep;
jp.sendPacket(udp);
System.out.println("发送完毕!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
JpcapCaptor jpcap = JpcapCaptor.openDevice(devices[0], 1024 * 10 , false, 20);
jpcap.setFilter("host 172.29.31.211", true);
jp = JpcapSender.openDevice(devices[0]);
TestWar4 t = new TestWar4();
t.init();
jpcap.loopPacket(-1, t);
}
}
以上几个关键点都解决了,相信开发出一个java写的魔兽局域网搜索器不是问题。
在这里先做个总结吧,以后有时间了,再开发出一套完整的客户端来。
还有,以上内容都是在工作时间写,由于近来公司刚结束完一个项目,所以一直比较闲,也没学公司的资料,就一直在偷偷的搞这个。写的比较粗糙,以后慢慢再改,仅供对jpacp,udp的学习参考。
下一篇: QT excel中添加新的表sheet