title: Common techniques for JavaScript reverse debugging description: Python3 crawler advanced: JavaScript reverse engineering and browser debugging tools explained

JavaScript Reverse Debugging Practical Guide (Chrome DevTools Core)

1. Preface

With the rapid iteration of web technology, more and more websites use JavaScript compression, obfuscation, dynamic generation and even WebAssembly encryption to protect interface data. For advanced Python3 crawler developers, whether you can skillfully control Chrome developer tools (DevTools) for reverse debugging often determines whether you are blocked by anti-crawling or whether you can successfully obtain data. Of course, these debugging skills are also applicable to common development scenarios such as front-end security testing and performance optimization.

This article will focus on the high-frequency usage of Chrome DevTools in reverse engineering, helping you quickly locate encryption parameters, extract encryption factors, and reuse existing requests. Subsequent articles will continue to delve into obfuscated code restoration, AST analysis, and WebAssembly reverse engineering.

2. Chrome DevTools core panel

2.1 Quick opening

Instead of clicking "More Tools" → "Developer Tools" step by step, the following methods are more efficient:

  • Windows / LinuxCtrl + Shift + IOr directly pressF12
  • MacCmd + Option + I
  • Right click anywhere on the page → Inspect (will directly locate the current DOM node)

2.2 Quick overview of reverse high frequency panel

Panel nameBasic functionsReverse-specific scenarios
ElementsView and edit HTML/CSS/DOM node attributesFind event bindings, trigger DOM breakpoints, and quickly extract data after DOM decryption
ConsoleExecute JS code, view logs, access global/scope variablesQuickly verify reverse logic, Hook key functions, expose hidden variables
SourcesView/breakpoint/edit/format source code, manage OverridesCore debugging area: single-step tracking logic, XHR/Fetch breakpoints, local replacement of obfuscated code
NetworkMonitor all network requests, parse request response headers and response bodiesLocate encryption interfaces, extract encryption parameter samples, and one-click Copy as cURL reuse requests
ApplicationView Cookie / localStorage / sessionStorage / IndexedDB, etc.Extract static encryption factor, session ID, anti-crawl token

3. Core skills of reverse debugging

3.1 Event monitoring and precise positioning

Many encryptions are triggered by user interaction (such as clicking on the login or search button). At this time, starting with event monitoring is the fastest way to locate:

  1. Directly select the interactive element (such as the login button) in the Elements panel**
  2. Switch to the Event Listeners tab on the right
  3. Uncheck "Framework listeners" to avoid interference by intermediate proxy functions of frameworks such as React and Vue.
  4. Click on a real business event (e.g.click) corresponding to the arrow icon on the right side of the processing function, DevTools will jump directly to the function definition in the Sources panel
// 常见真实业务事件结构示例
// 此时框架的 $emit 等函数已被过滤
document.getElementById('login-btn').addEventListener('click', function(e) {
    const raw = {
        username: $('#username').val(),
        password: $('#password').val(),
        timestamp: Date.now()
    };
    // 这里就是加密函数入口!
    const encrypted = encryptData(raw, secretKey);
    fetch('/api/login', { method: 'POST', body: JSON.stringify(encrypted) });
});

After locating the encryption entry, you can set a breakpoint and start following the logic.

3.2 Code formatting and source mapping processing

The JS in the production environment is basically compressed and obfuscated, and reading it directly is like reading a bible. DevTools provides two restore methods:

  • Source Map If the file comes with.mapFile (can be seen in the file tree on the left side of the Sources panel), DevTools will automatically map to the unobfuscated development version code, the variable names and comments are clearly visible, and you can debug directly. But be aware that the production environment does not necessarily provide source map files, because this will expose uncompressed source code.

  • Manual Formatting (Prettify) If there is no source mapping, you can click on the lower left corner of the Sources panel{}(Prettify code) button to generate a formatted temporary file (the file name will have:formatted)。
    The readability of the formatted code will be improved, but variable names and function names may still be single-letter or obfuscated, and further analysis needs to be combined with breakpoints and variable monitoring.

