当前位置: 首页 > news >正文

tcpdump源码分析

进入tcpdump.c(函数入口)之前,先看一些头文件netdissect.h里定义了一个数据结构struct netdissect_options来描述tcdpump支持的所有参数动作,每一个参数有对应的flag, 在tcpdump 的main 里面, 会根据用户的传入的参数来增加相应flag数值, 最后根据这些flag数值来实现特定动作。各个参数含义请参考源代码注释。

1.netdissect.h 头文件

struct netdissect_options {int ndo_bflag;              /* 以 ASDOT 表示法打印 4 字节 AS 号 */int ndo_eflag;              /* 打印以太网头 */int ndo_fflag;              /* 不翻译“外部”IP 地址 */int ndo_Kflag;              /* 不检查 IP、TCP 或 UDP 校验和 */int ndo_nflag;              /* 将地址显示为数字形式 */int ndo_Nflag;              /* 打印主机名时去掉域名 */int ndo_qflag;              /* 简短输出 */int ndo_Sflag;              /* 打印原始 TCP 序列号 */int ndo_tflag;              /* 打印数据包到达时间 */int ndo_uflag;              /* 打印未解码的 NFS 句柄 */int ndo_vflag;              /* 冗余级别 */int ndo_xflag;              /* 以十六进制打印数据包 */int ndo_Xflag;              /* 以十六进制/ASCII 打印数据包 */int ndo_Aflag;              /* 仅以 ASCII 打印数据包,并将 TAB、LF、CR 和 SPACE 视为图形字符 */int ndo_Hflag;              /* 解析 802.11s 草案网状标准 */const char *ndo_protocol;   /* 协议 */jmp_buf ndo_early_end;      /* 用于 setjmp()/longjmp() 的 jmp_buf */void *ndo_last_mem_p;       /* 指向最后分配的内存块的指针 */int ndo_packet_number;      /* 在行首打印数据包编号 */int ndo_print_sampling;     /* 打印每 N 个数据包 */int ndo_suppress_default_print; /* 对未知的数据包类型不使用 default_print() */int ndo_tstamp_precision;   /* 请求的时间戳精度 */const char *program_name;   /* 使用该库的程序名称 */char *ndo_espsecret;               /* ESP 密钥 */struct sa_list *ndo_sa_list_head;  /* 由 print-esp.c 使用 */struct sa_list *ndo_sa_default;char *ndo_sigsecret;        /* 签名验证密钥 */int ndo_packettype;         /* 由 -T 指定的数据包类型 */int ndo_snaplen;            /* 抓取长度 */int ndo_ll_hdr_len;         /* 链路层头长度 *//* 全局指针,指向当前数据包的开始和结束(在打印过程中) */const u_char *ndo_packetp;const u_char *ndo_snapend;/* 保存的数据包边界和缓冲区信息的堆栈 */struct netdissect_saved_packet_info *ndo_packet_info_stack;/* 指向 if_printer 函数的指针 */if_printer ndo_if_printer;/* 指向输出内容的 void 函数的指针 */void (*ndo_default_print)(netdissect_options *,const u_char *bp, u_int length);/* 指向执行常规输出的函数的指针 */int  (*ndo_printf)(netdissect_options *,const char *fmt, ...)PRINTFLIKE_FUNCPTR(2, 3);/* 指向输出错误的函数的指针 */void NORETURN_FUNCPTR (*ndo_error)(netdissect_options *,status_exit_codes_t status,const char *fmt, ...)PRINTFLIKE_FUNCPTR(3, 4);/* 指向输出警告的函数的指针 */void (*ndo_warning)(netdissect_options *,const char *fmt, ...)PRINTFLIKE_FUNCPTR(2, 3);
};

