Practical case: Himalayan audio link reverse engineering
In daily audio tool development or material research, sometimes it is necessary to obtain the real address of the audio. However, platforms like Himalaya often perform lightweight encryption on media streaming links in order to prevent link theft or abuse. This article takes the Himalaya PC album "<URL0>" as an example to dismantle the encryption logic step by step and provide the implementation code for cross-environment (pure JS/Node.js/Python calls).
Reverse web page analysis
First, we open the F12 developer tools and play any audio in the album according to the normal process:
- Switch to the Network tab
- The filter type is Media, or directly search for audio-related keywords (such as
.m4a、ximalaya.com/audio) - Find the request to return the real audio, and scroll up to find "API interface for obtaining encrypted links"

After getting the encrypted link, we need to find the JS code to decrypt it:
- Switch to the Sources tab
- Use the Global Search (Ctrl+Shift+F) function to search for the prefix/suffix of the encrypted link, or keywords
decrypt、base64、xor - After locating the encryption function, you can directly format it in the developer tools and debug it with breakpoints to verify the logic of each step.


Reverse core logic
The decrypted code extracted, organized and beautified from the developer tools is as follows:
Detailed explanation of encryption logic
The entire encrypted link can be disassembled into "Base64 transformation → fixed replacement → double XOR" three steps, the design depends on the device type (www1orwww2) Dynamically select different key tables to increase the difficulty of reverse engineering.
1. Base64 transformation and decoding
In the encrypted link returned by the API,_and-was replaced by/and+, which is the standard URL-safe Base64 variant. When decrypting, first restore it to standard Base64, and then select the decoding method according to the operating environment:
- Browser environment: use directly
atob() - Node.js environment: priority
Buffer.from(str, 'base64'), otherwise fall back to pure JS decoding
The binary string obtained after decoding, beforelength - 16The first byte is the encrypted body data, and the last 16 bytes are the initialization vector (IV).
2. Fixed replacement table (S-Box)
The platform pre-defines a 256-byte length replacement tablepermutationTable, used to scramble the original byte order. Execution process:
This step is similar to the SubBytes operation in AES, but the replacement table is hard-coded and captured from the JS code. Each iteration uses the current byte value as the index and takes the new value from the table for replacement.
3. Double XOR diffusion
- First Round XOR: XOR each block with the IV byte-by-byte in units of 16 bytes.
- Second round XOR: in 32-byte units, with fixed key
xorKeyXOR, the key comes from the array corresponding to the device type (such as the defaultalength is 32 bytes).
Since the key length is evenly divided by the data length, the second round will completely cover all the data.
4. UTF-8 decoding
The decrypted byte array is actually a UTF-8 encoded text. In order to be compatible with the environment, the code provides a manual UTF-8 decoder to splice multi-byte sequences into the final real audio address according to specifications.
Actual use and calling
Once the decryption is complete, the real audio link can be used for direct download or other operations. For convenience of calling, we willdecryptEncapsulated into modules and supported for use in Node.js or browser environments.
If batch decryption is required, just traverse the link array returned by the API and pass in the samedeviceType(Usually albums will use a fixed device type).
Summarize
This article analyzes the lightweight encryption scheme of Himalayan audio streams. The essence is to use Base64 deformation + custom substitution table + double XOR to protect the direct link. The key points to reproduce are:
- Correctly capture the encrypted link field returned by the API
- Extract the correct substitution table and XOR key from the JS source code
- Compatible with Base64 decoding in different operating environments
This case also confirms the general idea of "locating key code → extracting constants → restoring logic" in front-end reverse engineering. If you also need to batch download or analyze such resources, I hope this article can save you some time.