3.3 Four high-frequency breakpoint types

In the Sources panel, breakpoints are our core weapon for tracking encryption logic:

  • Line Breakpoint Click on the left side of the code line number to add a blue icon and pause when execution reaches that line. Suitable for debugging where the approximate location is known.

  • Conditional Breakpoint Right-click the line number → select Add conditional breakpoint and enter a Boolean expression (for exampleusername === 'test123'), it will only be paused when the conditions are met. Very useful in cyclic or high-frequency events.

  • XHR/Fetch breakpoint Find XHR/fetch Breakpoints on the left side of Sources and click+Add a rule (can be a full interface URL or a partial path, e.g./api/v1/All requests under this path will be intercepted). It is automatically paused when the request is initiated, and the construction location of the encrypted parameters can be found through the call stack traceback.

  • DOM breakpoint Right-click the target DOM node in the Elements panel → select Break on → select as needed:

  • Subtree modifications (sub-node changes)

  • Attributes modifications (attribute changes)

  • Node removal (node ​​removal) Automatically pauses when the DOM changes accordingly, which is very suitable for scenarios where data is extracted immediately after DOM dynamic decryption.

3.4 Debugging control and variable monitoring

After debugging is paused, 5 core control buttons will appear at the top of the Sources panel (the corresponding shortcut keys must also be memorized):

  1. Resume script execution (F8)
    Continue execution until the next breakpoint is encountered.

  2. Step over next function call (F10)
    Single-step execution, does not enter the function of the current line, and directly gets the function return value.

  3. Step into next function call (F11)
    Single-step execution, enter the function of the current line (whether it is a system function or a custom function).

  4. Step out of current function (Shift+F11)
    Jump out of the currently executing function and return to the point where it was called.

  5. 🎯 Deactivate breakpoints
    Temporarily disable all breakpoints and let the code run normally.

The Scope panel on the right will display the variables in the current scope in real time:

  • Local: local variables of the current function
  • Closure: closure variable (probably hiding an encryptedsecretKey!)
  • Global: global variables

Through these variable information, you can directly see the original data, keys and intermediate results received by the encryption function, thereby quickly understanding the encryption process.

4. Advanced reverse engineering: local replacement and Hook

4.1 Overrides Local modification of JS

If you need to repeatedly modify and debug the obfuscated code (such as adding logs, rewriting encryption results, replacing anti-debugging logic), the temporary format file will be reset every time the page is refreshed. In this case, the Overrides function can be enabled:

  1. Open Sources → Overrides on the left → click + Select folder for overrides
  2. Select a local empty folder, Chrome will request full access permission, click "Allow"
  3. Go back to the file you want to modify (it can be a formatted temporary file), right-click → select Save for overrides
  4. After modifying the file content, clickCtrl+S / Cmd+SSave and refresh the page and only the local version will be loaded.
// 典型 Overrides 应用:Hook 加密函数并暴露到全局
// 原始代码片段(格式化后)
function h(a, b) {
    // a 是原始数据,b 是 secretKey
    var c = md5(a + b);
    return c;
}

// 修改后的代码(保存为 Overrides)
function h(a, b) {
    console.log('原始数据:', a);
    console.log('加密密钥:', b);
    var c = md5(a + b);
    console.log('加密结果:', c);
    // 把加密函数暴露到全局,方便在控制台直接测试
    window._h = h;
    return c;
}

This not only allows you to observe internal data, but also calls it directly from the consolewindow._hCarry out unit testing to facilitate subsequent reproduction with Python.

4.2 Console Direct Hook

If you don’t want to use Overrides, you can also hook key functions directly in the Console panel (provided that the function is in the global scope or can be accessed through closures, etc.):

// Hook 全局加密函数
const originalEncrypt = window.encrypt;
window.encrypt = function(raw) {
    console.log('Hook 到原始数据:', raw);
    const result = originalEncrypt(raw);
    console.log('Hook 到加密结果:', result);
    return result;
};

