Skip to content

标题: 从运行中的Java进程空间转储class

创建: 2019-09-20 16:39 更新: 链接: https://scz.617.cn/misc/201909201639.txt


目录:

1) ClassFileTransformer
2) sun.jvm.hotspot.CLHSDB
3) sun.jvm.hotspot.HSDB
4) sun.jvm.hotspot.tools.jcore.ClassDump
5) 其他技术手段

这是一篇1024贴,起一个收集、汇总、广而告之的作用。

为什么有这种需求?Java恶意软件会在内存中动态创建class,一些商业软件的反破 解措施也会干这种事。在Java逆向工程中时不时会碰上这种需求。比如Burp 1.7.37 的burp.pyk,你在jar包中找不到,但它在调用栈回溯中出现了,你可能想看看这个 类在干什么。本文不是讲Burp逆向工程,只是举个例子,现在公开的破解版已至2.1。

1) ClassFileTransformer

参考手册:

Interface ClassFileTransformer https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/ClassFileTransformer.html

Class VirtualMachine https://docs.oracle.com/javase/8/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html

较早的一个完整示例:

Retrieving .class files from a running app - A. Sundararajan [2007-03-30] http://blogs.sun.com/sundararajan/entry/retrieving_class_files_from_a (这个已经不存在了) https://blogs.oracle.com/sundararajan/retrieving-class-files-from-a-running-app

话说Oracle就这样毁了Sun,现在访问上述链接,显示的作者是Guest Author, Oracle可真扯淡。

Dumping Embedded Java Classes - [2018-09-06] https://www.trustedsec.com/2018/09/dumping-embedded-java-classes/ https://www.trustedsec.com/wp-content/uploads/2018/09/ClassDumper.tar.gz

这篇就是Sundararajan那篇的转载,作者做了一些简单说明,代码完全是 Sundararajan的。

2) sun.jvm.hotspot.CLHSDB

sa-jdi.jar是JDK自带的。

$ java -cp "\sa-jdi.jar" sun.jvm.hotspot.CLHSDB

hsdb> attach

查看所有类:

hsdb> classes

查看指定类:

hsdb> class burp.pyk burp/pyk @0x00000007c038c428

转储指定类:

hsdb> dumpclass burp/pyk

这将生成:

./burp/pyk.class

hsdb> detach hsdb> quit

3) sun.jvm.hotspot.HSDB

$ java -cp "\sa-jdi.jar" sun.jvm.hotspot.HSDB

这是个图形界面。

Windows->Console

这相当于CLHSDB

Windows->Debugger Console

这是用

C:\Windows\System32\dbgeng.dll C:\Windows\System32\dbghelp.dll

提供了(windbg)提示符。"? $tpid"表明被调试进程不是HSDB,而是HSDB Attach的目 标进程,相当于windbg、HSDB对目标进程双调试。但这两个dll一般都是老旧的,除 非有意替换升级过,而且它找windbg插件也不成功。HSDB建议从外部自行使用最新版 windbg:


cdb -pv -p

-pv

Specifies that the debugger should attach to the target process
noninvasively

In noninvasive debugging, the debugger does not actually attach to the
target application. The debugger suspends all of the target's threads
and has access to the target's memory, registers, and other such
information. However, the debugger cannot control the target, so
commands like g (Go) do not work.

有些文章提到参数"-Dsun.jvm.hotspot.debugger.useWindbgDebugger=true",据我 实测,JDK 8中这个参数指不指定都没意义,指定成true或false都一样,估计是历史 遗迹。

HSDB里包含CLHSDB,可以用上一小节的办法转储class,同时HSDB提供了一些图形化 操作。

Tools->Class Browser->搜索"pyk"->点击"class burp.pyk"

这下面有很多超链接可以点击,点击"Create .class File",这将生成:

./burp/pyk.class

4) sun.jvm.hotspot.tools.jcore.ClassDump

如何dump出一个Java进程里类对应的Class文件 - RednaxelaFX [2010-08-03] http://rednaxelafx.iteye.com/blog/727938


import sun.jvm.hotspot.tools.jcore.ClassFilter; import sun.jvm.hotspot.oops.InstanceKlass; import sun.jvm.hotspot.tools.jcore.ClassDump;

public class dumpclass_filter implements ClassFilter { @Override public boolean canInclude ( InstanceKlass kls ) { String klassName = kls.getName().asString();

    return( klassName.startsWith( "burp/pyk" ) );
}

}

$ javac -g:none -cp "\sa-jdi.jar" dumpclass_filter.java

查看PID:

$ jps -mlv

从指定JVM中转储class:

$ java -cp "\lib*;." -Dsun.jvm.hotspot.tools.jcore.filter=dumpclass_filter -Dsun.jvm.hotspot.tools.jcore.outputDir=./dump sun.jvm.hotspot.tools.jcore.ClassDump

这将生成:

./dump/burp/pyk.class

这种方法还得自己写个过滤器,不如sun.jvm.hotspot.CLHSDB方便。

5) 其他技术手段

JVMClassDumper https://github.com/SytheMarket/JVMClassDumper

这是向JVM进程注入一个dll去Hook JVM中的defineClass()。作者写道:

This simple DLL injector hooks a running Java Virtual Machine's ClassLoader. Specifically it hooks the defineClass() method. It produces a dump of all classfiles loaded by the JVM from the point in time the hook is attached.

Reversing An Obfuscated Java Malware - [2015-10-01] https://onedrive.live.com/?authkey=%21AP%2DLGmNO74brJ6s&cid=E91E11F5FA1D754C&id=E91E11F5FA1D754C%21219&parId=E91E11F5FA1D754C%21126&o=OneUp

此文提到native agent,比java agent更强大。编写native agent,注册 "method exit event"的回调函数。作者写道:

The native agent will monitor all methods as they are being executed. If the method being executed, is the one we are interested, we will dump the contents of the returned byte array to a file.

The agent registers callback for method exit events. Such events are generated when java has finished executing a method, and is about to return to its caller. In the callback we examine if the current method is the one we are interested in.

这样指定native agent:

java -agentlib:

这样指定java agent:

java -javaagent:

常见示例:

java -agentlib:jdwp=transport=dt_socket,address=... java -javaagent:btrace-agent.jar=...

最后,可以自己从源码编译jvm.dll,这样不需要注入,直接在源码级加一些改动。 对于逆向工程人员来说,值得花点时间定制自己的jvm.dll。