Skip to main content
XsiSec.com
HomeReposBlogProjectsPortfolio
© 2026 XsiSec.com
Security rules |security.txt
Updated 2026-08-15 · v1.0.0+2026-08-14.82f92cb · 82f92cb
← Back to overview
Security article

HTB Academy - Deobfuscation , Encode and decode

HTB Academy - Deobfuscation , Encode and decode: Take an obfuscated JavaScript P.A.C.K.E.R snippet and turn it into readable code, then cover quick ways to decode embedded strings (base64, hex, rot13). Keep everything practical and copy‑pasteable. • HTB Academy • base64, decode

2022-09-306 tags
Tags

🎯 Objective

Take an obfuscated JavaScript P.A.C.K.E.R snippet and turn it into readable code, then cover quick ways to decode embedded strings (base64, hex, rot13). Keep everything practical and copy‑pasteable.


🧩 What I’m analyzing

A classic eval‑packer payload (Dean Edwards P.A.C.K.E.R style), where an eval(function(p,a,c,k,e,d){...})(...) unpacks itself at runtime and hides intent, endpoints, and strings.

Original snippet

js
eval(function (p, a, c, k, e, d) { e = function (c) { return c.toString(36) }; if (!''.replace(/^/, String)) { while (c--) { d[c.toString(a)] = k[c] || c.toString(a) } k = [function (e) { return d[e] }]; e = function () { return '\\w+' }; c = 1 }; while (c--) { if (k[c]) { p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]) } } return p }('g 4(){0 5="6{7!}";0 1=8 a();0 2="/9.c";1.d("e",2,f);1.b(3)}', 17, 17, 'var|xhr|url|null|generateSerial|flag|HTB|flag|new|serial|XMLHttpRequest|send|php|open|POST|true|function'.split('|'), 0, {}))

Safety note: Never run unknown eval on a real machine/page. Work offline and replace eval( with console.log( to print the unpacked code instead of executing it.


🧭 Steps I Took

  1. Beautify first (makes the wrapper readable)

    • Tools: Prettier Playground, Beautifier.io
    • Quick trick: replace leading eval( with console.log(, then run in a throwaway browser console/Node REPL to print the unpacked JS.
  2. JSNice pass for names & types

    • Paste the result into JSNice and click Nicify JavaScript to get better variable names and a clearer function.
  3. Read the plain intent

    • The unpacked code shows a function that POSTs to /serial.php and contains a flag string.

Deobfuscated output (from JSNice)

js
'use strict';
function generateSerial() {               // formerly: g 4()
  var flag = "HTB{flag!}";                // formerly: 0 5="6{7!}"
  var xhr = new XMLHttpRequest();         // formerly: 0 1=8 a()
  var url = "/serial.php";                // formerly: 0 2="/9.c"
  xhr.open("POST", url, true);            // formerly: 1.d("e",2,f)
  xhr.send(null);                         // formerly: 1.b(3)
}

📎 Copy‑paste helpers

1) Print instead of execute (browser/Node)

js
// Replace eval( with console.log(, then run in a safe REPL
const src = `eval(function(p,a,c,k,e,d){/* ... */})`;
console.log(src.replace(/^eval\(/, 'console.log('));

2) Minimal “packer” unwrap (conceptual)

If you can’t use online tools, the packer mechanism is just a dictionary substitution:

  • k.split('|') gives the dictionary of words.
  • Tokens like g, 4, 0, 5, ... map back to real identifiers via base‑a conversion (toString(36) in this case).
  • The wrapper replaces each \btoken\b with the dictionary entry.

Use an offline packer‑unpacker script (there are many small ones) or a JS sandbox that logs the output instead of executing it.

3) Curl sample (from the snippet’s endpoint)

bash
curl http://SERVER_IP:PORT/serial.php -X POST -d "param1=sample"
# Example base64 response:
# ZG8gdGhlIGV4ZXJjaXNlLCBkb24ndCBjb3B5IGFuZCBwYXN0ZSA7KQo=

🔐 Decoding embedded strings

Base64

  • Spot: alphanumeric + + / and often = padding; length multiple of 4.
  • Decode
bash
echo 'aHR0cHM6Ly93d3cuaGFja3RoZWJveC5ldS8K' | base64 -d
# https://www.hackthebox.eu/
  • From the curl example
bash
echo 'ZG8gdGhlIGV4ZXJjaXNlLCBkb24ndCBjb3B5IGFuZCBwYXN0ZSA7KQo=' | base64 -d
# do the exercise, don't copy and paste ;)

Hex

  • Spot: only 0–9 and a–f.
  • Encode
bash
echo 'https://www.hackthebox.eu/' | xxd -p
  • Decode
bash
echo '68747470733a2f2f7777772e6861636b746865626f782e65752f0a' | xxd -p -r

rot13 (Caesar)

  • Encode/Decode
bash
echo 'https://www.hackthebox.eu/' | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# uggcf://jjj.unpxgurobk.rh/
echo 'uggcf://jjj.unpxgurobk.rh/' | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# https://www.hackthebox.eu/

🧪 Troubleshooting

  • Blank output after replacing eval? Some payloads perform environment checks. Evaluate in a fresh Node REPL or a blank HTML page.
  • Tool blocked / offline? Keep local copies of a beautifier/unpacker, or use simple regex/logging to dump the inner string.
  • Still unreadable? Layers are common (packer + base64 + hex). Decode strings first, then beautify again.
  • Danger: don’t execute unknown code; always log/print the unpacked result, not run it.

🔒 Defense (dev notes)

  • Avoid eval/Function/setTimeout("<string>"); minify ≠ obfuscate.
  • Treat third‑party scripts as untrusted; pin with SRI & CSP; host locally where possible.
  • Monitor for unexpected POST targets (e.g., /serial.php) and anomalous base64/hex blobs in code.

✅ Result

  • The packer payload unpacks to a readable function generateSerial() that POSTs to /serial.php and embeds a string "HTB{flag!}".
  • The sample base64 blob decodes to:
text
do the exercise, don't copy and paste ;)
Navigate

In this post

  1. 01🎯 Objective
  2. 02🧩 What I’m analyzing
  3. 03🧭 Steps I Took
  4. 04📎 Copy‑paste helpers
  5. 051) Print instead of execute (browser/Node)
  6. 062) Minimal “packer” unwrap (conceptual)
  7. 073) Curl sample (from the snippet’s endpoint)
  8. 08🔐 Decoding embedded strings
  9. 09Base64
  10. 10Hex
  11. 11rot13 (Caesar)
  12. 12🧪 Troubleshooting
  13. 13🔒 Defense (dev notes)
  14. 14✅ Result
Search
Explore

Popular tags

Browse all 30 tags

Comments

0 comments

No comments yet — be the first to comment.