// 监控 fetch 请求(更推荐使用 XHR/Fetch 断点,但 Hook 方式可以灵活附加逻辑)
const originalFetch = window.fetch;
window.fetch = function(url, options) {
    console.log('Hook 到请求:', url);
    console.log('Hook 到请求参数:', options);
    return originalFetch(url, options);
};

Note: The console hook will only exist after the page is refreshed (provided you can inject it before the encryption function is loaded). For strong anti-crawling websites, you may need to execute the hook early in the page loading.

5. Practical tips for crawlers

5.1 Copy as cURL Directly reuse requests

Find the encrypted interface without manually splicing request headers and parameters:

  1. Right-click the target request in the Network panel
  2. Select CopyCopy as cURL (bash)
  3. Paste into the terminal, or use Python'scurlconverterTools (install:pip install curlconverter) into Python code
# 用 curlconverter 转换后的示例代码
import requests

headers = {
    'accept': 'application/json, text/plain, */*',
    'accept-language': 'zh-CN,zh;q=0.9',
    'content-type': 'application/json',
    'cookie': 'sessionid=xxx; csrftoken=yyy',
    'origin': 'https://example.com',
    'referer': 'https://example.com/login',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
}

json_data = {
    'username': 'test123',
    'password_encrypted': 'zxcvbnmasdfghjkl',
}

response = requests.post('https://example.com/api/login', headers=headers, json=json_data)
print(response.json())

In this way, requests in the browser can be quickly reproduced into the Python crawler to facilitate subsequent transformation.

5.2 Console shortcut operations

Chrome Console has many built-in shortcut functions that are friendly to crawlers/debugging. Memorizing them can greatly improve efficiency:

// DOM 选择(等价于原生 DOM 方法,但更短)
$('selector')        // document.querySelector
$$('selector')       // document.querySelectorAll(返回数组,可直接遍历)
$0                   // Elements 面板当前选中的 DOM 节点
$1                   // Elements 面板上一次选中的 DOM 节点

// 数组/对象处理
copy(variable)       // 把变量复制到剪贴板(比如复制提取的 DOM 解密数据)
dir($0)              // 以对象形式查看 DOM 节点的所有属性和方法(比 console.log 更清晰)

6. Security debugging and anti-debugging response

6.1 Safety debugging precautions

  1. Do not log in to your account in a formal environment to debug websites with high anti-crawling intensity to avoid your account being risk controlled or your IP blocked.
  2. Priority is given to using the Chrome incognito window (incognito mode). Close the window directly after debugging, and no traces of cookies, localStorage, Overrides, etc. will remain.
  3. Remember to clean up Overrides after debugging: Sources → Overrides → Uncheck "Enable Local Overrides", or remove the selected folder to prevent local code from interfering with normal access.
  4. Be careful when executing unknown codes that appear in the console. Some websites will output phishing codes through the console, such as inducing you to paste and execute scripts that steal cookies.

6.2 Initial responses to common anti-debugging mechanisms

At present, many websites will add anti-debugging methods. Here are two common scenarios and countermeasures:

  • Unlimited debugger Website passedsetIntervalexecute periodicallydebuggerstatement to keep DevTools in a paused state. Response: Found in the Sources paneldebuggerRight-click the line number → select Never pause here, and then this statement will no longer trigger a pause.

  • Check if DevTools is open Common methods include utilizingconsole.logMonitor window width changes, or by executingdebuggerCompare the execution time to determine whether you are debugging. Response: You can replace the detection logic through Overrides; you can also temporarily disable JavaScript in DevTools (but this may affect the normal function of the page, and is only suitable for quickly bypassing detection and capturing packets).

7. Summary

Mastering the reverse debugging capabilities of Chrome DevTools is the first step to advance in Python3 crawler. It can help you quickly locate the construction logic of encryption parameters, extract encryption factors, and reuse requests directly in Python. The techniques summarized in this article cover many aspects such as event location, use of breakpoints, variable monitoring, Hook and local replacement, request reuse, and security debugging, which are sufficient to deal with common web encryption scenarios.

In the future, we will also delve into more complex obfuscated code restoration, AST analysis, WebAssembly reverse engineering, etc., so stay tuned.