.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

References

Tools

Further Reading