.NET & Java Reversing
Overview
.NET and Java applications compile to intermediate bytecode (CIL/MSIL for .NET, Java bytecode for JVM) rather than native machine code. This intermediate representation retains much of the original source structure — class names, method names, string literals, and control flow — making decompilation significantly easier than for native binaries. Many malware families are written in .NET or Java due to rapid development, cross-platform capabilities, and ease of integrating libraries.
.NET Reversing
Identifying .NET Binaries
# Check if a PE file is .NET
file sample.exe
# Output includes "Mono/.Net assembly" for .NET binaries
# radare2
# https://github.com/radareorg/radare2
rabin2 -I sample.exe
# Look for: bintype=dotnet or lang=cil
.NET binaries contain a CLR header in the PE optional header's data directory entry at index 14 (COM_DESCRIPTOR / CLR Runtime Header).
Decompilation with monodis
# Mono
# https://www.mono-project.com/
# Disassemble .NET assembly to CIL (Common Intermediate Language)
monodis sample.exe
# Show specific metadata tables
monodis --typedef sample.exe # List all types/classes
monodis --method sample.exe # List all methods
monodis --assembly sample.exe # Show assembly metadata
monodis --moduleref sample.exe # Show module references
monodis --memberref sample.exe # Show member references
monodis --customattr sample.exe # Show custom attributes
monodis --fields sample.exe # Show fields
monodis --manifest sample.exe # Show manifest/resources
monodis --nested sample.exe # Show nested classes
monodis --mresources sample.exe # Show managed resources
# Redirect output to file
monodis sample.exe > disassembly.il
# Filter output for strings
monodis --strings sample.exe
monodis --userstrings sample.exe
.NET Analysis with radare2
# radare2
# https://github.com/radareorg/radare2
# Open .NET binary
r2 -A sample.exe
# List .NET classes
ic
# List methods in a class
ic ClassName
# List strings (including .NET metadata strings)
iz
izz
# Show imports
ii
dnSpy / dnSpyEx (Windows)
dnSpy (and its maintained fork dnSpyEx) is the most powerful .NET decompiler and debugger. It provides:
- Full C# and VB.NET decompilation
- Integrated debugger (set breakpoints, step through managed code)
- Assembly editing (modify IL code and save)
- Search across all types, methods, strings
- Resource extraction
Key operations in dnSpy:
Ctrl+Shift+K — Search assemblies
Ctrl+G — Go to token/address
F5 — Start debugging
F9 — Toggle breakpoint
F10 — Step over
F11 — Step into
Right-click → Edit Method Body (modify IL)
Right-click → Edit Class/Method (modify C#)
File → Save — Save modified assembly
.NET Obfuscation
Common .NET obfuscators and their indicators:
| Obfuscator | Indicators |
|---|---|
| ConfuserEx | Resource names like "Costura", anti-tamper watermarks |
| .NET Reactor | Embedded native stub, encrypted resources |
| Dotfuscator | Renamed identifiers (a, b, c...), control flow obfuscation |
| Eazfuscator | Virtualized methods, resource encryption |
| SmartAssembly | Compressed resources, string encoding |
de4dot (.NET Deobfuscator)
de4dot is an open-source .NET deobfuscator that supports many common obfuscators.
# de4dot
# https://github.com/de4dot/de4dot
# Deobfuscate (auto-detect obfuscator)
de4dot sample.exe
# Output: sample-cleaned.exe
# Specify output file
de4dot sample.exe -o deobfuscated.exe
# Force a specific deobfuscator by short type name (see help screen for names)
# e.g. SmartAssembly = sa, unknown/unsupported = un
de4dot sample.exe -p sa
de4dot sample.exe -p un
Extracting .NET Resources
# Python 3 (standard library)
# https://www.python.org/
# .NET assemblies often embed resources (configs, secondary payloads)
# Extract embedded resources from a .NET binary
import zipfile
import os
# .NET single-file bundles and some packers use zip-like structures
# For standard .NET resources, use monodis --mresources or dnSpy
# Mono
# https://www.mono-project.com/
# List managed resources
monodis --mresources sample.exe
# Extract using monodis
monodis --mresources sample.exe
# Resources are listed with their offsets and sizes
Java Reversing
Identifying Java Files
# Java class files start with magic bytes CA FE BA BE
xxd -l 4 sample.class
# JAR files are ZIP archives containing .class files
file sample.jar
# Output: sample.jar: Java archive data (JAR)
# List contents of a JAR
unzip -l sample.jar
Decompilation with jadx
jadx decompiles Android DEX files and Java class files / JARs back to Java source code.
# jadx
# https://github.com/skylot/jadx
# Decompile JAR to Java source
jadx sample.jar -d output_dir
# Decompile with deobfuscation
jadx --deobf sample.jar -d output_dir
# Decompile a single class
jadx --single-class com.example.Main sample.jar
# Export as Gradle project
jadx -e sample.jar -d output_dir
# Use fallback decompilation mode (for difficult code)
jadx -m fallback sample.jar -d output_dir
# Decompile with multiple threads
jadx -j 4 sample.jar -d output_dir
# No resource decoding (faster)
jadx -r sample.jar -d output_dir
javap (Java Disassembler)
javap is the standard Java class file disassembler included with the JDK.
# Java Development Kit (javap)
# https://www.oracle.com/java/
# Show public class members
javap sample.class
# Show all members (including private)
javap -p sample.class
# Show bytecode instructions
javap -c sample.class
# Show verbose information (constant pool, flags)
javap -v sample.class
# Show line numbers and local variables
javap -l sample.class
# Disassemble from a JAR
javap -c -cp sample.jar com.example.Main
Extracting and Analyzing JARs
# JARs are ZIP files — extract with standard tools
unzip sample.jar -d extracted/
# Find the main class
unzip -p sample.jar META-INF/MANIFEST.MF | grep Main-Class
# List all class files
unzip -l sample.jar | grep '\.class$'
# Search for strings across all class files
strings extracted/*.class | grep -iE 'http|password|key|secret|exec'
Java Obfuscation
| Obfuscator | Indicators |
|---|---|
| ProGuard | Short renamed identifiers (a, b, c), removed debug info |
| Allatori | String encryption methods, flow obfuscation |
| Zelix KlassMaster | Encrypted strings, flow obfuscation, name mangling |
| DashO | Reference obfuscation, string encryption |
Java String Decryption
Java malware frequently encrypts strings to hide URLs, C2 addresses, and commands. Common approaches:
1. Static analysis: Find the decryption method in the decompiled source
and re-implement it in a standalone script
2. Dynamic analysis: Set breakpoints on String constructors or
println/write calls to capture decrypted strings at runtime
3. Hook with Frida:
- Attach to the JVM process
- Hook java.lang.String constructor to log all new strings
// Frida
// https://github.com/frida/frida
// Hook Java String constructor to capture decrypted strings
Java.perform(function() {
var String = Java.use('java.lang.String');
String.$init.overload('[B').implementation = function(bytes) {
var result = this.$init(bytes);
var str = String.$new(bytes);
if (str.length() > 5) {
console.log("[String] " + str);
}
return result;
};
});
Analysis Workflow
.NET / Java sample received
│
├── file / magic bytes → confirm .NET (MZ + CLR) or Java (CA FE BA BE)
├── strings / monodis / javap → extract metadata and strings
├── Check for obfuscation (renamed identifiers, encrypted strings)
│
├── .NET path:
│ ├── monodis → CIL disassembly
│ ├── dnSpy (Windows) → full decompilation + debugging
│ ├── de4dot → deobfuscate if needed
│ └── Extract resources (configs, embedded payloads)
│
├── Java path:
│ ├── jadx → Java source decompilation
│ ├── javap → bytecode-level analysis
│ ├── Extract JAR contents → analyze manifest and classes
│ └── Decrypt strings (static reimplementation or Frida hooks)
│
└── Document findings: C2 addresses, encryption keys, capabilities