HackTheBox Mobile Challenges (قسمت ششم. SAW)

امروز میخوایم چالش SAW از پلتفرم HackTheBox که با درجه سختی medium به ثبت رسیده بررسی کنیم.

پس از دانلود فایل های چالش می بینیم که 2 تا فایل داریم:

ببینیم فایل txt چیه:

  1. Install this application in an API Level 29 or later (i.e. Android 10.0).

میگه که باید روی API 29 یا بالا تر نصبش کنیم. پس میریم داخل Android Studio و اندروید API 29 یا 10 رو نصب و راه اندازی می کنیم.

بعد از راه اندازی شبیه ساز اندرویدی اپلیکیشن رو روش نصب می کنیم و بازش می کنیم:

پس چرا میزنیم روش باز نمیشه؟؟ :/

بریم کداشو بررسی کنیم ببینیم چی به چیه

بله اینجور که معلومه همینجوری الکی باز نمیشه. باید با یه سری آرگیومنت خاص بازش کنیم.

پس با adb به دستگاه اندرویدیمون وصل میشیم و با دستور AM یا همون Activity Manager اپلیکیشنمونو باز می کنیم:

حالا اپلیکیشنمون باز شد :)

بازم که مشکل داره :/

چرا وقتی روی click me میزنیم بست میشه؟ :/

بریم logcat رو چک کنیم ببینیم چی به چیه

Window handle Window{17e575b u0 Application Error: com.stego.saw} has no registered input channel

مثل این که اپلیکیشنمون پرمیشن اضافه تر میخواد!! پس میریم از اینجا بهش برمیشن بدیم:

حالا دوباره تست می کنیم:

الان داره یه کارایی انجام میده

میتونیم بهش ورودی بدیم:

ولی وقتی XORIFY رو میزنیم دیگه چیزی نمیاد

بریم دوباره کد هارو نگاه کنیم:

توی mainActivity یه متد داریم به اسم a

بریم ببینیم a چیه و داره چیکار می کنه:

خب اینجا می بینیم که a یک متد native هستش که دوتا String به عنوان ورودی می گیره.

توی خط بعدی میبینیم که داره یه library رو load می کنه که اسمشو توی کد به عنوان default ذکر کرده. احتمالا اسم کتابخونه ما default.so هست.

بریم مسیر lib رو توی اپلیکیشنمون بررسی کنیم ببینیم چیا داره

خب اینجا میفهمیم که چیزی به اسم default.so وجود نداره و توی کد منظورش این بوده که بیاد از کتابخونه پیش فرض استفاده کنه.

حالا از کجا بفهمیم کتابخونه پیشفرض کدومه؟

در JVM دو راه برای یافتن و لینک کردن متدهای بومی با کد جاوا وجود دارد. اولین مورد این است که یک تابع بومی را به روشی خاص فراخوانی کنید تا JVM بتواند آن را پیدا کند. راه دیگر استفاده از متد JNI RegisterNatives() است.

حالا RegisterNatives متدی است که متدهای بومی را با کلاس ارسال شده به عنوان آرگومان ثبت می کند. با hook کردن آن و اطلاعات چاپی می توانیم تشخیص دهیم که کدام متد بومی متعلق به کدام کتابخانه است.

برای hook کردن از کد جاوا اسکریپت زیر که برای frida استفاده می شود میتونیم استفاده کنیم:

function find_RegisterNatives(params) {
    let symbols = Module.enumerateSymbolsSync(&quotlibart.so&quot);
    let addrRegisterNatives = null;
    for (let i = 0; i < symbols.length; i++) {
        let symbol = symbols[i];
        
        //_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
        if (symbol.name.indexOf(&quotart&quot) >= 0 &&
                symbol.name.indexOf(&quotJNI&quot) >= 0 && 
                symbol.name.indexOf(&quotRegisterNatives&quot) >= 0 && 
                symbol.name.indexOf(&quotCheckJNI&quot) < 0) {
            addrRegisterNatives = symbol.address;
            console.log(&quotRegisterNatives is at &quot, symbol.address, symbol.name);
            hook_RegisterNatives(addrRegisterNatives)
        }
    }

}

function hook_RegisterNatives(addrRegisterNatives) {

    if (addrRegisterNatives != null) {
        Interceptor.attach(addrRegisterNatives, {
            onEnter: function (args) {
                console.log(&quot[RegisterNatives] method_count:&quot, args[3]);
                let java_class = args[1];
                let class_name = Java.vm.tryGetEnv().getClassName(java_class);
                //console.log(class_name);

                let methods_ptr = ptr(args[2]);

                let method_count = parseInt(args[3]);
                for (let i = 0; i < method_count; i++) {
                    let name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                    let sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                    let fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));

                    let name = Memory.readCString(name_ptr);
                    let sig = Memory.readCString(sig_ptr);
                    let symbol = DebugSymbol.fromAddress(fnPtr_ptr)
                    console.log(&quot[RegisterNatives] java_class:&quot, class_name, &quotname:&quot, name, &quotsig:&quot, sig, &quotfnPtr:&quot, fnPtr_ptr,  &quot fnOffset:&quot, symbol, &quot callee:&quot, DebugSymbol.fromAddress(this.returnAddress));
                }
            }
        });
    }
}

setImmediate(find_RegisterNatives);

منبع:

https://raw.githubusercontent.com/lasting-yang/frida_hook_libart/master/hook_RegisterNatives.js

حالا عملیات hooking رو شروع می کنیم:

پیداش کردیم :) توی libdefault.so هستش

فهمیدیم که a به _Z1aP7_JNIEnvP8_1 داره call میشه.

بر اساس معماری دستگاهی که داریم روش تست انجام میدیم میتونیم هدس بزنیم که داره از چه کتابخونه ای استفاده می کنه.

حالا با استفاده از IDA میایم بررسیش می کنیم:

حالا میبینیم که a داره به یه جای دیگه pass میشه:

یک ورودی رو به عنوان path و ورودی دوم را به عنوان string صحیح مد نظر اپلیکیشن میگیره که اگر اون رو درست وارد کنیم یه سری دیتا در اون path ذخیره می کنه.

ولی آخه کجا داره save می کنه؟

با این کد فریدا میایم هوک می کنیم که ببینیم کجا داره دیتا ذخیره می کنه:

ولی ورودی ما صحیح نیست!

میریم توی IDA ببینیم میتونیم چیز دیگه ای پیدا کنیم یا نه

میبینیم که داره از دوتا لیست استفاده می کنه به اسم l و m که بررسی می کنه اگر اعضای l به ترتیب با اعضای a2 عملیاتی رو انجام بدن، نتیجش با هر یک از اعضای m برابری می کنه و مقدارش true میشه یا خیر.

بریم این دوتا لیست رو پیدا کنیم:

بیاید همون عملیات توی if رو با این دوتا انجام بدیم ببینیم چی میشه.

ولی اول باید به هگزادسیمال تبدیلشون کنیم. چجوری؟ کاری نداره

فقط کافیه اون h بعدشونو تبدیل به 0x کنیم و ببریم قبلشون

مثلا:

0Ah => 0x0A

حالا بریم سراغ کد نویسی:

بله :)

مثل اینکه کلمه جادوییمون fl0ating عه

داخل اپلیکیشن واردش می کنیم:

حالا میریم توی اون path که تونستیم hook کنیم ببینیم چی اونجا ذخیره کرده:

این هم از فلگ ?

منتظر نظرات و انتقادات شما هستم

در قسمت های بعدی، به بررسی سایر چالش های موبایل در HackTheBox خواهیم پرداخت ??