EpochZero Learn
EpochZero LearnMulti-Domain Tech Learning Hub
Courses
LeaderboardAbout
Dashboard
EpochZero
EpochZero Learn
Multi-Domain Tech Learning Hub

Structured learning for Reverse Engineering, Cloud Security, Cryptography, and Web Development. Articles, videos, tests, and peer discussion.

Learn

  • Learning Path
  • All Articles
  • Video Lessons
  • Podcast
  • eBooks & PDFs
  • Question Banks
  • Cheatsheets
  • MCQ Banks

Tests & Forum

  • All Tests
  • REMA Tests
  • Cloud Tests
  • Forum
  • REMA Forum
  • Cloud Forum
  • Crypto Forum
  • Web Dev Forum

Campus

  • REMA Club
  • Full Stack Dev Club
  • Extension Activity
  • Events
  • CTF Competitions
  • Workshops
  • Industrial Visits

Platform

  • Dashboard
  • Leaderboard
  • About
  • Verify Certificate

© 2026 EpochZero Learn. Educational content for learning purposes.

Course Instructor: Ashish Revar

All articles
Educationjavascriptdeobfuscationeval

JavaScript De-obfuscation

How to recover the cleartext payload from obfuscated JavaScript using eval interception, browser DevTools breakpoints, and CyberChef — with patterns for Base64, string concatenation, character codes, and nested eval.

Ashish Revar12 May 202614 min read3 views

Sign in to mark this article as read and track your progress.

Related to this topic

Continue learning

Reference material

eBook
REMA eBook 2026
v1.0
Open resource
Cheatsheet
REMA Cheatsheet 2026
v1.0
Open resource
MCQ Bank
REMA MCQ Bank 2026
v1.0
Open resource
Question Bank
REMA Question Bank 2026
v1.0
Open resource

External references

CyberChef — GCHQ Decode Tool

Browser-based tool for chaining decode operations. Build a recipe for Base64, URL decode, hex, character code substitution, and more.

tool
de4js — JavaScript De-obfuscator

Online JavaScript de-obfuscator. Paste obfuscated code and apply beautification and decode operations.

tool
MITRE ATT&CK — Obfuscated Files or Information: JavaScript (T1027)

ATT&CK technique for JavaScript obfuscation with real-world examples from threat actor campaigns.

reference
More articlesTest your knowledge

The Analyst''s Advantage

JavaScript runs in the browser, and browsers download scripts in plaintext. To hide payloads from security scanners, attackers obfuscate their JavaScript using encoding, string manipulation, dead code insertion, and variable renaming.

The analyst''s key advantage: no matter how many layers of obfuscation are applied, the browser must eventually produce executable JavaScript to run it. The final step is almost always a call to eval(), Function(), setTimeout(), or document.write() with the decoded string as the argument.

The strategy: intercept the decoded string after the decryption routine runs but before eval() executes it.

Common Obfuscation Patterns

PatternMechanismRecognition
Base64 encodingPayload decoded at runtime with atob()Strings ending in = or ==, long alphanumeric sequences
String concatenationSplit into fragments: "htt"+"p:/"+"/evil"Many + operators joining short quoted strings
Character codesString.fromCharCode(104,116,116,112) produces httpArrays of numbers 32–126
Variable renamingNames replaced with _0x4a3b, a1b2c3Hex-like variable names throughout
Dead codeUnused variables and unreachable blocks insertedLarge file size relative to apparent functionality
Nested evaleval(eval(atob(atob("..."))))Multiple eval/atob calls nested
Replace chains("hXXp://evil" .replace("XX","tt"))-replace, -split patterns

Technique 1: eval() Override in the Browser Console

Open browser DevTools (F12) before loading the page. In the Console tab, override execution functions to print instead of execute:

// Override eval
var original_eval = eval;
eval = function(code) {
    console.log("[INTERCEPTED eval]:", code);
    // deliberately NOT calling original_eval(code)
};

// Override document.write
document.write = function(html) {
    console.log("[INTERCEPTED document.write]:", html);
};

// Override Function constructor
var original_Function = Function;
Function = function() {
    console.log("[INTERCEPTED Function]:", arguments);
    return function(){};
};

After pasting these overrides, navigate to the malicious page. The decoded payload appears in the console log instead of executing.

Technique 2: Breakpoints in the Sources Panel

1. Open DevTools (F12) → Sources tab
2. Locate the script containing eval() or atob()
3. Click the line number to set a breakpoint on the eval() call
4. Reload the page — browser pauses at the breakpoint
5. Hover over the argument to eval() — tooltip shows the decoded string
6. Check the Scope panel for all local variables and their current values

This is safer than the override technique for complex scripts — you can step through each decode layer individually.

Technique 3: CyberChef for Static Decode

For scripts that are purely static transformations (no runtime behaviour needed), CyberChef decodes offline:

gchq.github.io/CyberChef

Recipe example for a Base64 + URL-encoded payload:
  1. From Base64
  2. URL Decode
  3. (repeat if nested)

Build a recipe in CyberChef by dragging operations from the left panel. The output updates live. If still obfuscated, add another decode step.

Step-by-Step De-obfuscation Workflow

1. Open DevTools BEFORE loading the page
2. Paste eval/document.write overrides into Console
3. Load the malicious page (in your isolated analysis VM only)
4. Copy intercepted payload from Console output
5. If still obfuscated:
   a. Identify the encoding type (Base64? char codes? hex?)
   b. Apply the appropriate decode in CyberChef
   c. Repeat until plaintext is recovered
6. Extract IOCs from the plaintext:
   - C2 URLs and IP addresses
   - File paths for dropped payloads
   - Shellcode or further encoded stages

Worked Example

Obfuscated input:

var _0x3f2a = ['\x68\x74\x74\x70','\x3a\x2f\x2f'];
eval(String.fromCharCode(105,110,110,101,114,72,84,77,76) +
     '="' + _0x3f2a[0] + _0x3f2a[1] + 'evil.com/gate.php"');

Step 1: Resolve hex escapes in _0x3f2a:

  • \x68\x74\x74\x70 = http
  • \x3a\x2f\x2f = ://

Step 2: Decode String.fromCharCode(105,110,110,101,114,72,84,77,76):

  • = innerHTM L → innerHTML

Step 3: Reassemble:

innerHTML = "http://evil.com/gate.php"

IOC extracted: http://evil.com/gate.php

Environmental Keying

Malicious JavaScript sometimes checks the environment before executing the payload:

if (navigator.language !== "en-US") { return; }
if (screen.width < 1024) { return; }
if (document.referrer === "") { return; }
// payload only executes if all checks pass

Environmental keying causes the script to exit silently if a specific domain, locale, or browser property is not present. This is why automated sandbox analysis sometimes misses the payload.

Bypass: manually set the required properties in the console before the script runs:

Object.defineProperty(navigator, 'language', {value: 'en-US'});