字段解释:

  • 标志位

    • ndo_bflag: 决定是否以 ASDOT 表示法打印 4 字节 AS 号。
    • ndo_eflag: 决定是否打印以太网头。
    • ndo_fflag: 决定是否不翻译“外部”IP 地址。
    • ndo_Kflag: 决定是否不检查 IP、TCP 或 UDP 校验和。
    • ndo_nflag: 决定是否将地址保留为数字形式。
    • ndo_Nflag: 决定是否在打印主机名时去掉域名。
    • ndo_qflag: 决定是否进行简短输出。
    • ndo_Sflag: 决定是否打印原始 TCP 序列号。
    • ndo_tflag: 决定是否打印数据包到达时间。
    • ndo_uflag: 决定是否打印未解码的 NFS 句柄。
    • ndo_vflag: 设置冗余级别。
    • ndo_xflag: 决定是否以十六进制打印数据包。
    • ndo_Xflag: 决定是否以十六进制和 ASCII 打印数据包。
    • ndo_Aflag: 决定是否仅以 ASCII 打印数据包,并将 TAB、LF、CR 和 SPACE 视为图形字符。
    • ndo_Hflag: 决定是否解析 802.11s 草案网状标准。
  • 其他选项

    • ndo_protocol: 指定的协议。
    • ndo_early_end: 用于 setjmp()/longjmp() 的跳转缓冲区。
    • ndo_last_mem_p: 指向最后分配的内存块的指针。
    • ndo_packet_number: 决定是否在行首打印数据包编号。
    • ndo_print_sampling: 打印每 N 个数据包。
    • ndo_suppress_default_print: 决定是否对未知的数据包类型不使用 default_print()。
    • ndo_tstamp_precision: 请求的时间戳精度。
    • program_name: 使用该库的程序名称。
  • ESP 和签名相关

    • ndo_espsecret: ESP 密钥。
    • ndo_sa_list_head, ndo_sa_default: 由 print-esp.c 使用的 SA 列表。
    • ndo_sigsecret: 签名验证密钥。
  • 数据包和链接层相关

    • ndo_packettype: 由 -T 指定的数据包类型。
    • ndo_snaplen: 抓取长度。
    • ndo_ll_hdr_len: 链路层头长度。
    • ndo_packetp, ndo_snapend: 当前数据包的开始和结束指针。
    • ndo_packet_info_stack: 保存的数据包边界和缓冲区信息的堆栈。
  • 函数指针

    • ndo_if_printer: 指向 if_printer 函数的指针。
    • ndo_default_print: 指向输出内容的 void 函数的指针。
    • ndo_printf: 指向执行常规输出的函数的指针。
    • ndo_error: 指向输出错误的函数的指针。
    • ndo_warning: 指向输出警告的函数的指针。

此次需要关注的是 “ndo_snaplen: 抓取长度”变量。

2.从指针安全读取x字节的相关宏定义

在 print-eigrp.c 中有如下代码:

GET_BE_U_2(eigrp_com_header->checksum),

 继续追踪到 extract.h 文件:

#define GET_BE_U_2(p) get_be_u_2(ndo, (const u_char *)(p))

  继续追踪,仍在 extract.h 文件中:get_be_u_2 可见是一个内联函数

static inline uint16_t
get_be_u_2(netdissect_options *ndo, const u_char *p)
{if (!ND_TTEST_2(p))nd_trunc_longjmp(ndo);return EXTRACT_BE_U_2(p);
}

这个内联函数 get_be_u_2 做了以下几件事:

  1. 调用 ND_TTEST_2(p) 来检查是否可以从指针 p 安全地读取 2 个字节。
  2. 如果检查失败,调用 nd_trunc_longjmp(ndo) 进行错误处理,通常会跳转到某个提前定义的错误处理位置。
  3. 如果检查成功,调用 EXTRACT_BE_U_2(p) 从指针 p 提取 2 个字节的数据,并将其从网络字节顺序转换为主机字节顺序。

继续追踪 ND_TTEST_2 宏函数,仍在 extract.h 文件中:

#define ND_TTEST_2(p) ND_TTEST_LEN((p), 2)
//这个宏调用 ND_TTEST_LEN,传递参数 p 和长度 2,表示要检查从指针 p 开始的 2 个字节。 

继续追踪 ND_TTEST_LEN 宏函数,跳转到 netdissect.h 文件中:


