/

Reserved Strings

Protection ID: reservedStrings

Reserved Strings allows you to specify patterns for string literals that should be excluded from String Array protection and other string obfuscation techniques. This ensures that critical string values remain untouched and function correctly in your obfuscated code.

This protection is available in all editions of ByteHide Shield.


How It Works

Reserved Strings works by defining regular expression patterns that identify which string literals should be exempt from obfuscation processes like String Array, Unicode Escape Sequence, and Split Strings. When a string literal in your code matches any of the patterns in your reserved strings list, ByteHide Shield will leave it as-is in the obfuscated output.

This is particularly important for preserving:

  1. Regular expressions that might break if transformed
  2. URLs and API endpoints that need to remain readable
  3. DOM selectors used with methods like querySelector
  4. Format strings that include special syntax
  5. Template literals with specific formatting

By carefully configuring reserved strings, you can ensure your code remains functional while still benefiting from string obfuscation for non-critical strings.


Parameters

  • Patterns string[] : An array of regular expression patterns for string literals that should not be obfuscated. [] (empty array) by default

Patterns are tested against string literals as JavaScript regular expressions. The patterns should match the content of the string, not including the quotes.


Configuration Examples

Basic Configuration (shield.config.json)

{
  "reservedStrings": ["^https?://", "^[.#][a-zA-Z]"]
}

Advanced Configuration

{
  "stringArray": true,
  "stringArrayThreshold": 0.8,
  "reservedStrings": [
    "^https?://",
    "^[.#][a-zA-Z]",
    "^\\d+(\\.\\d+){3}$",
    "\\${[^}]+}",
    "^/[^/]+/[gimuy]*$"
  ]
}

Build Tool Integration (Webpack)

// webpack.config.js
const ByteHideShieldPlugin = require('@bytehide/webpack-shield');

module.exports = {
  // ... other webpack config
  plugins: [
    new ByteHideShieldPlugin({
      projectToken: 'your-project-token',
      config: {
        stringArray: true,
        reservedStrings: ["^https?://", "^[.#][a-zA-Z]"]
      }
    })
  ]
}

Usage Examples

Preserving URLs and CSS Selectors

// Original code
function fetchUserData(userId) {
  return fetch(`https://api.example.com/users/${userId}`)
    .then(response => response.json());
}

function hideElement(selector) {
  const element = document.querySelector(selector);
  if (element) {
    element.style.display = 'none';
  }
}

document.addEventListener('DOMContentLoaded', () => {
  hideElement('#loading-spinner');
  fetchUserData('12345')
    .then(data => {
      document.querySelector('.user-name').textContent = data.name;
    });
});

To properly obfuscate this code while maintaining functionality, use these reserved strings:

{
  "reservedStrings": ["^https?://", "^[.#][a-zA-Z]"]
}

After obfuscation with String Array, the code might look like:

const _0x4a8e = [
    'then',
    'json',
    'style',
    'display',
    'none',
    'addEventListener',
    'DOMContentLoaded',
    'textContent',
    'name'
];

function _0x28fe(_0x37bd12, _0x29a8e4) {
    return _0x28fe = function(_0x4a8ed5, _0x28fe26) {
        _0x4a8ed5 = _0x4a8ed5 - 0x94;
        let _0x5731dc = _0x4a8e[_0x4a8ed5];
        return _0x5731dc;
    }, _0x28fe(_0x37bd12, _0x29a8e4);
}

function fetchUserData(_0x5db891) {
    const _0x2a4e78 = _0x28fe;
    return fetch(`https://api.example.com/users/${_0x5db891}`)[_0x2a4e78(0x94)]((_0x35bc12) => _0x35bc12[_0x2a4e78(0x95)]());
}

function hideElement(_0x47d621) {
    const _0x3a8df4 = _0x28fe;
    const _0x4f3a82 = document.querySelector(_0x47d621);
    if (_0x4f3a82) {
        _0x4f3a82[_0x3a8df4(0x96)][_0x3a8df4(0x97)] = _0x3a8df4(0x98);
    }
}

document[_0x28fe(0x99)](_0x28fe(0x9a), () => {
    const _0x5b3f1d = _0x28fe;
    hideElement('#loading-spinner');
    fetchUserData('12345')[_0x5b3f1d(0x94)]((_0x43f2c1) => {
        const _0x50b4ea = _0x5b3f1d;
        document.querySelector('.user-name')[_0x50b4ea(0x9b)] = _0x43f2c1[_0x50b4ea(0x9c)];
    });
});

Notice how the URL "https://api.example.com/users/${userId}" and the selectors "#loading-spinner" and ".user-name" remain unchanged, while other strings are moved to the string array.


Common Patterns to Reserve

Here are some common patterns you might want to include in your reserved strings:

  • URLs and endpoints: "^https?://", "^wss?://"
  • CSS selectors: "^[.#][a-zA-Z]", "^\\[[a-zA-Z]"
  • Regular expressions: "^/[^/]+/[gimuy]*$"
  • Template literals: "\\${[^}]+}", "{\\d+}"
  • IP addresses: "^\\d+(\\.\\d+){3}$"
  • Special formats: "^\\d{4}-\\d{2}-\\d{2}$" (dates), "^[-+]?\\d*\\.?\\d+$" (numbers)

When to Use

Reserved Strings should be used whenever you're obfuscating code that contains:

  • Regular expressions: To prevent breaking regex syntax
  • DOM selectors: CSS selectors used with querySelector and similar methods
  • URL patterns: API endpoints, resource locations, and websocket connections
  • Format strings: Date formats, number formats, and template strings
  • Configuration strings: Keys and values that need to remain readable

For optimal results:

  1. Start with a minimal set of reserved string patterns
  2. Test thoroughly after obfuscation
  3. Add patterns only when necessary to fix specific issues
  4. Be as specific as possible with patterns to maximize obfuscation

Compatibility Notes

Reserved Strings has the following compatibility considerations:

  • Pattern specificity: Overly broad patterns can leave too many strings unprotected
  • Performance impact: None; this only affects the obfuscation process, not runtime code
  • Regular expression syntax: Uses JavaScript regular expression syntax
  • Protection bypass: Reserved strings will still be visible in the obfuscated code

Be careful not to over-reserve strings. Each pattern you add potentially leaves sensitive information exposed in the obfuscated output. Always use the most specific patterns possible.


Reserved Strings is typically used alongside these protections:

Previous
Reserved Names