Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
基于RT-Thread使用wireshark抓取tls数据包
发布于 2019-04-10 10:33:37 浏览:1407
订阅该版
[tocm] * 本帖最后由 luanxueguang 于 2019-4-10 10:29 编辑 * # 前言 随着物联网的发展,连接到互联网的设备数量呈指数增长,物联网信息安全越来越重要。 因此,TLS 逐渐成为物联网通讯的标配。但是 TLS 是加密传输,这给调试增加了一定的难度。 笔者最近工作中一直用到 HTTPS,但是苦于 wireshark 只能抓取 HTTP 的明文数据包,无法抓取 HTTPS 的数据包,于是就有了这篇文章,在 RT-Thread 系统上,使用 wireshark 抓取 HTTPS 数据包. # 简单介绍TLS1.2握手和协商过程 ![handshake.png](/uploads/201904/10/100923h4884k7d87gv8gz7.png) ## client hello 客户端向服务器发送 tls 版本,加密方式,客户端随机数等。 ## server hello 服务器端返回协商信息的结果,包括使用的 tls 版本,使用哪一种加密方式(cipher suite), 服务器的随机数(random_s)。 ## 证书校验 客户端验证证书的合法性,如果验证通过才会进行后续通讯 ## client key exchange 客户端发送协商密钥发送给服务端 ## server change cipher spec 服务器通知客户端以后使用此协商密钥进行加密 ## hangshake message finish 客户端接收服务器发送的握手消息,验证通过后,握手完成。 此后的通讯都采用协商密钥和加密算法通讯。 # 设备端解密https数据包 查阅文档得知,wireshark 支持将 tls 会话中使用的密钥保存到外部文件中,供 wireshark 使用。 ## 流程图 ![flow.png](/uploads/201904/10/100952q9qv6nnz6zuznq6l.png) 在没有抓包路由器的情况下,使用方案A, 电脑创建 wifi 热点,设备端连接电脑热点,并发起 https 请求,服务器接收到请求,向设备端发出响应,设备端根据响应的内容,计算出密钥, 并将设备端随机数和密钥通过 udp 发送到 pc,保存到 sslkey.log 文件,wireshark 根据设备端随机数和密钥即可将 tls 数据包解密。 ## 配置wireshark - 新建 sslkey.log 文件,并配置为 windows 系统变量。 ![system.png](/uploads/201904/10/101016q5m1hp7tmxvht0ab.png) - 配置 wireshark 编辑->首选项->protocols->SSL(version 2.4.9),更高版本的 wireshark 操作步骤为:编辑->首选项->protocols->TLS ![wireshark_config.png](/uploads/201904/10/101039mqqud1ld8ff81hal.png) 配置好之后重启 wireshark 按照下面的格式,向 sslkey.log 写入客户端随机数和密钥, 即可使 wireshark 解密 tls 数据包. ``` CLIENT_RANDOM 5a497axx 3756f69b4axxx CLIENT_RANDOM 5dfb96xx b07a9da164xxx CLIENT_RANDOM 5a497axx 12e14567b9xxx CLIENT_RANDOM 55c00xxx b07a9da164xxx CLIENT_RANDOM 5a497xxx b03ca0d5fcxxx ``` 数据的含义如下: - CLIENT_RANDOM: 固定标签(支持 SSL 3.0, TLS 1.0, 1.1, 1.2) - 第二个参数:客户端随机数(random_c)32个字节,编码为64个十六进制字符 - 第三个参数: 48字节的协商密钥,编码为96个十六进制字符 接下来只要找到设备上的客户端随机数和密钥,保存到 syskey.log,即可通过 wireshark 解密 tls 数据包。 下面函数,保存了客户端随机数和密钥信息。 ssl_tls.c ```c int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) { ... MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", , 48 ); MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); ... } ``` 其中`session->master`保存的是密钥,`handshake->randbytes`保存的是客户端和服务器的随机数。 也就是说,将这两个参数保存到 sslkey.log 文件中,那么 wireshark 就能解密设备上的https数据包。 编写 udp 客户端,将客户端随机数和密钥发送到 windows,windows 编写 udp server python 脚本,用于接收数据,并将数据写入 sslkey.log 文件 ```c #include "rtthread.h" #include "stdio.h" #include
#include "netdb.h" static int port = 5000; void udpcli_send(char* ip, char* random_c, int random_len, char* master, int master_len) { int sock; struct hostent *host; struct sockaddr_in server_addr; char random_ptr[100] = {0}; char master_ptr[100] = {0}; int i = 0; if(random_c == RT_NULL || master == RT_NULL) { rt_kprintf("random_c or master is null
"); return; } host = (struct hostent *) gethostbyname(ip); if(host == RT_NULL) { rt_kprintf("Get host by name failed!
"); return; } //random server_random : 32bit + client_random : 32bit for(i = 0; i < 32; i++) { sprintf(&random_ptr[i*2], "%02x", random_c[32+i]); } for(i = 0; i < 48; i++) { sprintf(&master_ptr[i*2], "%02x", master); } rt_kprintf("random : %s
", random_ptr); rt_kprintf("master : %s
", master_ptr); if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { rt_kprintf("Create socket error"); return; } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); // sendto(sock, send_data, rt_strlen(send_data), 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); sendto(sock, random_ptr, 64, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); sendto(sock, master_ptr, 96, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); if(sock >= 0) { closesocket(sock); sock = -1; } } ``` udpserver.py ```python import socket BUFSIZ = 1024 ip_port = ('0.0.0.0', 5000) file = r'd:\work\tmp\sslkey.log' server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(ip_port) while True: random_c, client_addr = server.recvfrom(BUFSIZ) master, client_addr = server.recvfrom(BUFSIZ) print("open file" + " " + file) write_data = 'CLIENT_RANDOM ' + str(random_c, encoding='utf-8') + ' ' + str(master, encoding='utf-8') print(write_data) with open(file, 'a') as f: f.write(write_data) print("close file" + " " +file) ``` 需要注意的是,设备使用上述方法解密 https 的数据包,加密算法目前只能是 RSA,所以还需要强制客户端发送的加密方式(cipher suites)只能是 RSA。 修改`packages\mbedtls-latest\ports\inc\tls_config.h`,注释掉如下宏定义: ```c // #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED // #define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED // #define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED // #define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED // #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED // #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED // #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED // #define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED // #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ``` 这样就可以确保客户端和服务器只使用 RSA 的加密方式进行通信, 但是部分服务器不支持 RSA 的方式,握手过程会失败。 将`udpcli_send`函数添加到`mbedtls_ssl_derive_keys`函数中,如下所示 ```c MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); //replace your ip address udpcli_send("192.168.123.206", handshake->randbytes, 32, session->master, 48); mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); ``` windows 运行 python 脚本(注意修改sslkey.log的文件路径) ``` python udpserver.py ``` 设备联网成功后,在 MSH 终端输入 ``` \ | / - RT - Thread Operating System / | \ 4.0.1 build Apr 2 2019 2006 - 2019 Copyright by rt-thread team lwIP-2.0.2 initialized! [I/SAL_SOC] Socket Abstraction Layer initialize success. ........... msh /mnt/sdcard> msh /mnt/sdcard> msh /mnt/sdcard> msh /mnt/sdcard>wget https://www.rt-thread.com/service/rt-thread.txt 1.txt ``` ## wireshark抓包 加密的数据包 ![wireshark_encrypt.png](/uploads/201904/10/101153fs1blbrjmrda4kbh.png) 解密的数据包 ![wireshark_decode.png](/uploads/201904/10/101214rzkk0e159pd04ckx.png)
查看更多
2
个回答
默认排序
按发布时间排序
luanxueguang
2019-04-10
这家伙很懒,什么也没写!
测试代码
我夏了夏天
认证专家
2019-04-10
Life isn't about finding yourself, life is about creating yourself.
这个挺好用的
撰写答案
登录
注册新账号
关注者
0
被浏览
1.4k
关于作者
luanxueguang
这家伙很懒,什么也没写!
提问
1
回答
2
被采纳
0
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用RC522软件包驱动FM1722
2
常量数据类型和表达式陷阱分享
3
进行i2c驱动移植的经验总结
4
在VSCode中使用clang-format
5
我该如何使用这个微雪的WIFI400 WIFI-LPB-100在rtt里或者我该怎样为它开发驱动
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部