|
1 | | -# Java Forensics Toolkit |
| 1 | +# Easy and compact Java Forensics Toolkit |
2 | 2 |
|
3 | 3 |  |
4 | 4 |
|
5 | | -A little *Java Forensics Toolkit* that can dump all loaded classes within a JVM |
| 5 | +# Java Forensics Toolkit |
| 6 | + |
| 7 | +The **Java Forensics Toolkit** is a lightweight JVM agent that allows you to **inspect, snapshot, and export all loaded classes** from a running Java process.<br> |
| 8 | +Designed for **forensic analysis, debugging, and reverse engineering**, making it easier to discover unexpected or malicious code inside live JVMs. |
| 9 | + |
| 10 | +## Features |
| 11 | + |
| 12 | +- 📦 **Snapshot all loaded classes** – capture bytecode *after* any runtime transformations. |
| 13 | +- 🔍 **Class loader analysis** – see which classes exist in which class loader. |
| 14 | +- 🛡️ **Security investigations** – detect hidden, injected, or malicious classes. |
| 15 | +- 🧩 **Reverse engineering** – dumped classes can be decompiled with standard tools. |
| 16 | +- 🎯 **Flexible filters** – include/exclude classes with regex filters. |
| 17 | +- ⚡ **Simple usage** – attach to any running JVM by PID with a single command. |
| 18 | + |
| 19 | +## Installation |
| 20 | + |
| 21 | +Download the latest release JAR from [here](https://github.com/BenjaminSoelberg/JavaForensicsToolkit/releases). |
| 22 | + |
| 23 | +## Usage |
| 24 | + |
6 | 25 | ``` |
| 26 | +java -jar JavaForensicsToolkit-<version>.jar |
| 27 | +
|
| 28 | +--------------------------------------------------------- |
| 29 | +--> Java Forensics Toolkit v1.0.2 by Benjamin Sølberg <-- |
| 30 | +--------------------------------------------------------- |
| 31 | +https://github.com/BenjaminSoelberg/JavaForensicsToolkit |
| 32 | +
|
7 | 33 | usage: java -jar JavaForensicsToolkit.jar [-v] [-e] [-d destination.jar] [-f filter]... [-x] <pid> |
8 | 34 |
|
9 | 35 | options: |
10 | | --v verbose agent logging |
11 | | --e agent will log to stderr instead of stdout |
12 | | --d jar file destination of dumped classes |
13 | | - Relative paths will be relative with respect to the target process. |
14 | | - A jar file in temp will be generated if no destination was provided. |
15 | | --f regular expression class name filter |
16 | | - Can be specified multiple times. |
17 | | --x exclude classes matching the filter |
18 | | -pid process id of the target java process |
| 36 | +-v verbose agent logging |
| 37 | +-e agent will log to stderr instead of stdout |
| 38 | +-d jar file destination of dumped classes |
| 39 | + Relative paths will be relative with respect to the target process. |
| 40 | + A jar file in temp will be generated if no destination was provided. |
| 41 | +-f regular expression class name filter |
| 42 | + Can be specified multiple times. |
| 43 | +-x exclude classes matching the filter |
| 44 | +pid process id of the target java process |
19 | 45 |
|
20 | 46 | example: |
21 | 47 | java -jar JavaForensicsToolkit.jar -d dump.jar -f java\\..* -f sun\\..* -f jdk\\..* -f com\\.sun\\..* -x 123456 |
22 | 48 | ``` |
23 | 49 |
|
24 | | -A small report with information about each class is generated and placed in the destination jar as well. |
| 50 | +## Example |
| 51 | + |
| 52 | +Dump all non-JDK classes from a running process with PID 123456: |
25 | 53 |
|
26 | | -Here is an example: |
27 | 54 | ``` |
28 | | -$ java -jar JavaForensicsToolkit.jar -v 24576 |
29 | | --------------------------------------------------------- |
30 | | ---> Java Forensics Toolkit v1.00 by Benjamin Sølberg <-- |
31 | | --------------------------------------------------------- |
32 | | -https://github.com/BenjaminSoelberg/JavaForensicsToolkit |
| 55 | +java -jar JavaForensicsToolkit.jar -v -d dump.jar -f java\\..* -f sun\\..* -f jdk\\..* -f com\\.sun\\..* -x 123456 |
| 56 | +``` |
33 | 57 |
|
34 | | -Injecting agent into JVM with pid: 24576 |
35 | | -Dumping classes to: /tmp/dump-24651-9890604330559988075.jar |
36 | | --------------------------------------------------------- |
37 | | ---> Java Forensics Toolkit v1.00 by Benjamin Sølberg <-- |
38 | | --------------------------------------------------------- |
39 | | -https://github.com/BenjaminSoelberg/JavaForensicsToolkit |
| 58 | +## Typical Use Cases |
40 | 59 |
|
41 | | -Agent loaded with options: -v -d /tmp/dump-24651-9890604330559988075.jar -f .* 24576 |
42 | | -
|
43 | | -Querying classes... |
44 | | -
|
45 | | -Dumping started... |
46 | | -Ignoring io/github/benjaminsoelberg/jft/Transformer |
47 | | -Ignoring io/github/benjaminsoelberg/jft/ParserException |
48 | | -Ignoring io/github/benjaminsoelberg/jft/Utils |
49 | | -Ignoring io/github/benjaminsoelberg/jft/Options |
50 | | -Ignoring io/github/benjaminsoelberg/jft/ClassInfo |
51 | | -Ignoring io/github/benjaminsoelberg/jft/Report |
52 | | -Ignoring io/github/benjaminsoelberg/jft/ClassDumper |
53 | | -Ignoring io/github/benjaminsoelberg/jft/DummyRunner |
54 | | -Dumping java.io.FileOutputStream$1 |
55 | | -Dumping java.util.Vector$Itr |
56 | | -Dumping java.util.concurrent.ConcurrentLinkedQueue$CLQSpliterator |
57 | | -Dumping java.util.zip.ZipOutputStream$XEntry |
58 | | -... |
59 | | -Dumping java.lang.Throwable |
60 | | -Dumping java.lang.System |
61 | | -Dumping java.lang.ClassLoader |
62 | | -Dumping java.lang.Cloneable |
63 | | -Dumping java.lang.Class |
64 | | -Dumping java.lang.reflect.Type |
65 | | -Dumping java.lang.reflect.GenericDeclaration |
66 | | -Dumping java.lang.reflect.AnnotatedElement |
67 | | -Dumping java.lang.String |
68 | | -Dumping java.lang.CharSequence |
69 | | -Dumping java.lang.Comparable |
70 | | -Dumping java.io.Serializable |
71 | | -Dumping java.lang.Object |
72 | | -
|
73 | | -Creating jar... |
74 | | -Class info: java.io.FileOutputStream$1@null@0 726 bytes |
75 | | -Class info: java.util.Vector$Itr@null@0 2492 bytes |
76 | | -Class info: java.util.concurrent.ConcurrentLinkedQueue$CLQSpliterator@null@0 3608 bytes |
77 | | -Class info: java.util.zip.ZipOutputStream$XEntry@null@0 563 bytes |
78 | | -Class info: java.time.chrono.IsoChronology@null@0 11739 bytes |
79 | | -Class info: java.time.chrono.AbstractChronology@null@0 15281 bytes |
80 | | -Class info: java.time.chrono.Chronology@null@0 8639 bytes |
81 | | -Class info: java.time.temporal.TemporalAdjusters@null@0 6423 bytes |
82 | | -Class info: java.time.LocalDate@null@0 27720 bytes |
83 | | -... |
84 | | -Class info: java.time.chrono.ChronoLocalDate@null@0 9575 bytes |
85 | | -Class info: java.time.zone.ZoneOffsetTransition@null@0 6109 bytes |
86 | | -Class info: java.time.temporal.ValueRange@null@0 4463 bytes |
87 | | -Class info: java.math.BigInteger@null@0 59485 bytes |
88 | | -Class info: java.time.Duration@null@0 18086 bytes |
89 | | -Class info: java.time.temporal.TemporalAmount@null@0 399 bytes |
90 | | -Class info: java.lang.Comparable@null@0 235 bytes |
91 | | -Class info: java.io.Serializable@null@0 113 bytes |
92 | | -Class info: java.lang.Object@null@0 1944 bytes |
93 | | -
|
94 | | -Dumped classes, including report.txt, can be found in: /tmp/dump-24651-9890604330559988075.jar |
95 | | -Done |
96 | | -``` |
| 60 | +- 🔐 **Malware hunting** – identify injected or malicious classes hidden inside a compromised JVM. |
| 61 | +- 🛠️ **Debugging classpath issues** – find out which versions of classes are actually loaded and by which class loaders. |
| 62 | +- 📊 **Security audits** – verify that only expected code is running inside production JVMs. |
| 63 | +- 🕵️ **Incident response** – capture a live snapshot of loaded classes for later offline analysis. |
| 64 | +- ⚙️ **Reverse engineering & research** – decompile transformed classes to understand runtime modifications (e.g. instrumentation, bytecode weaving, or AOP frameworks). |
| 65 | + |
| 66 | +## How It Works |
| 67 | + |
| 68 | +1) **Attach to target JVM**<br>The toolkit uses the standard com.sun.tools.attach API to connect to a running Java process by PID. |
| 69 | +2) **Load agent**<br>Once attached, it dynamically loads a lightweight Java agent into the target JVM without requiring a restart. |
| 70 | +3) **Enumerate classes**<br>The agent queries the JVM for all currently loaded classes and their associated class loaders. |
| 71 | +4) **Dump bytecode**<br>Each class is retrieved as it exists in memory after any transformations (e.g. instrumentation, weaving, or obfuscation). |
| 72 | +5) **Write output**<br>The classes are packaged into a JAR file (either user-specified or temporary) for convenient storage and analysis. |
| 73 | + |
| 74 | +This approach ensures the dumped classes reflect the exact state of the JVM at runtime, providing a faithful snapshot for investigation. |
0 commit comments