/** True if "l" bytes from "p" were captured.** The "ndo->ndo_snapend - (l) <= ndo->ndo_snapend" checks to make sure* "l" isn't so large that "ndo->ndo_snapend - (l)" underflows.** The check is for <= rather than < because "l" might be 0.** We cast the pointers to uintptr_t to make sure that the compiler* doesn't optimize away any of these tests (which it is allowed to* do, as adding an integer to, or subtracting an integer from, a* pointer assumes that the pointer is a pointer to an element of an* array and that the result of the addition or subtraction yields a* pointer to another member of the array, so that, for example, if* you subtract a positive integer from a pointer, the result is* guaranteed to be less than the original pointer value). See**	https://www.kb.cert.org/vuls/id/162289*//** Test in two parts to avoid these warnings:* comparison of unsigned expression >= 0 is always true [-Wtype-limits],* comparison is always true due to limited range of data type [-Wtype-limits].*//** 如果从 "p" 开始的 "l" 字节被捕获,则返回真。** 通过 "ndo->ndo_snapend - (l) <= ndo->ndo_snapend" 的检查来确保* "l" 不会大到使 "ndo->ndo_snapend - (l)" 发生下溢。** 检查使用 <= 而不是 < 是因为 "l" 可能为 0。** 我们将指针转换为 uintptr_t 是为了确保编译器不会优化掉这些测试* (编译器被允许这样做,因为将整数加到指针上,或从指针上减去整数,* 假定指针是一个数组元素的指针,并且加法或减法的结果会生成另一个数组成员的指针,* 因此,例如,如果从指针上减去一个正整数,结果保证小于原始指针值)。参见**	https://www.kb.cert.org/vuls/id/162289*//** 分两部分测试以避免这些警告:* unsigned 表达式的比较总是大于等于 0 是始终为真的 [-Wtype-limits],* 由于数据类型的有限范围,比较总是为真 [-Wtype-limits]。*/#define IS_NOT_NEGATIVE(x) (((x) > 0) || ((x) == 0))#define ND_TTEST_LEN(p, l) \(IS_NOT_NEGATIVE(l) && \((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend && \(uintptr_t)(p) <= (uintptr_t)ndo->ndo_snapend - (l)))
  1. 这个宏检查以下几个条件:

    • IS_NOT_NEGATIVE(l):长度 l 必须是非负数。
    • ((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend):确保 ndo->ndo_snapend 减去 l 不会发生下溢。
    • ((uintptr_t)(p) <= (uintptr_t)ndo->ndo_snapend - (l)):确保指针 p 不会越过数据包的边界。

ND_TTEST_2 是一个宏,用于检查是否可以安全地从指定的指针 p 读取 2 个字节(即 16 位)。它通过验证内存边界和指针合法性来确保不会发生越界访问。具体来说,它结合了多个宏和函数,形成一个完整的边界检查机制。

总结

ND_TTEST_2 的主要目的是确保在从数据包读取数据时不会发生越界访问,从而保证程序的安全性和稳定性。它通过一系列的检查来验证指针和长度的合法性,防止因非法内存访问导致的崩溃或数据损坏。

3.setjmp/longjmp 非局部跳转函数的应用

现在存在的问题是没有搞清tcpdump 的执行流程:

调用顺序:

(gdb) bt
#0  eigrp_print (ndo=0x7fffffffcf00, pptr=0x8ea512 "\002\005\356h", len=40) at ./print-eigrp.c:233
#1  0x0000000000458255 in ip_demux_print (ndo=0x7fffffffcf00, bp=0x8ea512 "\002\005\356h", length=40, ver=4, fragmented=0, ttl_hl=2, nh=88 'X', iph=0x8ea4fe "E\300") at ./print-ip-demux.c:143
#2  0x00000000004227cf in ip_print (ndo=0x7fffffffcf00, bp=0x8ea4fe "E\300", length=60) at ./print-ip.c:487
#3  0x000000000041dbbc in ethertype_print (ndo=0x7fffffffcf00, ether_type=2048, p=0x8ea4fe "E\300", length=60, caplen=60, src=0x7fffffffccb0, dst=0x7fffffffcca0) at ./print-ether.c:536
#4  0x000000000041d680 in ether_common_print (ndo=0x7fffffffcf00, p=0x8ea4fe "E\300", length=60, caplen=60, print_switch_tag=0x0, switch_tag_len=0, print_encap_header=0x0, encap_header_arg=0x0) at ./print-ether.c:391
#5  0x000000000041d7c1 in ether_print (ndo=0x7fffffffcf00, p=0x8ea4f0 "\001", length=74, caplen=74, print_encap_header=0x0, encap_header_arg=0x0)at ./print-ether.c:448
#6  0x000000000041d81a in ether_if_print (ndo=0x7fffffffcf00, h=0x7fffffffce40, p=0x8ea4f0 "\001") at ./print-ether.c:464
#7  0x0000000000407ead in pretty_print_packet (ndo=0x7fffffffcf00, h=0x7fffffffce40, sp=0x8ea4f0 "\001", packets_captured=1) at ./print.c:414
#8  0x0000000000407343 in print_packet (user=0x7fffffffcf00 "", h=0x7fffffffce40, sp=0x8ea4f0 "\001") at ./tcpdump.c:3127
#9  0x00000000004f4f07 in pcap_offline_read (p=p@entry=0x8ea250, cnt=2147483647, cnt@entry=-1, callback=callback@entry=0x4072ed <print_packet>, user=user@entry=0x7fffffffcf00 "") at ./savefile.c:691
#10 0x00000000004e2baf in pcap_loop (p=0x8ea250, cnt=-1, callback=0x4072ed <print_packet>, user=0x7fffffffcf00 "") at ./pcap.c:2916
#11 0x00000000004066c2 in main (argc=3, argv=0x7fffffffe3c8) at ./tcpdump.c:2569

setjmp() 函数是在 #7 的 pretty_print_packet() 函数中调用的。

参考:

1、非局部跳转:8.6 非本地跳转 | 深入理解计算机系统(CSAPP) (gitbook.io)

2、 【C指针(五)】6种转移表实现整合longjmp()/setjmp()函数和qsort函数详解分析&&模拟实现-支付宝开发者社区 (alipay.com)

3、tcpdump 源码解析:https://www.cnblogs.com/pangblog/p/3364690.html

 分析2:tcpdump源码分析-CSDN博客

4、tcpdump 越界访问追踪: tcpdump 4.5.1 crash 深入分析-安全客 - 安全资讯平台

相关文章:

tcpdump源码分析

进入tcpdump.c&#xff08;函数入口&#xff09;之前&#xff0c;先看一些头文件netdissect.h里定义了一个数据结构struct netdissect_options来描述tcdpump支持的所有参数动作&#xff0c;每一个参数有对应的flag, 在tcpdump 的main 里面&#xff0c; 会根据用户的传入的参数来…...

搭建Harbor镜像仓库

前言 1、系统版本&#xff1a;CentOS9 2、harbor版本&#xff1a;v2.9.4 3、提前安装好docker和docker-compose&#xff0c;参考地址。我这里安装的版本是docker&#xff1a;26.1.3 docker-compose&#xff1a;v2.27.1 安装步骤 下载安装包 1、下载地址&#xff1a;ha…...

【C/C++】Makefile文件的介绍与基本用法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…...

PHP生成二维码+二维码包含logo图片展示

composer require chillerlan/php-qrcode 用到的扩展自己安装&#xff08;注&#xff1a;只生成二维码只要开gd扩展就行&#xff09; 仅生成二维码看这个&#xff1a; use chillerlan\QRCode\QRCode;public function QRCode(){$qrcode new QRCode();$url "http://ww…...

vue项目打包教程

如果是用 vue-cli 创建的项目&#xff0c;则项目目录中没有 config 文件夹&#xff0c;所以我们需要自建一个配置文件&#xff1b;在vue项目目录下创建文件 vue.config.js&#xff0c;需注意文件名称必须是 vue.config.js&#xff0c;然后在文件中插入以下代码&#xff1a; 文件…...

制作电子画册速成攻略,快来试试

​当今社会&#xff0c;数字媒体日益普及&#xff0c;电子画册作为一种崭新的展示方式&#xff0c;受到了越来越多人的青睐。它不仅形式新颖&#xff0c;互动性强&#xff0c;而且制作起来也并不复杂。想知道如何快速掌握制作电子画册的技巧吗&#xff1f;我来教你吧。 接下来&…...

【java程序设计期末复习】chapter7 内部类和异常类

内部类和异常类 内部类 ava支持在一个类中声明另一个类&#xff0c;这样的类称作内部类&#xff0c;而包含内部类的类成为内部类的外嵌类。 注意 &#xff08;1&#xff09;内部类的类体中不可以声明类变量和类方法。 &#xff08;2&#xff09;外嵌类的类体中可以用内部类…...

Windows下安装配置深度学习环境

Windows下安装配置深度学习环境 1. 准备工作 1.1 环境准备 操作系统&#xff1a;win10 22H2 GPU&#xff1a;Nvidia GeForce RTX 3060 12G 1.2 安装Nvidia驱动、cuda、cuDNN 下载驱动需要注册并登录英伟达账号。我这里将下面用到的安装包放到了百度网盘&#xff0c;可以关注微信…...

如何使用ssh将vscode 连接到服务器上,手把手指导

一、背景 我们在开发时&#xff0c;经常是window上安装一个vscode编辑器&#xff0c;去连接一个虚拟机上的linux&#xff0c;这里常用的是SSH协议&#xff0c;了解其中的操作非常必要。 二、SSH协议 SSH&#xff08;Secure Shell&#xff09;是一种安全协议&#xff0c;用于…...

Tomcat调优参数

JVM优化 Tomcat是一个Web容器&#xff0c;所有的jar其实都共享Tomcat中的JVM参数&#xff0c;所以Tomcat的JVM参数优化至关重要。 Tomcat的JVM参数是在启动脚本中设置的&#xff0c;如想要设置最大堆内存和最小堆内存时&#xff1a; 在windows的启动脚本catalina.bat中的set &q…...

云计算和大数据处理

文章目录 1.云计算基础知识1.1 基本概念1.2 云计算分类 2.大数据处理基础知识2.1 基础知识2.3 大数据处理技术 1.云计算基础知识 1.1 基本概念 云计算是一种提供资源的网络&#xff0c;使用者可以随时获取“云”上的资源&#xff0c;按需求量使用&#xff0c;并且可以看成是无…...

VAE-变分自编码器(Variational Autoencoder,VAE)

变分自编码器&#xff08;Variational Autoencoder&#xff0c;VAE&#xff09;是一种生成模型&#xff0c;结合了概率图模型与神经网络技术&#xff0c;广泛应用于数据生成、表示学习和数据压缩等领域。以下是对VAE的详细解释和理解&#xff1a; 基本概念 1. 自编码器&#…...

Android Room 使用模版

文章目录 一、配置依赖 plugins {id kotlin-kapt }android {compileOptions {sourceCompatibility JavaVersion.VERSION_17targetCompatibility JavaVersion.VERSION_17}kotlinOptions {jvmTarget 17} }dependencies {implementation("androidx.room:room-runtime:2.4.2&…...

Linux/Ubuntu 中安装 ZeroTier,实现内网穿透,2分钟搞定

相信很多人都有远程连接家中设备的需求&#xff0c;如远程连接家中的NAS、Windows等服务&#xff0c;所以会涉及到一个内网穿透工具的使用&#xff0c;如果没有公网IP的情况下&#xff0c;推荐大家使用ZeroTier&#xff0c;这是一款强大的内网穿透工具。 mac和windows版的操作…...

java技术:oauth2协议

目录 一、黑马程序员Java进阶教程快速入门Spring Security OAuth2.0认证授权详解 1、oauth服务 WebSecurityConfig TokenConfig AuthorizationServer 改写密码校验逻辑实现类 2、oauth2支持的四种方式&#xff1a; 3、oauth2授权 ResouceServerConfig TokenConfig 4、…...

Java 18 新特性详解

Java 18 新特性详解 Java 18 作为 Oracle 推出的又一重要版本&#xff0c;继续秉持着 Java 平台“创新但不破坏”的原则&#xff0c;带来了多项旨在提升开发效率、性能和安全性的新特性。本篇文章将深入解析 Java 18 引入的主要特性&#xff0c;并探讨它们如何影响开发者的工作…...

【css3】06-css3新特性之网页布局篇

目录 伸缩布局或者弹性布局【响应式布局】 1 设置父元素为伸缩盒子 2 设置伸缩盒子主轴方向 3 设置元素在主轴的对齐方式 4 设置元素在侧轴的对齐方式 5 设置元素是否换行显示 6 设置元素换行后的对齐方式 7 效果测试原码 伸缩布局或者弹性布局【响应式布局】 1 设置父元…...

【开源】大学生竞赛管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、系统介绍 学生管理模块 教师管理模块 竞赛信息模块 竞赛报名模块 二、系统截图 三、核心代码 一、系统介绍 基于Vue.js和SpringBoot的大学生竞赛管理系统&#xff0c;分为管理后台和用户网页端&#xff0c;可以给管理员、学生和教师角色使用&#xff0c;包括学…...

跨境选品师不是神话:普通人也能轻松掌握,开启全球贸易新篇章!

随着互联网技术的飞速发展&#xff0c;跨境电商行业已成为全球经济的新增长点。在这个背景下&#xff0c;一个新兴的职业——跨境选品师&#xff0c;逐渐走进了人们的视野。那么&#xff0c;跨境选品师究竟是做什么的?普通人又该如何成为优秀的跨境选品师呢? 一、跨境选品师的…...

前缀和,差分算法理解

前缀和是什么&#xff1a; 前缀和指一个数组的某下标之前的所有数组元素的和&#xff08;包含其自身&#xff09;。前缀和分为一维前缀和&#xff0c;以及二维前缀和。前缀和是一种重要的预处理&#xff0c;能够降低算法的时间复杂度 说个人话就是比如有一个数组&#xff1a; …...

用ESP32-C3的PWM做个RGB呼吸灯吧:从配置结构体到色彩渐变(乐鑫ESP-IDF实战)

ESP32-C3 RGB呼吸灯实战&#xff1a;从PWM配置到色彩渐变算法 当智能家居的灯光不再只是简单的开关控制&#xff0c;而是能像呼吸般自然渐变时&#xff0c;整个空间的氛围立刻变得生动起来。ESP32-C3凭借其出色的LED PWM控制器&#xff08;LEDC&#xff09;外设&#xff0c;为开…...

3步开启Windows 11安卓应用新体验:WSA完整使用指南

3步开启Windows 11安卓应用新体验&#xff1a;WSA完整使用指南 【免费下载链接】WSA Developer-related issues and feature requests for Windows Subsystem for Android 项目地址: https://gitcode.com/gh_mirrors/ws/WSA Windows Subsystem for Android&#xff08;简…...

如何在原神中解放双手:自动钓鱼、拾取与对话跳过的终极指南

如何在原神中解放双手&#xff1a;自动钓鱼、拾取与对话跳过的终极指南 【免费下载链接】genshin-impact-script 原神脚本&#xff0c;包含自动钓鱼、自动拾取、自动跳过对话等多项实用功能。A Genshin Impact script includes many useful features such as automatic fishing…...

LaMa图像修复:用AI魔法轻松移除照片中的不想要元素

LaMa图像修复&#xff1a;用AI魔法轻松移除照片中的不想要元素 【免费下载链接】lama &#x1f999; LaMa Image Inpainting, Resolution-robust Large Mask Inpainting with Fourier Convolutions, WACV 2022 项目地址: https://gitcode.com/GitHub_Trending/la/lama 你…...

如何将B站缓存视频从m4s格式无损转换为通用MP4?

如何将B站缓存视频从m4s格式无损转换为通用MP4&#xff1f; 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾遇到过这样的情况&#xff1…...

量子循环神经网络在混沌时序预测中的参数效率与架构对比

1. 项目概述 最近几年&#xff0c;量子机器学习&#xff08;QML&#xff09;的热度持续攀升&#xff0c;大家都想看看&#xff0c;用量子计算那套“叠加”和“纠缠”的玩法来处理经典问题&#xff0c;到底能不能带来点惊喜。时序预测&#xff0c;尤其是混沌系统预测&#xff0c…...

Wand-Enhancer:三步解锁WeMod专业版功能的终极本地增强工具

Wand-Enhancer&#xff1a;三步解锁WeMod专业版功能的终极本地增强工具 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 还在为WeMod专业版的高额订阅费用…...

高光谱成像与机器学习:LDA+SVM/KNN实现蜂蜜植物源精准鉴别

1. 项目概述&#xff1a;当高光谱成像遇上机器学习&#xff0c;如何为蜂蜜“验明正身”&#xff1f;在食品行业&#xff0c;尤其是像蜂蜜这样的高价值农产品领域&#xff0c;“真实性”一直是消费者和生产者共同关注的焦点。一瓶标着“新西兰麦卢卡”或“东北椴树蜜”的蜂蜜&am…...

Unity打包Linux服务器应用踩坑记:从发布到后台稳定运行(含Systemd服务配置)

Unity服务器应用Linux部署实战&#xff1a;从Systemd配置到稳定运维引言&#xff1a;当Unity遇见Linux服务器三年前接手第一个Unity服务器项目时&#xff0c;我完全没料到会在部署环节连踩72小时坑。那个本该简单的部署过程&#xff0c;最终演变成与Linux权限、内存泄漏和日志管…...

TMSpeech与腾讯会议集成:高效会议纪要生成的实际应用场景

TMSpeech与腾讯会议集成&#xff1a;高效会议纪要生成的实际应用场景 【免费下载链接】TMSpeech 腾讯会议摸鱼工具 项目地址: https://gitcode.com/gh_mirrors/tm/TMSpeech TMSpeech是一款专为腾讯会议设计的高效语音识别工具&#xff0c;能够实时将会议中的语音内容转换…...