Полет нормальный (Flight is Normal)
Полет нормальный (Flight is Normal)
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: js_deobfuscation, xor_decryption, source_code_analysis
Summary
Walkthrough of the CUSTOM Web Полет нормальный (Flight is Normal). URL: http://tasks.duckerz.ru:30061
Description
На этот раз придется доказать свое упорство, набрав всего 1000000 очков в самой знаменитой игре.
(This time you'll have to prove your persistence by scoring 1,000,000 points in the most famous game.)
URL: http://tasks.duckerz.ru:30061
Analysis
Opening the URL reveals an HTML5 Canvas game — a Flappy Bird clone. According to the task, we need to score 1,000,000 points to get the flag.
Obviously, playing legitimately is not an option. This is a web challenge, so we need to look for vulnerabilities in the client-side code.
Source Code Investigation
Opening DevTools (F12) we find game.js. The code is obfuscated but readable:
javascript read-only • copy allowedfunction xorEncryptDecrypt(_0x2d7b81,_0x4dc697){ let _0xb1c238=''; for(let _0x20c86b=0x0;_0x20c86b<_0x2d7b81['length'];_0x20c86b++){ _0xb1c238+=String['fromCharCode'](_0x2d7b81['charCodeAt'](_0x20c86b)^_0x4dc697['charCodeAt'](_0x20c86b%_0x4dc697['length'])); } return _0xb1c238; } function getFlag(){ const _0x480cb6='DUCKERZ_THE_BEST!', // XOR key _0x496538='\x00\x00\x00\x00\x00\x00\x00$\x06{3l06`\x0bk\x17\x0a\x00$!7\x27', // encrypted flag _0x225a3e=xorEncryptDecrypt(_0x496538,_0x480cb6); alert(_0x225a3e); }
Findings:
- The
getFlag()function is called when reaching 1,000,000 points - The flag is XOR encrypted with the key
DUCKERZ_THE_BEST! - The encrypted flag is stored directly in the code
- Obfuscation is NOT encryption — all data is accessible
Solution
Method 1: Calling the function in console
Simply call getFlag() in the browser console:
javascript read-only • copy allowedgetFlag()
Method 2: Manual XOR decryption
javascript read-only • copy allowedfunction xorEncryptDecrypt(data, key) { let result = ''; for (let i = 0; i < data.length; i++) { result += String.fromCharCode(data.charCodeAt(i) ^ key.charCodeAt(i % key.length)); } return result; } const key = 'DUCKERZ_THE_BEST!'; const encrypted = '\x00\x00\x00\x00\x00\x00\x00$\x06{3l06`\x0bk\x17\x0a\x00$!7\x27'; const flag = xorEncryptDecrypt(encrypted, key); console.log('Flag:', flag); // Flag: DUCKERZ{REDACTED}
Method 3: Modifying the score variable
In the browser console:
javascript read-only • copy allowedscore = 1000000;
Lessons
- Client-side = Game Over — any logic on the client can be bypassed
- Obfuscation != Security — renaming variables doesn't protect secrets
- XOR with known key = plaintext — if the key is in the same file, encryption is useless
- Flag name is a hint —
REDACTEDdirectly points to the solution method
Alternative Approaches
- Use Burp Suite to intercept and modify requests
- Patch JS in browser via Local Overrides
- Use debugger to modify variables at runtime
Key Takeaways / Lessons
- Mastering js_deobfuscation, xor_decryption, source_code_analysis was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-01-09 • CUSTOM • Полет нормальный (Flight is Normal) • Difficulty: Easy