- Published on
Frontend Reverse Engineering: A Comprehensive Analysis from Webpack/Vite Bundling to Slider CAPTCHA and Public-Private Key Encryption
- Authors
- Name
- MASON Joey
- https://x.com/JoeyJoeMA
Frontend Reverse Engineering: A Comprehensive Analysis from Webpack/Vite Bundling to Slider CAPTCHA and Public-Private Key Encryption
1. Overview of Frontend Reverse Engineering
Frontend reverse engineering refers to analyzing JavaScript code running in browsers, extracting key logic (such as encryption algorithms and CAPTCHA verification), and reusing it in other environments (like Node.js). With the widespread use of modern bundling tools like Webpack and Vite, frontend code is typically compressed and obfuscated, increasing the difficulty of reverse engineering. This article demonstrates a complete reverse engineering process using a case study of Tonghuashun's login slider verification, combined with Webpack code extraction techniques.
1.1 Reverse Engineering Goals
- Tonghuashun Login Slider Reverse Engineering: Extract encryption parameters (such as
uname
,passwdSalt
) and slider CAPTCHA verification logic from the login process to achieve automated login. - Webpack Code Extraction: Port Webpack-bundled browser code to Node.js environment to call key functions (such as MD5, RSA encryption).
- Public-Private Key Encryption: Analyze RSA encryption implementation and discuss the security implications of fixed public key exponents.
- Slider CAPTCHA: Understand why CAPTCHA can be represented by data and implement automated recognition.
1.2 Tool Preparation
Browser Developer Tools:
- Chrome/Firefox DevTools for analyzing network requests and JavaScript code
- Use Network panel to monitor API requests
- Use Sources panel for code debugging
- Use Console panel to execute test code
Deobfuscation Tools:
- de4js: Beautify compressed code
- JS Beautifier: Format JavaScript
- AST Explorer: Analyze code structure
Source Map Tools:
unwebpack-sourcemap
: Restore Webpack Source Mapsource-map-explorer
: Analyze bundle structurewebpack-bundle-analyzer
: Visualize dependencies
Packet Capture Tools:
- Fiddler: Windows platform packet capture
- Burp Suite: Cross-platform packet capture with HTTPS support
- Charles: Mac platform packet capture
Image Processing:
- Python's
ddddocr
: OCR recognition Pillow
: Image processingOpenCV
: Computer vision
- Python's
Node.js Environment:
- Run reverse-engineered code
- Reuse Webpack modules
- Simulate browser environment
2. Reverse Engineering Webpack and Vite Bundled Code
2.1 Webpack Bundling Characteristics
Webpack is a commonly used frontend module bundler that packages JavaScript, CSS, and other resources into bundle files (like main.js
). Its characteristics include:
Modularity:
- Uses
__webpack_require__
to load modules - Modules organized by numeric IDs (like
1337
) - Stored in
window.webpackChunk
or__webpack_modules__
- Uses
Compression and Obfuscation:
- Uses Terser for code compression in production mode
- Shortens variable names
- Renames functions
- Removes comments and whitespace
Source Map:
- Generates
.map
files in development mode - Contains original code mapping
- Supports debugging and error tracking
- Generates
Dynamic Import:
- Supports code splitting
- Generates chunk files (like
chunk-xxx.js
) - Optimizes performance through on-demand loading
2.2 Vite Bundling Characteristics
Vite is based on ES modules (ESM) and Rollup, with the following characteristics:
ESM-Driven:
- Uses browser native modules directly in development
- Uses Rollup for production bundling
- Faster development server startup
Clean Bundle:
- Clearer code structure compared to Webpack
- Lower obfuscation level
- Better readability
Dependency Pre-bundling:
- Bundles
node_modules
dependencies intodist/assets
- Uses esbuild for pre-building
- Improves development environment performance
- Bundles
2.3 Reverse Engineering Steps
2.3.1 Obtaining Frontend Resources
Open DevTools:
// Disable F12 detection document.addEventListener('keydown', function(e) { if (e.key === 'F12') { e.preventDefault(); } });
Extract Source Map:
# Install tools npm install -g unwebpack-sourcemap # Restore code unwebpack-sourcemap main.js.map # Analyze bundle npx source-map-explorer main.js.map
2.3.2 Deobfuscate Code
- Use de4js:
// Compressed code function a(b,c){return b+c} // Beautified function add(num1, num2) { return num1 + num2; }
2.3.3 Locate Key Logic
Search Keywords:
// Search in Tonghuashun case thsencrypt passwdsalt
Breakpoint Debugging:
// Set conditional breakpoint in DevTools if (plaintext === 'user@example.com') { debugger; }
Module Structure:
// Webpack module registration (window.webpackChunk = window.webpackChunk || []).push([[245], { 245: (module, exports, __webpack_require__) => { module.exports = { encode: function(plaintext) { // Encryption logic } }; } }]);
2.3.4 Extract Webpack Runtime
Locate webpack_require:
function __webpack_require__(moduleId) { var cachedModule = __webpack_module_cache__[moduleId]; if (cachedModule !== undefined) { return cachedModule.exports; } var module = __webpack_module_cache__[moduleId] = { exports: {} }; __webpack_modules__[moduleId].call( module.exports, module, module.exports, __webpack_require__ ); return module.exports; }
Global Export:
// Add global access globalThis.__exposedWebpackRequire = __webpack_require__;
2.3.5 Collect Dependency Modules
- Set Log Breakpoints:
// Add logging to __webpack_require__ window.module_array += moduleId + ':' + __webpack_modules__[moduleId] + ',\n'; // Clear cache to force loading __webpack_module_cache__ = {};
2.3.6 Environment Patching
- Simulate Browser Environment:
// Node.js environment patches global.self = global; global.window = global; global.navigator = { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }; global.document = { createEvent: () => ({ timeStamp: Number(process.hrtime.bigint() / 1_000_000n) }) };
2.3.7 Run in Node.js
- Write Run Script:
// run_encrypt.js global.self = global; require('./main.bundle.js'); require('./chunk-xxx.js'); let __webpack_require__ = globalThis.__exposedWebpackRequire; let module_xxx = __webpack_require__('xxx'); console.log(module_xxx.encode('user@example.com'));
3. Tonghuashun Login Slider Reverse Engineering
3.1 Background
Tonghuashun login involves account password encryption and slider CAPTCHA verification. The core goals are: Encrypt uname and passwdSalt parameters and send them to getGS and dologinreturnjson2 interfaces. Automatically recognize slider CAPTCHA and generate verification parameters (such as phrase and signature).
3.2 Encryption Logic
3.2.1 RSA Encryption
Frontend Implementation: Uses thsencrypt.encode function, based on RSA algorithm to encrypt account and password:
var thsencrypt = {
encode: function(plaintext, modulus_hex, exponent_hex) {
var rsa = new JSEncrypt();
rsa.setPublicKey(modulus_hex, exponent_hex);
return rsa.encrypt(plaintext);
}
};
var uname = thsencrypt.encode('user@example.com', 'YOUR_MODULUS', '10001');
Python Implementation:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from base64 import b64encode
def encrypt_encode(plaintext: str) -> str:
modulus_hex = "YOUR_MODULUS_HERE" # Get from getGS
exponent_hex = "10001"
modulus = int(modulus_hex, 16)
exponent = int(exponent_hex, 16)
key = RSA.construct((modulus, exponent))
cipher = PKCS1_v1_5.new(key)
plaintext_bytes = plaintext.encode('utf-8')
encrypted_bytes = cipher.encrypt(plaintext_bytes)
return b64encode(encrypted_bytes).decode('utf-8')
Password Encryption: Password is first encrypted with MD5:
import hashlib
def hex_md5(text: str) -> str:
return hashlib.md5(text.encode('utf-8')).hexdigest().lower()
passwd_md5 = hex_md5('mypassword')
passwd_encrypted = encrypt_encode(passwd_md5)
3.2.2 passwdSalt Generation
Logic: Involves MD5, HmacSHA256, and XOR operations:
import hmac
import hashlib
from base64 import b64decode, b64encode
def get_str_xor(e: str, t: str) -> str:
s = len(e)
r = len(t)
o = []
for d in range(s):
n = d % r
xor_char = chr(ord(e[d]) ^ ord(t[n]))
o.append(xor_char)
return ''.join(o)
def encode_data_salt_once(passwd: str, uname: str, crnd: str, dsk: str, ssv: str, dsv: str) -> str:
n = hashlib.sha256((crnd + dsk).encode('utf-8')).hexdigest()
ssv_decoded = b64decode(ssv).decode('utf-8')
n = get_str_xor(n, ssv_decoded)
passwd_md5 = hex_md5(passwd)
n = hmac.new(n.encode('utf-8'), passwd_md5.encode('utf-8'), hashlib.sha256).hexdigest()
dsv_sha256 = hashlib.sha256(dsv.encode('utf-8')).hexdigest()
n = get_str_xor(n, dsv_sha256)
n = b64encode(n.encode('utf-8')).decode('utf-8')
return encrypt_encode(n)
3.3 Slider CAPTCHA Implementation
3.3.1 CAPTCHA Analysis
The core of slider CAPTCHA is verifying whether the user's sliding trajectory is legitimate. Main verification points include:
Trajectory Data:
- Sliding distance
- Sliding time
- Acceleration changes
- Trajectory point distribution
Feature Extraction:
def extract_track_features(track_points): features = { 'distance': calculate_distance(track_points), 'duration': track_points[-1]['timestamp'] - track_points[0]['timestamp'], 'acceleration': calculate_acceleration(track_points), 'point_count': len(track_points) } return features
Trajectory Generation:
def generate_human_like_track(distance: int) -> List[Dict]: track = [] current_x = 0 current_time = int(time.time() * 1000) # Initial acceleration for i in range(5): current_x += random.randint(2, 4) current_time += random.randint(10, 20) track.append({'x': current_x, 'y': 0, 'timestamp': current_time}) # Constant speed sliding while current_x < distance - 10: current_x += random.randint(1, 3) current_time += random.randint(15, 25) track.append({'x': current_x, 'y': 0, 'timestamp': current_time}) # Deceleration while current_x < distance: current_x += random.randint(0, 2) current_time += random.randint(20, 30) track.append({'x': current_x, 'y': 0, 'timestamp': current_time}) return track
3.3.2 CAPTCHA Bypass
Image Recognition:
import ddddocr def get_slider_distance(bg_image: bytes, slider_image: bytes) -> int: ocr = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False) res = ocr.slide_match(bg_image, slider_image, simple_target=True) return res['target'][0]
Trajectory Optimization:
def optimize_track(track: List[Dict], target_distance: int) -> List[Dict]: # Adjust trajectory point distribution optimized = [] for point in track: # Add random offset point['y'] = random.randint(-2, 2) # Adjust time intervals point['timestamp'] += random.randint(-5, 5) optimized.append(point) return optimized
Request Construction:
def construct_verify_request(track: List[Dict], distance: int) -> Dict: return { 'phrase': base64.b64encode(json.dumps(track).encode()).decode(), 'signature': calculate_signature(track, distance), 'distance': distance }
3.4 Complete Login Process
async def login(username: str, password: str) -> Dict:
# 1. Get encryption parameters
gs_response = await get_gs()
modulus = gs_response['modulus']
crnd = gs_response['crnd']
# 2. Encrypt username and password
encrypted_username = encrypt_encode(username, modulus)
encrypted_password = encrypt_encode(hex_md5(password), modulus)
# 3. Generate passwdSalt
passwd_salt = encode_data_salt_once(
password, username, crnd,
gs_response['dsk'],
gs_response['ssv'],
gs_response['dsv']
)
# 4. Handle slider CAPTCHA
slider_data = await get_slider()
distance = get_slider_distance(slider_data['bg'], slider_data['slider'])
track = generate_human_like_track(distance)
verify_data = construct_verify_request(track, distance)
# 5. Send login request
login_data = {
'uname': encrypted_username,
'passwd': encrypted_password,
'passwdSalt': passwd_salt,
**verify_data
}
return await send_login_request(login_data)
4. Security Recommendations
4.1 Frontend Encryption
Avoid Fixed Public Keys:
- Regularly rotate RSA key pairs
- Use dynamically generated keys
- Consider alternative asymmetric encryption schemes
Increase Verification Complexity:
- Add timestamp verification
- Use dynamic salt values
- Implement request signature mechanism
Obfuscation Protection:
- Use JavaScript obfuscation tools
- Implement self-modifying code
- Add anti-debugging mechanisms
4.2 CAPTCHA Optimization
Trajectory Verification:
- Increase trajectory point verification
- Add acceleration detection
- Implement trajectory feature analysis
Image Processing:
- Add image interference
- Use dynamic backgrounds
- Implement multi-image verification
Behavior Analysis:
- Record user behavior characteristics
- Implement risk scoring
- Add secondary verification
5. Summary
Frontend reverse engineering is a complex and fascinating technical field that requires deep understanding of frontend frameworks, encryption algorithms, and CAPTCHA mechanisms. Through this case study, we have demonstrated:
- Methods for reverse engineering Webpack/Vite bundled code
- Implementation and security analysis of RSA encryption algorithm
- Automated solutions for slider CAPTCHA
- Implementation of complete login process
In practical applications, we need to find a balance between security and user experience, protecting system security while ensuring good user experience. At the same time, we must also be mindful of the legal and ethical boundaries of reverse engineering to ensure appropriate use of technology.
Note: This article is for technical research and learning purposes only. Please do not use it for illegal purposes. In actual projects, it is recommended to adopt more secure encryption schemes and verification mechanisms.
- Table of Contents
- Frontend Reverse Engineering: A Comprehensive Analysis from Webpack/Vite Bundling to Slider CAPTCHA and Public-Private Key Encryption
- 1. Overview of Frontend Reverse Engineering
- 1.1 Reverse Engineering Goals
- 1.2 Tool Preparation
- 2. Reverse Engineering Webpack and Vite Bundled Code
- 2.1 Webpack Bundling Characteristics
- 2.2 Vite Bundling Characteristics
- 2.3 Reverse Engineering Steps
- 2.3.1 Obtaining Frontend Resources
- 2.3.2 Deobfuscate Code
- 2.3.3 Locate Key Logic
- 2.3.4 Extract Webpack Runtime
- 2.3.5 Collect Dependency Modules
- 2.3.6 Environment Patching
- 2.3.7 Run in Node.js
- 3. Tonghuashun Login Slider Reverse Engineering
- 3.1 Background
- 3.2 Encryption Logic
- 3.2.1 RSA Encryption
- 3.2.2 passwdSalt Generation
- 3.3 Slider CAPTCHA Implementation
- 3.3.1 CAPTCHA Analysis
- 3.3.2 CAPTCHA Bypass
- 3.4 Complete Login Process
- 4. Security Recommendations
- 4.1 Frontend Encryption
- 4.2 CAPTCHA Optimization
- 5. Summary