
โจทย์นี้จะได้ File .apk มา เหมือนกับโจทย์ที่แล้วเลย โดยจะหา MainActivity เหมือนเดิมจนไปสะดุด function หนึ่ง (อีกแล้ว 555)

อืมม เหมือนโจทย์ Festival Secrets เลย ก็เลยลองไปส่องดูในของ getCompleteFlag เหมือนจะเป็น Function สำหรับดึง Flag ออกมา

โอ้… งานไม่ง่ายแล้วล่ะสิ เหมือนว่าจะใช้ Native ในการ Process เพื่อรับ Flag ส่วนที่เหลืออกมา เนื่องด้วยมี Flag WANLAI{3f651648 อยู่ในหน้านี้แล้ว ดังนั้นเราต้องเอาส่วนที่เหลือออกมาให้ได้
โดยจะใช้ Frida ในการ Inject process และรัน Function getCompleteFlag ใน Native เพื่อดึง Flag ส่วนที่เหลืออกมา โดย Script จะเขียนคล้าย ๆ กับโจทย์ De4Flag เลย แต่…
WANLAI{3f651648INVALID_FRIDA_DETECTED}โอ้ มีตัวระบบดัก Frida process ด้วยหรอเนี่ย! ความยากอยู่ตรงนี้แหล่ะ เพราะอันนี้ก็เพิ่งรู้ว่ามี Lib สำหรับตรวจสอบ Frida ได้ แบบโอ้ 555
ก็เลยลองหาข้อมูลดู รวมถึงให้ AI ช่วยวิเคราะห์ด้วยว่าจะมีเวย์ไหนที่เวิดบ้างจนได้เป็น Script แบบนี้ออกมา
Java.perform(function () { console.log("[*] Starting ThaiGuardian CTF Bypass (V2)...");
const GuardianChecker = Java.use('com.ctf.songkran.hard.GuardianChecker');
// 1. บายพาส Java Layer (เพิ่ม .overload() ป้องกัน TypeError) GuardianChecker.environmentCheck.overload().implementation = function () { console.log("[+] Java: Bypassed environmentCheck()"); return true; };
// 2. บายพาส Native Layer const moduleName = "libnative-lib.so"; const detectorSymbol = "_ZN13FridaDetector6detectEv";
// const detectorPtr = Module.findExportByName(moduleName, detectorSymbol); const detectorPtr = Process.getModuleByName(moduleName).findExportByName(detectorSymbol);
if (detectorPtr) { console.log("[+] Native: Found FridaDetector::detect() at " + detectorPtr);
// เขียนทับฟังก์ชันให้ Return 0 (False) เสมอ Interceptor.replace(detectorPtr, new NativeCallback(function () { console.log("[!] Native: Blocked FridaDetector::detect()!"); return 0; }, 'int', [])); } else { console.log("[-] Native: detector symbol not found (or library not loaded yet)."); }
// 3. ใช้ Java.choose เพื่อหา Instance ใน Memory แทนการใช้ INSTANCE.value console.log("[*] Scanning memory for GuardianChecker instance...");
setTimeout(function() { Java.choose('com.ctf.songkran.hard.GuardianChecker', { onMatch: function (instance) { console.log("[+] Found GuardianChecker in memory!"); // เรียก getCompleteFlag ผ่าน Instance ที่หาเจอ const flag = instance.getCompleteFlag(); console.log("\n=============================="); console.log("🎉 FLAG: " + flag); console.log("==============================\n"); }, onComplete: function () { console.log("[*] Memory scan complete."); } }); }, 1500); // ดีเลย์ 1.5 วิ ให้แอปโหลดเสร็จสมบูรณ์});เป็นหลักการทับตัว NativeCallback ของ FridaDetector::detect() เข้ามาเพื่อไม่ให้ฟ้องว่ามี Frida process อยู่ โดยอันนี้คือเป็นความรู้ใหม่สำหรับผมมาก ๆ เลยล่ะ
พอตัว App รันแล้วตัว Frida จะ Cooldown ให้เวลาตัว Frida ไป Inject Native ไปทับ Function FridaDetector::detect() ก่อนแล้วค่อยรัน Function getCompleteFlag เพื่อได้ Flag ออกมาถูกต้อง
[+] Native: Found FridaDetector::detect() at 0x746cb6bca4[*] Scanning memory for GuardianChecker instance...[*] Memory scan complete.[+] Java: Bypassed environmentCheck()[!] Native: Blocked FridaDetector::detect()![+] Java: Bypassed environmentCheck()[!] Native: Blocked FridaDetector::detect()![*] Starting ThaiGuardian CTF Bypass (V2)...[+] Native: Found FridaDetector::detect() at 0x746cb6bca4[*] Scanning memory for GuardianChecker instance...[*] Starting ThaiGuardian CTF Bypass (V2)...[+] Native: Found FridaDetector::detect() at 0x746cb6bca4[*] Scanning memory for GuardianChecker instance...[+] Found GuardianChecker in memory![+] Java: Bypassed environmentCheck()[!] Native: Blocked FridaDetector::detect()!
==============================🎉 FLAG: WANLAI{3f65164863c251e7604c9c2351f1ae7d}==============================
[*] Memory scan complete.[Android Emulator 5554::com.ctf.songkran ]->ได้แล้ว! ยากจริง ;w;
WANLAI{3f65164863c251e7604c9c2351f1ae7d}