如何使自制的 TLS 数据包在 Wireshark 中显示为 tls 而不是数据
how to make a self made TLS packet appear as tls in Wireshark and not as data
最近我开始为这项运动实施 TLS 作为一个有趣的项目,我目前正在尝试自己制作并在本地发送一个客户端 hello TLS 数据包(最小的一个)。
当通过 Wireshark 中的环回接口观察时,它显示为纯数据而不是包含所有不同字段的 tls 层,经过大量尝试我决定在这里问以下问题:
- 我自制的数据包和真正的 TLS 客户端 hello one 有什么区别?
- Wireshark 如何有选择地使数据显示为 TLS 分层而不是纯数据,数据包中是否有标识符字段声明其为纯数据或 TLS 分层?
- 如何使我的数据包显示为客户端 hello TLS 数据包而不是纯数据?
这是我的服务器和客户端,它们基本上发送我的 C 代码输出(请记住,它们不是为真正的 TLS 处理而制作的,只是为了在 Wireshark 中显示数据包):
server.py
import socket
TCP_IP = '0.0.0.0'
TCP_PORT = 2004
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
tcpServer.listen(4)
(conn, (ip,port)) = tcpServer.accept()
client.py
import socket
host = "127.0.0.1"
port = 2004
BUFFER_SIZE = 2000
tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpClientA.connect((host, port))
tcpClientA.send(b"\x16\x03\x01\x00\xa5\x01\xa1\x00\x00\x03\x03\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x73\x64\x66\x67\x68\x6a\x6b\x6c\x7a\x78\x63\x76\x62\x6e\x6d\x61\x73\x64\x66\x67\x68\x6a\x00\x20\x00\xcc\xa8\xcc\xa9\xc0\x2f\xc0\x30\xc0\x2b\xc0\x2c\xc0\x13\xc0\x09\xc0\x14\xc0\x0a\x00\x9c\x00\x9d\x00\x2f\x00\x35\xc0\x12\x00\x0a")
这是我用于创建数据包的 C 代码,它表明我已经为 Wireshark 设置了所有必要的客户端 hello TLS 字段(此外,我使用以下站点作为指导 https://tls.ulfheim.net/) :
#include <stdint.h>
#include <stdio.h>
#include <string.h>
struct __attribute__((__packed__)) record {
// record layer
uint8_t record_type;
uint16_t version;
uint16_t length;
// handshake layer
uint8_t handshake_type;
char hello_length[3];
// client version
uint16_t tls_version;
// client random
char client_random[32];
// session id
uint8_t session_id;
// cipher suites
uint16_t suites_length;
uint16_t suites[1000];
};
void print_struct(struct record r)
{
unsigned char packet[sizeof(r)] = {0x00};
memcpy(packet, &r, sizeof(r));
for(int i = 0; i < sizeof(packet); i++) {
if(packet[i] != 0xff) {
printf("%02x", packet[i]);
}
}
}
int main()
{
struct record client_hello = {0};
client_hello.record_type = 0x16;
client_hello.version = 0x0103;
client_hello.length = 0xA500;
client_hello.handshake_type = 0x01;
client_hello.hello_length[0] = 0xA1;
client_hello.hello_length[1] = 0x00;
client_hello.hello_length[2] = 0x00;
client_hello.tls_version = 0x0303;
memcpy(client_hello.client_random, "123456789asdfghjklzxcvbnmasdfghj", 32);
client_hello.session_id = 0x00;
client_hello.suites_length = 32;
uint16_t arr[] = {0xa8cc, 0xa9cc, 0x2fc0, 0x30c0, 0x2bc0, 0x2cc0, 0x13c0, 0x09c0, 0x14c0, 0x0ac0, 0x9c00, 0x9d00, 0x2f00, 0x3500, 0x12c0, 0x0a00};
memset(client_hello.suites, 0xffff, sizeof(client_hello.suites));
memcpy(client_hello.suites, arr, sizeof(arr));
print_struct(client_hello);
return 0;
}
这是 Wireshark 显示已发送的自制 TLS 客户端问候数据包的方式:
0000 02 00 00 00 45 00 00 76 74 c5 40 00 80 06 00 00 ....E..vt.@.....
0010 7f 00 00 01 7f 00 00 01 d9 2f 07 d4 7f 69 9a d9 ........./...i..
0020 99 2a 47 85 50 18 27 f9 03 da 00 00 16 03 01 00 .*G.P.'.........
0030 a5 01 a1 00 00 03 03 31 32 33 34 35 36 37 38 39 .......123456789
0040 61 73 64 66 67 68 6a 6b 6c 7a 78 63 76 62 6e 6d asdfghjklzxcvbnm
0050 61 73 64 66 67 68 6a 00 20 00 cc a8 cc a9 c0 2f asdfghj. ....../
0060 c0 30 c0 2b c0 2c c0 13 c0 09 c0 14 c0 0a 00 9c .0.+.,..........
0070 00 9d 00 2f 00 35 c0 12 00 0a .../.5....
这是我希望如何显示的屏幕截图:
首先,TLS 长度字段是错误的。 Wireshark 的 TCP 解析器表明 TCP 负载长度为 78 字节;但 TLS 长度为 165 (0x00a5),因此不正确。另外,握手长度也是错误的。尝试改变这个:
0030 a5 01 a1 00 00 03 03 31 32 33 34 35 36 37 38 39 .......123456789
对此:
0030 49 01 00 00 45 03 03 31 32 33 34 35 36 37 38 39 I...-..123456789
之后,您必须修复密码套件长度字段,该字段当前设置为 8192 (0x2000),也是伪造的。最多是 32 (0x0020),所以你可以尝试改变这个:
0050 61 73 64 66 67 68 6a 00 20 00 cc a8 cc a9 c0 2f asdfghj. ....../
对此:
0050 61 73 64 66 67 68 6a 00 00 20 cc a8 cc a9 c0 2f asdfghj. ....../
这应该会让你更接近,但你必须从那里继续调整数据。对于任何想要对此进行测试的人,您可以将以下数据保存到文本文件中,然后使用 text2pcap
将其转换为 Wireshark 可以加载的 pcap 文件:
0000 02 00 00 00 45 00 00 76 74 c5 40 00 80 06 00 00 ....E..vt.@.....
0010 7f 00 00 01 7f 00 00 01 d9 2f 01 bb 7f 69 9a d9 ........./...i..
0020 99 2a 47 85 50 18 27 f9 03 da 00 00 16 03 01 00 .*G.P.'.........
0030 49 01 00 00 45 03 03 31 32 33 34 35 36 37 38 39 I...-..123456789
0040 61 73 64 66 67 68 6a 6b 6c 7a 78 63 76 62 6e 6d asdfghjklzxcvbnm
0050 61 73 64 66 67 68 6a 00 00 20 cc a8 cc a9 c0 2f asdfghj. ....../
0060 c0 30 c0 2b c0 2c c0 13 c0 09 c0 14 c0 0a 00 9c .0.+.,..........
0070 00 9d 00 2f 00 35 c0 12 00 0a .../.5....
运行 text2pcap
如下:
text2pcap.exe -l0 file.txt file.pcap
最近我开始为这项运动实施 TLS 作为一个有趣的项目,我目前正在尝试自己制作并在本地发送一个客户端 hello TLS 数据包(最小的一个)。
当通过 Wireshark 中的环回接口观察时,它显示为纯数据而不是包含所有不同字段的 tls 层,经过大量尝试我决定在这里问以下问题:
- 我自制的数据包和真正的 TLS 客户端 hello one 有什么区别?
- Wireshark 如何有选择地使数据显示为 TLS 分层而不是纯数据,数据包中是否有标识符字段声明其为纯数据或 TLS 分层?
- 如何使我的数据包显示为客户端 hello TLS 数据包而不是纯数据?
这是我的服务器和客户端,它们基本上发送我的 C 代码输出(请记住,它们不是为真正的 TLS 处理而制作的,只是为了在 Wireshark 中显示数据包):
server.py
import socket
TCP_IP = '0.0.0.0'
TCP_PORT = 2004
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
tcpServer.listen(4)
(conn, (ip,port)) = tcpServer.accept()
client.py
import socket
host = "127.0.0.1"
port = 2004
BUFFER_SIZE = 2000
tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpClientA.connect((host, port))
tcpClientA.send(b"\x16\x03\x01\x00\xa5\x01\xa1\x00\x00\x03\x03\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x73\x64\x66\x67\x68\x6a\x6b\x6c\x7a\x78\x63\x76\x62\x6e\x6d\x61\x73\x64\x66\x67\x68\x6a\x00\x20\x00\xcc\xa8\xcc\xa9\xc0\x2f\xc0\x30\xc0\x2b\xc0\x2c\xc0\x13\xc0\x09\xc0\x14\xc0\x0a\x00\x9c\x00\x9d\x00\x2f\x00\x35\xc0\x12\x00\x0a")
这是我用于创建数据包的 C 代码,它表明我已经为 Wireshark 设置了所有必要的客户端 hello TLS 字段(此外,我使用以下站点作为指导 https://tls.ulfheim.net/) :
#include <stdint.h>
#include <stdio.h>
#include <string.h>
struct __attribute__((__packed__)) record {
// record layer
uint8_t record_type;
uint16_t version;
uint16_t length;
// handshake layer
uint8_t handshake_type;
char hello_length[3];
// client version
uint16_t tls_version;
// client random
char client_random[32];
// session id
uint8_t session_id;
// cipher suites
uint16_t suites_length;
uint16_t suites[1000];
};
void print_struct(struct record r)
{
unsigned char packet[sizeof(r)] = {0x00};
memcpy(packet, &r, sizeof(r));
for(int i = 0; i < sizeof(packet); i++) {
if(packet[i] != 0xff) {
printf("%02x", packet[i]);
}
}
}
int main()
{
struct record client_hello = {0};
client_hello.record_type = 0x16;
client_hello.version = 0x0103;
client_hello.length = 0xA500;
client_hello.handshake_type = 0x01;
client_hello.hello_length[0] = 0xA1;
client_hello.hello_length[1] = 0x00;
client_hello.hello_length[2] = 0x00;
client_hello.tls_version = 0x0303;
memcpy(client_hello.client_random, "123456789asdfghjklzxcvbnmasdfghj", 32);
client_hello.session_id = 0x00;
client_hello.suites_length = 32;
uint16_t arr[] = {0xa8cc, 0xa9cc, 0x2fc0, 0x30c0, 0x2bc0, 0x2cc0, 0x13c0, 0x09c0, 0x14c0, 0x0ac0, 0x9c00, 0x9d00, 0x2f00, 0x3500, 0x12c0, 0x0a00};
memset(client_hello.suites, 0xffff, sizeof(client_hello.suites));
memcpy(client_hello.suites, arr, sizeof(arr));
print_struct(client_hello);
return 0;
}
这是 Wireshark 显示已发送的自制 TLS 客户端问候数据包的方式:
0000 02 00 00 00 45 00 00 76 74 c5 40 00 80 06 00 00 ....E..vt.@.....
0010 7f 00 00 01 7f 00 00 01 d9 2f 07 d4 7f 69 9a d9 ........./...i..
0020 99 2a 47 85 50 18 27 f9 03 da 00 00 16 03 01 00 .*G.P.'.........
0030 a5 01 a1 00 00 03 03 31 32 33 34 35 36 37 38 39 .......123456789
0040 61 73 64 66 67 68 6a 6b 6c 7a 78 63 76 62 6e 6d asdfghjklzxcvbnm
0050 61 73 64 66 67 68 6a 00 20 00 cc a8 cc a9 c0 2f asdfghj. ....../
0060 c0 30 c0 2b c0 2c c0 13 c0 09 c0 14 c0 0a 00 9c .0.+.,..........
0070 00 9d 00 2f 00 35 c0 12 00 0a .../.5....
这是我希望如何显示的屏幕截图:
首先,TLS 长度字段是错误的。 Wireshark 的 TCP 解析器表明 TCP 负载长度为 78 字节;但 TLS 长度为 165 (0x00a5),因此不正确。另外,握手长度也是错误的。尝试改变这个:
0030 a5 01 a1 00 00 03 03 31 32 33 34 35 36 37 38 39 .......123456789
对此:
0030 49 01 00 00 45 03 03 31 32 33 34 35 36 37 38 39 I...-..123456789
之后,您必须修复密码套件长度字段,该字段当前设置为 8192 (0x2000),也是伪造的。最多是 32 (0x0020),所以你可以尝试改变这个:
0050 61 73 64 66 67 68 6a 00 20 00 cc a8 cc a9 c0 2f asdfghj. ....../
对此:
0050 61 73 64 66 67 68 6a 00 00 20 cc a8 cc a9 c0 2f asdfghj. ....../
这应该会让你更接近,但你必须从那里继续调整数据。对于任何想要对此进行测试的人,您可以将以下数据保存到文本文件中,然后使用 text2pcap
将其转换为 Wireshark 可以加载的 pcap 文件:
0000 02 00 00 00 45 00 00 76 74 c5 40 00 80 06 00 00 ....E..vt.@..... 0010 7f 00 00 01 7f 00 00 01 d9 2f 01 bb 7f 69 9a d9 ........./...i.. 0020 99 2a 47 85 50 18 27 f9 03 da 00 00 16 03 01 00 .*G.P.'......... 0030 49 01 00 00 45 03 03 31 32 33 34 35 36 37 38 39 I...-..123456789 0040 61 73 64 66 67 68 6a 6b 6c 7a 78 63 76 62 6e 6d asdfghjklzxcvbnm 0050 61 73 64 66 67 68 6a 00 00 20 cc a8 cc a9 c0 2f asdfghj. ....../ 0060 c0 30 c0 2b c0 2c c0 13 c0 09 c0 14 c0 0a 00 9c .0.+.,.......... 0070 00 9d 00 2f 00 35 c0 12 00 0a .../.5....
运行 text2pcap
如下:
text2pcap.exe -l0 file.txt file.pcap